Documentation
¶
Index ¶
- Variables
- func Shortcuts() []common.Shortcut
- type BlockElementType
- type CategoryName
- type ContentBlock
- type ContentBlockElement
- type ContentBlockElementV1
- type ContentBlockV1
- type ContentColor
- type ContentDocsLink
- type ContentGallery
- type ContentGalleryV1
- type ContentImageItem
- type ContentImageItemV1
- type ContentLink
- type ContentList
- type ContentListV1
- type ContentMention
- type ContentParagraph
- type ContentParagraphElement
- type ContentParagraphElementV1
- type ContentParagraphStyle
- type ContentParagraphStyleV1
- type ContentParagraphV1
- type ContentPersonV1
- type ContentTextRun
- type ContentTextRunV1
- type ContentTextStyle
- type ContentTextStyleV1
- type Cycle
- type CycleStatus
- type KeyResult
- type ListType
- type Objective
- type Owner
- type OwnerType
- type ParagraphElementType
- type ParagraphElementTypeV1
- type Progress
- type ProgressRate
- type ProgressRateV1
- type ProgressStatus
- type ProgressV1
- type RespAlignment
- type RespCategory
- type RespCycle
- type RespIndicator
- type RespIndicatorUnit
- type RespKeyResult
- type RespObjective
- type RespOwner
- type RespProgress
- type RespProgressRate
- type StatusCalculateType
Constants ¶
This section is empty.
Variables ¶
var OKRCreateProgressRecord = common.Shortcut{ Service: "okr", Command: "+progress-create", Description: "Create an OKR progress", Risk: "write", Scopes: []string{"okr:okr.progress:writeonly"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "content", Desc: "progress content in ContentBlock JSON format", Required: true, Input: []string{common.File, common.Stdin}}, {Name: "target-id", Desc: "target ID (objective or key result ID)", Required: true}, {Name: "target-type", Desc: "target type: objective | key_result", Required: true, Enum: []string{"objective", "key_result"}}, {Name: "progress-percent", Desc: "progress percentage"}, {Name: "progress-status", Desc: "progress status: normal | overdue | done. must provided with --progress-percent", Enum: []string{"normal", "overdue", "done"}}, {Name: "source-title", Default: "created by lark-cli", Desc: "source title for display"}, {Name: "source-url", Desc: "source URL for display (defaults to open platform URL based on brand)"}, {Name: "user-id-type", Default: "open_id", Desc: "user ID type: open_id | union_id | user_id"}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { content := runtime.Str("content") if content == "" { return common.FlagErrorf("--content is required") } if err := validate.RejectControlChars(content, "content"); err != nil { return err } // Validate content is valid JSON and can be parsed as ContentBlock var cb ContentBlock if err := json.Unmarshal([]byte(content), &cb); err != nil { return common.FlagErrorf("--content must be valid ContentBlock JSON: %s", err) } targetID := runtime.Str("target-id") if targetID == "" { return common.FlagErrorf("--target-id is required") } if err := validate.RejectControlChars(targetID, "target-id"); err != nil { return err } if id, err := strconv.ParseInt(targetID, 10, 64); err != nil || id <= 0 { return common.FlagErrorf("--target-id must be a positive int64") } targetType := runtime.Str("target-type") if _, ok := targetTypeAllowed[targetType]; !ok { return common.FlagErrorf("--target-type must be one of: objective | key_result") } if v := runtime.Str("source-title"); v != "" { if err := validate.RejectControlChars(v, "source-title"); err != nil { return err } } if v := runtime.Str("source-url"); v != "" { if err := validate.RejectControlChars(v, "source-url"); err != nil { return err } } if v := runtime.Str("progress-percent"); v != "" { percent, err := strconv.ParseFloat(v, 64) if err != nil || math.IsNaN(percent) || math.IsInf(percent, 0) || percent < -99999999999 || percent > 99999999999 { return common.FlagErrorf("--progress-percent must be a number between -99999999999 and 99999999999") } } if v := runtime.Str("progress-status"); v != "" { if _, ok := ParseProgressStatus(v); !ok { return common.FlagErrorf("--progress-status must be one of: normal | overdue | done") } if v := runtime.Str("progress-percent"); v == "" { return common.FlagErrorf("--progress-percent must provided with --progress-status") } } idType := runtime.Str("user-id-type") if idType != "open_id" && idType != "union_id" && idType != "user_id" { return common.FlagErrorf("--user-id-type must be one of: open_id | union_id | user_id") } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { p, _ := parseCreateProgressRecordParams(runtime) params := map[string]interface{}{ "user_id_type": p.UserIDType, } body := map[string]interface{}{ "content": p.ContentV1, "target_id": p.TargetID, "target_type": p.TargetType, "source_title": p.SourceTitle, "source_url": p.SourceURL, } if p.ProgressRate != nil { body["progress_rate"] = p.ProgressRate } return common.NewDryRunAPI(). POST("/open-apis/okr/v1/progress_records/"). Params(params). Body(body). Desc(fmt.Sprintf("Create OKR progress for %s", runtime.Str("target-type"))) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { p, err := parseCreateProgressRecordParams(runtime) if err != nil { return err } body := map[string]interface{}{ "content": p.ContentV1, "target_id": p.TargetID, "target_type": p.TargetType, "source_title": p.SourceTitle, "source_url": p.SourceURL, } if p.ProgressRate != nil { body["progress_rate"] = p.ProgressRate } queryParams := make(larkcore.QueryParams) queryParams.Set("user_id_type", p.UserIDType) data, err := runtime.DoAPIJSON("POST", "/open-apis/okr/v1/progress_records/", queryParams, body) if err != nil { return err } record, err := parseProgressRecord(data) if err != nil { return err } resp := record.ToResp() result := map[string]interface{}{ "progress": resp, } runtime.OutFormat(result, nil, func(w io.Writer) { fmt.Fprintf(w, "Created Progress [%s]\n", resp.ID) fmt.Fprintf(w, " ModifyTime: %s\n", resp.ModifyTime) if resp.ProgressRate != nil && resp.ProgressRate.Percent != nil { fmt.Fprintf(w, " ProgressRate: %.1f%%\n", *resp.ProgressRate.Percent) } if resp.Content != nil { fmt.Fprintf(w, " Content: %s\n", *resp.Content) } }) return nil }, }
OKRCreateProgressRecord creates a progress.
var OKRCycleDetail = common.Shortcut{ Service: "okr", Command: "+cycle-detail", Description: "List objectives and key results under an OKR cycle", Risk: "read", Scopes: []string{"okr:okr.content:readonly"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "cycle-id", Desc: "OKR cycle id (int64)", Required: true}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { cycleID := runtime.Str("cycle-id") if cycleID == "" { return common.FlagErrorf("--cycle-id is required") } if id, err := strconv.ParseInt(cycleID, 10, 64); err != nil || id <= 0 { return common.FlagErrorf("--cycle-id must be a positive int64") } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { cycleID := runtime.Str("cycle-id") params := map[string]interface{}{ "page_size": 100, } return common.NewDryRunAPI(). GET("/open-apis/okr/v2/cycles/:cycle_id/objectives"). Params(params). Set("cycle_id", cycleID). Desc("Auto-paginates objectives in the cycle, then calls GET /open-apis/okr/v2/objectives/:objective_id/key_results for each objective to fetch key results") }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { cycleID := runtime.Str("cycle-id") queryParams := make(larkcore.QueryParams) queryParams.Set("page_size", "100") var objectives []Objective page := 0 for { if err := ctx.Err(); err != nil { return err } if page > 0 { select { case <-ctx.Done(): return ctx.Err() case <-time.After(500 * time.Millisecond): } } page++ path := fmt.Sprintf("/open-apis/okr/v2/cycles/%s/objectives", cycleID) data, err := runtime.DoAPIJSON("GET", path, queryParams, nil) if err != nil { return err } itemsRaw, _ := data["items"].([]interface{}) for _, item := range itemsRaw { raw, err := json.Marshal(item) if err != nil { continue } var obj Objective if err := json.Unmarshal(raw, &obj); err != nil { continue } objectives = append(objectives, obj) } hasMore, pageToken := common.PaginationMeta(data) if !hasMore || pageToken == "" { break } queryParams.Set("page_token", pageToken) } respObjectives := make([]*RespObjective, 0, len(objectives)) for i := range objectives { if err := ctx.Err(); err != nil { return err } obj := &objectives[i] krQuery := make(larkcore.QueryParams) krQuery.Set("page_size", "100") var keyResults []KeyResult krPage := 0 for { if err := ctx.Err(); err != nil { return err } if krPage > 0 { select { case <-ctx.Done(): return ctx.Err() case <-time.After(500 * time.Millisecond): } } krPage++ path := fmt.Sprintf("/open-apis/okr/v2/objectives/%s/key_results", obj.ID) data, err := runtime.DoAPIJSON("GET", path, krQuery, nil) if err != nil { return err } itemsRaw, _ := data["items"].([]interface{}) for _, item := range itemsRaw { raw, err := json.Marshal(item) if err != nil { continue } var kr KeyResult if err := json.Unmarshal(raw, &kr); err != nil { continue } keyResults = append(keyResults, kr) } hasMore, pageToken := common.PaginationMeta(data) if !hasMore || pageToken == "" { break } krQuery.Set("page_token", pageToken) } respObj := obj.ToResp() if respObj == nil { continue } respKRs := make([]RespKeyResult, 0, len(keyResults)) for j := range keyResults { if r := keyResults[j].ToResp(); r != nil { respKRs = append(respKRs, *r) } } respObj.KeyResults = respKRs respObjectives = append(respObjectives, respObj) } result := map[string]interface{}{ "cycle_id": cycleID, "objectives": respObjectives, "total": len(respObjectives), } runtime.OutFormat(result, nil, func(w io.Writer) { fmt.Fprintf(w, "Cycle %s: %d objective(s)\n", cycleID, len(respObjectives)) for _, o := range respObjectives { fmt.Fprintf(w, "Objective [%s]: %s \n Notes: %s \n score=%.2f weight=%.2f\n", o.ID, ptrStr(o.Content), ptrStr(o.Notes), ptrFloat64(o.Score), ptrFloat64(o.Weight)) for _, kr := range o.KeyResults { fmt.Fprintf(w, " - KR [%s]: %s \n score=%.2f weight=%.2f\n", kr.ID, ptrStr(kr.Content), ptrFloat64(kr.Score), ptrFloat64(kr.Weight)) } } }) return nil }, }
OKRCycleDetail lists all objectives and their key results under a given OKR cycle.
var OKRDeleteProgressRecord = common.Shortcut{ Service: "okr", Command: "+progress-delete", Description: "Delete an OKR progress by ID", Risk: "high-risk-write", Scopes: []string{"okr:okr.progress:delete"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "progress-id", Desc: "progress ID (int64)", Required: true}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { progressID := runtime.Str("progress-id") if progressID == "" { return common.FlagErrorf("--progress-id is required") } if id, err := strconv.ParseInt(progressID, 10, 64); err != nil || id <= 0 { return common.FlagErrorf("--progress-id must be a positive int64") } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { progressID := runtime.Str("progress-id") return common.NewDryRunAPI(). DELETE("/open-apis/okr/v1/progress_records/:progress_id"). Set("progress_id", progressID). Desc("Delete OKR progress") }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { progressID := runtime.Str("progress-id") path := fmt.Sprintf("/open-apis/okr/v1/progress_records/%s", progressID) _, err := runtime.DoAPIJSON("DELETE", path, larkcore.QueryParams{}, nil) if err != nil { return err } result := map[string]interface{}{ "deleted": true, "progress_id": progressID, } runtime.OutFormat(result, nil, func(w io.Writer) { fmt.Fprintf(w, "Deleted progress record %s\n", progressID) }) return nil }, }
OKRDeleteProgressRecord deletes a progress by ID.
var OKRGetProgressRecord = common.Shortcut{ Service: "okr", Command: "+progress-get", Description: "Get an OKR progress by ID", Risk: "read", Scopes: []string{"okr:okr.progress:readonly"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "progress-id", Desc: "progress ID (int64)", Required: true}, {Name: "user-id-type", Default: "open_id", Desc: "user ID type: open_id | union_id | user_id"}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { progressID := runtime.Str("progress-id") if progressID == "" { return common.FlagErrorf("--progress-id is required") } if id, err := strconv.ParseInt(progressID, 10, 64); err != nil || id <= 0 { return common.FlagErrorf("--progress-id must be a positive int64") } idType := runtime.Str("user-id-type") if idType != "open_id" && idType != "union_id" && idType != "user_id" { return common.FlagErrorf("--user-id-type must be one of: open_id | union_id | user_id") } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { progressID := runtime.Str("progress-id") params := map[string]interface{}{ "user_id_type": runtime.Str("user-id-type"), } return common.NewDryRunAPI(). GET("/open-apis/okr/v1/progress_records/:progress_id"). Params(params). Set("progress_id", progressID). Desc("Get OKR progress") }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { progressID := runtime.Str("progress-id") userIDType := runtime.Str("user-id-type") queryParams := make(larkcore.QueryParams) queryParams.Set("user_id_type", userIDType) path := fmt.Sprintf("/open-apis/okr/v1/progress_records/%s", progressID) data, err := runtime.DoAPIJSON("GET", path, queryParams, nil) if err != nil { return err } record, err := parseProgressRecord(data) if err != nil { return err } resp := record.ToResp() result := map[string]interface{}{ "progress": resp, } runtime.OutFormat(result, nil, func(w io.Writer) { fmt.Fprintf(w, "Progress [%s]\n", resp.ID) fmt.Fprintf(w, " ModifyTime: %s\n", resp.ModifyTime) if resp.ProgressRate != nil && resp.ProgressRate.Percent != nil { fmt.Fprintf(w, " ProgressRate: %.1f%%\n", *resp.ProgressRate.Percent) } if resp.Content != nil { fmt.Fprintf(w, " Content: %s\n", *resp.Content) } }) return nil }, }
OKRGetProgressRecord gets a progress by ID.
var OKRListCycles = common.Shortcut{ Service: "okr", Command: "+cycle-list", Description: "List okr cycles of a certain user", Risk: "read", Scopes: []string{"okr:okr.period:readonly"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "user-id", Desc: "user ID", Required: true}, {Name: "user-id-type", Default: "open_id", Desc: "user ID type: open_id | union_id | user_id"}, {Name: "time-range", Desc: "specify time range. Use Format as YYYY-MM--YYYY-MM. leave empty to fetch all user cycles."}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { idType := runtime.Str("user-id-type") if idType != "open_id" && idType != "union_id" && idType != "user_id" { return common.FlagErrorf("--user-id-type must be one of: open_id | union_id | user_id") } userID := runtime.Str("user-id") if err := validate.RejectControlChars(userID, "user-id"); err != nil { return err } tr := runtime.Str("time-range") if tr != "" { if err := validate.RejectControlChars(tr, "time-range"); err != nil { return err } if _, _, err := parseTimeRange(tr); err != nil { return common.FlagErrorf("--time-range: %s", err) } } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { params := map[string]interface{}{ "user_id": runtime.Str("user-id"), "user_id_type": runtime.Str("user-id-type"), "page_size": 100, } return common.NewDryRunAPI(). GET("/open-apis/okr/v2/cycles"). Params(params). Desc("List OKR cycles for user, paginated at 100 per page, filtered by time-range") }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { userID := runtime.Str("user-id") userIDType := runtime.Str("user-id-type") timeRange := runtime.Str("time-range") // Parse time range for filtering var rangeStart, rangeEnd time.Time var hasRange bool if timeRange != "" { var err error rangeStart, rangeEnd, err = parseTimeRange(timeRange) if err != nil { return common.FlagErrorf("--time-range: %s", err) } hasRange = true } queryParams := make(larkcore.QueryParams) queryParams.Set("user_id", userID) queryParams.Set("user_id_type", userIDType) queryParams.Set("page_size", "100") var allCycles []Cycle page := 0 for { if err := ctx.Err(); err != nil { return err } if page > 0 { select { case <-ctx.Done(): return ctx.Err() case <-time.After(500 * time.Millisecond): } } page++ data, err := runtime.DoAPIJSON("GET", "/open-apis/okr/v2/cycles", queryParams, nil) if err != nil { return err } itemsRaw, _ := data["items"].([]interface{}) for _, item := range itemsRaw { raw, err := json.Marshal(item) if err != nil { continue } var cycle Cycle if err := json.Unmarshal(raw, &cycle); err != nil { continue } allCycles = append(allCycles, cycle) } hasMore, pageToken := common.PaginationMeta(data) if !hasMore || pageToken == "" { break } queryParams.Set("page_token", pageToken) } // Filter by time-range overlap var filtered []Cycle for i := range allCycles { if !hasRange || cycleOverlaps(&allCycles[i], rangeStart, rangeEnd) { filtered = append(filtered, allCycles[i]) } } respCycles := make([]*RespCycle, 0, len(filtered)) for i := range filtered { respCycles = append(respCycles, filtered[i].ToResp()) } runtime.OutFormat(map[string]interface{}{ "cycles": respCycles, "total": len(respCycles), }, nil, func(w io.Writer) { fmt.Fprintf(w, "Found %d cycle(s)\n", len(respCycles)) for _, c := range respCycles { fmt.Fprintf(w, " [%s] %s ~ %s (status: %s)\n", c.ID, c.StartTime, c.EndTime, ptrStr(c.CycleStatus)) } }) return nil }, }
var OKRListProgress = common.Shortcut{ Service: "okr", Command: "+progress-list", Description: "List progress for an objective or key result", Risk: "read", Scopes: []string{"okr:okr.progress:readonly"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "target-id", Desc: "target ID (objective or key result ID)", Required: true}, {Name: "target-type", Desc: "target type: objective | key_result", Required: true, Enum: []string{"objective", "key_result"}}, {Name: "user-id-type", Default: "open_id", Desc: "user ID type: open_id | union_id | user_id"}, {Name: "department-id-type", Default: "open_department_id", Desc: "department ID type: department_id | open_department_id"}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { targetID := runtime.Str("target-id") if targetID == "" { return common.FlagErrorf("--target-id is required") } if err := validate.RejectControlChars(targetID, "target-id"); err != nil { return err } if id, err := strconv.ParseInt(targetID, 10, 64); err != nil || id <= 0 { return common.FlagErrorf("--target-id must be a positive int64") } targetType := runtime.Str("target-type") if _, ok := targetTypeAllowed[targetType]; !ok { return common.FlagErrorf("--target-type must be one of: objective | key_result") } idType := runtime.Str("user-id-type") if idType != "open_id" && idType != "union_id" && idType != "user_id" { return common.FlagErrorf("--user-id-type must be one of: open_id | union_id | user_id") } deptIDType := runtime.Str("department-id-type") if deptIDType != "department_id" && deptIDType != "open_department_id" { return common.FlagErrorf("--department-id-type must be one of: department_id | open_department_id") } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { targetID := runtime.Str("target-id") targetType := runtime.Str("target-type") params := map[string]interface{}{ "user_id_type": runtime.Str("user-id-type"), "department_id_type": runtime.Str("department-id-type"), "page_size": 100, } switch targetType { case "objective": return common.NewDryRunAPI(). GET("/open-apis/okr/v2/objectives/:objective_id/progresses"). Params(params). Set("objective_id", targetID). Desc("List progresses for objective") case "key_result": return common.NewDryRunAPI(). GET("/open-apis/okr/v2/key_results/:key_result_id/progresses"). Params(params). Set("key_result_id", targetID). Desc("List progresses for key result") } return nil }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { targetID := runtime.Str("target-id") targetType := runtime.Str("target-type") userIDType := runtime.Str("user-id-type") deptIDType := runtime.Str("department-id-type") queryParams := make(larkcore.QueryParams) queryParams.Set("user_id_type", userIDType) queryParams.Set("department_id_type", deptIDType) queryParams.Set("page_size", "100") var apiPath string switch targetType { case "objective": apiPath = fmt.Sprintf("/open-apis/okr/v2/objectives/%s/progresses", targetID) case "key_result": apiPath = fmt.Sprintf("/open-apis/okr/v2/key_results/%s/progresses", targetID) } var allProgress []*Progress for { if err := ctx.Err(); err != nil { return err } data, err := runtime.DoAPIJSON("GET", apiPath, queryParams, nil) if err != nil { return err } itemsRaw, _ := data["items"].([]interface{}) for _, item := range itemsRaw { raw, err := json.Marshal(item) if err != nil { continue } var progress Progress if err := json.Unmarshal(raw, &progress); err != nil { continue } allProgress = append(allProgress, &progress) } hasMore, pageToken := common.PaginationMeta(data) if !hasMore || pageToken == "" { break } queryParams.Set("page_token", pageToken) } respProgress := make([]*RespProgress, 0, len(allProgress)) for _, p := range allProgress { respProgress = append(respProgress, p.ToResp()) } runtime.OutFormat(map[string]interface{}{ "progress_list": respProgress, "total": len(respProgress), }, nil, func(w io.Writer) { fmt.Fprintf(w, "Found %d progress(es)\n", len(respProgress)) for _, p := range respProgress { fmt.Fprintf(w, " [%s] , %s", p.ID, p.ModifyTime) if p.ProgressRate != nil && p.ProgressRate.Percent != nil { fmt.Fprintf(w, " (%.2f%%", *p.ProgressRate.Percent) if p.ProgressRate.Status != nil { fmt.Fprintf(w, ", %s", *p.ProgressRate.Status) } fmt.Fprintf(w, ")\n") if p.Content != nil { fmt.Fprintf(w, " Content: %s\n", *p.Content) } } fmt.Fprintln(w) } }) return nil }, }
OKRListProgress lists progress for an objective or key result.
var OKRUpdateProgressRecord = common.Shortcut{ Service: "okr", Command: "+progress-update", Description: "Update an OKR progress", Risk: "write", Scopes: []string{"okr:okr.progress:writeonly"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, Flags: []common.Flag{ {Name: "progress-id", Desc: "progress ID (int64)", Required: true}, {Name: "content", Desc: "progress content in ContentBlock JSON format", Required: true, Input: []string{common.File, common.Stdin}}, {Name: "progress-percent", Desc: "progress percentage"}, {Name: "progress-status", Desc: "progress status: normal | overdue | done", Enum: []string{"normal", "overdue", "done"}}, {Name: "user-id-type", Default: "open_id", Desc: "user ID type: open_id | union_id | user_id"}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { progressID := runtime.Str("progress-id") if progressID == "" { return common.FlagErrorf("--progress-id is required") } if id, err := strconv.ParseInt(progressID, 10, 64); err != nil || id <= 0 { return common.FlagErrorf("--progress-id must be a positive int64") } content := runtime.Str("content") if content == "" { return common.FlagErrorf("--content is required") } if err := validate.RejectControlChars(content, "content"); err != nil { return err } var cb ContentBlock if err := json.Unmarshal([]byte(content), &cb); err != nil { return common.FlagErrorf("--content must be valid ContentBlock JSON: %s", err) } if v := runtime.Str("progress-percent"); v != "" { percent, err := strconv.ParseFloat(v, 64) if err != nil || math.IsNaN(percent) || math.IsInf(percent, 0) || percent < -99999999999 || percent > 99999999999 { return common.FlagErrorf("--progress-percent must be a number between -99999999999 and 99999999999") } } if v := runtime.Str("progress-status"); v != "" { if _, ok := ParseProgressStatus(v); !ok { return common.FlagErrorf("--progress-status must be one of: normal | overdue | done") } if v := runtime.Str("progress-percent"); v == "" { return common.FlagErrorf("--progress-percent must provided with --progress-status") } } idType := runtime.Str("user-id-type") if idType != "open_id" && idType != "union_id" && idType != "user_id" { return common.FlagErrorf("--user-id-type must be one of: open_id | union_id | user_id") } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { p, _ := parseUpdateProgressRecordParams(runtime) params := map[string]interface{}{ "user_id_type": p.UserIDType, } body := map[string]interface{}{ "content": p.ContentV1, } if p.ProgressRate != nil { body["progress_rate"] = p.ProgressRate } return common.NewDryRunAPI(). PUT("/open-apis/okr/v1/progress_records/:progress_id"). Params(params). Body(body). Set("progress_id", p.ProgressID). Desc("Update OKR progress") }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { p, err := parseUpdateProgressRecordParams(runtime) if err != nil { return err } body := map[string]interface{}{ "content": p.ContentV1, } if p.ProgressRate != nil { body["progress_rate"] = p.ProgressRate } queryParams := make(larkcore.QueryParams) queryParams.Set("user_id_type", p.UserIDType) path := fmt.Sprintf("/open-apis/okr/v1/progress_records/%s", p.ProgressID) data, err := runtime.DoAPIJSON("PUT", path, queryParams, body) if err != nil { return err } record, err := parseProgressRecord(data) if err != nil { return err } resp := record.ToResp() result := map[string]interface{}{ "progress": resp, } runtime.OutFormat(result, nil, func(w io.Writer) { fmt.Fprintf(w, "Updated Progress [%s]\n", resp.ID) fmt.Fprintf(w, " ModifyTime: %s\n", resp.ModifyTime) if resp.ProgressRate != nil && resp.ProgressRate.Percent != nil { fmt.Fprintf(w, " Progress: %.1f%%\n", *resp.ProgressRate.Percent) } if resp.Content != nil { fmt.Fprintf(w, " Content: %s\n", *resp.Content) } }) return nil }, }
OKRUpdateProgressRecord updates a progress.
var OKRUploadImage = common.Shortcut{ Service: "okr", Command: "+upload-image", Description: "Upload an image for use in OKR progress rich text", Risk: "write", Scopes: []string{"okr:okr.progress.file:upload"}, AuthTypes: []string{"user", "bot"}, Flags: []common.Flag{ {Name: "file", Desc: "local image path (supports JPG, JPEG, PNG, GIF, BMP)", Required: true}, {Name: "target-id", Desc: "target ID (objective or key result ID) for the progress", Required: true}, {Name: "target-type", Desc: "target type: objective | key_result", Required: true, Enum: []string{"objective", "key_result"}}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { filePath := runtime.Str("file") if filePath == "" { return common.FlagErrorf("--file is required") } ext := strings.ToLower(filepath.Ext(filePath)) if !allowedImageExts[ext] { return common.FlagErrorf("--file must be an image (supported: JPG, JPEG, PNG, GIF, BMP), got %q", ext) } targetID := runtime.Str("target-id") if targetID == "" { return common.FlagErrorf("--target-id is required") } if id, err := strconv.ParseInt(targetID, 10, 64); err != nil || id <= 0 { return common.FlagErrorf("--target-id must be a positive int64") } targetType := runtime.Str("target-type") if _, ok := targetTypeAllowed[targetType]; !ok { return common.FlagErrorf("--target-type must be one of: objective | key_result") } return nil }, DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { filePath := runtime.Str("file") targetID := runtime.Str("target-id") targetType := runtime.Str("target-type") targetTypeVal := targetTypeAllowed[targetType] return common.NewDryRunAPI(). POST("/open-apis/okr/v1/images/upload"). Body(map[string]interface{}{ "file": "@" + filePath, "target_id": targetID, "target_type": targetTypeVal, }). Desc(fmt.Sprintf("Upload image for OKR %s %s", targetType, targetID)) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { filePath := runtime.Str("file") targetID := runtime.Str("target-id") targetType := runtime.Str("target-type") targetTypeVal := targetTypeAllowed[targetType] info, err := runtime.FileIO().Stat(filePath) if err != nil { return common.WrapInputStatError(err) } f, err := runtime.FileIO().Open(filePath) if err != nil { return common.WrapInputStatError(err) } defer f.Close() fileName := filepath.Base(filePath) fmt.Fprintf(runtime.IO().ErrOut, "Uploading: %s (%s)\n", fileName, common.FormatSize(info.Size())) fd := larkcore.NewFormdata() fd.AddField("target_id", targetID) fd.AddField("target_type", fmt.Sprintf("%d", targetTypeVal)) fd.AddFile("data", f) apiResp, err := runtime.DoAPI(&larkcore.ApiReq{ HttpMethod: "POST", ApiPath: "/open-apis/okr/v1/images/upload", Body: fd, }, larkcore.WithFileUpload()) if err != nil { var exitErr *output.ExitError if errors.As(err, &exitErr) { return err } return output.ErrNetwork("upload failed: %v", err) } var result map[string]interface{} if err := json.Unmarshal(apiResp.RawBody, &result); err != nil { return output.Errorf(output.ExitAPI, "api_error", "upload failed: invalid response JSON: %v", err) } if larkCode := int(common.GetFloat(result, "code")); larkCode != 0 { msg, _ := result["msg"].(string) return output.ErrAPI(larkCode, fmt.Sprintf("upload failed: [%d] %s", larkCode, msg), result["error"]) } data, _ := result["data"].(map[string]interface{}) fileToken, _ := data["file_token"].(string) url, _ := data["url"].(string) if fileToken == "" { return output.Errorf(output.ExitAPI, "api_error", "upload failed: no file_token returned") } runtime.Out(map[string]interface{}{ "file_token": fileToken, "url": url, "file_name": fileName, "size": info.Size(), }, nil) return nil }, }
OKRUploadImage uploads an image for use in OKR progress rich text.
Functions ¶
Types ¶
type BlockElementType ¶
type BlockElementType string
BlockElementType 块元素类型
const ( BlockElementTypeGallery BlockElementType = "gallery" BlockElementTypeParagraph BlockElementType = "paragraph" )
func (BlockElementType) Ptr ¶
func (t BlockElementType) Ptr() *BlockElementType
type CategoryName ¶
type CategoryName struct {
Zh *string `json:"zh,omitempty"`
En *string `json:"en,omitempty"`
Ja *string `json:"ja,omitempty"`
}
CategoryName 分类名称
type ContentBlock ¶
type ContentBlock struct {
Blocks []ContentBlockElement `json:"blocks,omitempty"`
}
ContentBlock 内容块
func (*ContentBlock) ToV1 ¶ added in v1.0.21
func (c *ContentBlock) ToV1() *ContentBlockV1
ToV1 将 ContentBlock 转换为 ContentBlockV1
type ContentBlockElement ¶
type ContentBlockElement struct {
BlockElementType *BlockElementType `json:"block_element_type,omitempty"`
Paragraph *ContentParagraph `json:"paragraph,omitempty"`
Gallery *ContentGallery `json:"gallery,omitempty"`
}
ContentBlockElement 内容块元素
func (*ContentBlockElement) ToV1 ¶ added in v1.0.21
func (e *ContentBlockElement) ToV1() ContentBlockElementV1
ToV1 将 ContentBlockElement 转换为 ContentBlockElementV1
type ContentBlockElementV1 ¶ added in v1.0.21
type ContentBlockElementV1 struct {
Type *BlockElementType `json:"type,omitempty"`
Paragraph *ContentParagraphV1 `json:"paragraph,omitempty"`
Gallery *ContentGalleryV1 `json:"gallery,omitempty"`
}
ContentBlockElementV1 内容块元素
func (*ContentBlockElementV1) ToV2 ¶ added in v1.0.21
func (e *ContentBlockElementV1) ToV2() ContentBlockElement
ToV2 将 ContentBlockElementV1 转换为 ContentBlockElement
type ContentBlockV1 ¶ added in v1.0.21
type ContentBlockV1 struct {
Blocks []ContentBlockElementV1 `json:"blocks,omitempty"`
}
ContentBlockV1 是 OKR v1 API 使用的内容块
func (*ContentBlockV1) ToV2 ¶ added in v1.0.21
func (c *ContentBlockV1) ToV2() *ContentBlock
ToV2 将 ContentBlockV1 转换为 ContentBlock
type ContentColor ¶
type ContentColor struct {
Red *int32 `json:"red,omitempty"`
Green *int32 `json:"green,omitempty"`
Blue *int32 `json:"blue,omitempty"`
Alpha *float64 `json:"alpha,omitempty"`
}
ContentColor 颜色
type ContentDocsLink ¶
type ContentDocsLink struct {
URL *string `json:"url,omitempty"`
Title *string `json:"title,omitempty"`
}
ContentDocsLink 文档链接
type ContentGallery ¶
type ContentGallery struct {
Images []ContentImageItem `json:"images,omitempty"`
}
ContentGallery 图库
func (*ContentGallery) ToV1 ¶ added in v1.0.21
func (g *ContentGallery) ToV1() *ContentGalleryV1
ToV1 将 ContentGallery 转换为 ContentGalleryV1
type ContentGalleryV1 ¶ added in v1.0.21
type ContentGalleryV1 struct {
ImageList []ContentImageItemV1 `json:"imageList,omitempty"`
}
ContentGalleryV1 图库
func (*ContentGalleryV1) ToV2 ¶ added in v1.0.21
func (g *ContentGalleryV1) ToV2() *ContentGallery
ToV2 将 ContentGalleryV1 转换为 ContentGallery
type ContentImageItem ¶
type ContentImageItem struct {
FileToken *string `json:"file_token,omitempty"`
Src *string `json:"src,omitempty"`
Width *float64 `json:"width,omitempty"`
Height *float64 `json:"height,omitempty"`
}
ContentImageItem 图片项
func (*ContentImageItem) ToV1 ¶ added in v1.0.21
func (i *ContentImageItem) ToV1() ContentImageItemV1
ToV1 将 ContentImageItem 转换为 ContentImageItemV1
type ContentImageItemV1 ¶ added in v1.0.21
type ContentImageItemV1 struct {
FileToken *string `json:"fileToken,omitempty"`
Src *string `json:"src,omitempty"`
Width *float64 `json:"width,omitempty"`
Height *float64 `json:"height,omitempty"`
}
ContentImageItemV1 图片项
func (*ContentImageItemV1) ToV2 ¶ added in v1.0.21
func (i *ContentImageItemV1) ToV2() ContentImageItem
ToV2 将 ContentImageItemV1 转换为 ContentImageItem
type ContentList ¶
type ContentList struct {
ListType *ListType `json:"list_type,omitempty"`
IndentLevel *int32 `json:"indent_level,omitempty"`
Number *int32 `json:"number,omitempty"`
}
ContentList 列表
func (*ContentList) ToV1 ¶ added in v1.0.21
func (l *ContentList) ToV1() *ContentListV1
ToV1 将 ContentList 转换为 ContentListV1
type ContentListV1 ¶ added in v1.0.21
type ContentListV1 struct {
Type *ListType `json:"type,omitempty"`
IndentLevel *int32 `json:"indentLevel,omitempty"`
Number *int32 `json:"number,omitempty"`
}
ContentListV1 列表
func (*ContentListV1) ToV2 ¶ added in v1.0.21
func (l *ContentListV1) ToV2() *ContentList
ToV2 将 ContentListV1 转换为 ContentList
type ContentMention ¶
type ContentMention struct {
UserID *string `json:"user_id,omitempty"`
}
ContentMention 提及
func (*ContentMention) ToV1 ¶ added in v1.0.21
func (m *ContentMention) ToV1() *ContentPersonV1
ToV1 将 ContentMention 转换为 ContentPersonV1
type ContentParagraph ¶
type ContentParagraph struct {
Style *ContentParagraphStyle `json:"style,omitempty"`
Elements []ContentParagraphElement `json:"elements,omitempty"`
}
ContentParagraph 段落
func (*ContentParagraph) ToV1 ¶ added in v1.0.21
func (p *ContentParagraph) ToV1() *ContentParagraphV1
ToV1 将 ContentParagraph 转换为 ContentParagraphV1
type ContentParagraphElement ¶
type ContentParagraphElement struct {
ParagraphElementType *ParagraphElementType `json:"paragraph_element_type,omitempty"`
TextRun *ContentTextRun `json:"text_run,omitempty"`
DocsLink *ContentDocsLink `json:"docs_link,omitempty"`
Mention *ContentMention `json:"mention,omitempty"`
}
ContentParagraphElement 段落元素
func (*ContentParagraphElement) ToV1 ¶ added in v1.0.21
func (e *ContentParagraphElement) ToV1() ContentParagraphElementV1
ToV1 将 ContentParagraphElement 转换为 ContentParagraphElementV1
type ContentParagraphElementV1 ¶ added in v1.0.21
type ContentParagraphElementV1 struct {
Type *ParagraphElementTypeV1 `json:"type,omitempty"`
TextRun *ContentTextRunV1 `json:"textRun,omitempty"`
DocsLink *ContentDocsLink `json:"docsLink,omitempty"`
Person *ContentPersonV1 `json:"person,omitempty"`
}
ContentParagraphElementV1 段落元素
func (*ContentParagraphElementV1) ToV2 ¶ added in v1.0.21
func (e *ContentParagraphElementV1) ToV2() ContentParagraphElement
ToV2 将 ContentParagraphElementV1 转换为 ContentParagraphElement
type ContentParagraphStyle ¶
type ContentParagraphStyle struct {
List *ContentList `json:"list,omitempty"`
}
ContentParagraphStyle 段落样式
func (*ContentParagraphStyle) ToV1 ¶ added in v1.0.21
func (s *ContentParagraphStyle) ToV1() *ContentParagraphStyleV1
ToV1 将 ContentParagraphStyle 转换为 ContentParagraphStyleV1
type ContentParagraphStyleV1 ¶ added in v1.0.21
type ContentParagraphStyleV1 struct {
List *ContentListV1 `json:"list,omitempty"`
}
ContentParagraphStyleV1 段落样式
func (*ContentParagraphStyleV1) ToV2 ¶ added in v1.0.21
func (s *ContentParagraphStyleV1) ToV2() *ContentParagraphStyle
ToV2 将 ContentParagraphStyleV1 转换为 ContentParagraphStyle
type ContentParagraphV1 ¶ added in v1.0.21
type ContentParagraphV1 struct {
Style *ContentParagraphStyleV1 `json:"style,omitempty"`
Elements []ContentParagraphElementV1 `json:"elements,omitempty"`
}
ContentParagraphV1 段落
func (*ContentParagraphV1) ToV2 ¶ added in v1.0.21
func (p *ContentParagraphV1) ToV2() *ContentParagraph
ToV2 将 ContentParagraphV1 转换为 ContentParagraph
type ContentPersonV1 ¶ added in v1.0.21
type ContentPersonV1 struct {
OpenID *string `json:"openId,omitempty"`
}
ContentPersonV1 提及的人
func (*ContentPersonV1) ToV2 ¶ added in v1.0.21
func (p *ContentPersonV1) ToV2() *ContentMention
ToV2 将 ContentPersonV1 转换为 ContentMention
type ContentTextRun ¶
type ContentTextRun struct {
Text *string `json:"text,omitempty"`
Style *ContentTextStyle `json:"style,omitempty"`
}
ContentTextRun 文本块
func (*ContentTextRun) ToV1 ¶ added in v1.0.21
func (t *ContentTextRun) ToV1() *ContentTextRunV1
ToV1 将 ContentTextRun 转换为 ContentTextRunV1
type ContentTextRunV1 ¶ added in v1.0.21
type ContentTextRunV1 struct {
Text *string `json:"text,omitempty"`
Style *ContentTextStyleV1 `json:"style,omitempty"`
}
ContentTextRunV1 文本块
func (*ContentTextRunV1) ToV2 ¶ added in v1.0.21
func (t *ContentTextRunV1) ToV2() *ContentTextRun
ToV2 将 ContentTextRunV1 转换为 ContentTextRun
type ContentTextStyle ¶
type ContentTextStyle struct {
Bold *bool `json:"bold,omitempty"`
StrikeThrough *bool `json:"strike_through,omitempty"`
BackColor *ContentColor `json:"back_color,omitempty"`
TextColor *ContentColor `json:"text_color,omitempty"`
Link *ContentLink `json:"link,omitempty"`
}
ContentTextStyle 文本样式
func (*ContentTextStyle) ToV1 ¶ added in v1.0.21
func (s *ContentTextStyle) ToV1() *ContentTextStyleV1
ToV1 将 ContentTextStyle 转换为 ContentTextStyleV1
type ContentTextStyleV1 ¶ added in v1.0.21
type ContentTextStyleV1 struct {
Bold *bool `json:"bold,omitempty"`
StrikeThrough *bool `json:"strikeThrough,omitempty"`
BackColor *ContentColor `json:"backColor,omitempty"`
TextColor *ContentColor `json:"textColor,omitempty"`
Link *ContentLink `json:"link,omitempty"`
}
ContentTextStyleV1 文本样式
func (*ContentTextStyleV1) ToV2 ¶ added in v1.0.21
func (s *ContentTextStyleV1) ToV2() *ContentTextStyle
ToV2 将 ContentTextStyleV1 转换为 ContentTextStyle
type Cycle ¶
type Cycle struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
TenantCycleID string `json:"tenant_cycle_id"`
Owner Owner `json:"owner"`
StartTime string `json:"start_time"`
EndTime string `json:"end_time"`
CycleStatus *CycleStatus `json:"cycle_status,omitempty"`
Score *float64 `json:"score,omitempty"`
}
Cycle 周期
type CycleStatus ¶
type CycleStatus int32
CycleStatus 周期状态
const ( CycleStatusDefault CycleStatus = 0 CycleStatusNormal CycleStatus = 1 CycleStatusInvalid CycleStatus = 2 CycleStatusHidden CycleStatus = 3 )
func (CycleStatus) Ptr ¶
func (t CycleStatus) Ptr() *CycleStatus
type KeyResult ¶
type KeyResult struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
Owner Owner `json:"owner"`
ObjectiveID string `json:"objective_id"`
Position *int32 `json:"position,omitempty"`
Content *ContentBlock `json:"content,omitempty"`
Score *float64 `json:"score,omitempty"`
Weight *float64 `json:"weight,omitempty"`
Deadline *string `json:"deadline,omitempty"`
}
KeyResult 关键结果
func (*KeyResult) ToResp ¶
func (k *KeyResult) ToResp() *RespKeyResult
ToResp converts KeyResult to RespKeyResult
type Objective ¶
type Objective struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
Owner Owner `json:"owner"`
CycleID string `json:"cycle_id"`
Position *int32 `json:"position,omitempty"`
Content *ContentBlock `json:"content,omitempty"`
Score *float64 `json:"score,omitempty"`
Notes *ContentBlock `json:"notes,omitempty"`
Weight *float64 `json:"weight,omitempty"`
Deadline *string `json:"deadline,omitempty"`
CategoryID *string `json:"category_id,omitempty"`
}
Objective 目标
func (*Objective) ToResp ¶
func (o *Objective) ToResp() *RespObjective
ToResp converts Objective to RespObjective
type Owner ¶
type Owner struct {
OwnerType OwnerType `json:"owner_type"`
UserID *string `json:"user_id,omitempty"`
}
Owner OKR 所有者
type ParagraphElementType ¶
type ParagraphElementType string
ParagraphElementType 段落元素类型
const ( ParagraphElementTypeDocsLink ParagraphElementType = "docsLink" ParagraphElementTypeMention ParagraphElementType = "mention" ParagraphElementTypeTextRun ParagraphElementType = "textRun" )
func (ParagraphElementType) Ptr ¶
func (t ParagraphElementType) Ptr() *ParagraphElementType
func (ParagraphElementType) ToV1 ¶ added in v1.0.21
func (t ParagraphElementType) ToV1() ParagraphElementTypeV1
ToV1 将 ParagraphElementType 转换为 ParagraphElementTypeV1
type ParagraphElementTypeV1 ¶ added in v1.0.21
type ParagraphElementTypeV1 string
const ( ParagraphElementTypeV1DocsLink ParagraphElementTypeV1 = "docsLink" ParagraphElementTypeV1Mention ParagraphElementTypeV1 = "person" ParagraphElementTypeV1TextRun ParagraphElementTypeV1 = "textRun" )
func (ParagraphElementTypeV1) Ptr ¶ added in v1.0.21
func (t ParagraphElementTypeV1) Ptr() *ParagraphElementTypeV1
func (ParagraphElementTypeV1) ToV2 ¶ added in v1.0.21
func (t ParagraphElementTypeV1) ToV2() ParagraphElementType
ToV2 将 ParagraphElementTypeV1 转换为 ParagraphElementType
type Progress ¶ added in v1.0.21
type Progress struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
Owner Owner `json:"owner"`
EntityType *int32 `json:"entity_type,omitempty"`
EntityID string `json:"entity_id"`
Content *ContentBlock `json:"content,omitempty"`
ProgressRate *ProgressRate `json:"progress_rate,omitempty"`
}
Progress 进展记录(v2 API)
func (*Progress) ToResp ¶ added in v1.0.21
func (p *Progress) ToResp() *RespProgress
ToResp converts Progress to RespProgress
type ProgressRate ¶ added in v1.0.21
type ProgressRate struct {
ProgressPercent *float64 `json:"progress_percent,omitempty"`
ProgressStatus *int32 `json:"progress_status,omitempty"`
}
ProgressRate 进度率(v2 API)
type ProgressRateV1 ¶ added in v1.0.21
type ProgressRateV1 struct {
Percent *float64 `json:"percent,omitempty"`
Status *int32 `json:"status,omitempty"`
}
ProgressRateV1 进度率
type ProgressStatus ¶ added in v1.0.21
type ProgressStatus int32
ProgressStatus 进展状态
const ( ProgressStatusNormal ProgressStatus = 0 // 正常 ProgressStatusOverdue ProgressStatus = 1 // 逾期 ProgressStatusDone ProgressStatus = 2 // 已完成 )
func ParseProgressStatus ¶ added in v1.0.21
func ParseProgressStatus(s string) (ProgressStatus, bool)
ParseProgressStatus parses a progress status string into ProgressStatus. Accepts "normal", "overdue", "done" or their numeric values "0", "1", "2".
func (ProgressStatus) String ¶ added in v1.0.21
func (s ProgressStatus) String() string
String returns a human-readable name for ProgressStatus.
type ProgressV1 ¶ added in v1.0.21
type ProgressV1 struct {
ID string `json:"progress_id"`
ModifyTime string `json:"modify_time"`
Content *ContentBlockV1 `json:"content,omitempty"`
ProgressRate *ProgressRateV1 `json:"progress_rate,omitempty"`
}
ProgressV1 进展记录
func (*ProgressV1) ToResp ¶ added in v1.0.21
func (p *ProgressV1) ToResp() *RespProgress
ToResp converts ProgressV1 to RespProgress
type RespAlignment ¶
type RespAlignment struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
FromOwner RespOwner `json:"from_owner"`
ToOwner RespOwner `json:"to_owner"`
FromEntityType string `json:"from_entity_type"`
FromEntityID string `json:"from_entity_id"`
ToEntityType string `json:"to_entity_type"`
ToEntityID string `json:"to_entity_id"`
}
RespAlignment 对齐关系
type RespCategory ¶
type RespCategory struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
CategoryType string `json:"category_type"`
Enabled *bool `json:"enabled,omitempty"`
Color *string `json:"color,omitempty"`
Name CategoryName `json:"name"`
}
RespCategory 分类
type RespCycle ¶
type RespCycle struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
TenantCycleID string `json:"tenant_cycle_id"`
Owner RespOwner `json:"owner"`
StartTime string `json:"start_time"`
EndTime string `json:"end_time"`
CycleStatus *string `json:"cycle_status,omitempty"`
Score *float64 `json:"score,omitempty"`
}
RespCycle 周期
type RespIndicator ¶
type RespIndicator struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
Owner RespOwner `json:"owner"`
EntityType *string `json:"entity_type,omitempty"`
EntityID *string `json:"entity_id,omitempty"`
IndicatorStatus *string `json:"indicator_status,omitempty"`
StatusCalculateType *string `json:"status_calculate_type,omitempty"`
StartValue *float64 `json:"start_value,omitempty"`
TargetValue *float64 `json:"target_value,omitempty"`
CurrentValue *float64 `json:"current_value,omitempty"`
CurrentValueCalculateType *string `json:"current_value_calculate_type,omitempty"`
Unit *RespIndicatorUnit `json:"unit,omitempty"`
}
RespIndicator 指标
type RespIndicatorUnit ¶
type RespIndicatorUnit struct {
UnitType *string `json:"unit_type,omitempty"`
UnitValue *string `json:"unit_value,omitempty"`
}
RespIndicatorUnit 指标单位
type RespKeyResult ¶
type RespKeyResult struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
Owner RespOwner `json:"owner"`
ObjectiveID string `json:"objective_id"`
Position *int32 `json:"position,omitempty"`
Content *string `json:"content,omitempty"`
Score *float64 `json:"score,omitempty"`
Weight *float64 `json:"weight,omitempty"`
Deadline *string `json:"deadline,omitempty"`
}
RespKeyResult 关键结果
type RespObjective ¶
type RespObjective struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
Owner RespOwner `json:"owner"`
CycleID string `json:"cycle_id"`
Position *int32 `json:"position,omitempty"`
Content *string `json:"content,omitempty"`
Score *float64 `json:"score,omitempty"`
Notes *string `json:"notes,omitempty"`
Weight *float64 `json:"weight,omitempty"`
Deadline *string `json:"deadline,omitempty"`
CategoryID *string `json:"category_id,omitempty"`
KeyResults []RespKeyResult `json:"key_results,omitempty"`
}
RespObjective 目标
type RespOwner ¶
type RespOwner struct {
OwnerType string `json:"owner_type"`
UserID *string `json:"user_id,omitempty"`
}
RespOwner OKR 所有者
type RespProgress ¶ added in v1.0.21
type RespProgress struct {
ID string `json:"progress_id"`
ModifyTime string `json:"modify_time"`
CreateTime *string `json:"create_time,omitempty"`
Content *string `json:"content,omitempty"`
ProgressRate *RespProgressRate `json:"progress_rate,omitempty"`
}
RespProgress 进展记录
type RespProgressRate ¶ added in v1.0.21
type RespProgressRate struct {
Percent *float64 `json:"percent,omitempty"`
Status *string `json:"status,omitempty"`
}
RespProgressRate 进度率(面向用户的响应格式,Status 为可读字符串)
type StatusCalculateType ¶
type StatusCalculateType int32
StatusCalculateType 状态计算类型
const ( StatusCalculateTypeManualUpdate StatusCalculateType = 0 StatusCalculateTypeAutomaticallyUpdatesBasedOnProgressAndCurrentTime StatusCalculateType = 1 StatusCalculateTypeStatusUpdatesBasedOnTheHighestRiskKeyResults StatusCalculateType = 2 )