package plane_v1 import ( "fmt" "go.uber.org/zap" ) // ==================== Project API ==================== // ListProjects 列出项目 func ListProjects() ([]byte, error) { url := fmt.Sprintf("/api/v1/workspaces/%s/projects/", planeWorkspaceSlug) resp, err := planeHttpGet(url) if err != nil { zap.L().Error("[Plane] ListProjects 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] ListProjects 返回错误", zap.String("status", resp.Status)) return nil, fmt.Errorf("ListProjects 失败: %s", resp.Status) } return resp.Body, nil } // CreateProject 创建项目 func CreateProject(data map[string]interface{}) ([]byte, error) { url := fmt.Sprintf("/api/v1/workspaces/%s/projects/", planeWorkspaceSlug) resp, err := planeHttpPost(url, data) if err != nil { zap.L().Error("[Plane] CreateProject 请求失败", zap.Error(err)) return nil, err } if resp.StatusCode != 201 { zap.L().Error("[Plane] CreateProject 返回错误", zap.String("status", resp.Status), zap.String("body", string(resp.Body))) return nil, fmt.Errorf("CreateProject 失败: %s", resp.Status) } return resp.Body, nil } // GetProject 获取项目详情 func GetProject(projectID string) ([]byte, error) { url := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/", planeWorkspaceSlug, projectID) resp, err := planeHttpGet(url) if err != nil { zap.L().Error("[Plane] GetProject 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] GetProject 返回错误", zap.String("status", resp.Status)) return nil, fmt.Errorf("GetProject 失败: %s", resp.Status) } return resp.Body, nil } // UpdateProject 更新项目 func UpdateProject(projectID string, data map[string]interface{}) ([]byte, error) { url := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/", planeWorkspaceSlug, projectID) resp, err := planeHttpPatch(url, data) if err != nil { zap.L().Error("[Plane] UpdateProject 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] UpdateProject 返回错误", zap.String("status", resp.Status), zap.String("body", string(resp.Body))) return nil, fmt.Errorf("UpdateProject 失败: %s", resp.Status) } return resp.Body, nil } // DeleteProject 删除项目 func DeleteProject(projectID string) error { url := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/", planeWorkspaceSlug, projectID) resp, err := planeHttpDelete(url) if err != nil { zap.L().Error("[Plane] DeleteProject 请求失败", zap.Error(err)) return err } if resp.StatusCode != 204 { zap.L().Error("[Plane] DeleteProject 返回错误", zap.String("status", resp.Status)) return fmt.Errorf("DeleteProject 失败: %s", resp.Status) } return nil } // ArchiveProject 归档项目 func ArchiveProject(projectID string) error { url := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/archive/", planeWorkspaceSlug, projectID) resp, err := planeHttpPost(url, map[string]interface{}{}) if err != nil { zap.L().Error("[Plane] ArchiveProject 请求失败", zap.Error(err)) return err } if resp.StatusCode != 204 { zap.L().Error("[Plane] ArchiveProject 返回错误", zap.String("status", resp.Status)) return fmt.Errorf("ArchiveProject 失败: %s", resp.Status) } return nil } // UnarchiveProject 取消归档项目 func UnarchiveProject(projectID string) error { url := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/archive/", planeWorkspaceSlug, projectID) resp, err := planeHttpDelete(url) if err != nil { zap.L().Error("[Plane] UnarchiveProject 请求失败", zap.Error(err)) return err } if resp.StatusCode != 204 { zap.L().Error("[Plane] UnarchiveProject 返回错误", zap.String("status", resp.Status)) return fmt.Errorf("UnarchiveProject 失败: %s", resp.Status) } return nil } // GetProjectSummary 获取项目摘要 func GetProjectSummary(projectID, fields string) ([]byte, error) { url := fmt.Sprintf("/api/v1/workspaces/%s/projects/%s/summary/", planeWorkspaceSlug, projectID) if fields != "" { url += "?fields=" + fields } resp, err := planeHttpGet(url) if err != nil { zap.L().Error("[Plane] GetProjectSummary 请求失败", zap.Error(err)) return nil, err } if !isSuccess(resp.StatusCode) { zap.L().Error("[Plane] GetProjectSummary 返回错误", zap.String("status", resp.Status)) return nil, fmt.Errorf("GetProjectSummary 失败: %s", resp.Status) } return resp.Body, nil }