Documentation
¶
Index ¶
- Variables
- func Shortcuts() []common.Shortcut
- type BlockElementType
- type CategoryName
- type ContentBlock
- type ContentBlockElement
- type ContentColor
- type ContentDocsLink
- type ContentGallery
- type ContentImageItem
- type ContentLink
- type ContentList
- type ContentMention
- type ContentParagraph
- type ContentParagraphElement
- type ContentParagraphStyle
- type ContentTextRun
- type ContentTextStyle
- type Cycle
- type CycleStatus
- type KeyResult
- type ListType
- type Objective
- type Owner
- type OwnerType
- type ParagraphElementType
- type RespAlignment
- type RespCategory
- type RespCycle
- type RespIndicator
- type RespIndicatorUnit
- type RespKeyResult
- type RespObjective
- type RespOwner
- type StatusCalculateType
Constants ¶
This section is empty.
Variables ¶
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 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 }, }
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 内容块
type ContentBlockElement ¶
type ContentBlockElement struct {
BlockElementType *BlockElementType `json:"block_element_type,omitempty"`
Paragraph *ContentParagraph `json:"paragraph,omitempty"`
Gallery *ContentGallery `json:"gallery,omitempty"`
}
ContentBlockElement 内容块元素
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 图库
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 图片项
type ContentList ¶
type ContentList struct {
ListType *ListType `json:"list_type,omitempty"`
IndentLevel *int32 `json:"indent_level,omitempty"`
Number *int32 `json:"number,omitempty"`
}
ContentList 列表
type ContentMention ¶
type ContentMention struct {
UserID *string `json:"user_id,omitempty"`
}
ContentMention 提及
type ContentParagraph ¶
type ContentParagraph struct {
Style *ContentParagraphStyle `json:"style,omitempty"`
Elements []ContentParagraphElement `json:"elements,omitempty"`
}
ContentParagraph 段落
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 段落元素
type ContentParagraphStyle ¶
type ContentParagraphStyle struct {
List *ContentList `json:"list,omitempty"`
}
ContentParagraphStyle 段落样式
type ContentTextRun ¶
type ContentTextRun struct {
Text *string `json:"text,omitempty"`
Style *ContentTextStyle `json:"style,omitempty"`
}
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 文本样式
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
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 StatusCalculateType ¶
type StatusCalculateType int32
StatusCalculateType 状态计算类型
const ( StatusCalculateTypeManualUpdate StatusCalculateType = 0 StatusCalculateTypeAutomaticallyUpdatesBasedOnProgressAndCurrentTime StatusCalculateType = 1 StatusCalculateTypeStatusUpdatesBasedOnTheHighestRiskKeyResults StatusCalculateType = 2 )