378 lines
16 KiB
Go
378 lines
16 KiB
Go
package helpers
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/corecmd/contract"
|
||
"github.com/spf13/cobra"
|
||
)
|
||
|
||
func newFloatImageCmds() []*cobra.Command {
|
||
createFloatImageCmd := &cobra.Command{
|
||
Use: "create-float-image",
|
||
Short: "创建浮动图片",
|
||
Long: `在钉钉表格的指定工作表上创建一个浮动图片。
|
||
|
||
浮动图片悬浮于单元格之上,不占用单元格内容,可自由定位和调整大小。
|
||
|
||
使用流程:
|
||
1. 先通过 media-upload 上传本地图片获取 resourceUrl
|
||
2. 再通过 create-float-image 将图片以浮动方式放置到工作表上
|
||
|
||
--range 指定浮动图片锚定的单元格位置,使用 A1 表示法(如 A1、B3)。
|
||
--width / --height 为必填,单位像素,必须为正整数。
|
||
--offset-x / --offset-y 可选,表示相对锚点单元格左上角的偏移量(像素),默认 0。`,
|
||
Example: ` # 先上传图片获取 resourceUrl
|
||
dws sheet media-upload --node NODE_ID --file ./chart.png
|
||
# 输出: resourceUrl: /core/api/resources/img/xxxx...
|
||
|
||
# 再创建浮动图片(--src 传入 media-upload 返回的 resourceUrl)
|
||
dws sheet create-float-image --node NODE_ID --sheet-id SHEET_ID \
|
||
--src "/core/api/resources/img/xxxx..." --range A1 --width 400 --height 300
|
||
|
||
# 带偏移量
|
||
dws sheet create-float-image --node NODE_ID --sheet-id SHEET_ID \
|
||
--src "/core/api/resources/img/xxxx..." --range B2 --width 200 --height 150 --offset-x 10 --offset-y 20`,
|
||
RunE: func(cmd *cobra.Command, args []string) error {
|
||
if err := validateRequiredFlags(cmd, "node", "sheet-id", "src", "range"); err != nil {
|
||
return err
|
||
}
|
||
width, err := cmd.Flags().GetInt("width")
|
||
if err != nil {
|
||
return fmt.Errorf("--width 解析失败: %w", err)
|
||
}
|
||
if width <= 0 {
|
||
return fmt.Errorf("--width 必须为正整数,当前值: %d", width)
|
||
}
|
||
height, err := cmd.Flags().GetInt("height")
|
||
if err != nil {
|
||
return fmt.Errorf("--height 解析失败: %w", err)
|
||
}
|
||
if height <= 0 {
|
||
return fmt.Errorf("--height 必须为正整数,当前值: %d", height)
|
||
}
|
||
toolArgs := map[string]any{
|
||
"nodeId": mustGetFlag(cmd, "node"),
|
||
"sheetId": mustGetFlag(cmd, "sheet-id"),
|
||
"src": mustGetFlag(cmd, "src"),
|
||
"range": mustGetFlag(cmd, "range"),
|
||
"width": width,
|
||
"height": height,
|
||
}
|
||
if cmd.Flags().Changed("offset-x") {
|
||
ox, _ := cmd.Flags().GetInt("offset-x")
|
||
if ox < 0 {
|
||
return fmt.Errorf("--offset-x 不能为负数,当前值: %d", ox)
|
||
}
|
||
toolArgs["offsetX"] = ox
|
||
}
|
||
if cmd.Flags().Changed("offset-y") {
|
||
oy, _ := cmd.Flags().GetInt("offset-y")
|
||
if oy < 0 {
|
||
return fmt.Errorf("--offset-y 不能为负数,当前值: %d", oy)
|
||
}
|
||
toolArgs["offsetY"] = oy
|
||
}
|
||
return callMCPTool("create_float_image", toolArgs)
|
||
},
|
||
}
|
||
DeclareLeafMetadata(createFloatImageCmd, LeafSpec{
|
||
Safety: contract.SafetySpec{
|
||
Effect: "write", Risk: "medium",
|
||
Confirmation: "not_required", Idempotency: "unknown",
|
||
},
|
||
Contract: LeafContract{
|
||
Identity: contract.ToolIdentitySpec{
|
||
ProductID: "sheet",
|
||
Name: "create_float_image",
|
||
CanonicalPath: "sheet.create_float_image",
|
||
CLIPath: "sheet create-float-image",
|
||
PrimaryCLIPath: "sheet create-float-image",
|
||
},
|
||
Description: "创建浮动图片(src 必须来自 media-upload 的 resourceUrl)。",
|
||
Interface: &contract.InterfaceSpec{
|
||
Mode: "mcp",
|
||
Availability: "available",
|
||
Ref: &contract.InterfaceRefSpec{ProductID: "sheet", RPCName: "create_float_image"},
|
||
},
|
||
Selection: contract.SelectionSpec{
|
||
AgentSummary: "创建浮动图片(src 必须来自 media-upload 的 resourceUrl)。",
|
||
UseWhen: []string{"需要在单元格上方悬浮图片、不占用单元格内容时"},
|
||
AvoidWhen: []string{"单元格内嵌图片用 write-image;更新/删除浮动图用 update/delete-float-image"},
|
||
Examples: []string{"dws sheet create-float-image --node <NODE_ID> --sheet-id <SHEET_ID> --src \"/core/api/resources/img/...\" --range A1 --width 400 --height 300"},
|
||
},
|
||
Parameters: []contract.ParamDecl{
|
||
{Name: "node", Property: "nodeId"},
|
||
},
|
||
},
|
||
})
|
||
createFloatImageCmd.Flags().String("node", "", "表格文档 ID 或 URL (必填)")
|
||
createFloatImageCmd.Flags().String("sheet-id", "", "工作表 ID 或名称 (必填)")
|
||
createFloatImageCmd.Flags().String("src", "", "图片资源路径,通过 media-upload 获取的 resourceUrl (必填)")
|
||
createFloatImageCmd.Flags().String("range", "", "锚点单元格,A1 表示法,如 A1、B3 (必填)")
|
||
createFloatImageCmd.Flags().Int("width", 0, "图片宽度,像素 (必填)")
|
||
createFloatImageCmd.Flags().Int("height", 0, "图片高度,像素 (必填)")
|
||
createFloatImageCmd.Flags().Int("offset-x", 0, "水平偏移量,像素 (默认 0)")
|
||
createFloatImageCmd.Flags().Int("offset-y", 0, "垂直偏移量,像素 (默认 0)")
|
||
|
||
getFloatImageCmd := &cobra.Command{
|
||
Use: "get-float-image",
|
||
Short: "获取浮动图片详情",
|
||
Long: `获取钉钉表格指定工作表中某个浮动图片的详细信息。
|
||
|
||
返回浮动图片的 ID、图片 URL、锚点位置、尺寸和偏移量等信息。
|
||
floatImageId 可通过 list-float-images 获取。`,
|
||
Example: ` dws sheet get-float-image --node NODE_ID --sheet-id SHEET_ID --float-image-id FI_ID`,
|
||
RunE: func(cmd *cobra.Command, args []string) error {
|
||
return callMCPTool("get_float_image", map[string]any{
|
||
"nodeId": mustGetFlag(cmd, "node"),
|
||
"sheetId": mustGetFlag(cmd, "sheet-id"),
|
||
"floatImageId": mustGetFlag(cmd, "float-image-id"),
|
||
})
|
||
},
|
||
}
|
||
DeclareLeafMetadata(getFloatImageCmd, LeafSpec{
|
||
Safety: contract.SafetySpec{
|
||
Effect: "read", Risk: "low",
|
||
Confirmation: "not_required", Idempotency: "idempotent",
|
||
},
|
||
Contract: LeafContract{
|
||
Identity: contract.ToolIdentitySpec{
|
||
ProductID: "sheet",
|
||
Name: "get_float_image",
|
||
CanonicalPath: "sheet.get_float_image",
|
||
CLIPath: "sheet get-float-image",
|
||
PrimaryCLIPath: "sheet get-float-image",
|
||
},
|
||
Description: "获取单张浮动图片详情。",
|
||
Interface: &contract.InterfaceSpec{
|
||
Mode: "mcp",
|
||
Availability: "available",
|
||
Ref: &contract.InterfaceRefSpec{ProductID: "sheet", RPCName: "get_float_image"},
|
||
},
|
||
Selection: contract.SelectionSpec{
|
||
AgentSummary: "获取单张浮动图片详情。",
|
||
UseWhen: []string{"已知 float-image-id,需要查看锚点/尺寸/src 时"},
|
||
AvoidWhen: []string{"列出全部浮动图用 list-float-images"},
|
||
Examples: []string{"dws sheet get-float-image --node <NODE_ID> --sheet-id <SHEET_ID> --float-image-id <FI_ID>"},
|
||
},
|
||
Parameters: []contract.ParamDecl{
|
||
{Name: "node", Property: "nodeId"},
|
||
},
|
||
},
|
||
})
|
||
getFloatImageCmd.Flags().String("node", "", "表格文档 ID 或 URL (必填)")
|
||
getFloatImageCmd.Flags().String("sheet-id", "", "工作表 ID 或名称 (必填)")
|
||
getFloatImageCmd.Flags().String("float-image-id", "", "浮动图片 ID (必填)")
|
||
|
||
listFloatImagesCmd := &cobra.Command{
|
||
Use: "list-float-images",
|
||
Short: "列出工作表所有浮动图片",
|
||
Long: `列出钉钉表格指定工作表中所有浮动图片。
|
||
|
||
返回每个浮动图片的 ID、图片 URL、锚点位置、尺寸和偏移量等信息,以及总数。`,
|
||
Example: ` dws sheet list-float-images --node NODE_ID --sheet-id SHEET_ID`,
|
||
RunE: func(cmd *cobra.Command, args []string) error {
|
||
return callMCPTool("list_float_images", map[string]any{
|
||
"nodeId": mustGetFlag(cmd, "node"),
|
||
"sheetId": mustGetFlag(cmd, "sheet-id"),
|
||
})
|
||
},
|
||
}
|
||
DeclareLeafMetadata(listFloatImagesCmd, LeafSpec{
|
||
Safety: contract.SafetySpec{
|
||
Effect: "read", Risk: "low",
|
||
Confirmation: "not_required", Idempotency: "idempotent",
|
||
},
|
||
Contract: LeafContract{
|
||
Identity: contract.ToolIdentitySpec{
|
||
ProductID: "sheet",
|
||
Name: "list_float_images",
|
||
CanonicalPath: "sheet.list_float_images",
|
||
CLIPath: "sheet list-float-images",
|
||
PrimaryCLIPath: "sheet list-float-images",
|
||
},
|
||
Description: "列出工作表全部浮动图片。",
|
||
Interface: &contract.InterfaceSpec{
|
||
Mode: "mcp",
|
||
Availability: "available",
|
||
Ref: &contract.InterfaceRefSpec{ProductID: "sheet", RPCName: "list_float_images"},
|
||
},
|
||
Selection: contract.SelectionSpec{
|
||
AgentSummary: "列出工作表全部浮动图片。",
|
||
UseWhen: []string{"需要枚举浮动图 ID 以便后续 get/update/delete 时"},
|
||
AvoidWhen: []string{"查单张详情用 get-float-image"},
|
||
Examples: []string{"dws sheet list-float-images --node <NODE_ID> --sheet-id <SHEET_ID>"},
|
||
},
|
||
Parameters: []contract.ParamDecl{
|
||
{Name: "node", Property: "nodeId"},
|
||
},
|
||
},
|
||
})
|
||
listFloatImagesCmd.Flags().String("node", "", "表格文档 ID 或 URL (必填)")
|
||
listFloatImagesCmd.Flags().String("sheet-id", "", "工作表 ID 或名称 (必填)")
|
||
|
||
updateFloatImageCmd := &cobra.Command{
|
||
Use: "update-float-image",
|
||
Short: "更新浮动图片属性",
|
||
Long: `更新钉钉表格指定工作表中浮动图片的属性。
|
||
|
||
可更新的属性包括:图片资源路径(src)、锚点位置、尺寸、偏移量。
|
||
至少需要传入一个更新字段(--src / --range / --width / --height / --offset-x / --offset-y)。
|
||
floatImageId 可通过 list-float-images 获取。`,
|
||
Example: ` # 移动浮动图片到新位置
|
||
dws sheet update-float-image --node NODE_ID --sheet-id SHEET_ID --float-image-id FI_ID --range C5
|
||
|
||
# 调整尺寸
|
||
dws sheet update-float-image --node NODE_ID --sheet-id SHEET_ID --float-image-id FI_ID --width 600 --height 400
|
||
|
||
# 替换图片(需先 media-upload 新图片获取 resourceUrl)
|
||
dws sheet update-float-image --node NODE_ID --sheet-id SHEET_ID --float-image-id FI_ID \
|
||
--src "/core/api/resources/img/xxxx..."`,
|
||
RunE: func(cmd *cobra.Command, args []string) error {
|
||
srcChanged := cmd.Flags().Changed("src")
|
||
rangeChanged := cmd.Flags().Changed("range")
|
||
widthChanged := cmd.Flags().Changed("width")
|
||
heightChanged := cmd.Flags().Changed("height")
|
||
oxChanged := cmd.Flags().Changed("offset-x")
|
||
oyChanged := cmd.Flags().Changed("offset-y")
|
||
|
||
if !srcChanged && !rangeChanged && !widthChanged && !heightChanged && !oxChanged && !oyChanged {
|
||
return fmt.Errorf("--src、--range、--width、--height、--offset-x、--offset-y 至少必须提供一个")
|
||
}
|
||
|
||
toolArgs := map[string]any{
|
||
"nodeId": mustGetFlag(cmd, "node"),
|
||
"sheetId": mustGetFlag(cmd, "sheet-id"),
|
||
"floatImageId": mustGetFlag(cmd, "float-image-id"),
|
||
}
|
||
if srcChanged {
|
||
toolArgs["src"], _ = cmd.Flags().GetString("src")
|
||
}
|
||
if rangeChanged {
|
||
toolArgs["range"], _ = cmd.Flags().GetString("range")
|
||
}
|
||
if widthChanged {
|
||
w, _ := cmd.Flags().GetInt("width")
|
||
if w <= 0 {
|
||
return fmt.Errorf("--width 必须为正整数,当前值: %d", w)
|
||
}
|
||
toolArgs["width"] = w
|
||
}
|
||
if heightChanged {
|
||
h, _ := cmd.Flags().GetInt("height")
|
||
if h <= 0 {
|
||
return fmt.Errorf("--height 必须为正整数,当前值: %d", h)
|
||
}
|
||
toolArgs["height"] = h
|
||
}
|
||
if oxChanged {
|
||
ox, _ := cmd.Flags().GetInt("offset-x")
|
||
if ox < 0 {
|
||
return fmt.Errorf("--offset-x 不能为负数,当前值: %d", ox)
|
||
}
|
||
toolArgs["offsetX"] = ox
|
||
}
|
||
if oyChanged {
|
||
oy, _ := cmd.Flags().GetInt("offset-y")
|
||
if oy < 0 {
|
||
return fmt.Errorf("--offset-y 不能为负数,当前值: %d", oy)
|
||
}
|
||
toolArgs["offsetY"] = oy
|
||
}
|
||
return callMCPTool("update_float_image", toolArgs)
|
||
},
|
||
}
|
||
DeclareLeafMetadata(updateFloatImageCmd, LeafSpec{
|
||
Safety: contract.SafetySpec{
|
||
Effect: "write", Risk: "medium",
|
||
Confirmation: "not_required", Idempotency: "unknown",
|
||
},
|
||
Contract: LeafContract{
|
||
Identity: contract.ToolIdentitySpec{
|
||
ProductID: "sheet",
|
||
Name: "update_float_image",
|
||
CanonicalPath: "sheet.update_float_image",
|
||
CLIPath: "sheet update-float-image",
|
||
PrimaryCLIPath: "sheet update-float-image",
|
||
},
|
||
Description: "更新浮动图片锚点、尺寸、偏移或资源路径。",
|
||
Interface: &contract.InterfaceSpec{
|
||
Mode: "mcp",
|
||
Availability: "available",
|
||
Ref: &contract.InterfaceRefSpec{ProductID: "sheet", RPCName: "update_float_image"},
|
||
},
|
||
Selection: contract.SelectionSpec{
|
||
AgentSummary: "更新浮动图片锚点、尺寸、偏移或资源路径。",
|
||
UseWhen: []string{"需要移动/缩放/替换已有浮动图片时"},
|
||
AvoidWhen: []string{"创建用 create-float-image;删除用 delete-float-image"},
|
||
Examples: []string{"dws sheet update-float-image --node <NODE_ID> --sheet-id <SHEET_ID> --float-image-id <FI_ID> --range C5"},
|
||
},
|
||
Parameters: []contract.ParamDecl{
|
||
{Name: "node", Property: "nodeId"},
|
||
},
|
||
},
|
||
})
|
||
updateFloatImageCmd.Flags().String("node", "", "表格文档 ID 或 URL (必填)")
|
||
updateFloatImageCmd.Flags().String("sheet-id", "", "工作表 ID 或名称 (必填)")
|
||
updateFloatImageCmd.Flags().String("float-image-id", "", "浮动图片 ID (必填)")
|
||
updateFloatImageCmd.Flags().String("src", "", "新的图片资源路径,通过 media-upload 获取的 resourceUrl")
|
||
updateFloatImageCmd.Flags().String("range", "", "新的锚点单元格,A1 表示法")
|
||
updateFloatImageCmd.Flags().Int("width", 0, "新的图片宽度,像素")
|
||
updateFloatImageCmd.Flags().Int("height", 0, "新的图片高度,像素")
|
||
updateFloatImageCmd.Flags().Int("offset-x", 0, "新的水平偏移量,像素")
|
||
updateFloatImageCmd.Flags().Int("offset-y", 0, "新的垂直偏移量,像素")
|
||
|
||
deleteFloatImageCmd := &cobra.Command{
|
||
Use: "delete-float-image",
|
||
Short: "删除浮动图片",
|
||
Long: `删除钉钉表格指定工作表中的浮动图片。
|
||
|
||
操作不可恢复,删除后图片将从工作表中移除。
|
||
floatImageId 可通过 list-float-images 获取。`,
|
||
Example: ` dws sheet delete-float-image --node NODE_ID --sheet-id SHEET_ID --float-image-id FI_ID --yes`,
|
||
RunE: func(cmd *cobra.Command, args []string) error {
|
||
return callMCPTool("delete_float_image", map[string]any{
|
||
"nodeId": mustGetFlag(cmd, "node"),
|
||
"sheetId": mustGetFlag(cmd, "sheet-id"),
|
||
"floatImageId": mustGetFlag(cmd, "float-image-id"),
|
||
})
|
||
},
|
||
}
|
||
DeclareLeafMetadata(deleteFloatImageCmd, LeafSpec{
|
||
Safety: contract.SafetySpec{
|
||
Effect: "write", Risk: "medium",
|
||
Confirmation: "user_required", Idempotency: "unknown",
|
||
},
|
||
Contract: LeafContract{
|
||
Identity: contract.ToolIdentitySpec{
|
||
ProductID: "sheet",
|
||
Name: "delete_float_image",
|
||
CanonicalPath: "sheet.delete_float_image",
|
||
CLIPath: "sheet delete-float-image",
|
||
PrimaryCLIPath: "sheet delete-float-image",
|
||
},
|
||
Description: "删除浮动图片(需确认后加 --yes)。",
|
||
Interface: &contract.InterfaceSpec{
|
||
Mode: "mcp",
|
||
Availability: "available",
|
||
Ref: &contract.InterfaceRefSpec{ProductID: "sheet", RPCName: "delete_float_image"},
|
||
},
|
||
Selection: contract.SelectionSpec{
|
||
AgentSummary: "删除浮动图片(需确认后加 --yes)。",
|
||
UseWhen: []string{"用户明确要求删除某张浮动图片时"},
|
||
AvoidWhen: []string{"删除单元格内嵌图需改写单元格;列目录用 list-float-images"},
|
||
Examples: []string{"dws sheet delete-float-image --node <NODE_ID> --sheet-id <SHEET_ID> --float-image-id <FI_ID>"},
|
||
},
|
||
Parameters: []contract.ParamDecl{
|
||
{Name: "node", Property: "nodeId"},
|
||
},
|
||
},
|
||
})
|
||
deleteFloatImageCmd.Flags().String("node", "", "表格文档 ID 或 URL (必填)")
|
||
deleteFloatImageCmd.Flags().String("sheet-id", "", "工作表 ID 或名称 (必填)")
|
||
deleteFloatImageCmd.Flags().String("float-image-id", "", "浮动图片 ID (必填)")
|
||
|
||
return []*cobra.Command{createFloatImageCmd, getFloatImageCmd, listFloatImagesCmd, updateFloatImageCmd, deleteFloatImageCmd}
|
||
}
|