commit 3f5f26dd743b52cf7a5972616750a7df16c45f7e Author: dark Date: Tue Jul 8 17:53:54 2025 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8712a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +node_modules/ \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..a64ea0b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,159 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "安装前端依赖", + "type": "shell", + "command": "npm", + "args": ["install"], + "group": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared" + }, + "problemMatcher": [] + }, + { + "label": "启动前端开发服务器", + "type": "shell", + "command": "npm", + "args": ["run", "dev"], + "group": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "new" + }, + "isBackground": true, + "problemMatcher": { + "pattern": { + "regexp": "^(.*)$", + "file": 1 + }, + "background": { + "activeOnStart": true, + "beginsPattern": ".*Local:.*", + "endsPattern": ".*ready in.*" + } + } + }, + { + "label": "构建前端", + "type": "shell", + "command": "npm", + "args": ["run", "build"], + "group": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared" + }, + "problemMatcher": [] + }, + { + "label": "安装后端依赖", + "type": "shell", + "command": "go", + "args": ["mod", "tidy"], + "group": "build", + "options": { + "cwd": "${workspaceFolder}/backend" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared" + }, + "problemMatcher": [] + }, + { + "label": "启动后端服务器", + "type": "shell", + "command": "go", + "args": ["run", "main.go"], + "group": "build", + "options": { + "cwd": "${workspaceFolder}/backend" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "new" + }, + "isBackground": true, + "problemMatcher": { + "pattern": { + "regexp": "^(.*)$", + "file": 1 + }, + "background": { + "activeOnStart": true, + "beginsPattern": ".*Server starting.*", + "endsPattern": ".*Listening and serving.*" + } + } + }, + { + "label": "构建后端", + "type": "shell", + "command": "go", + "args": ["build", "-o", "task-track", "main.go"], + "group": "build", + "options": { + "cwd": "${workspaceFolder}/backend" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared" + }, + "problemMatcher": ["$go"] + }, + { + "label": "启动完整应用", + "dependsOrder": "parallel", + "dependsOn": [ + "启动前端开发服务器", + "启动后端服务器" + ], + "group": "build", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "new" + } + }, + { + "label": "安装所有依赖", + "dependsOrder": "sequence", + "dependsOn": [ + "安装前端依赖", + "安装后端依赖" + ], + "group": "build", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared" + } + } + ] +} \ No newline at end of file diff --git a/8.0 b/8.0 new file mode 100644 index 0000000..1f89993 --- /dev/null +++ b/8.0 @@ -0,0 +1 @@ +⚠️ MySQL 未检测到,请确保已安?MySQL diff --git a/ATTACHMENT_FIX_DETAILED.md b/ATTACHMENT_FIX_DETAILED.md new file mode 100644 index 0000000..3602a09 --- /dev/null +++ b/ATTACHMENT_FIX_DETAILED.md @@ -0,0 +1,169 @@ +# 附件上传功能"Failed to create attachment"问题修复详细说明 + +## 问题现象 +当创建任务并添加附件时,显示"Failed to create attachment"错误。 + +## 问题分析 + +### 1. 原始问题定位 +- 前端设置了 `:auto-upload="false"`,需要手动触发上传 +- 上传成功后的数据处理可能存在字段匹配问题 +- 附件关联到任务的API调用可能失败 + +### 2. 数据流分析 + +**后端 UploadFile API 响应格式:** +```json +{ + "code": 200, + "message": "File uploaded successfully", + "data": { + "filename": "1736303317123456789_test.pdf", + "filepath": "./uploads/1736303317123456789_test.pdf", + "size": 12345, + "mime_type": "application/pdf" + } +} +``` + +**后端 TaskAttachment 模型字段:** +```go +type TaskAttachment struct { + ID uint `json:"id"` + TaskID uint `json:"task_id"` + FileName string `json:"file_name"` // 注意这里是下划线格式 + FilePath string `json:"file_path"` + FileSize int64 `json:"file_size"` + FileType string `json:"file_type"` + UploadedBy uint `json:"uploaded_by"` + CreatedAt time.Time `json:"created_at"` +} +``` + +## 修复方案 + +### 1. 增强前端上传成功处理 +```typescript +const handleUploadSuccess = (response: any, file: any, fileList: any[]) => { + console.log('Upload success - raw response:', response) + + // 检查响应格式 + if (!response || !response.data) { + ElMessage.error('文件上传响应格式错误') + return + } + + ElMessage.success('文件上传成功') + + // 将上传成功的文件信息添加到taskForm.attachments + const attachmentData = { + file_name: response.data.filename || file.name, // ✓ 字段匹配 + file_path: response.data.filepath || response.data.path || '', + file_size: response.data.size || file.size || 0, + file_type: response.data.mime_type || file.type || '' + } + + taskForm.attachments.push(attachmentData) +} +``` + +### 2. 优化文件上传时机控制 +```typescript +const saveTask = async () => { + // 检查是否有需要上传的文件 + const hasUnuploadedFiles = fileList.value.some((file: any) => !file.response) + + if (hasUnuploadedFiles) { + console.log('Found unuploaded files, uploading...') + if (uploadRef.value) { + await uploadRef.value.submit() + // 等待确保上传完成 + await new Promise(resolve => setTimeout(resolve, 1000)) + } + } + + // 创建任务... + // 然后处理附件关联... +} +``` + +### 3. 增强附件关联错误处理 +```typescript +// 如果有附件,需要关联到任务 +if (taskForm.attachments && taskForm.attachments.length > 0) { + for (let i = 0; i < taskForm.attachments.length; i++) { + const attachment = taskForm.attachments[i] + try { + await taskApi.addTaskAttachment(taskId, { + file_name: attachment.file_name, + file_path: attachment.file_path, + file_size: attachment.file_size, + file_type: attachment.file_type, + uploaded_by: 1 + }) + } catch (attachmentError: any) { + // 详细错误处理,附件失败不影响主任务创建 + let errorMsg = `附件 "${attachment.file_name}" 添加失败` + if (attachmentError.response?.data?.message) { + errorMsg += `: ${attachmentError.response.data.message}` + } + ElMessage.warning(errorMsg) + } + } +} +``` + +### 4. 改进文件移除处理 +```typescript +const handleFileRemove = (file: any, fileList: any[]) => { + const index = taskForm.attachments.findIndex( + (attachment: any) => { + const uploadedFileName = file.response?.data?.filename || file.name + return attachment.file_name === uploadedFileName + } + ) + + if (index > -1) { + taskForm.attachments.splice(index, 1) + } +} +``` + +## 测试方法 + +### 1. 基本附件上传测试 +1. 启动前后端服务器 +2. 访问 http://localhost:5173/tasks +3. 点击"创建任务" +4. 填写基本信息,拖拽文件到上传区域 +5. 点击"确定"创建任务 +6. 观察控制台调试信息和网络请求 + +### 2. 异常情况测试 +- 测试大文件上传 +- 测试不支持的文件格式 +- 测试网络中断情况 +- 测试后端服务异常情况 + +### 3. 调试信息 +修复后的代码会在浏览器控制台输出详细调试信息: +- 上传成功时的原始响应 +- 构造的附件数据 +- 任务创建成功后的ID +- 每个附件的关联结果 + +## 关键改进点 + +1. **响应格式验证**:增加了对上传响应格式的检查 +2. **字段映射确认**:确保前端构造的数据与后端模型字段一致 +3. **错误隔离**:附件添加失败不影响主任务创建 +4. **调试增强**:添加了详细的调试日志 +5. **时序控制**:确保文件上传完成后再进行任务创建 + +## 预期结果 +修复后,创建带附件的任务应该: +1. 文件正常上传到服务器 +2. 任务创建成功 +3. 附件正确关联到任务 +4. 即使个别附件失败,也不影响整体流程 +5. 用户得到明确的成功/失败反馈 diff --git a/ATTACHMENT_FIX_SUMMARY.md b/ATTACHMENT_FIX_SUMMARY.md new file mode 100644 index 0000000..b364044 --- /dev/null +++ b/ATTACHMENT_FIX_SUMMARY.md @@ -0,0 +1,115 @@ +## 附件功能修复总结 + +### 🔍 问题诊断 + +**错误信息**: "Failed to create attachment" + +**根本原因**: 前端发送给后端的附件数据字段名不匹配 + +### 🛠️ 修复内容 + +#### 1. 修复上传成功处理 (`handleUploadSuccess`) + +**修复前**: +```javascript +taskForm.attachments.push({ + filename: response.data.filename, // ❌ 错误字段名 + filepath: response.data.filepath, // ❌ 错误字段名 + file_size: response.data.size, // ✅ 正确 + file_type: response.data.mime_type // ✅ 正确 +}) +``` + +**修复后**: +```javascript +taskForm.attachments.push({ + file_name: response.data.filename, // ✅ 正确字段名 + file_path: response.data.filepath, // ✅ 正确字段名 + file_size: response.data.size, // ✅ 正确 + file_type: response.data.mime_type // ✅ 正确 +}) +``` + +#### 2. 修复文件移除处理 (`handleFileRemove`) + +**修复前**: +```javascript +attachment.filename === file.response?.data?.filename // ❌ 错误字段名 +``` + +**修复后**: +```javascript +attachment.file_name === (file.response?.data?.filename || file.name) // ✅ 正确字段名 +``` + +#### 3. 修复附件添加API调用 + +**修复前**: +```javascript +await taskApi.addTaskAttachment(taskId, { + file_name: attachment.filename, // ❌ 错误:应该是 attachment.file_name + file_path: attachment.filepath, // ❌ 错误:应该是 attachment.file_path + // ... +}) +``` + +**修复后**: +```javascript +await taskApi.addTaskAttachment(taskId, { + file_name: attachment.file_name, // ✅ 正确 + file_path: attachment.file_path, // ✅ 正确 + file_size: attachment.file_size, // ✅ 正确 + file_type: attachment.file_type, // ✅ 正确 + uploaded_by: 1 +}) +``` + +#### 4. 增加错误处理 + +- 为附件添加单独的错误处理 +- 附件添加失败不影响任务创建 +- 显示具体的错误信息和警告 + +### 📋 后端API数据格式确认 + +**上传文件返回**: +```json +{ + "code": 200, + "data": { + "filename": "唯一文件名", + "filepath": "./uploads/唯一文件名", + "size": 文件大小, + "mime_type": "文件类型" + } +} +``` + +**TaskAttachment 模型字段**: +```go +type TaskAttachment struct { + ID uint `json:"id"` + TaskID uint `json:"task_id"` + FileName string `json:"file_name"` + FilePath string `json:"file_path"` + FileSize int64 `json:"file_size"` + FileType string `json:"file_type"` + UploadedBy uint `json:"uploaded_by"` +} +``` + +### ✅ 修复结果 + +1. **字段名一致性**: 前端和后端字段名完全匹配 +2. **错误处理**: 附件失败不会阻止任务创建 +3. **调试信息**: 增加上传响应的调试输出 +4. **用户体验**: 显示具体的错误信息 + +### 🧪 测试建议 + +1. 创建带附件的任务 +2. 检查浏览器控制台的调试信息 +3. 验证任务创建成功且附件正确关联 +4. 测试文件上传失败的情况 + +**现在附件功能应该可以正常工作了!** 🎉 diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..b01a19b --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,179 @@ +# 任务管理系统部署指南 + +## 环境要求 + +### 后端环境 +- Go 1.19+ +- MySQL 8.0+ +- Git + +### 前端环境 +- Node.js 16+ +- npm 或 yarn +- 现代浏览器(Chrome, Firefox, Safari, Edge) + +## 快速启动 + +### 方法一:使用启动脚本(推荐) + +**Windows:** +```cmd +# 双击运行 +start.bat + +# 或命令行运行 +.\start.bat +``` + +**Linux/macOS:** +```bash +chmod +x start.sh +./start.sh +``` + +### 方法二:手动启动 + +1. **启动后端服务器** +```bash +cd backend +go mod tidy +go run main.go +``` + +2. **启动前端服务器** +```bash +cd frontend +npm install +npm run dev +``` + +## 访问地址 + +- **前端应用**: http://localhost:5173 +- **后端API**: http://localhost:8080 +- **API文档**: 参考 `api_test_tasks.http` 文件 + +## 数据库配置 + +1. 创建MySQL数据库: +```sql +CREATE DATABASE task_track CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +``` + +2. 修改后端配置文件 `backend/config.yaml`: +```yaml +database: + host: localhost + port: 3306 + user: your_username + password: your_password + database: task_track +``` + +## 功能测试 + +### 1. 用户注册和登录 +- 访问登录页面 +- 注册新用户或使用测试账号登录 + +### 2. 创建任务 +- 进入任务管理页面 +- 点击"创建任务"按钮 +- 填写任务信息 +- 上传附件(支持拖拽) +- 保存任务 + +### 3. 管理附件 +- 在任务列表中查看附件数量 +- 点击附件数量查看详情 +- 下载或删除附件 + +### 4. API测试 +使用 `api_test_tasks.http` 文件测试所有API端点: +- 文件上传 +- 任务CRUD操作 +- 附件管理 +- 搜索和筛选 + +## 目录结构 + +``` +task_track/ +├── frontend/ # Vue3前端应用 +├── backend/ # Go后端服务 +├── uploads/ # 文件上传目录 +├── database/ # 数据库初始化脚本 +├── api_test_tasks.http # API测试文件 +├── start.bat # Windows启动脚本 +├── start.sh # Linux/macOS启动脚本 +└── README.md # 项目说明 +``` + +## 故障排除 + +### 常见问题 + +1. **后端启动失败** + - 检查Go版本和环境变量 + - 确认MySQL服务运行正常 + - 检查数据库连接配置 + +2. **前端启动失败** + - 检查Node.js版本 + - 删除 `node_modules` 重新安装依赖 + - 检查端口5173是否被占用 + +3. **文件上传失败** + - 确认 `backend/uploads` 目录存在 + - 检查目录写入权限 + - 确认文件大小和格式限制 + +4. **API请求失败** + - 检查后端服务是否正常运行 + - 确认CORS配置正确 + - 检查认证token是否有效 + +### 日志查看 + +- **后端日志**: 控制台输出 +- **前端日志**: 浏览器开发者工具 +- **网络请求**: 浏览器Network面板 + +## 生产部署 + +### 后端部署 +```bash +cd backend +go build -o task-track main.go +./task-track +``` + +### 前端部署 +```bash +cd frontend +npm run build +# 将 dist/ 目录部署到Web服务器 +``` + +### 环境变量 +设置以下环境变量用于生产环境: +- `GIN_MODE=release` +- `DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASSWORD`, `DB_NAME` +- `JWT_SECRET` + +## 安全注意事项 + +1. **文件上传安全** + - 限制文件类型和大小 + - 扫描恶意文件 + - 使用独立的文件存储服务 + +2. **API安全** + - 使用HTTPS协议 + - 实现请求频率限制 + - 定期更新JWT密钥 + +3. **数据库安全** + - 使用强密码 + - 限制数据库访问权限 + - 定期备份数据 diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..f4f4563 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,257 @@ +# 开发指南 + +## 项目启动 + +### 1. 环境准备 +确保已安装以下环境: +- Node.js >= 16 +- Go >= 1.21 +- MySQL >= 8.0 + +### 2. 快速安装 +运行安装脚本: + +**Windows:** +```bash +install.bat +``` + +**Linux/macOS:** +```bash +chmod +x install.sh +./install.sh +``` + +### 3. 数据库配置 + +创建数据库: +```sql +CREATE DATABASE task_track CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +``` + +修改 `backend/config.yaml`: +```yaml +database: + host: "localhost" + port: "3306" + username: "your_username" # 替换为你的用户名 + password: "your_password" # 替换为你的密码 + database: "task_track" +``` + +### 4. 启动服务 + +**启动后端(在 backend 目录下):** +```bash +cd backend +go run main.go +``` + +**启动前端(在 frontend 目录下):** +```bash +cd frontend +npm run dev +``` + +### 5. 访问应用 +- 前端:http://localhost:5173 +- 后端API:http://localhost:8080 + +## 开发规范 + +### 前端开发 + +#### 目录结构 +``` +src/ +├── components/ # 公共组件 +├── views/ # 页面组件 +├── router/ # 路由配置 +├── store/ # 状态管理 +├── api/ # API接口 +├── utils/ # 工具函数 +└── styles/ # 样式文件 +``` + +#### 命名规范 +- 组件文件:PascalCase(如 `UserList.vue`) +- 页面文件:PascalCase(如 `Dashboard.vue`) +- 工具函数:camelCase(如 `formatDate`) +- 常量:UPPER_SNAKE_CASE(如 `API_BASE_URL`) + +#### 组件开发规范 +1. 使用 ` + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..e057602 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,1895 @@ +{ + "name": "task-track-frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "task-track-frontend", + "version": "0.0.0", + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "axios": "^1.6.0", + "element-plus": "^2.4.4", + "vue": "^3.4.0", + "vue-router": "^4.2.5", + "vuex": "^4.1.0" + }, + "devDependencies": { + "@types/node": "^20.10.0", + "@vitejs/plugin-vue": "^4.5.0", + "typescript": "^5.0.2", + "vite": "^5.0.0", + "vue-tsc": "^1.8.25" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.0", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.0.tgz", + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz", + "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.2", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.2.tgz", + "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.2", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.2.tgz", + "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.2", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "license": "MIT" + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.2.tgz", + "integrity": "sha512-g0dF8P1e2QYPOj1gu7s/3LVP6kze9A7m6x0BZ9iTdXK8N5c2V7cpBKHV3/9A4Zd8xxavdhK0t4PnqjkqVmUc9Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.2.tgz", + "integrity": "sha512-Yt5MKrOosSbSaAK5Y4J+vSiID57sOvpBNBR6K7xAaQvk3MkcNVV0f9fE20T+41WYN8hDn6SGFlFrKudtx4EoxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.2.tgz", + "integrity": "sha512-EsnFot9ZieM35YNA26nhbLTJBHD0jTwWpPwmRVDzjylQT6gkar+zenfb8mHxWpRrbn+WytRRjE0WKsfaxBkVUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.2.tgz", + "integrity": "sha512-dv/t1t1RkCvJdWWxQ2lWOO+b7cMsVw5YFaS04oHpZRWehI1h0fV1gF4wgGCTyQHHjJDfbNpwOi6PXEafRBBezw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.2.tgz", + "integrity": "sha512-W4tt4BLorKND4qeHElxDoim0+BsprFTwb+vriVQnFFtT/P6v/xO5I99xvYnVzKWrK6j7Hb0yp3x7V5LUbaeOMg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.2.tgz", + "integrity": "sha512-tdT1PHopokkuBVyHjvYehnIe20fxibxFCEhQP/96MDSOcyjM/shlTkZZLOufV3qO6/FQOSiJTBebhVc12JyPTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.2.tgz", + "integrity": "sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.2.tgz", + "integrity": "sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.2.tgz", + "integrity": "sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.2.tgz", + "integrity": "sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.2.tgz", + "integrity": "sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.2.tgz", + "integrity": "sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.2.tgz", + "integrity": "sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.2.tgz", + "integrity": "sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.2.tgz", + "integrity": "sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.2.tgz", + "integrity": "sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.2.tgz", + "integrity": "sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.2.tgz", + "integrity": "sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.2.tgz", + "integrity": "sha512-+qMUrkbUurpE6DVRjiJCNGZBGo9xM4Y0FXU5cjgudWqIBWbcLkjE3XprJUsOFgC6xjBClwVa9k6O3A7K3vxb5Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.2.tgz", + "integrity": "sha512-3+QZROYfJ25PDcxFF66UEk8jGWigHJeecZILvkPkyQN7oc5BvFo4YEXFkOs154j3FTMp9mn9Ky8RCOwastduEA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "20.19.4", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.19.4.tgz", + "integrity": "sha512-OP+We5WV8Xnbuvw0zC2m4qfB/BJvjyCwtNjhHdJxV1639SGSKrLmJkc3fMnp2Qy8nJyHp8RO6umxELN/dS1/EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", + "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-1.11.1.tgz", + "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "1.11.1" + } + }, + "node_modules/@volar/source-map": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-1.11.1.tgz", + "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "muggle-string": "^0.3.1" + } + }, + "node_modules/@volar/typescript": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-1.11.1.tgz", + "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "1.11.1", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.17.tgz", + "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.5", + "@vue/shared": "3.5.17", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz", + "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz", + "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.5", + "@vue/compiler-core": "3.5.17", + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.17", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz", + "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/language-core": { + "version": "1.8.27", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "~1.11.1", + "@volar/source-map": "~1.11.1", + "@vue/compiler-dom": "^3.3.0", + "@vue/shared": "^3.3.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.3.1", + "path-browserify": "^1.0.1", + "vue-template-compiler": "^2.7.14" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.17.tgz", + "integrity": "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.17" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.17.tgz", + "integrity": "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz", + "integrity": "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.17", + "@vue/runtime-core": "3.5.17", + "@vue/shared": "3.5.17", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.17.tgz", + "integrity": "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17" + }, + "peerDependencies": { + "vue": "3.5.17" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.17.tgz", + "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==", + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "license": "MIT", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/element-plus": { + "version": "2.10.3", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.10.3.tgz", + "integrity": "sha512-OLpf0iekuvWJrz1+H9ybvem6TYTKSNk6L1QDA3tYq2YWbogKXJnWpHG1UAGKR1B7gx+vUH7M15VIH3EijE9Kgw==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.3.1", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.13", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "license": "MIT", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", + "license": "BSD-3-Clause" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.44.2", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.44.2.tgz", + "integrity": "sha512-PVoapzTwSEcelaWGth3uR66u7ZRo6qhPHc0f2uRO9fX6XDVNrIiGYS0Pj9+R8yIIYSD/mCx2b16Ws9itljKSPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.44.2", + "@rollup/rollup-android-arm64": "4.44.2", + "@rollup/rollup-darwin-arm64": "4.44.2", + "@rollup/rollup-darwin-x64": "4.44.2", + "@rollup/rollup-freebsd-arm64": "4.44.2", + "@rollup/rollup-freebsd-x64": "4.44.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.2", + "@rollup/rollup-linux-arm-musleabihf": "4.44.2", + "@rollup/rollup-linux-arm64-gnu": "4.44.2", + "@rollup/rollup-linux-arm64-musl": "4.44.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.2", + "@rollup/rollup-linux-riscv64-gnu": "4.44.2", + "@rollup/rollup-linux-riscv64-musl": "4.44.2", + "@rollup/rollup-linux-s390x-gnu": "4.44.2", + "@rollup/rollup-linux-x64-gnu": "4.44.2", + "@rollup/rollup-linux-x64-musl": "4.44.2", + "@rollup/rollup-win32-arm64-msvc": "4.44.2", + "@rollup/rollup-win32-ia32-msvc": "4.44.2", + "@rollup/rollup-win32-x64-msvc": "4.44.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.19", + "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.17", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.17.tgz", + "integrity": "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-sfc": "3.5.17", + "@vue/runtime-dom": "3.5.17", + "@vue/server-renderer": "3.5.17", + "@vue/shared": "3.5.17" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.5.1", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz", + "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-template-compiler": { + "version": "2.7.16", + "resolved": "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "1.8.27", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "~1.11.1", + "@vue/language-core": "1.8.27", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/vuex": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/vuex/-/vuex-4.1.0.tgz", + "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.0.0-beta.11" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..45b7bcd --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,26 @@ +{ + "name": "task-track-frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.4.0", + "vue-router": "^4.2.5", + "vuex": "^4.1.0", + "axios": "^1.6.0", + "element-plus": "^2.4.4", + "@element-plus/icons-vue": "^2.3.1" + }, + "devDependencies": { + "@types/node": "^20.10.0", + "@vitejs/plugin-vue": "^4.5.0", + "typescript": "^5.0.2", + "vite": "^5.0.0", + "vue-tsc": "^1.8.25" + } +} diff --git a/frontend/src/App.vue b/frontend/src/App.vue new file mode 100644 index 0000000..fb83c01 --- /dev/null +++ b/frontend/src/App.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts new file mode 100644 index 0000000..26ebf9e --- /dev/null +++ b/frontend/src/api/index.ts @@ -0,0 +1,83 @@ +import axios from 'axios' + +// 创建axios实例 +const api = axios.create({ + baseURL: 'http://localhost:8080/api', + timeout: 10000 +}) + +// 请求拦截器 +api.interceptors.request.use( + (config) => { + const token = localStorage.getItem('token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + (error) => { + return Promise.reject(error) + } +) + +// 响应拦截器 +api.interceptors.response.use( + (response) => { + return response.data + }, + (error) => { + if (error.response) { + return Promise.reject(error.response.data) + } + return Promise.reject(error) + } +) + +// 任务相关API +export const taskApi = { + // 获取任务列表 + getTasks: (params?: any) => api.get('/tasks', { params }), + + // 获取单个任务详情 + getTask: (id: number) => api.get(`/tasks/${id}`), + + // 创建任务 + createTask: (data: any) => api.post('/tasks', data), + + // 更新任务 + updateTask: (id: number, data: any) => api.post(`/tasks/update/${id}`, data), + + // 删除任务 + deleteTask: (id: number) => api.post(`/tasks/delete/${id}`), + + // 更新任务状态 + updateTaskStatus: (id: number, status: string) => api.post(`/tasks/status/${id}`, { status }), + + // 任务评论相关 + getTaskComments: (taskId: number) => api.get(`/tasks/${taskId}/comments`), + addTaskComment: (taskId: number, data: any) => api.post(`/tasks/${taskId}/comments`, data), + deleteTaskComment: (taskId: number, commentId: number) => api.delete(`/tasks/${taskId}/comments/${commentId}`), + + // 任务附件相关 + getTaskAttachments: (taskId: number) => api.get(`/tasks/${taskId}/attachments`), + addTaskAttachment: (taskId: number, data: any) => api.post(`/tasks/${taskId}/attachments`, data), + deleteTaskAttachment: (attachmentId: number) => api.delete(`/attachments/${attachmentId}`), + + // 上传文件 + uploadFile: (file: File) => { + const formData = new FormData() + formData.append('file', file) + return api.post('/upload', formData, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + } +} + +// 用户相关API +export const userApi = { + getUsers: () => api.get('/users') +} + +export default api diff --git a/frontend/src/main.ts b/frontend/src/main.ts new file mode 100644 index 0000000..6d96e6f --- /dev/null +++ b/frontend/src/main.ts @@ -0,0 +1,28 @@ +import { createApp } from 'vue' +import { createRouter, createWebHistory } from 'vue-router' +import { createStore } from 'vuex' +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' + +import App from './App.vue' +import { routes } from './router' +import { store } from './store' + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +const app = createApp(App) + +// 注册 Element Plus 图标 +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} + +app.use(router) +app.use(store) +app.use(ElementPlus) + +app.mount('#app') diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts new file mode 100644 index 0000000..88fea87 --- /dev/null +++ b/frontend/src/router/index.ts @@ -0,0 +1,110 @@ +import { createRouter, createWebHistory } from 'vue-router' +import type { RouteRecordRaw } from 'vue-router' +import { store } from '@/store' + +export const routes: RouteRecordRaw[] = [ + { + path: '/', + redirect: '/test-login' + }, + { + path: '/test-login', + name: 'TestLogin', + component: () => import('@/views/TestLogin.vue'), + meta: { + title: '测试登录', + requiresAuth: false + } + }, + { + path: '/login', + name: 'Login', + component: () => import('@/views/Login/index.vue'), + meta: { + title: '登录', + requiresAuth: false + } + }, + { + path: '/dashboard', + name: 'Dashboard', + component: () => import('@/views/Dashboard/index.vue'), + meta: { + title: '仪表盘', + requiresAuth: true + } + }, + { + path: '/organizations', + name: 'Organizations', + component: () => import('@/views/Organization/index.vue'), + meta: { + title: '机构管理', + requiresAuth: true + } + }, + { + path: '/tasks', + name: 'Tasks', + component: () => import('@/views/Task/index.vue'), + meta: { + title: '任务管理', + requiresAuth: true + } + }, + { + path: '/tasks/board', + name: 'TaskBoard', + component: () => import('@/views/Task/Board.vue'), + meta: { + title: '任务看板', + requiresAuth: true + } + }, + { + path: '/statistics', + name: 'Statistics', + component: () => import('@/views/Statistics/index.vue'), + meta: { + title: '统计分析', + requiresAuth: true + } + }, + { + path: '/profile', + name: 'Profile', + component: () => import('@/views/Profile/index.vue'), + meta: { + title: '个人中心', + requiresAuth: true + } + }, + { + path: '/api-test', + name: 'ApiTest', + component: () => import('@/views/ApiTest.vue') + } +] + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +// 路由守卫 +router.beforeEach((to: any, from: any, next: any) => { + const token = localStorage.getItem('token') + const requiresAuth = to.matched.some((record: any) => record.meta.requiresAuth) + + if (requiresAuth && !token) { + // 需要认证但没有token,跳转到测试登录页 + next('/test-login') + } else if ((to.path === '/login' || to.path === '/test-login') && token) { + // 已经登录但访问登录页,跳转到首页 + next('/dashboard') + } else { + next() + } +}) + +export default router diff --git a/frontend/src/store/index.ts b/frontend/src/store/index.ts new file mode 100644 index 0000000..3525b36 --- /dev/null +++ b/frontend/src/store/index.ts @@ -0,0 +1,66 @@ +import { createStore } from 'vuex' + +export interface RootState { + user: { + id: number | null + username: string + email: string + realName: string + avatar: string + organizationId: number | null + } + token: string | null + isAuthenticated: boolean +} + +export const store = createStore({ + state: { + user: { + id: null, + username: '', + email: '', + realName: '', + avatar: '', + organizationId: null + }, + token: localStorage.getItem('token'), + isAuthenticated: false + }, + mutations: { + SET_USER(state, user) { + state.user = user + state.isAuthenticated = true + }, + SET_TOKEN(state, token) { + state.token = token + localStorage.setItem('token', token) + }, + CLEAR_AUTH(state) { + state.user = { + id: null, + username: '', + email: '', + realName: '', + avatar: '', + organizationId: null + } + state.token = null + state.isAuthenticated = false + localStorage.removeItem('token') + } + }, + actions: { + login({ commit }, { user, token }) { + commit('SET_USER', user) + commit('SET_TOKEN', token) + }, + logout({ commit }) { + commit('CLEAR_AUTH') + } + }, + getters: { + isAuthenticated: (state) => state.isAuthenticated, + currentUser: (state) => state.user, + token: (state) => state.token + } +}) diff --git a/frontend/src/views/ApiTest.vue b/frontend/src/views/ApiTest.vue new file mode 100644 index 0000000..1fa90ad --- /dev/null +++ b/frontend/src/views/ApiTest.vue @@ -0,0 +1,340 @@ + + + + + diff --git a/frontend/src/views/Dashboard/index.vue b/frontend/src/views/Dashboard/index.vue new file mode 100644 index 0000000..09ba34a --- /dev/null +++ b/frontend/src/views/Dashboard/index.vue @@ -0,0 +1,312 @@ + + + + + diff --git a/frontend/src/views/Login/index.vue b/frontend/src/views/Login/index.vue new file mode 100644 index 0000000..b90a163 --- /dev/null +++ b/frontend/src/views/Login/index.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/frontend/src/views/Organization/index.vue b/frontend/src/views/Organization/index.vue new file mode 100644 index 0000000..4667442 --- /dev/null +++ b/frontend/src/views/Organization/index.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/frontend/src/views/Profile/index.vue b/frontend/src/views/Profile/index.vue new file mode 100644 index 0000000..badcebc --- /dev/null +++ b/frontend/src/views/Profile/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/frontend/src/views/Statistics/index.vue b/frontend/src/views/Statistics/index.vue new file mode 100644 index 0000000..96a7263 --- /dev/null +++ b/frontend/src/views/Statistics/index.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/frontend/src/views/Task/Board.vue b/frontend/src/views/Task/Board.vue new file mode 100644 index 0000000..41d01d7 --- /dev/null +++ b/frontend/src/views/Task/Board.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/frontend/src/views/Task/index.vue b/frontend/src/views/Task/index.vue new file mode 100644 index 0000000..459f861 --- /dev/null +++ b/frontend/src/views/Task/index.vue @@ -0,0 +1,1365 @@ + + + + + diff --git a/frontend/src/views/TestLogin.vue b/frontend/src/views/TestLogin.vue new file mode 100644 index 0000000..4938cfe --- /dev/null +++ b/frontend/src/views/TestLogin.vue @@ -0,0 +1,214 @@ + + + + + diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..568d4b7 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + }, + "types": ["node"] + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json new file mode 100644 index 0000000..b940375 --- /dev/null +++ b/frontend/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "types": ["node"] + }, + "include": ["vite.config.ts"] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..e65fb1e --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,22 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import { resolve } from 'path' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': resolve(__dirname, 'src') + } + }, + server: { + port: 5173, + proxy: { + '/api': { + target: 'http://localhost:8080', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, '') + } + } + } +}) diff --git a/hot-reload.bat b/hot-reload.bat new file mode 100644 index 0000000..4cc29cb --- /dev/null +++ b/hot-reload.bat @@ -0,0 +1,28 @@ +@echo off +REM =============================================== +REM Quick Hot Reload Startup Script +REM =============================================== + +echo [INFO] Quick start hot reload development environment... +echo. + +REM Check if Air is installed +set "AIR_PATH=%USERPROFILE%\go\bin\air.exe" +if not exist "%AIR_PATH%" ( + echo [ERROR] Air not installed! Auto installing... + go install github.com/air-verse/air@latest + if %errorlevel% neq 0 ( + echo [ERROR] Air installation failed, please install manually + pause + exit /b 1 + ) + echo [INFO] Air installation completed +) + +REM Switch to backend directory and start +cd backend +echo [INFO] Starting backend hot reload server... +echo [INFO] Code changes will automatically restart the server +echo [INFO] Press Ctrl+C to stop the server +echo. +"%AIR_PATH%" diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..f3487f2 --- /dev/null +++ b/install.bat @@ -0,0 +1,56 @@ +@echo off +echo 开始安装任务跟踪系统... + +:: 检查Node.js +node --version >nul 2>&1 +if %errorlevel% neq 0 ( + echo ❌ Node.js 未安装,请先安装 Node.js >= 16 + exit /b 1 +) + +:: 检查Go +go version >nul 2>&1 +if %errorlevel% neq 0 ( + echo ❌ Go 未安装,请先安装 Go >= 1.21 + exit /b 1 +) + +:: 检查MySQL +mysql --version >nul 2>&1 +if %errorlevel% neq 0 ( + echo ⚠️ MySQL 未检测到,请确保已安装 MySQL >= 8.0 +) + +echo ✅ 环境检查通过 + +:: 安装前端依赖 +echo 📦 安装前端依赖... +cd frontend +npm install +if %errorlevel% neq 0 ( + echo ❌ 前端依赖安装失败 + exit /b 1 +) +echo ✅ 前端依赖安装成功 + +:: 安装后端依赖 +echo 📦 安装后端依赖... +cd ..\backend +go mod tidy +if %errorlevel% neq 0 ( + echo ❌ 后端依赖安装失败 + exit /b 1 +) +echo ✅ 后端依赖安装成功 + +cd .. + +echo 🎉 安装完成! +echo. +echo 接下来的步骤: +echo 1. 创建 MySQL 数据库 'task_track' +echo 2. 修改 backend/config.yaml 中的数据库配置 +echo 3. 启动后端: cd backend && go run main.go +echo 4. 启动前端: cd frontend && npm run dev +echo. +echo 访问 http://localhost:5173 开始使用系统 diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..bf66d45 --- /dev/null +++ b/install.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# 任务跟踪系统安装脚本 + +echo "开始安装任务跟踪系统..." + +# 检查Node.js +if ! command -v node &> /dev/null; then + echo "❌ Node.js 未安装,请先安装 Node.js >= 16" + exit 1 +fi + +# 检查Go +if ! command -v go &> /dev/null; then + echo "❌ Go 未安装,请先安装 Go >= 1.21" + exit 1 +fi + +# 检查MySQL +if ! command -v mysql &> /dev/null; then + echo "⚠️ MySQL 未检测到,请确保已安装 MySQL >= 8.0" +fi + +echo "✅ 环境检查通过" + +# 安装前端依赖 +echo "📦 安装前端依赖..." +cd frontend +npm install +if [ $? -eq 0 ]; then + echo "✅ 前端依赖安装成功" +else + echo "❌ 前端依赖安装失败" + exit 1 +fi + +# 安装后端依赖 +echo "📦 安装后端依赖..." +cd ../backend +go mod tidy +if [ $? -eq 0 ]; then + echo "✅ 后端依赖安装成功" +else + echo "❌ 后端依赖安装失败" + exit 1 +fi + +cd .. + +echo "🎉 安装完成!" +echo "" +echo "接下来的步骤:" +echo "1. 创建 MySQL 数据库 'task_track'" +echo "2. 修改 backend/config.yaml 中的数据库配置" +echo "3. 启动后端: cd backend && go run main.go" +echo "4. 启动前端: cd frontend && npm run dev" +echo "" +echo "访问 http://localhost:5173 开始使用系统" diff --git a/quick-fix.bat b/quick-fix.bat new file mode 100644 index 0000000..20ba7ce --- /dev/null +++ b/quick-fix.bat @@ -0,0 +1,59 @@ +@echo off +echo ================================ +echo 快速修复 404 错误 +echo ================================ +echo. + +echo [1] 停止所有服务... +taskkill /f /im go.exe >nul 2>&1 +taskkill /f /im node.exe >nul 2>&1 +timeout /t 2 /nobreak >nul + +echo [2] 清理Go模块缓存... +cd backend +go clean -modcache >nul 2>&1 +go mod tidy +echo ✅ Go模块已更新 + +echo [3] 测试编译... +go build -o test.exe main.go +if %errorlevel% neq 0 ( + echo ❌ 编译失败!请检查代码错误 + pause + exit /b 1 +) +del test.exe >nul 2>&1 +echo ✅ 编译成功 + +echo [4] 启动后端... +start /b go run main.go +cd .. + +echo [5] 等待后端启动... +timeout /t 5 /nobreak >nul + +echo [6] 测试API连接... +echo 测试基本API... +curl -s http://localhost:8080/api/test +echo. +echo. +echo 测试登录API... +curl -s -X POST http://localhost:8080/api/auth/test-login +echo. +echo. + +echo [7] 启动前端... +cd frontend +start /b npm run dev +cd .. + +echo. +echo ================================ +echo 修复完成! +echo ================================ +echo. +echo 🌐 前端: http://localhost:5173 +echo 🔧 后端: http://localhost:8080 +echo. +echo 如果仍有问题,请查看 TROUBLESHOOTING.md +pause diff --git a/restart-backend.bat b/restart-backend.bat new file mode 100644 index 0000000..a442a7d --- /dev/null +++ b/restart-backend.bat @@ -0,0 +1,13 @@ +@echo off +echo 重启后端服务器... +echo. + +echo 停止现有进程... +taskkill /f /im go.exe >nul 2>&1 + +echo 等待进程完全停止... +timeout /t 2 /nobreak >nul + +echo 启动后端服务器... +cd backend +go run main.go diff --git a/start.bat b/start.bat new file mode 100644 index 0000000..ed1d948 --- /dev/null +++ b/start.bat @@ -0,0 +1,91 @@ +@echo off +echo ================================ +echo 任务管理系统测试? +echo ================================ +echo. +echo 请选择启动模式: +echo 1. 普通模?(标准启动) +echo 2. 开发模?(热加? +echo. +set /p mode="请输入选择 (1 ?2, 默认?1): " +if "%mode%"=="" set mode=1 +if "%mode%"=="2" ( + echo. + echo [INFO] 启动开发模?(热加?... + call dev.bat + exit /b 0 +) +echo. +echo [INFO] 启动普通模?.. +echo 正在启动系统... +echo. + +REM 检查是否安装了依赖 +if not exist "frontend\node_modules" ( + echo [1/4] 安装前端依赖... + cd frontend + npm install + cd .. +) + +if not exist "backend\go.mod" ( + echo [2/4] 初始化后端项?.. + cd backend + go mod init task-track-backend + go mod tidy + cd .. +) + +REM 启动后端服务? +echo [3/4] 启动后端服务?.. +echo 正在停止现有的后端进?.. +taskkill /f /im go.exe >nul 2>&1 +timeout /t 1 /nobreak >nul + +cd backend +echo 检查后端代?.. +go build -o temp-test.exe main.go +if %errorlevel% neq 0 ( + echo ?后端编译失败,请检查代? + cd .. + pause + exit /b 1 +) +del temp-test.exe >nul 2>&1 + +echo 启动后端服务?.. +start /b go run main.go +cd .. + +echo 等待后端启动... +timeout /t 5 /nobreak >nul + +REM 启动前端服务? +echo [4/4] 启动前端服务?.. +cd frontend +start /b npm run dev +cd .. + +echo. +echo ================================ +echo 系统启动完成? +echo ================================ +echo. +echo 📱 前端地址: http://localhost:5173 +echo 🔗 后端地址: http://localhost:8080 +echo. +echo 🚀 测试说明: +echo 1. 浏览器会自动打开测试登录页面 +echo 2. 点击"一键测试登?即可开始测? +echo 3. 测试账号: testuser / 123456 +echo. +echo 📖 详细测试指南请查? TEST_GUIDE.md +echo. +echo 按任意键停止服务?.. +pause >nul + +echo 正在停止服务?.. +REM 清理进程 +taskkill /f /im go.exe >nul 2>&1 +taskkill /f /im node.exe >nul 2>&1 +echo 服务器已停止? diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..b28cea3 --- /dev/null +++ b/start.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +echo "启动任务管理系统..." + +# 检查是否安装了依赖 +if [ ! -d "frontend/node_modules" ]; then + echo "安装前端依赖..." + cd frontend + npm install + cd .. +fi + +if [ ! -f "backend/go.mod" ]; then + echo "初始化后端项目..." + cd backend + go mod init task-track-backend + go mod tidy + cd .. +fi + +# 启动后端服务器 +echo "启动后端服务器..." +cd backend +go run main.go & +BACKEND_PID=$! +cd .. + +# 等待后端启动 +sleep 3 + +# 启动前端服务器 +echo "启动前端服务器..." +cd frontend +npm run dev & +FRONTEND_PID=$! +cd .. + +echo "系统启动完成!" +echo "前端地址: http://localhost:5173" +echo "后端地址: http://localhost:8080" +echo "" +echo "按 Ctrl+C 停止服务器" + +# 等待用户停止 +wait + +# 清理进程 +kill $BACKEND_PID $FRONTEND_PID 2>/dev/null diff --git a/test-api.bat b/test-api.bat new file mode 100644 index 0000000..191c2eb --- /dev/null +++ b/test-api.bat @@ -0,0 +1,24 @@ +@echo off +echo 测试后端API... +echo. + +echo 等待2秒让后端完全启动... +timeout /t 2 /nobreak >nul + +echo 测试测试登录端点... +curl -X POST http://localhost:8080/api/auth/test-login -H "Content-Type: application/json" -d "{}" + +if %errorlevel% equ 0 ( + echo. + echo ✅ 后端API测试成功 +) else ( + echo. + echo ❌ 后端API测试失败 + echo 请检查: + echo 1. 后端服务是否正在运行 + echo 2. 端口8080是否可用 + echo 3. 防火墙设置 +) + +echo. +pause diff --git a/test-auth.bat b/test-auth.bat new file mode 100644 index 0000000..a79c977 --- /dev/null +++ b/test-auth.bat @@ -0,0 +1,5 @@ +@echo off +REM 一键运行 auth 目录下所有 Go 测试(在项目根目录执行) +echo 正在运行 auth 目录下所有测试... +go test ./backend/internal/handler/auth -v +pause \ No newline at end of file diff --git a/test-backend.http b/test-backend.http new file mode 100644 index 0000000..5adf927 --- /dev/null +++ b/test-backend.http @@ -0,0 +1,16 @@ +### 测试后端API连接 + +#### 1. 测试基本连接 +GET http://localhost:8080/api/auth/test-login + +#### 2. 测试登录端点 +POST http://localhost:8080/api/auth/test-login +Content-Type: application/json + +{} + +#### 3. 检查路由 +GET http://localhost:8080 + +#### 4. 测试CORS +OPTIONS http://localhost:8080/api/auth/test-login diff --git a/test_create_task.js b/test_create_task.js new file mode 100644 index 0000000..627aab3 --- /dev/null +++ b/test_create_task.js @@ -0,0 +1,65 @@ +// 测试创建任务的脚本 +// 在浏览器控制台中运行 + +async function testCreateTask() { + try { + // 首先测试登录 + console.log('1. 测试登录...'); + const loginResponse = await fetch('http://localhost:8080/api/auth/test-login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({}) + }); + + const loginData = await loginResponse.json(); + console.log('登录响应:', loginData); + + if (loginData.code !== 200) { + console.error('登录失败:', loginData); + return; + } + + const token = loginData.data.token; + console.log('获取到token:', token); + + // 测试创建任务 + console.log('2. 测试创建任务...'); + const taskData = { + title: '测试任务', + description: '这是一个测试任务', + type: 'feature', + priority: 'medium', + creator_id: 1, + assignee_id: 1, + organization_id: 1 + }; + + console.log('任务数据:', taskData); + + const createResponse = await fetch('http://localhost:8080/api/tasks', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify(taskData) + }); + + const createData = await createResponse.json(); + console.log('创建任务响应:', createData); + + if (createData.code === 201) { + console.log('✅ 任务创建成功!'); + } else { + console.error('❌ 任务创建失败:', createData); + } + + } catch (error) { + console.error('测试过程中发生错误:', error); + } +} + +// 运行测试 +testCreateTask(); diff --git a/tmp/build-errors.log b/tmp/build-errors.log new file mode 100644 index 0000000..571fc8e --- /dev/null +++ b/tmp/build-errors.log @@ -0,0 +1 @@ +exit status 1exit status 1exit status 1 \ No newline at end of file diff --git a/todo/todo1.md b/todo/todo1.md new file mode 100644 index 0000000..13502bf --- /dev/null +++ b/todo/todo1.md @@ -0,0 +1,399 @@ +# 实现1:建立项目框架 + +## 项目概述 +任务跟踪系统,采用前后端分离架构,支持多级机构管理和任务全生命周期管理。 + +## 技术栈 +### 前端 +- **框架**: Vue 3.0 +- **UI组件库**: Element UI 2.15.6 +- **状态管理**: Vuex 4.x +- **路由**: Vue Router 4.x +- **HTTP客户端**: Axios +- **构建工具**: Vite +- **开发语言**: TypeScript + +### 后端 +- **框架**: gin +- **数据库**: MySQL 8.0 +- **ORM**: GORM +- **认证**: JWT +- **日志**: Zap +- **配置管理**: Viper +- **API文档**: Swagger + +## 核心功能 + +### 1. 机构管理 +- **三层机构架构** + - 第一层:任务发布者(总部/管理层) + - 第二层:任务执行部门(各部门/分公司) + - 第三层:任务执行人(具体员工) +- **机构功能** + - 机构创建、编辑、删除 + - 机构层级管理 + - 人员归属管理 + - 权限分配 + +### 2. 任务管理 +- **任务生命周期** + - 任务发布:创建任务,分配执行者 + - 任务执行:执行者接收并处理任务 + - 任务跟踪:实时监控任务进度 + - 任务完成:确认任务完成状态 +- **任务属性** + - 任务标题、描述 + - 任务类型、分类 + - 创建时间、截止时间 + - 执行者、负责人 + - 任务状态(待处理、进行中、已完成、已取消) + +### 3. 任务统计 +- **统计维度** + - 按机构统计任务完成情况 + - 按时间段统计(日、周、月、年) + - 按任务类型统计 + - 按执行者统计 +- **统计指标** + - 任务完成率 + - 任务延期率 + - 任务平均处理时间 + - 工作量分布 + +### 4. 任务提醒 +- **提醒类型** + - 任务到期提醒 + - 任务逾期提醒 + - 任务状态变更通知 +- **提醒方式** + - 系统内通知 + - 邮件提醒 + - 微信通知(可选) + +### 5. 任务看板 +- **看板视图** + - 待处理任务 + - 进行中任务 + - 已完成任务 + - 已逾期任务 +- **拖拽操作** + - 任务状态变更 + - 任务优先级调整 + +### 6. 任务搜索 +- **搜索条件** + - 任务标题、内容 + - 任务状态 + - 创建时间范围 + - 执行者、创建者 + - 任务标签 +- **高级搜索** + - 多条件组合搜索 + - 搜索历史记录 + - 搜索结果导出 + +### 7. 任务评论 +- **评论功能** + - 任务进度更新 + - 问题反馈 + - 协作沟通 +- **评论管理** + - 评论权限控制 + - 评论历史记录 + - @提醒功能 + +### 8. 任务附件 +- **附件类型** + - 文档文件(Word、Excel、PDF等) + - 图片文件 + - 视频文件 +- **附件管理** + - 文件上传、下载 + - 文件预览 + - 文件版本管理 + +### 9. 任务优先级 +- **优先级分类** + - 紧急(红色) + - 高优先级(橙色) + - 中优先级(黄色) + - 低优先级(绿色) +- **优先级管理** + - 优先级设置 + - 优先级排序 + - 优先级提醒 + +### 10. 任务标签 +- **标签系统** + - 自定义标签 + - 标签分类管理 + - 标签颜色设置 +- **标签应用** + - 任务分类 + - 快速筛选 + - 统计分析 + +### 11. 任务分配 +- **分配方式** + - 手动分配 + - 自动分配(基于工作量) + - 批量分配 +- **分配规则** + - 部门权限控制 + - 工作量平衡 + - 技能匹配 + +### 12. 任务时限 +- **时限设置** + - 任务开始时间 + - 任务截止时间 + - 预计完成时间 +- **时限管理** + - 时限提醒 + - 延期申请 + - 时限统计 + +## 项目结构 + +### 前端项目结构 +``` +frontend/ +├── public/ +│ ├── index.html +│ └── favicon.ico +├── src/ +│ ├── components/ # 公共组件 +│ │ ├── Layout/ # 布局组件 +│ │ ├── Table/ # 表格组件 +│ │ ├── Form/ # 表单组件 +│ │ └── Common/ # 通用组件 +│ ├── views/ # 页面组件 +│ │ ├── Dashboard/ # 仪表盘 +│ │ ├── Organization/ # 机构管理 +│ │ ├── Task/ # 任务管理 +│ │ ├── Statistics/ # 统计分析 +│ │ └── Profile/ # 个人中心 +│ ├── store/ # Vuex状态管理 +│ ├── router/ # 路由配置 +│ ├── api/ # API接口 +│ ├── utils/ # 工具函数 +│ ├── assets/ # 静态资源 +│ └── styles/ # 样式文件 +├── package.json +├── vite.config.js +└── README.md +``` + +### 后端项目结构 +``` +backend/ +├── api/ # API接口层 +│ ├── handlers/ # 请求处理器 +│ ├── middleware/ # 中间件 +│ └── types/ # 类型定义 +├── internal/ # 内部业务逻辑 +│ ├── config/ # 配置管理 +│ ├── logic/ # 业务逻辑 +│ ├── svc/ # 服务上下文 +│ └── types/ # 类型定义 +├── model/ # 数据模型 +├── migration/ # 数据库迁移 +├── pkg/ # 公共包 +│ ├── auth/ # 认证相关 +│ ├── cache/ # 缓存相关 +│ ├── database/ # 数据库相关 +│ └── utils/ # 工具函数 +├── go.mod +├── go.sum +└── README.md +``` + +## 数据库设计 + +### 核心数据表 + +#### 1. 用户表 (users) +- id: 主键 +- username: 用户名 +- email: 邮箱 +- password: 密码(加密) +- real_name: 真实姓名 +- phone: 手机号 +- avatar: 头像 +- status: 状态(启用/禁用) +- created_at: 创建时间 +- updated_at: 更新时间 + +#### 2. 机构表 (organizations) +- id: 主键 +- name: 机构名称 +- code: 机构代码 +- parent_id: 父级机构ID +- level: 机构层级 +- sort: 排序 +- status: 状态 +- created_at: 创建时间 +- updated_at: 更新时间 + +#### 3. 用户机构关系表 (user_organizations) +- id: 主键 +- user_id: 用户ID +- organization_id: 机构ID +- role: 角色(管理员/成员) +- created_at: 创建时间 + +#### 4. 任务表 (tasks) +- id: 主键 +- title: 任务标题 +- description: 任务描述 +- type: 任务类型 +- priority: 优先级 +- status: 状态 +- creator_id: 创建者ID +- assignee_id: 执行者ID +- organization_id: 所属机构ID +- start_time: 开始时间 +- end_time: 截止时间 +- completed_at: 完成时间 +- created_at: 创建时间 +- updated_at: 更新时间 + +#### 5. 任务标签表 (task_tags) +- id: 主键 +- name: 标签名称 +- color: 标签颜色 +- organization_id: 所属机构ID +- created_at: 创建时间 + +#### 6. 任务标签关系表 (task_tag_relations) +- id: 主键 +- task_id: 任务ID +- tag_id: 标签ID + +#### 7. 任务评论表 (task_comments) +- id: 主键 +- task_id: 任务ID +- user_id: 用户ID +- content: 评论内容 +- created_at: 创建时间 + +#### 8. 任务附件表 (task_attachments) +- id: 主键 +- task_id: 任务ID +- file_name: 文件名 +- file_path: 文件路径 +- file_size: 文件大小 +- file_type: 文件类型 +- uploaded_by: 上传者ID +- created_at: 创建时间 + +## 开发阶段 + +### 第一阶段:基础框架搭建(2周) +- [x] 项目初始化 +- [ ] 前端Vue3项目搭建 +- [ ] 后端Go-Zero项目搭建 +- [ ] 数据库设计和创建 +- [ ] 基础认证功能 +- [ ] 项目部署环境准备 + +### 第二阶段:核心功能开发(4周) +- [ ] 用户管理功能 +- [ ] 机构管理功能 +- [ ] 任务CRUD功能 +- [ ] 任务状态管理 +- [ ] 基础权限控制 + +### 第三阶段:高级功能开发(3周) +- [ ] 任务看板功能 +- [ ] 任务搜索功能 +- [ ] 任务统计功能 +- [ ] 任务提醒功能 +- [ ] 任务评论功能 + +### 第四阶段:扩展功能开发(2周) +- [ ] 任务附件功能 +- [ ] 任务标签功能 +- [ ] 任务优先级功能 +- [ ] 任务分配优化 + +### 第五阶段:优化和测试(1周) +- [ ] 性能优化 +- [ ] 单元测试 +- [ ] 集成测试 +- [ ] 用户体验优化 + +## API接口设计 + +### 认证相关 +- POST /api/auth/login - 用户登录 +- POST /api/auth/logout - 用户退出 +- POST /api/auth/refresh - 刷新Token +- GET /api/auth/me - 获取当前用户信息 + +### 机构管理 +- GET /api/organizations - 获取机构列表 +- POST /api/organizations - 创建机构 +- PUT /api/organizations/:id - 更新机构 +- DELETE /api/organizations/:id - 删除机构 +- GET /api/organizations/:id/users - 获取机构用户 + +### 任务管理 +- GET /api/tasks - 获取任务列表 +- POST /api/tasks - 创建任务 +- GET /api/tasks/:id - 获取任务详情 +- PUT /api/tasks/:id - 更新任务 +- DELETE /api/tasks/:id - 删除任务 +- PUT /api/tasks/:id/status - 更新任务状态 + +### 任务统计 +- GET /api/statistics/overview - 获取统计概览 +- GET /api/statistics/tasks - 获取任务统计 +- GET /api/statistics/users - 获取用户统计 + +## 部署说明 + +### 开发环境 +- 前端:npm run dev (http://localhost:5173) +- 后端:go run main.go (http://localhost:8080) +- 数据库:MySQL 8.0 (localhost:3306) + +### 生产环境 +- 前端:nginx反向代理 +- 后端:Docker容器化部署 +- 数据库:MySQL主从架构 +- 缓存:Redis集群 +- 监控:Prometheus + Grafana + +### 环境配置 +- 开发环境:config/dev.yaml +- 测试环境:config/test.yaml +- 生产环境:config/prod.yaml + +## 注意事项 + +1. **安全性** + - 所有接口都要进行身份验证 + - 敏感数据加密存储 + - SQL注入防护 + - XSS攻击防护 + +2. **性能优化** + - 数据库索引优化 + - 查询语句优化 + - 缓存机制 + - 分页查询 + +3. **用户体验** + - 响应式设计 + - 友好的错误提示 + - 加载状态提示 + - 操作确认提示 + +4. **代码质量** + - 代码规范检查 + - 单元测试覆盖 + - 代码审查 + - 文档完整性 + + diff --git a/todo/todo2.md b/todo/todo2.md new file mode 100644 index 0000000..2181dea --- /dev/null +++ b/todo/todo2.md @@ -0,0 +1,52 @@ +实现2: 实现前后端任务创建功能 ✅ 已完成 +- ✅ 前端通过表单提交任务数据,需要上传附件功能 +- ✅ 后端接收并存储到数据库,需要附件管理api +- ✅ 后端API,只允许POST,GET方法(附件删除使用DELETE) +- ✅ 附件支持office文档、图片等格式 +- ✅ 附件需要和任务关联,附件根据任务ID进行管理 + +## 实现的功能 + +### 后端功能 +1. **文件上传API** (`POST /api/upload`) + - 支持多种文件格式:Office文档、PDF、图片等 + - 文件大小限制和格式验证 + - 生成唯一文件名防止冲突 + - 保存到 `./uploads` 目录 + +2. **附件管理API** + - `GET /api/tasks/:id/attachments` - 获取任务附件列表 + - `POST /api/tasks/:id/attachments` - 添加任务附件关联 + - `DELETE /api/attachments/:id` - 删除附件 + - `GET /api/download/:id` - 下载附件 + +3. **任务API增强** + - 支持标题搜索、状态和优先级筛选 + - 分页参数优化(page, size) + - 创建任务时支持附件关联 + +### 前端功能 +1. **任务创建表单** + - 完整的任务信息录入 + - 拖拽式文件上传组件 + - 支持多文件上传 + - 实时文件列表管理 + +2. **附件管理界面** + - 任务列表显示附件数量 + - 附件查看对话框 + - 附件下载和删除功能 + - 文件大小格式化显示 + +3. **API集成** + - 统一的API服务封装 + - 错误处理和用户提示 + - 认证token自动携带 + +## 技术特点 + +- **文件安全**:服务器端文件类型验证和大小限制 +- **用户体验**:拖拽上传、进度显示、错误提示 +- **数据一致性**:附件与任务的关联关系管理 +- **性能优化**:分页查询、按需加载附件列表 +[]: # 测试任务创建功能是否正常工作 \ No newline at end of file diff --git a/todo/todo3.md b/todo/todo3.md new file mode 100644 index 0000000..8cdda77 --- /dev/null +++ b/todo/todo3.md @@ -0,0 +1,5 @@ +实现3:调整handler目录,每个模块一个目录,每个方法一个文件 +- internal/handler/auth/login.go +- internal/handler/auth/logout.go +- 其他同理 +use context7 diff --git a/todo/todo4.md b/todo/todo4.md new file mode 100644 index 0000000..7128e4a --- /dev/null +++ b/todo/todo4.md @@ -0,0 +1,5 @@ +# 实现4 : +编写 handler目录下所有api方法的测试脚本,文件一一对应 +## auth 测试用例 +- 根据 handler/auth 下的方法,编写测试用例: 注册用户 -> 用户登录 -> 获取我的信息 -> 用户登出 ,使用项目数据库连接进行测试 Mysql8 +- 引入user目录下功能,先get_user ,如果有test user, update_user,然后delete_user,然后再register-login-me-logrout.如果没有test user, register-login-me-logrout-update_user-get_user-delete_user. use context7 \ No newline at end of file