From 2a5bf19e7dedbec349731602c7cc8c9feff8077b Mon Sep 17 00:00:00 2001 From: Kerwin Date: Fri, 12 Sep 2025 18:06:09 +0800 Subject: [PATCH] =?UTF-8?q?update:=20=E6=B7=BB=E5=8A=A0=E6=89=A9=E5=AE=B9U?= =?UTF-8?q?I?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/entity/task.go | 1 + db/repo/task_repository.go | 2 +- handlers/task_handler.go | 147 +++++++++ main.go | 6 + task/expansion_processor.go | 190 +++++++++++ web/components.d.ts | 4 + web/composables/useApi.ts | 4 +- web/pages/admin/accounts-expansion.vue | 427 +++++++++++++++++++++++++ web/pages/admin/accounts.vue | 11 + web/pages/admin/tasks/index.vue | 20 +- web/public/assets/images/fxt.jpg | Bin 0 -> 157001 bytes web/stores/task.ts | 2 +- 12 files changed, 802 insertions(+), 12 deletions(-) create mode 100644 task/expansion_processor.go create mode 100644 web/pages/admin/accounts-expansion.vue create mode 100644 web/public/assets/images/fxt.jpg diff --git a/db/entity/task.go b/db/entity/task.go index 94683c2..3359810 100644 --- a/db/entity/task.go +++ b/db/entity/task.go @@ -23,6 +23,7 @@ type TaskType string const ( TaskTypeBatchTransfer TaskType = "batch_transfer" // 批量转存 + TaskTypeExpansion TaskType = "expansion" // 账号扩容 ) // Task 任务表 diff --git a/db/repo/task_repository.go b/db/repo/task_repository.go index 1f6050c..15651cd 100644 --- a/db/repo/task_repository.go +++ b/db/repo/task_repository.go @@ -58,7 +58,7 @@ func (r *TaskRepositoryImpl) GetList(page, pageSize int, taskType, status string // 添加过滤条件 if taskType != "" { - query = query.Where("task_type = ?", taskType) + query = query.Where("type = ?", taskType) } if status != "" { query = query.Where("status = ?", status) diff --git a/handlers/task_handler.go b/handlers/task_handler.go index 548905f..c834922 100644 --- a/handlers/task_handler.go +++ b/handlers/task_handler.go @@ -2,6 +2,7 @@ package handlers import ( "encoding/json" + "fmt" "net/http" "strconv" @@ -387,3 +388,149 @@ func (h *TaskHandler) DeleteTask(c *gin.Context) { "message": "任务删除成功", }) } + +// CreateExpansionTask 创建扩容任务 +func (h *TaskHandler) CreateExpansionTask(c *gin.Context) { + var req struct { + PanAccountID uint `json:"pan_account_id" binding:"required"` + Description string `json:"description"` + } + + if err := c.ShouldBindJSON(&req); err != nil { + ErrorResponse(c, "参数错误: "+err.Error(), http.StatusBadRequest) + return + } + + utils.Debug("创建扩容任务: 账号ID %d", req.PanAccountID) + + // 获取账号信息,用于构建任务标题 + cks, err := h.repoMgr.CksRepository.FindByID(req.PanAccountID) + if err != nil { + utils.Error("获取账号信息失败: %v", err) + ErrorResponse(c, "获取账号信息失败: "+err.Error(), http.StatusInternalServerError) + return + } + + // 构建账号名称 + accountName := cks.Username + if accountName == "" { + accountName = cks.Remark + } + if accountName == "" { + accountName = fmt.Sprintf("账号%d", cks.ID) + } + + // 构建任务配置(存储账号ID) + taskConfig := map[string]interface{}{ + "pan_account_id": req.PanAccountID, + } + configJSON, _ := json.Marshal(taskConfig) + + // 创建任务标题,包含账号名称 + taskTitle := fmt.Sprintf("账号扩容 - %s", accountName) + + // 创建任务 + newTask := &entity.Task{ + Title: taskTitle, + Description: req.Description, + Type: "expansion", + Status: "pending", + TotalItems: 1, // 扩容任务只有一个项目 + Config: string(configJSON), + CreatedAt: utils.GetCurrentTime(), + UpdatedAt: utils.GetCurrentTime(), + } + + if err := h.repoMgr.TaskRepository.Create(newTask); err != nil { + utils.Error("创建扩容任务失败: %v", err) + ErrorResponse(c, "创建任务失败: "+err.Error(), http.StatusInternalServerError) + return + } + + // 创建任务项 + expansionInput := task.ExpansionInput{ + PanAccountID: req.PanAccountID, + } + + inputJSON, _ := json.Marshal(expansionInput) + + taskItem := &entity.TaskItem{ + TaskID: newTask.ID, + Status: "pending", + InputData: string(inputJSON), + CreatedAt: utils.GetCurrentTime(), + UpdatedAt: utils.GetCurrentTime(), + } + + err = h.repoMgr.TaskItemRepository.Create(taskItem) + if err != nil { + utils.Error("创建扩容任务项失败: %v", err) + // 继续处理,不返回错误 + } + + utils.Debug("扩容任务创建完成: %d", newTask.ID) + + SuccessResponse(c, gin.H{ + "task_id": newTask.ID, + "total_items": 1, + "message": "扩容任务创建成功", + }) +} + +// GetExpansionAccounts 获取支持扩容的账号列表 +func (h *TaskHandler) GetExpansionAccounts(c *gin.Context) { + // 获取所有有效的账号 + cksList, err := h.repoMgr.CksRepository.FindByIsValid(false) + if err != nil { + utils.Error("获取账号列表失败: %v", err) + ErrorResponse(c, "获取账号列表失败: "+err.Error(), http.StatusInternalServerError) + return + } + + // 过滤出 quark 账号 + var expansionAccounts []gin.H + tasks, _, _ := h.repoMgr.TaskRepository.GetList(1, 1000, "expansion", "completed") + for _, ck := range cksList { + if ck.ServiceType == "quark" { + // 使用 Username 作为账号名称,如果为空则使用 Remark + accountName := ck.Username + if accountName == "" { + accountName = ck.Remark + } + if accountName == "" { + accountName = "账号 " + fmt.Sprintf("%d", ck.ID) + } + + // 检查是否已经扩容过 + expanded := false + for _, task := range tasks { + if task.Config != "" { + var taskConfig map[string]interface{} + if err := json.Unmarshal([]byte(task.Config), &taskConfig); err == nil { + if configAccountID, ok := taskConfig["pan_account_id"].(float64); ok { + if uint(configAccountID) == ck.ID { + expanded = true + break + } + } + } + } + } + + expansionAccounts = append(expansionAccounts, gin.H{ + "id": ck.ID, + "name": accountName, + "service_type": ck.ServiceType, + "expanded": expanded, + "created_at": ck.CreatedAt, + "updated_at": ck.UpdatedAt, + }) + } + } + + SuccessResponse(c, gin.H{ + "accounts": expansionAccounts, + "total": len(expansionAccounts), + "message": "获取支持扩容账号列表成功", + }) +} diff --git a/main.go b/main.go index 970e64e..393f17c 100644 --- a/main.go +++ b/main.go @@ -92,6 +92,10 @@ func main() { transferProcessor := task.NewTransferProcessor(repoManager) taskManager.RegisterProcessor(transferProcessor) + // 注册扩容任务处理器 + expansionProcessor := task.NewExpansionProcessor(repoManager) + taskManager.RegisterProcessor(expansionProcessor) + // 初始化Meilisearch管理器 meilisearchManager := services.NewMeilisearchManager(repoManager) if err := meilisearchManager.Initialize(); err != nil { @@ -285,6 +289,8 @@ func main() { // 任务管理路由 api.POST("/tasks/transfer", middleware.AuthMiddleware(), middleware.AdminMiddleware(), taskHandler.CreateBatchTransferTask) + api.POST("/tasks/expansion", middleware.AuthMiddleware(), middleware.AdminMiddleware(), taskHandler.CreateExpansionTask) + api.GET("/tasks/expansion/accounts", middleware.AuthMiddleware(), middleware.AdminMiddleware(), taskHandler.GetExpansionAccounts) api.GET("/tasks", middleware.AuthMiddleware(), middleware.AdminMiddleware(), taskHandler.GetTasks) api.GET("/tasks/:id", middleware.AuthMiddleware(), middleware.AdminMiddleware(), taskHandler.GetTaskStatus) api.POST("/tasks/:id/start", middleware.AuthMiddleware(), middleware.AdminMiddleware(), taskHandler.StartTask) diff --git a/task/expansion_processor.go b/task/expansion_processor.go new file mode 100644 index 0000000..7b81ddc --- /dev/null +++ b/task/expansion_processor.go @@ -0,0 +1,190 @@ +package task + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/ctwj/urldb/db/entity" + "github.com/ctwj/urldb/db/repo" + "github.com/ctwj/urldb/utils" +) + +// ExpansionProcessor 扩容任务处理器 +type ExpansionProcessor struct { + repoMgr *repo.RepositoryManager +} + +// NewExpansionProcessor 创建扩容任务处理器 +func NewExpansionProcessor(repoMgr *repo.RepositoryManager) *ExpansionProcessor { + return &ExpansionProcessor{ + repoMgr: repoMgr, + } +} + +// GetTaskType 获取任务类型 +func (ep *ExpansionProcessor) GetTaskType() string { + return "expansion" +} + +// ExpansionInput 扩容任务输入数据结构 +type ExpansionInput struct { + PanAccountID uint `json:"pan_account_id"` +} + +// ExpansionOutput 扩容任务输出数据结构 +type ExpansionOutput struct { + Success bool `json:"success"` + Message string `json:"message"` + Error string `json:"error,omitempty"` + Time string `json:"time"` +} + +// Process 处理扩容任务项 +func (ep *ExpansionProcessor) Process(ctx context.Context, taskID uint, item *entity.TaskItem) error { + utils.Info("开始处理扩容任务项: %d", item.ID) + + // 解析输入数据 + var input ExpansionInput + if err := json.Unmarshal([]byte(item.InputData), &input); err != nil { + return fmt.Errorf("解析输入数据失败: %v", err) + } + + // 验证输入数据 + if err := ep.validateInput(&input); err != nil { + return fmt.Errorf("输入数据验证失败: %v", err) + } + + // 检查账号是否已经扩容过 + exists, err := ep.checkExpansionExists(input.PanAccountID) + if err != nil { + utils.Error("检查扩容记录失败: %v", err) + return fmt.Errorf("检查扩容记录失败: %v", err) + } + + if exists { + output := ExpansionOutput{ + Success: false, + Message: "账号已扩容过", + Error: "每个账号只能扩容一次", + Time: utils.GetCurrentTimeString(), + } + + outputJSON, _ := json.Marshal(output) + item.OutputData = string(outputJSON) + + utils.Info("账号已扩容过,跳过扩容: 账号ID %d", input.PanAccountID) + return fmt.Errorf("账号已扩容过") + } + + // 检查账号类型(只支持quark账号) + if err := ep.checkAccountType(input.PanAccountID); err != nil { + output := ExpansionOutput{ + Success: false, + Message: "账号类型不支持扩容", + Error: err.Error(), + Time: utils.GetCurrentTimeString(), + } + + outputJSON, _ := json.Marshal(output) + item.OutputData = string(outputJSON) + + utils.Error("账号类型不支持扩容: %v", err) + return err + } + + // 执行扩容操作(这里留空,直接返回成功) + if err := ep.performExpansion(ctx, input.PanAccountID); err != nil { + output := ExpansionOutput{ + Success: false, + Message: "扩容失败", + Error: err.Error(), + Time: utils.GetCurrentTimeString(), + } + + outputJSON, _ := json.Marshal(output) + item.OutputData = string(outputJSON) + + utils.Error("扩容任务项处理失败: %d, 错误: %v", item.ID, err) + return fmt.Errorf("扩容失败: %v", err) + } + + // 扩容成功 + output := ExpansionOutput{ + Success: true, + Message: "扩容成功", + Time: utils.GetCurrentTimeString(), + } + + outputJSON, _ := json.Marshal(output) + item.OutputData = string(outputJSON) + + utils.Info("扩容任务项处理完成: %d, 账号ID: %d", item.ID, input.PanAccountID) + return nil +} + +// validateInput 验证输入数据 +func (ep *ExpansionProcessor) validateInput(input *ExpansionInput) error { + if input.PanAccountID == 0 { + return fmt.Errorf("账号ID不能为空") + } + return nil +} + +// checkExpansionExists 检查账号是否已经扩容过 +func (ep *ExpansionProcessor) checkExpansionExists(panAccountID uint) (bool, error) { + // 查询所有expansion类型的任务 + tasks, _, err := ep.repoMgr.TaskRepository.GetList(1, 1000, "expansion", "completed") + if err != nil { + return false, fmt.Errorf("获取扩容任务列表失败: %v", err) + } + + // 检查每个任务的配置中是否包含该账号ID + for _, task := range tasks { + if task.Config != "" { + var taskConfig map[string]interface{} + if err := json.Unmarshal([]byte(task.Config), &taskConfig); err == nil { + if configAccountID, ok := taskConfig["pan_account_id"].(float64); ok { + if uint(configAccountID) == panAccountID { + // 找到了该账号的扩容任务,检查任务状态 + if task.Status == "completed" { + // 如果任务已完成,说明已经扩容过 + return true, nil + } + } + } + } + } + } + + return false, nil +} + +// checkAccountType 检查账号类型(只支持quark账号) +func (ep *ExpansionProcessor) checkAccountType(panAccountID uint) error { + // 获取账号信息 + cks, err := ep.repoMgr.CksRepository.FindByID(panAccountID) + if err != nil { + return fmt.Errorf("获取账号信息失败: %v", err) + } + + // 检查是否为quark账号 + if cks.ServiceType != "quark" { + return fmt.Errorf("只支持quark账号扩容,当前账号类型: %s", cks.ServiceType) + } + + return nil +} + +// performExpansion 执行扩容操作 +func (ep *ExpansionProcessor) performExpansion(ctx context.Context, panAccountID uint) error { + // 扩容逻辑暂时留空,直接返回成功 + // TODO: 实现具体的扩容逻辑 + + utils.Info("执行扩容操作,账号ID: %d", panAccountID) + + // 模拟扩容操作延迟 + // time.Sleep(2 * time.Second) + + return nil +} diff --git a/web/components.d.ts b/web/components.d.ts index cf7c7d9..db43598 100644 --- a/web/components.d.ts +++ b/web/components.d.ts @@ -15,11 +15,15 @@ declare module 'vue' { NButtonGroup: typeof import('naive-ui')['NButtonGroup'] NCard: typeof import('naive-ui')['NCard'] NCheckbox: typeof import('naive-ui')['NCheckbox'] + NCollapse: typeof import('naive-ui')['NCollapse'] + NCollapseItem: typeof import('naive-ui')['NCollapseItem'] NDataTable: typeof import('naive-ui')['NDataTable'] NDatePicker: typeof import('naive-ui')['NDatePicker'] NDescriptions: typeof import('naive-ui')['NDescriptions'] NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem'] NDialogProvider: typeof import('naive-ui')['NDialogProvider'] + NDrawer: typeof import('naive-ui')['NDrawer'] + NDrawerContent: typeof import('naive-ui')['NDrawerContent'] NEmpty: typeof import('naive-ui')['NEmpty'] NForm: typeof import('naive-ui')['NForm'] NFormItem: typeof import('naive-ui')['NFormItem'] diff --git a/web/composables/useApi.ts b/web/composables/useApi.ts index 260a188..436f6eb 100644 --- a/web/composables/useApi.ts +++ b/web/composables/useApi.ts @@ -244,6 +244,8 @@ export const usePublicSystemConfigApi = () => { // 任务管理API export const useTaskApi = () => { const createBatchTransferTask = (data: any) => useApiFetch('/tasks/transfer', { method: 'POST', body: data }).then(parseApiResponse) + const createExpansionTask = (data: any) => useApiFetch('/tasks/expansion', { method: 'POST', body: data }).then(parseApiResponse) + const getExpansionAccounts = () => useApiFetch('/tasks/expansion/accounts').then(parseApiResponse) const getTasks = (params?: any) => useApiFetch('/tasks', { params }).then(parseApiResponse) const getTaskStatus = (id: number) => useApiFetch(`/tasks/${id}`).then(parseApiResponse) const startTask = (id: number) => useApiFetch(`/tasks/${id}/start`, { method: 'POST' }).then(parseApiResponse) @@ -251,7 +253,7 @@ export const useTaskApi = () => { const pauseTask = (id: number) => useApiFetch(`/tasks/${id}/pause`, { method: 'POST' }).then(parseApiResponse) const deleteTask = (id: number) => useApiFetch(`/tasks/${id}`, { method: 'DELETE' }).then(parseApiResponse) const getTaskItems = (id: number, params?: any) => useApiFetch(`/tasks/${id}/items`, { params }).then(parseApiResponse) - return { createBatchTransferTask, getTasks, getTaskStatus, startTask, stopTask, pauseTask, deleteTask, getTaskItems } + return { createBatchTransferTask, createExpansionTask, getExpansionAccounts, getTasks, getTaskStatus, startTask, stopTask, pauseTask, deleteTask, getTaskItems } } // 日志函数:只在开发环境打印 diff --git a/web/pages/admin/accounts-expansion.vue b/web/pages/admin/accounts-expansion.vue new file mode 100644 index 0000000..f96364d --- /dev/null +++ b/web/pages/admin/accounts-expansion.vue @@ -0,0 +1,427 @@ + + + + + \ No newline at end of file diff --git a/web/pages/admin/accounts.vue b/web/pages/admin/accounts.vue index d30ed1d..073591c 100644 --- a/web/pages/admin/accounts.vue +++ b/web/pages/admin/accounts.vue @@ -13,6 +13,12 @@ 添加账号 + + + 账号扩容 +