Files
dingtalk-workspace-cli/internal/helpers/sheet_float_image.go

378 lines
16 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}
}