package plane_v1 import ( "fmt" "go.uber.org/zap" ) // ==================== Module API ==================== // ListModules 列出模块 func ListModules() ([]byte, error) { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/", planeWorkspaceSlug, planeProjectId) resp, err := planeHttpGet(path) if err != nil { zap.L().Error("[Plane] ListModules 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] ListModules 返回错误", zap.String("status", resp.Status)) return nil, fmt.Errorf("ListModules 失败: %s", resp.Status) } return resp.Body, nil } // CreateModule 创建模块 func CreateModule(data map[string]interface{}) ([]byte, error) { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/", planeWorkspaceSlug, planeProjectId) resp, err := planeHttpPost(path, data) if err != nil { zap.L().Error("[Plane] CreateModule 请求失败", zap.Error(err)) return nil, err } if resp.StatusCode != 201 { zap.L().Error("[Plane] CreateModule 返回错误", zap.String("status", resp.Status), zap.String("body", string(resp.Body))) return nil, fmt.Errorf("CreateModule 失败: %s", resp.Status) } return resp.Body, nil } // GetModule 获取模块详情 func GetModule(moduleID string) ([]byte, error) { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/%s/", planeWorkspaceSlug, planeProjectId, moduleID) resp, err := planeHttpGet(path) if err != nil { zap.L().Error("[Plane] GetModule 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] GetModule 返回错误", zap.String("status", resp.Status)) return nil, fmt.Errorf("GetModule 失败: %s", resp.Status) } return resp.Body, nil } // UpdateModule 更新模块 func UpdateModule(moduleID string, data map[string]interface{}) ([]byte, error) { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/%s/", planeWorkspaceSlug, planeProjectId, moduleID) resp, err := planeHttpPatch(path, data) if err != nil { zap.L().Error("[Plane] UpdateModule 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] UpdateModule 返回错误", zap.String("status", resp.Status), zap.String("body", string(resp.Body))) return nil, fmt.Errorf("UpdateModule 失败: %s", resp.Status) } return resp.Body, nil } // DeleteModule 删除模块 func DeleteModule(moduleID string) error { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/%s/", planeWorkspaceSlug, planeProjectId, moduleID) resp, err := planeHttpDelete(path) if err != nil { zap.L().Error("[Plane] DeleteModule 请求失败", zap.Error(err)) return err } if resp.StatusCode != 204 { zap.L().Error("[Plane] DeleteModule 返回错误", zap.String("status", resp.Status)) return fmt.Errorf("DeleteModule 失败: %s", resp.Status) } return nil } // ListModuleIssues 列出模块中的工作项 func ListModuleIssues(moduleID string) ([]byte, error) { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/%s/module-issues/", planeWorkspaceSlug, planeProjectId, moduleID) resp, err := planeHttpGet(path) if err != nil { zap.L().Error("[Plane] ListModuleIssues 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] ListModuleIssues 返回错误", zap.String("status", resp.Status)) return nil, fmt.Errorf("ListModuleIssues 失败: %s", resp.Status) } return resp.Body, nil } // AddIssuesToModule 添加工作项到模块 func AddIssuesToModule(moduleID string, issueIDs []string) ([]byte, error) { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/%s/module-issues/", planeWorkspaceSlug, planeProjectId, moduleID) payload := map[string]interface{}{"issues": issueIDs} resp, err := planeHttpPost(path, payload) if err != nil { zap.L().Error("[Plane] AddIssuesToModule 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] AddIssuesToModule 返回错误", zap.String("status", resp.Status), zap.String("body", string(resp.Body))) return nil, fmt.Errorf("AddIssuesToModule 失败: %s", resp.Status) } return resp.Body, nil } // RemoveIssueFromModule 从模块移除工作项 func RemoveIssueFromModule(moduleID, issueID string) error { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/%s/module-issues/%s/", planeWorkspaceSlug, planeProjectId, moduleID, issueID) resp, err := planeHttpDelete(path) if err != nil { zap.L().Error("[Plane] RemoveIssueFromModule 请求失败", zap.Error(err)) return err } if resp.StatusCode != 204 { zap.L().Error("[Plane] RemoveIssueFromModule 返回错误", zap.String("status", resp.Status)) return fmt.Errorf("RemoveIssueFromModule 失败: %s", resp.Status) } return nil } // ArchiveModule 归档模块 func ArchiveModule(moduleID string) error { path := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/modules/%s/archive/", planeWorkspaceSlug, planeProjectId, moduleID) resp, err := planeHttpPost(path, map[string]interface{}{}) if err != nil { zap.L().Error("[Plane] ArchiveModule 请求失败", zap.Error(err)) return err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] ArchiveModule 返回错误", zap.String("status", resp.Status)) return fmt.Errorf("ArchiveModule 失败: %s", resp.Status) } return nil }