From d409882c64cd0f7610f198540279c4f1da0b4e18 Mon Sep 17 00:00:00 2001 From: jc <2646393949@qq.com> Date: Mon, 22 Sep 2025 21:07:30 +0800 Subject: [PATCH] first commit --- .vscode/launch.json | 30 + data/dialog_result.json | 88 + data/superbrowser.json | 292 ++ data/templete1.json | 167 + data/test.json | 3058 ++++++++++++ readme.md | 0 .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 1019 bytes src/Converter/utils.py | 36 + src/Xbot/Blockly/BlockManager.py | 193 + src/Xbot/Blockly/BlockPrototype.py | 196 + src/Xbot/Blockly/Field.py | 111 + src/Xbot/Blockly/FieldValue.py | 191 + src/Xbot/Blockly/Variable.py | 93 + src/Xbot/Blockly/XbotBlock.py | 198 + src/Xbot/Blockly/__init__.py | 4 + .../__pycache__/BlockManager.cpython-310.pyc | Bin 0 -> 5608 bytes .../__pycache__/BlockManager.cpython-312.pyc | Bin 0 -> 9227 bytes .../__pycache__/BlockManager.cpython-313.pyc | Bin 0 -> 9312 bytes .../BlockPrototype.cpython-310.pyc | Bin 0 -> 5847 bytes .../BlockPrototype.cpython-312.pyc | Bin 0 -> 9515 bytes .../BlockPrototype.cpython-313.pyc | Bin 0 -> 9735 bytes .../Blockly/__pycache__/Field.cpython-310.pyc | Bin 0 -> 3938 bytes .../Blockly/__pycache__/Field.cpython-312.pyc | Bin 0 -> 8997 bytes .../Blockly/__pycache__/Field.cpython-313.pyc | Bin 0 -> 9186 bytes .../__pycache__/FieldValue.cpython-310.pyc | Bin 0 -> 6265 bytes .../__pycache__/FieldValue.cpython-312.pyc | Bin 0 -> 9245 bytes .../__pycache__/FieldValue.cpython-313.pyc | Bin 0 -> 9359 bytes .../__pycache__/Variable.cpython-310.pyc | Bin 0 -> 2576 bytes .../__pycache__/Variable.cpython-312.pyc | Bin 0 -> 3750 bytes .../__pycache__/Variable.cpython-313.pyc | Bin 0 -> 3870 bytes .../__pycache__/XbotBlock.cpython-310.pyc | Bin 0 -> 5310 bytes .../__pycache__/XbotBlock.cpython-312.pyc | Bin 0 -> 8621 bytes .../__pycache__/XbotBlock.cpython-313.pyc | Bin 0 -> 8847 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 286 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 313 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 313 bytes src/Xbot/CodeFlow.py | 93 + src/Xbot/FlowParameter.py | 89 + src/Xbot/ShadowBotPaths.py | 32 + src/Xbot/VisualFlow.py | 75 + src/Xbot/XBotHelper.py | 47 + src/Xbot/XbotApp.py | 46 + src/Xbot/XbotAppCreator.py | 317 ++ .../xbot_robot/.dev/main.flow.json | 8 + .../XbotAppTemplate/xbot_robot/__init__.py | 0 .../XbotAppTemplate/xbot_robot/imagesV2.xml | 3 + src/Xbot/XbotAppTemplate/xbot_robot/main.py | 7 + .../XbotAppTemplate/xbot_robot/package.json | 13 + .../XbotAppTemplate/xbot_robot/package.py | 49 + .../xbot_robot/resources/aocc.yaml | 22 + .../xbot_robot/selectorsV2.xml | 3 + src/Xbot/XbotFlow.py | 248 + src/Xbot/XbotProject.py | 405 ++ src/Xbot/__init__.py | 5 + src/Xbot/__pycache__/CodeFlow.cpython-310.pyc | Bin 0 -> 3468 bytes .../__pycache__/FlowParameter.cpython-310.pyc | Bin 0 -> 2538 bytes .../ShadowBotPaths.cpython-310.pyc | Bin 0 -> 1323 bytes .../__pycache__/VisualFlow.cpython-310.pyc | Bin 0 -> 2811 bytes .../XbotAppCreator.cpython-310.pyc | Bin 0 -> 7593 bytes src/Xbot/__pycache__/XbotFlow.cpython-310.pyc | Bin 0 -> 8765 bytes .../__pycache__/XbotProject.cpython-310.pyc | Bin 0 -> 12910 bytes src/Xbot/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 306 bytes .../__pycache__/bot_import.cpython-310.pyc | Bin 0 -> 1229 bytes src/Xbot/bot_import.py | 33 + src/assert/block_settings/asset.blocks.json | 77 + src/assert/block_settings/base64.blocks.json | 101 + src/assert/block_settings/buildin_types.json | 142 + src/assert/block_settings/chatgpt.blocks.json | 212 + .../block_settings/clipboard.blocks.json | 83 + src/assert/block_settings/code.template.py | 13 + src/assert/block_settings/csv.blocks.json | 176 + .../block_settings/database.blocks.json | 250 + .../block_settings/datetime.blocks.json | 583 +++ src/assert/block_settings/dialog.blocks.json | 926 ++++ .../block_settings/dictionary.blocks.json | 239 + src/assert/block_settings/dir.blocks.json | 747 +++ src/assert/block_settings/email.blocks.json | 519 ++ src/assert/block_settings/excel.blocks.json | 4149 ++++++++++++++++ src/assert/block_settings/file.blocks.json | 651 +++ src/assert/block_settings/ftp.blocks.json | 684 +++ src/assert/block_settings/image.blocks.json | 628 +++ src/assert/block_settings/json.blocks.json | 67 + src/assert/block_settings/list.blocks.json | 605 +++ src/assert/block_settings/mobile.blocks.json | 445 ++ src/assert/block_settings/nlp.blocks.json | 405 ++ src/assert/block_settings/ocr.blocks.json | 4153 +++++++++++++++++ src/assert/block_settings/pdf.blocks.json | 687 +++ src/assert/block_settings/process.blocks.json | 258 + .../block_settings/programing.blocks.json | 538 +++ .../programing.databook.blocks.json | 1001 ++++ src/assert/block_settings/rdp.blocks.json | 78 + .../block_settings/resourcesfile.blocks.json | 210 + .../block_settings/sap.element.blocks.json | 294 ++ src/assert/block_settings/system.blocks.json | 746 +++ src/assert/block_settings/text.blocks.json | 976 ++++ .../block_settings/visual.activities.xml | 500 ++ src/assert/block_settings/web.blocks.json | 1819 ++++++++ .../block_settings/web.browser.blocks.json | 1279 +++++ .../block_settings/web.element.blocks.json | 3409 ++++++++++++++ .../block_settings/web.service.blocks.json | 2135 +++++++++ src/assert/block_settings/win32.blocks.json | 808 ++++ .../block_settings/win32.element.blocks.json | 2571 ++++++++++ .../block_settings/win32.window.blocks.json | 1564 +++++++ src/assert/block_settings/word.blocks.json | 1211 +++++ .../block_settings/workflow.blocks.json | 795 ++++ .../block_settings/workqueue.blocks.json | 279 ++ ..._extensions.activity_temu_shop.blocks.json | 2560 ++++++++++ ...xbot_extensions.popup_detector.blocks.json | 348 ++ .../xbot_extensions.super_browser.blocks.json | 1104 +++++ src/assert/block_settings/zip.blocks.json | 146 + src/assert/icon-big.ico | Bin 0 -> 198272 bytes src/main.py | 19 + src/main_test.py | 19 + tests/create_xbot_app.py | 20 + 114 files changed, 47381 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 data/dialog_result.json create mode 100644 data/superbrowser.json create mode 100644 data/templete1.json create mode 100644 data/test.json create mode 100644 readme.md create mode 100644 src/Converter/__pycache__/utils.cpython-310.pyc create mode 100644 src/Converter/utils.py create mode 100644 src/Xbot/Blockly/BlockManager.py create mode 100644 src/Xbot/Blockly/BlockPrototype.py create mode 100644 src/Xbot/Blockly/Field.py create mode 100644 src/Xbot/Blockly/FieldValue.py create mode 100644 src/Xbot/Blockly/Variable.py create mode 100644 src/Xbot/Blockly/XbotBlock.py create mode 100644 src/Xbot/Blockly/__init__.py create mode 100644 src/Xbot/Blockly/__pycache__/BlockManager.cpython-310.pyc create mode 100644 src/Xbot/Blockly/__pycache__/BlockManager.cpython-312.pyc create mode 100644 src/Xbot/Blockly/__pycache__/BlockManager.cpython-313.pyc create mode 100644 src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-310.pyc create mode 100644 src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-312.pyc create mode 100644 src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-313.pyc create mode 100644 src/Xbot/Blockly/__pycache__/Field.cpython-310.pyc create mode 100644 src/Xbot/Blockly/__pycache__/Field.cpython-312.pyc create mode 100644 src/Xbot/Blockly/__pycache__/Field.cpython-313.pyc create mode 100644 src/Xbot/Blockly/__pycache__/FieldValue.cpython-310.pyc create mode 100644 src/Xbot/Blockly/__pycache__/FieldValue.cpython-312.pyc create mode 100644 src/Xbot/Blockly/__pycache__/FieldValue.cpython-313.pyc create mode 100644 src/Xbot/Blockly/__pycache__/Variable.cpython-310.pyc create mode 100644 src/Xbot/Blockly/__pycache__/Variable.cpython-312.pyc create mode 100644 src/Xbot/Blockly/__pycache__/Variable.cpython-313.pyc create mode 100644 src/Xbot/Blockly/__pycache__/XbotBlock.cpython-310.pyc create mode 100644 src/Xbot/Blockly/__pycache__/XbotBlock.cpython-312.pyc create mode 100644 src/Xbot/Blockly/__pycache__/XbotBlock.cpython-313.pyc create mode 100644 src/Xbot/Blockly/__pycache__/__init__.cpython-310.pyc create mode 100644 src/Xbot/Blockly/__pycache__/__init__.cpython-312.pyc create mode 100644 src/Xbot/Blockly/__pycache__/__init__.cpython-313.pyc create mode 100644 src/Xbot/CodeFlow.py create mode 100644 src/Xbot/FlowParameter.py create mode 100644 src/Xbot/ShadowBotPaths.py create mode 100644 src/Xbot/VisualFlow.py create mode 100644 src/Xbot/XBotHelper.py create mode 100644 src/Xbot/XbotApp.py create mode 100644 src/Xbot/XbotAppCreator.py create mode 100644 src/Xbot/XbotAppTemplate/xbot_robot/.dev/main.flow.json create mode 100644 src/Xbot/XbotAppTemplate/xbot_robot/__init__.py create mode 100644 src/Xbot/XbotAppTemplate/xbot_robot/imagesV2.xml create mode 100644 src/Xbot/XbotAppTemplate/xbot_robot/main.py create mode 100644 src/Xbot/XbotAppTemplate/xbot_robot/package.json create mode 100644 src/Xbot/XbotAppTemplate/xbot_robot/package.py create mode 100644 src/Xbot/XbotAppTemplate/xbot_robot/resources/aocc.yaml create mode 100644 src/Xbot/XbotAppTemplate/xbot_robot/selectorsV2.xml create mode 100644 src/Xbot/XbotFlow.py create mode 100644 src/Xbot/XbotProject.py create mode 100644 src/Xbot/__init__.py create mode 100644 src/Xbot/__pycache__/CodeFlow.cpython-310.pyc create mode 100644 src/Xbot/__pycache__/FlowParameter.cpython-310.pyc create mode 100644 src/Xbot/__pycache__/ShadowBotPaths.cpython-310.pyc create mode 100644 src/Xbot/__pycache__/VisualFlow.cpython-310.pyc create mode 100644 src/Xbot/__pycache__/XbotAppCreator.cpython-310.pyc create mode 100644 src/Xbot/__pycache__/XbotFlow.cpython-310.pyc create mode 100644 src/Xbot/__pycache__/XbotProject.cpython-310.pyc create mode 100644 src/Xbot/__pycache__/__init__.cpython-310.pyc create mode 100644 src/Xbot/__pycache__/bot_import.cpython-310.pyc create mode 100644 src/Xbot/bot_import.py create mode 100644 src/assert/block_settings/asset.blocks.json create mode 100644 src/assert/block_settings/base64.blocks.json create mode 100644 src/assert/block_settings/buildin_types.json create mode 100644 src/assert/block_settings/chatgpt.blocks.json create mode 100644 src/assert/block_settings/clipboard.blocks.json create mode 100644 src/assert/block_settings/code.template.py create mode 100644 src/assert/block_settings/csv.blocks.json create mode 100644 src/assert/block_settings/database.blocks.json create mode 100644 src/assert/block_settings/datetime.blocks.json create mode 100644 src/assert/block_settings/dialog.blocks.json create mode 100644 src/assert/block_settings/dictionary.blocks.json create mode 100644 src/assert/block_settings/dir.blocks.json create mode 100644 src/assert/block_settings/email.blocks.json create mode 100644 src/assert/block_settings/excel.blocks.json create mode 100644 src/assert/block_settings/file.blocks.json create mode 100644 src/assert/block_settings/ftp.blocks.json create mode 100644 src/assert/block_settings/image.blocks.json create mode 100644 src/assert/block_settings/json.blocks.json create mode 100644 src/assert/block_settings/list.blocks.json create mode 100644 src/assert/block_settings/mobile.blocks.json create mode 100644 src/assert/block_settings/nlp.blocks.json create mode 100644 src/assert/block_settings/ocr.blocks.json create mode 100644 src/assert/block_settings/pdf.blocks.json create mode 100644 src/assert/block_settings/process.blocks.json create mode 100644 src/assert/block_settings/programing.blocks.json create mode 100644 src/assert/block_settings/programing.databook.blocks.json create mode 100644 src/assert/block_settings/rdp.blocks.json create mode 100644 src/assert/block_settings/resourcesfile.blocks.json create mode 100644 src/assert/block_settings/sap.element.blocks.json create mode 100644 src/assert/block_settings/system.blocks.json create mode 100644 src/assert/block_settings/text.blocks.json create mode 100644 src/assert/block_settings/visual.activities.xml create mode 100644 src/assert/block_settings/web.blocks.json create mode 100644 src/assert/block_settings/web.browser.blocks.json create mode 100644 src/assert/block_settings/web.element.blocks.json create mode 100644 src/assert/block_settings/web.service.blocks.json create mode 100644 src/assert/block_settings/win32.blocks.json create mode 100644 src/assert/block_settings/win32.element.blocks.json create mode 100644 src/assert/block_settings/win32.window.blocks.json create mode 100644 src/assert/block_settings/word.blocks.json create mode 100644 src/assert/block_settings/workflow.blocks.json create mode 100644 src/assert/block_settings/workqueue.blocks.json create mode 100644 src/assert/block_settings/xbot_extensions.activity_temu_shop.blocks.json create mode 100644 src/assert/block_settings/xbot_extensions.popup_detector.blocks.json create mode 100644 src/assert/block_settings/xbot_extensions.super_browser.blocks.json create mode 100644 src/assert/block_settings/zip.blocks.json create mode 100644 src/assert/icon-big.ico create mode 100644 src/main.py create mode 100644 src/main_test.py create mode 100644 tests/create_xbot_app.py diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..1fa6b3e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,30 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "cmake", + "request": "launch", + "name": "CMake: 配置项目", + "cmakeDebugType": "configure", + "clean": false, + "configureAll": false + }, + { + "name": "Python 调试程序: 当前文件", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/src/main.py", + "console": "integratedTerminal" + }, + { + "name": "test_main_create_block", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/src/main_test.py", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/data/dialog_result.json b/data/dialog_result.json new file mode 100644 index 0000000..9fb13d5 --- /dev/null +++ b/data/dialog_result.json @@ -0,0 +1,88 @@ +{ + "dependency": [ + ], + "flow": [ + { + "name": "0_基本配置", + "memo": null, + "kind": "visual", + "blocks": [ + { + "id": "b60be60e-d970-4e4f-9564-6a66b138d08a", + "name": "dialog.show_custom_dialog", + "isEnabled": true, + "inputs": { + "settings": { + "value": "10:{\"dialogTitle\":null,\"height\":0,\"width\":0,\"timeout\":0,\"autoCloseButton\":null,\"use_wait_timeout\":false,\"canRememberContent\":false,\"settings\":{\"editors\":[],\"buttons\":[{\"type\":\"Button\",\"label\":\"确定\",\"theme\":\"white\",\"hotKey\":\"Return\",\"uuid\":\"e49138d8-6857-4ef3-9550-4d098e95e7ce\"},{\"type\":\"Button\",\"label\":\"取消\",\"theme\":\"white\",\"hotKey\":\"Escape\",\"uuid\":\"5b7bd90e-50c1-4583-9e8a-d59ea1c1efc9\"}]}}" + }, + "dialog_title": { + "value": "10:" + }, + "default_btn": { + "value": "10:确定", + "display": "确定" + }, + "is_auto_click": { + "value": "13:False" + }, + "timeout": { + "value": null + }, + "globals": { + "value": "13:globals()" + }, + "locals": { + "value": "13:locals()" + }, + "storage_key": { + "value": "13:`block_id`" + } + }, + "outputs": { + "dialog_result": { + "name": "dialog_result", + "isEnable": true + } + } + }, + { + "id": "6e80cd80-7109-427c-87e8-22ffd91ef176", + "name": "workflow.if", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "operand1": { + "value": "11:dialog_result.pressed_button" + }, + "operator": { + "value": "10:!=", + "display": "不等于" + }, + "operand2": { + "value": "10:确定" + }, + "operator_options": { + "value": "10:{}" + } + }, + "outputs": {} + }, + { + "id": "2a389cae-75f6-43f1-a365-b2e47c1d4e18", + "name": "process.exit", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "2091634e-7ee7-4c1f-b3a8-cb3f00dc4770", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + } + ], + "parameters": [] + } + ] +} \ No newline at end of file diff --git a/data/superbrowser.json b/data/superbrowser.json new file mode 100644 index 0000000..e49a47c --- /dev/null +++ b/data/superbrowser.json @@ -0,0 +1,292 @@ +{ + "dependency": [ + "super_browser==25.9.3", + "activity_f4d5de04==23.11.1" + ], + "flow": [ + { + "name": "main", + "memo": "我的自动化应用", + "kind": "visual", + "blocks": [ + { + "id": "48a2e4c6-3b44-4e55-a581-0ed0d56323cc", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%,无返回结果", + "inputs": { + "process": { + "value": "10:setting_process", + "display": "0_基本配置" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result", + "isEnable": false + } + } + }, + { + "id": "ed930e1f-722d-43b9-9b84-0a0a175944ce", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%并传入参数%inputs:WyLotKblj7flgLzkuLol6LSm5Y+3Je+8jCIsIuWvhueggeWAvOS4uiXlr4bnoIEl77yMIiwi5LyB5Lia5ZCN56ew5YC85Li6JeS8geS4muWQjeensCXvvIwiXQ==%无返回结果", + "inputs": { + "process": { + "value": "10:login_process", + "display": "1_登录" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[{\"账号\":\"10:\"},{\"密码\":\"10:\"},{\"企业名称\":\"10:\"}]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result2", + "isEnable": false + } + } + }, + { + "id": "80850dab-a050-435e-b6b4-09f2aa2455f8", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%并传入参数%inputs:WyLlupfpk7rlkI3np7DlgLzkuLol5bqX6ZO65ZCN56ewJe+8jCJd%无返回结果", + "inputs": { + "process": { + "value": "10:func_process", + "display": "2_功能模块" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[{\"店铺名称\":\"10:\"}]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result3", + "isEnable": false + } + } + } + ], + "parameters": [] + }, + { + "name": "0_基本配置", + "memo": "setting_process", + "kind": "visual", + "blocks": [ + { + "id": "b60be60e-d970-4e4f-9564-6a66b138d08a", + "name": "dialog.show_custom_dialog", + "isEnabled": true, + "inputs": { + "settings": { + "value": "10:{\"dialogTitle\":null,\"height\":0,\"width\":0,\"timeout\":0,\"autoCloseButton\":null,\"use_wait_timeout\":false,\"canRememberContent\":false,\"settings\":{\"editors\":[],\"buttons\":[{\"type\":\"Button\",\"label\":\"确定\",\"theme\":\"white\",\"hotKey\":\"Return\",\"uuid\":\"e49138d8-6857-4ef3-9550-4d098e95e7ce\"},{\"type\":\"Button\",\"label\":\"取消\",\"theme\":\"white\",\"hotKey\":\"Escape\",\"uuid\":\"5b7bd90e-50c1-4583-9e8a-d59ea1c1efc9\"}]}}" + }, + "dialog_title": { + "value": "10:" + }, + "default_btn": { + "value": "10:确定", + "display": "确定" + }, + "is_auto_click": { + "value": "13:False" + }, + "timeout": { + "value": null + }, + "globals": { + "value": "13:globals()" + }, + "locals": { + "value": "13:locals()" + }, + "storage_key": { + "value": "13:`block_id`" + } + }, + "outputs": { + "dialog_result": { + "name": "dialog_result", + "isEnable": true + } + } + }, + { + "id": "6e80cd80-7109-427c-87e8-22ffd91ef176", + "name": "workflow.if", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "operand1": { + "value": "11:dialog_result.pressed_button" + }, + "operator": { + "value": "10:!=", + "display": "不等于" + }, + "operand2": { + "value": "10:确定" + }, + "operator_options": { + "value": "10:{}" + } + }, + "outputs": {} + }, + { + "id": "2a389cae-75f6-43f1-a365-b2e47c1d4e18", + "name": "process.exit", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "2091634e-7ee7-4c1f-b3a8-cb3f00dc4770", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + } + ], + "parameters": [] + }, + { + "name": "1_登录", + "memo": "login_process", + "kind": "visual", + "blocks": [ + { + "id": "81b42701-4cb6-4603-b262-75f793c92d58", + "name": "xbot_extensions.super_browser.A4 紫鸟登录", + "isEnabled": true, + "inputs": { + "紫鸟版本": { + "value": "10:V5", + "display": "V5" + }, + "企业名称": { + "value": "11:企业名称" + }, + "企业用户名": { + "value": "11:账号" + }, + "密码": { + "value": "11:密码" + }, + "是否填写账号密码": { + "value": "13:False" + }, + "是否退出登录": { + "value": "13:False" + } + }, + "outputs": {}, + "block_title": "紫鸟控制台操作/紫鸟登录" + } + ], + "parameters": [ + { + "name": "账号", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + }, + { + "name": "密码", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + }, + { + "name": "企业名称", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + } + ] + }, + { + "name": "2_功能模块", + "memo": "func_process", + "kind": "visual", + "blocks": [ + { + "id": "a1d0e848-2023-4bb9-abbf-25214bb93ef5", + "name": "xbot_extensions.super_browser.A2 打开店铺", + "isEnabled": true, + "inputs": { + "店铺名称": { + "value": "11:店铺名称" + }, + "匹配类型": { + "value": "10:相等", + "display": "相等" + }, + "打开账号": { + "value": "10:点击", + "display": "点击" + }, + "隐私模式": { + "value": "13:False" + }, + "超时时间": { + "value": "13:50" + } + }, + "outputs": { + "完整店铺名称": { + "name": "完整店铺名称", + "isEnable": true + }, + "web_page": { + "name": "web_page", + "isEnable": true + } + }, + "block_title": "紫鸟控制台操作/打开店铺" + } + ], + "parameters": [ + { + "name": "店铺名称", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + } + ] + } + ] +} diff --git a/data/templete1.json b/data/templete1.json new file mode 100644 index 0000000..cab97b9 --- /dev/null +++ b/data/templete1.json @@ -0,0 +1,167 @@ +{ + "name": "main", + "memo": "测试_jc", + "kind": "visual", + "blocks": [ + { + "id": "51db7333-6ae1-4429-ac86-354bd60e86d3", + "name": "excel.launch", + "isEnabled": true, + "inputs": { + "launch_way": { + "value": "10:open", + "display": "打开已有的Excel" + }, + "driver_way": { + "value": "10:auto_check", + "display": "自动检测" + }, + "open_filename": { + "value": "10:D:\\env_text\\京东商智商家版\\16839740_成交订单_2025-07-01~2025-07-31.xlsx" + }, + "save_filename": { + "value": "10:" + }, + "isvisible": { + "value": "13:False" + }, + "ignoreformula": { + "value": "13:False" + }, + "password": { + "value": null + }, + "write_password": { + "value": null + }, + "update_links": { + "value": "13:False" + } + }, + "outputs": { + "excel_instance": { + "name": "excel_instance", + "variableLabel": "打开的Excel对象", + "isEnable": true + } + } + }, + { + "id": "1ed06cd6-2b02-4ef9-a714-7a010f4e3e19", + "name": "excel.read_data_from_workbook", + "isEnabled": true, + "comment": "从Excel对象%workbook%中读取已使用的矩形区域内容,将数据保存到%excel_data%", + "inputs": { + "workbook": { + "value": "11:excel_instance", + "display": "excel_instance" + }, + "read_way": { + "value": "10:used_range", + "display": "已使用区域内容" + }, + "range": { + "value": null + }, + "cell_row_num": { + "value": null + }, + "cell_column_name": { + "value": null + }, + "area_begin_row_num": { + "value": null + }, + "area_begin_column_name": { + "value": null + }, + "area_end_row_num": { + "value": null + }, + "area_end_column_name": { + "value": null + }, + "row_row_num": { + "value": null + }, + "get_display_text": { + "value": "13:False" + }, + "has_header_row": { + "value": "13:False" + }, + "column_column_name": { + "value": null + }, + "sheet_name": { + "value": "10:" + }, + "using_text": { + "value": "13:False" + }, + "text_cols": { + "value": "10:" + }, + "clear_space": { + "value": "13:False" + } + }, + "outputs": { + "excel_data": { + "name": "excel_data", + "variableLabel": "Excel已使用区域内容", + "type": "list>", + "isEnable": true + } + } + }, + { + "id": "6da8c5eb-fcf5-4199-80f5-df5fd529a375", + "name": "excel.close", + "isEnabled": true, + "inputs": { + "operation": { + "value": "10:close_specified", + "display": "关闭指定Excel文件" + }, + "excel_instance": { + "value": "11:excel_instance" + }, + "close_way": { + "value": "10:save", + "display": "保存" + }, + "filename": { + "value": null + }, + "overwrite_file": { + "value": "13:True" + }, + "close_process": { + "value": "10:office", + "display": "office" + }, + "task_kill": { + "value": "13:True" + } + }, + "outputs": {} + }, + { + "id": "ee73d8ec-1441-45b2-8bec-4d4d10b4153a", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:info", + "display": "信息" + }, + "text": { + "value": "11:excel_data" + } + }, + "outputs": {} + } + ], + "parameters": [] +} \ No newline at end of file diff --git a/data/test.json b/data/test.json new file mode 100644 index 0000000..fde032e --- /dev/null +++ b/data/test.json @@ -0,0 +1,3058 @@ +{ + "dependency": [ + "super_browser==25.9.3", + "activity_f4d5de04==23.11.1", + "activity_temu_shop==25.9.34", + "popup_detector==24.12.0" + ], + "name": "Temu通用模板", + "flow":[ + { + "name": "main", + "memo": "我的自动化应用", + "kind": "visual", + "blocks": [ + { + "id": "d27ac450-84a1-4ddd-957a-c61ee0d13931", + "name": "xbot_extensions.popup_detector.A1 智能屏蔽弹窗(web)", + "isEnabled": true, + "inputs": {}, + "outputs": {}, + "block_title": "弹窗智能侦测器/智能屏蔽弹窗(web)" + }, + { + "id": "5946f7ac-b75e-429b-8d87-dd63214c502e", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:唤起自定义对话框配置" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "3329baf5-8469-4c9a-9bb2-fead84bd35bb", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%,无返回结果", + "inputs": { + "process": { + "value": "10:process1", + "display": "0配置应用" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result", + "isEnable": false + } + } + }, + { + "id": "99fb4d22-e969-4233-9df8-244b165356dd", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:业务流程" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "f5703eff-78bc-44d8-9726-3da0c3723876", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:读取导入的文件数据:A列:账号 B列:密码 C列:店铺名称 D列:站点" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "0b7f3fd7-e404-4645-b40e-c7ef180e25f5", + "name": "excel.launch", + "isEnabled": true, + "inputs": { + "launch_way": { + "value": "10:open", + "display": "打开已有的Excel" + }, + "driver_way": { + "value": "10:auto_check", + "display": "自动检测" + }, + "open_filename": { + "value": "13:glv['config_path']" + }, + "save_filename": { + "value": "10:" + }, + "isvisible": { + "value": "13:True" + }, + "ignoreformula": { + "value": "13:False" + }, + "password": { + "value": null + }, + "write_password": { + "value": null + }, + "update_links": { + "value": "13:False" + } + }, + "outputs": { + "excel_instance": { + "name": "excel_instance", + "variableLabel": "打开的Excel对象", + "isEnable": true + } + } + }, + { + "id": "7404c49e-49d6-417d-aa20-f969d418d7c7", + "name": "excel.read_data_from_workbook", + "isEnabled": true, + "comment": "从Excel对象%workbook%中读取已使用的矩形区域内容,将数据保存到%excel_data%", + "inputs": { + "workbook": { + "value": "11:excel_instance", + "display": "excel_instance" + }, + "read_way": { + "value": "10:used_range", + "display": "已使用区域内容" + }, + "range": { + "value": null + }, + "cell_row_num": { + "value": null + }, + "cell_column_name": { + "value": null + }, + "area_begin_row_num": { + "value": null + }, + "area_begin_column_name": { + "value": null + }, + "area_end_row_num": { + "value": null + }, + "area_end_column_name": { + "value": null + }, + "row_row_num": { + "value": null + }, + "get_display_text": { + "value": "13:False" + }, + "has_header_row": { + "value": "13:False" + }, + "column_column_name": { + "value": null + }, + "sheet_name": { + "value": "10:" + }, + "using_text": { + "value": "13:False" + }, + "text_cols": { + "value": "10:" + }, + "clear_space": { + "value": "13:False" + } + }, + "outputs": { + "excel_data": { + "name": "excel_data", + "variableLabel": "Excel已使用区域内容", + "type": "list>", + "isEnable": true + } + } + }, + { + "id": "040ab193-5163-4929-bfd3-49b1e12c43bd", + "name": "programing.snippet", + "isEnabled": true, + "inputs": { + "snippet": { + "value": "10:glv['excel_data'] = excel_data" + } + }, + "outputs": {} + }, + { + "id": "9c1b7628-0fc4-413a-a656-0bc353e30b6c", + "name": "excel.close", + "isEnabled": true, + "inputs": { + "operation": { + "value": "10:close_specified", + "display": "关闭指定Excel文件" + }, + "excel_instance": { + "value": "11:excel_instance" + }, + "close_way": { + "value": "10:save", + "display": "保存" + }, + "filename": { + "value": null + }, + "overwrite_file": { + "value": "13:True" + }, + "close_process": { + "value": "10:office", + "display": "office" + }, + "task_kill": { + "value": "13:True" + } + }, + "outputs": {} + }, + { + "id": "ef3063ce-cbf3-420e-8f65-492b97501ce6", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:将店铺名称和站点进行数据格式化,转为dict" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "09bf777f-c43a-4d9a-b35d-e51fd92db501", + "name": "process.invoke_module", + "isEnabled": true, + "comment": "调用模块%module%中的%function%方法并传入参数%params:WyJhcmdz5YC85Li6JWFyZ3Ml77yMIl0=%将结果保存到%invoke_result%", + "inputs": { + "module": { + "value": "10:deal_with_data", + "display": "deal_with_data" + }, + "function": { + "value": "10:main" + }, + "params": { + "value": "16:[{\"args\":\"10:\"}]" + }, + "returnType": { + "value": "10:any" + } + }, + "outputs": { + "invoke_result": { + "name": "invoke_result", + "type": "any", + "isEnable": true + } + } + }, + { + "id": "09c0226c-01e2-4083-95c8-9f8443f01dee", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:info", + "display": "信息" + }, + "text": { + "value": "10:成功读取配置文件" + } + }, + "outputs": {} + }, + { + "id": "ef66c8f8-2d25-498c-b018-b0c29eaac85e", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:获取店铺名称和站点格式化后的数据" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "85b04538-6a57-4750-b561-439f447daf91", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置任意类型变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:any" + }, + "value": { + "value": "13:glv['shop_dict']" + } + }, + "outputs": { + "variable": { + "name": "shop_dict", + "variableLabel": "任意类型", + "type": "any", + "isEnable": true + } + } + }, + { + "id": "ae6f635a-b9d1-4ef0-9581-6fad00f36f43", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:循环外层元组组成的账号密码为键的字典" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "c31f7c1c-7865-40d6-ace2-378d293714aa", + "name": "workflow.loop_dict", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "dict": { + "value": "11:shop_dict" + } + }, + "outputs": { + "loop_key": { + "name": "企业信息元组", + "isEnable": true + }, + "loop_value": { + "name": "紫鸟店铺信息字典", + "isEnable": true + } + } + }, + { + "id": "5d53fe24-fba1-49f3-842d-e0f677752f94", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:获取账号密码" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "d4cf0c05-1b42-42ac-9a18-8e68f3443a6d", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:企业信息元组[0]" + } + }, + "outputs": { + "variable": { + "name": "company", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "345a6650-02fc-4c48-9ff5-74c2b1005994", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:企业信息元组[1]" + } + }, + "outputs": { + "variable": { + "name": "username", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "7f92dbfb-07cb-4210-b721-e3f24a0f2f0b", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:企业信息元组[2]" + } + }, + "outputs": { + "variable": { + "name": "password", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "d3cfee96-37e2-4aa3-8fd7-84cefddc0e2f", + "name": "programing.try", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": {} + }, + { + "id": "5e47d621-365f-417f-8e45-10f703b55125", + "name": "xbot_extensions.super_browser.A4 紫鸟登录", + "isEnabled": true, + "inputs": { + "紫鸟版本": { + "value": "10:V6", + "display": "V6" + }, + "企业名称": { + "value": "11:company" + }, + "企业用户名": { + "value": "11:username" + }, + "密码": { + "value": "11:password" + }, + "是否填写账号密码": { + "value": "13:True" + }, + "是否退出登录": { + "value": "13:True" + } + }, + "outputs": {}, + "block_title": "紫鸟控制台操作/紫鸟登录" + }, + { + "id": "f51d935e-8914-46d2-a359-fe4ee3c43c92", + "name": "programing.catch", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": { + "exception": { + "name": "exception", + "isEnable": true + } + } + }, + { + "id": "cf5ab997-8f81-494b-a257-d03d65f4ad55", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:error", + "display": "错误" + }, + "text": { + "value": "13:f'{username} 账号登录失败,失败原因:{exception}'" + } + }, + "outputs": {} + }, + { + "id": "9cab7db4-7c08-4c6b-ac05-f14f823ee357", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%并传入参数%inputs:WyLlupfpk7rkv6Hmga/lgLzkuLol5bqX6ZO65L+h5oGvJe+8jCIsIumUmeivr+aXpeW/l+WAvOS4uiXplJnor6/ml6Xlv5cl77yMIl0=%无返回结果", + "inputs": { + "process": { + "value": "10:process5", + "display": "D错误文件" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[{\"店铺信息\":\"13:f'{username} 紫鸟账号'\"},{\"错误日志\":\"11:exception\"}]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result5", + "isEnable": false + } + } + }, + { + "id": "2819e1d9-d0bc-4d48-87c2-8075280a011f", + "name": "workflow.continue", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "924599f5-e0ae-4a29-a268-d090eedcefe2", + "name": "programing.endtry", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "97742e6e-a42d-4c9f-873f-d634ba9a1e2a", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:循环内层店铺名称为键的字典" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "22ff4535-f365-49cb-bb00-28c54aa84496", + "name": "workflow.loop_dict", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "dict": { + "value": "11:紫鸟店铺信息字典" + } + }, + "outputs": { + "loop_key": { + "name": "紫鸟店铺", + "isEnable": true + }, + "loop_value": { + "name": "temu店铺", + "isEnable": true + } + } + }, + { + "id": "2a0407d2-39e4-48e0-92da-c7afa9222561", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置任意类型变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:any" + }, + "value": { + "value": "11:紫鸟店铺" + } + }, + "outputs": { + "variable": { + "name": "purple_shop_name", + "variableLabel": "任意类型", + "type": "any", + "isEnable": true + } + } + }, + { + "id": "890ca1b0-add2-48b8-9951-0cb08cc651b5", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:进行打开紫鸟店铺以及temu账号登录" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "64518066-e5b6-4602-87e9-c9d2a17f660d", + "name": "programing.try", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": {} + }, + { + "id": "39d8df76-df25-43f8-953f-a41e4776003e", + "name": "xbot_extensions.super_browser.A2 打开店铺", + "isEnabled": true, + "inputs": { + "店铺名称": { + "value": "11:紫鸟店铺" + }, + "匹配类型": { + "value": "10:相等", + "display": "相等" + }, + "打开账号": { + "value": "10:点击", + "display": "点击" + }, + "隐私模式": { + "value": "13:False" + }, + "超时时间": { + "value": "13:50" + } + }, + "outputs": { + "完整店铺名称": { + "name": "完整店铺名称", + "isEnable": true + }, + "web_page": { + "name": "web_page2", + "isEnable": true + } + }, + "block_title": "紫鸟控制台操作/打开店铺" + }, + { + "id": "d4816254-f981-4984-aa88-9c7b2db8ab5c", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:将网页最大化" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "51c4e882-53ba-4a94-9e2a-3caf9cb2c4dc", + "name": "win32.window.get_window", + "isEnabled": true, + "comment": "获取当前激活窗口,将窗口对象保存到%result_window_instance%", + "inputs": { + "window_type": { + "value": "10:active", + "display": "当前激活窗口" + }, + "selector": { + "value": null + }, + "handle": { + "value": "10:" + }, + "title": { + "value": "10:" + }, + "handle_checked": { + "value": "13:False" + }, + "class_name": { + "value": "10:" + }, + "use_wildcard": { + "value": "13:False" + } + }, + "outputs": { + "result_window_instance": { + "name": "software_window", + "isEnable": true + } + } + }, + { + "id": "8e948c81-8e05-4141-9b2b-c56dee367c31", + "name": "win32.window.set_state", + "isEnabled": true, + "inputs": { + "window_type": { + "value": "10:window_instance", + "display": "窗口对象" + }, + "window": { + "value": "11:software_window", + "display": "software_window" + }, + "selector": { + "value": null + }, + "handle": { + "value": "10:" + }, + "title": { + "value": "10:" + }, + "handle_checked": { + "value": "13:False" + }, + "class_name": { + "value": "10:" + }, + "use_wildcard": { + "value": "13:False" + }, + "flag": { + "value": "10:maximize", + "display": "最大化窗口" + } + }, + "outputs": {} + }, + { + "id": "e98b676d-2b2f-46b5-a29e-194dbe5b3e79", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%,无返回结果", + "inputs": { + "process": { + "value": "10:process2", + "display": "A账号登录" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result4", + "isEnable": false + } + } + }, + { + "id": "a377f277-8ed3-4d17-bfad-fb452fbd5825", + "name": "programing.catch", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": { + "exception": { + "name": "exception2", + "isEnable": true + } + } + }, + { + "id": "b46a5364-88e5-40d5-832c-3d4333ea9b48", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:error", + "display": "错误" + }, + "text": { + "value": "13:f'{username} 账号的 {purple_shop_name} 紫鸟店铺切换失败,失败原因:{exception2}'" + } + }, + "outputs": {} + }, + { + "id": "5bf893ae-822d-4a81-a2e7-8dcd74c73aa5", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%并传入参数%inputs:WyLlupfpk7rkv6Hmga/lgLzkuLol5bqX6ZO65L+h5oGvJe+8jCIsIumUmeivr+aXpeW/l+WAvOS4uiXplJnor6/ml6Xlv5cl77yMIl0=%无返回结果", + "inputs": { + "process": { + "value": "10:process5", + "display": "D错误文件" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[{\"店铺信息\":\"13:f'{username} 账号 {purple_shop_name} 紫鸟店铺'\"},{\"错误日志\":\"11:exception2\"}]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result6", + "isEnable": false + } + } + }, + { + "id": "1893516d-5b9a-4bf6-894d-d06f62fe6e7e", + "name": "workflow.continue", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "3b6c922b-576c-4de9-8c1a-365ff595eed1", + "name": "programing.endtry", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "b862a2e5-947d-4406-a548-a1b98ed6f41a", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:循环站点,进行操作" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "cfd449e7-fb4e-4042-9384-bb08d94ca32e", + "name": "workflow.loop_dict", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "dict": { + "value": "11:temu店铺" + } + }, + "outputs": { + "loop_key": { + "name": "temu店铺名称", + "isEnable": true + }, + "loop_value": { + "name": "站点列表", + "isEnable": true + } + } + }, + { + "id": "e1dac6ce-390d-467e-b7ca-e74a4b549fc4", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:获取temu店铺名称" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "b80bf350-726c-427b-bea2-fd7aaede9520", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置任意类型变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:any" + }, + "value": { + "value": "13:temu店铺名称[0]" + } + }, + "outputs": { + "variable": { + "name": "temu_shop_name", + "variableLabel": "任意类型", + "type": "any", + "isEnable": true + } + } + }, + { + "id": "a8ca1e4b-36fe-4ba9-9e77-f9214f765d6a", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:temu店铺名称[1]" + } + }, + "outputs": { + "variable": { + "name": "temu_shop_type", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "d4329bc1-4e83-499b-ac78-d70a4f41025e", + "name": "programing.try", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": {} + }, + { + "id": "d2e62b12-9499-4a01-a883-f237042294a3", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%并传入参数%inputs:WyLlupfpk7rlkI3np7DlgLzkuLol5bqX6ZO65ZCN56ewJe+8jCJd%无返回结果", + "inputs": { + "process": { + "value": "10:process3", + "display": "B切换店铺" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[{\"店铺名称\":\"11:temu_shop_name\"}]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result2", + "isEnable": false + } + } + }, + { + "id": "a6db9b17-8be6-42da-a39e-83d7345cedeb", + "name": "programing.catch", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": { + "exception": { + "name": "exception3", + "isEnable": true + } + } + }, + { + "id": "e3f015df-683d-4d74-a1cb-f5de379aed7f", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:error", + "display": "错误" + }, + "text": { + "value": "13:f' {purple_sho_name} 紫鸟店铺的 {temu_shop_name} temu店铺数据切换失败,失败原因:{exception3}'" + } + }, + "outputs": {} + }, + { + "id": "4e2221b0-1802-490e-b74e-987cc607afc5", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%并传入参数%inputs:WyLlupfpk7rkv6Hmga/lgLzkuLol5bqX6ZO65L+h5oGvJe+8jCIsIumUmeivr+aXpeW/l+WAvOS4uiXplJnor6/ml6Xlv5cl77yMIl0=%无返回结果", + "inputs": { + "process": { + "value": "10:process5", + "display": "D错误文件" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[{\"店铺信息\":\"13:f'{purple_sho_name} 紫鸟店铺的{temu_shop_name} temu店铺'\"},{\"错误日志\":\"11:exception3\"}]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result7", + "isEnable": false + } + } + }, + { + "id": "205ec243-1983-49ba-880c-98ade21eeb18", + "name": "workflow.continue", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "e41ef13a-692e-455e-b30d-35d318374abc", + "name": "programing.endtry", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "0d41d023-df67-4756-aaf2-d3394e77b8b0", + "name": "workflow.forin", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "list": { + "value": "11:站点列表" + }, + "loop_start_index": { + "value": "10:0" + }, + "loop_end_index": { + "value": "10:-1" + }, + "output_with_index": { + "value": "13:False" + } + }, + "outputs": { + "loop_item": { + "name": "站点", + "type": "any", + "isEnable": true + }, + "loop_index": { + "name": "loop_item_index", + "isEnable": false + } + } + }, + { + "id": "38f76393-6183-42cb-a701-24b2b998e94e", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置任意类型变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:any" + }, + "value": { + "value": "11:站点" + } + }, + "outputs": { + "variable": { + "name": "station", + "variableLabel": "任意类型", + "type": "any", + "isEnable": true + } + } + }, + { + "id": "4107cae8-f2cf-4e7b-b05a-bf1658666291", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:进行站点切换以及数据导出" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "51ac85fd-b189-409c-95f5-37dd9e7a3cd4", + "name": "programing.try", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": {} + }, + { + "id": "86eaedbf-7d15-4072-b626-995bd96eab35", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%并传入参数%inputs:WyLnq5nngrnlgLzkuLol56uZ54K5Je+8jCIsIuW6l+mTuueKtuaAgeWAvOS4uiXlupfpk7rnirbmgIEl77yMIiwidGVtdeW6l+mTuuWQjeensOWAvOS4uiV0ZW115bqX6ZO65ZCN56ewJe+8jCJd%无返回结果", + "inputs": { + "process": { + "value": "10:process4", + "display": "C切换站点数据导出" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[{\"站点\":\"11:station\"},{\"店铺状态\":\"11:temu_shop_type\"},{\"temu店铺名称\":\"11:temu_shop_name\"}]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result3", + "isEnable": false + } + } + }, + { + "id": "6a48cb2f-618b-4971-9cc2-ef2fcf2ab9fe", + "name": "programing.catch", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": { + "exception": { + "name": "exception4", + "isEnable": true + } + } + }, + { + "id": "ac8a0129-ee83-4294-bda5-e799892f820f", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:error", + "display": "错误" + }, + "text": { + "value": "13:f'{purple_shop_name} 紫鸟店铺的 {temu_shop_name} temu店铺 的 {station}站点 数据导出失败,失败原因:{exception4}'" + } + }, + "outputs": {} + }, + { + "id": "6ea12c7e-e278-460d-ae86-6c6374419735", + "name": "process.run", + "isEnabled": true, + "comment": "执行流程%process%并传入参数%inputs:WyLlupfpk7rkv6Hmga/lgLzkuLol5bqX6ZO65L+h5oGvJe+8jCIsIumUmeivr+aXpeW/l+WAvOS4uiXplJnor6/ml6Xlv5cl77yMIl0=%无返回结果", + "inputs": { + "process": { + "value": "10:process5", + "display": "D错误文件" + }, + "package": { + "value": "11:__name__" + }, + "inputs": { + "value": "16:[{\"店铺信息\":\"10:{purple_shop_name} 紫鸟店铺的 {temu_shop_name} temu店铺 的 {station}站点\"},{\"错误日志\":\"11:exception4\"}]" + }, + "outputs": { + "value": "10:[]" + } + }, + "outputs": { + "process_result": { + "name": "process_result8", + "isEnable": false + } + } + }, + { + "id": "929c89bb-fcc4-4b93-9741-01d985a5b177", + "name": "workflow.continue", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "d43c5698-cf30-4288-90ff-0f4b0cc46068", + "name": "programing.endtry", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "90580bb9-69f5-441e-9e19-4f5d3b83c41b", + "name": "workflow.endloop", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "73a0de0a-439c-4f01-81b8-f93e7c79d029", + "name": "workflow.endloop", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "39769698-72af-48ea-8941-53004253ba6a", + "name": "workflow.endloop", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "d4435245-0099-4965-bafe-398150201d44", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:一个账号运行完毕,关闭浏览器" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "ae777f90-037d-42da-b484-4dbe32f0e6cb", + "name": "workflow.endloop", + "isEnabled": true, + "inputs": {}, + "outputs": {} + } + ], + "parameters": [] + }, + { + "name": "0配置应用", + "memo": "process1", + "kind": "visual", + "blocks": [ + { + "id": "6fccbaa3-0ebd-451d-a0b3-441a034bcea1", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:自定义对话框,配置文件" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "b05b2640-3a81-4695-a29e-c867230611d8", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "10:Temu-活动数据导出" + } + }, + "outputs": { + "variable": { + "name": "dialog_title", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "cae316ae-c333-4a2e-a28f-23868a286418", + "name": "dialog.show_custom_dialog", + "isEnabled": true, + "inputs": { + "settings": { + "value": "10:{\"dialogTitle\":{\"VAR\":\"dialog_title\"},\"height\":0,\"width\":0,\"timeout\":0,\"autoCloseButton\":null,\"use_wait_timeout\":false,\"canRememberContent\":true,\"settings\":{\"editors\":[{\"type\":\"File\",\"label\":\"配置文件\",\"VariableName\":\"shop_info_file\",\"kind\":0,\"filter\":\"所有文件|*.*\",\"value\":null,\"nullText\":\"请传入店铺信息文件\",\"uuid\":\"8cd377d3-4546-413e-bb2f-5ebd0a8dfc6b\"},{\"type\":\"File\",\"label\":\"文件夹路径\",\"VariableName\":\"save_dir\",\"kind\":2,\"filter\":\"所有文件|*.*\",\"value\":null,\"nullText\":\"导出的数据保存的文件夹位置\",\"uuid\":\"5915768d-a0e6-46b1-b16a-1d26b1aaeef1\"},{\"type\":\"Date\",\"label\":\"开始时间\",\"VariableName\":\"start_time\",\"value\":\"2025-09-17T19:54:25.5890395+08:00\",\"nullText\":null,\"dateFormat\":\"yyyy/MM/dd\",\"uuid\":\"e668d3dc-ae6c-48f0-bce6-1fe4c767b15d\"},{\"type\":\"Date\",\"label\":\"结束时间\",\"VariableName\":\"end_time\",\"value\":\"2025-09-17T19:54:38.6452829+08:00\",\"nullText\":null,\"dateFormat\":\"yyyy/MM/dd\",\"uuid\":\"ce203dfe-10f5-4a92-b463-296b7d83f885\"}],\"buttons\":[{\"type\":\"Button\",\"label\":\"确定\",\"theme\":\"white\",\"hotKey\":\"Return\",\"uuid\":\"d0da9a5e-76e0-4aad-b11a-c648353dd56b\"},{\"type\":\"Button\",\"label\":\"取消\",\"theme\":\"white\",\"hotKey\":\"Escape\",\"uuid\":\"bf1d4072-927b-4be8-a660-d3007f31fcc3\"}]}}" + }, + "dialog_title": { + "value": "11:dialog_title" + }, + "default_btn": { + "value": "10:确定", + "display": "确定" + }, + "is_auto_click": { + "value": "13:False" + }, + "timeout": { + "value": null + }, + "globals": { + "value": "13:globals()" + }, + "locals": { + "value": "13:locals()" + }, + "storage_key": { + "value": "13:`block_id`" + } + }, + "outputs": { + "dialog_result": { + "name": "dialog_result", + "isEnable": true + } + } + }, + { + "id": "abaddb33-0a09-42df-b218-d5263b6f3c6f", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:点击取消,则退出应用" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "ec4b1cd6-694c-477c-9380-f4ed50a1e4b4", + "name": "workflow.if", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "operand1": { + "value": "11:dialog_result.pressed_button" + }, + "operator": { + "value": "10:==", + "display": "等于" + }, + "operand2": { + "value": "10:取消" + }, + "operator_options": { + "value": "10:{}" + } + }, + "outputs": {} + }, + { + "id": "a27caba4-6b0f-47e9-bb59-b8fb2fc5b6a8", + "name": "process.exit", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "10ddf611-1dda-40a5-824e-6d432fc96bdc", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "f31595c7-9a08-4cd6-b217-28b429c16cc0", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:将选择的配置文件放到全局变量\r\nglv['config_path'] 全局店铺信息文件\r\nglv['config_save_dir'] 活动数据保存的文件夹" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "34614599-d822-4571-b17a-a8963e37407b", + "name": "programing.snippet", + "isEnabled": true, + "inputs": { + "snippet": { + "value": "10:glv['config_path'] = dialog_result.shop_info_file" + } + }, + "outputs": {} + }, + { + "id": "0477c739-a5f6-4b17-bce6-a85df4fd44e6", + "name": "programing.snippet", + "isEnabled": true, + "inputs": { + "snippet": { + "value": "10:glv['config_save_dir'] = dialog_result.save_dir" + } + }, + "outputs": {} + }, + { + "id": "409e2619-acd2-454f-b530-f65b128bc7e4", + "name": "programing.snippet", + "isEnabled": true, + "inputs": { + "snippet": { + "value": "10:glv['config_start_time'] = dialog_result.start_time" + } + }, + "outputs": {} + }, + { + "id": "415b81c0-7d3d-4104-993f-94de952116d4", + "name": "programing.snippet", + "isEnabled": true, + "inputs": { + "snippet": { + "value": "10:glv['config_end_time'] = dialog_result.end_time" + } + }, + "outputs": {} + }, + { + "id": "906a2a92-0647-4287-8152-7cdb67ea22a2", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:错误文件" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "d2bc4e45-a23b-4009-9f53-5255e5a31869", + "name": "datetime.now", + "isEnabled": true, + "inputs": {}, + "outputs": { + "datetime_instance": { + "name": "current_datetime", + "isEnable": true + } + } + }, + { + "id": "c5e0dc7d-e765-47c2-ac3f-d4a6669b4fe3", + "name": "datetime.to_string", + "isEnabled": true, + "inputs": { + "datetime": { + "value": "11:current_datetime" + }, + "format": { + "value": "10:%Y-%m-%d" + } + }, + "outputs": { + "text": { + "name": "current_day", + "isEnable": true + } + } + }, + { + "id": "b67e0a98-3bb2-4bec-9464-c9498dbf7b3f", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:f'错误文件-{current_day}'" + } + }, + "outputs": { + "variable": { + "name": "file_name", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "64eaca12-3dc4-4303-afec-3a53c330bcc4", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:f'{glv[\"config_save_dir\"]}' + '\\\\' + f'{file_name}.xlsx'" + } + }, + "outputs": { + "variable": { + "name": "file_path", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "510ed54b-f505-4017-804d-dabdfa456d57", + "name": "programing.snippet", + "isEnabled": true, + "inputs": { + "snippet": { + "value": "10:glv['config_error_path'] = file_path" + } + }, + "outputs": {} + }, + { + "id": "eff85b9b-a573-46c2-9954-f4f2e198e417", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:判断店铺数据文件是否存在,若不存在则终止应用" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "d615db4f-4710-41f5-93ce-0118e1cd3610", + "name": "file.if_exist", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "path": { + "value": "13:glv['config_path']" + }, + "expect_exist": { + "value": "10:no_exist", + "display": "不存在" + } + }, + "outputs": {} + }, + { + "id": "e3cd90a2-da13-4c53-bdc3-9eda16bcd7e0", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:error", + "display": "错误" + }, + "text": { + "value": "10:店铺信息文件不存在" + } + }, + "outputs": {} + }, + { + "id": "8c416b5b-f208-4d7d-bbeb-b235159b9a79", + "name": "process.exit", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "800acec7-e8e7-412b-b895-f278ebcba7ca", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "2079320f-a813-4e0b-978a-9f954e7bb9cf", + "name": "dir.if_exist", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "path": { + "value": "13:glv['config_save_dir']" + }, + "expect_exist": { + "value": "10:no_exist", + "display": "不存在" + } + }, + "outputs": {} + }, + { + "id": "b6a48fa8-e0cf-4a4b-8299-9fe38e3e6ec9", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:error", + "display": "错误" + }, + "text": { + "value": "10:数据导出的文件夹不存在" + } + }, + "outputs": {} + }, + { + "id": "02de4f5d-ae2b-463c-bcc4-60b03a79148a", + "name": "process.exit", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "2febe4b9-11bf-4e49-aaf2-f79df3fbbc77", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "5017c5a3-eec2-478a-ac84-f9d6ac3e0894", + "name": "file.if_exist", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "path": { + "value": "11:file_path" + }, + "expect_exist": { + "value": "10:no_exist", + "display": "不存在" + } + }, + "outputs": {} + }, + { + "id": "143ecd57-a842-407d-a2e7-c98e3711812a", + "name": "excel.launch", + "isEnabled": true, + "comment": "%launch_way% %save_filename%,将Excel对象保存到%excel_instance%", + "inputs": { + "launch_way": { + "value": "10:create", + "display": "新建Excel" + }, + "driver_way": { + "value": "10:auto_check", + "display": "自动检测" + }, + "open_filename": { + "value": "10:" + }, + "save_filename": { + "value": "11:file_path" + }, + "isvisible": { + "value": "13:True" + }, + "ignoreformula": { + "value": "13:False" + }, + "password": { + "value": "10:" + }, + "write_password": { + "value": "10:" + }, + "update_links": { + "value": "13:False" + } + }, + "outputs": { + "excel_instance": { + "name": "excel_instance", + "variableLabel": "新建的Excel对象", + "isEnable": true + } + } + }, + { + "id": "21afd482-a16b-40db-8320-bcd89c26c3d9", + "name": "excel.write_data_to_workbook", + "isEnabled": true, + "comment": "在Excel对象%workbook%中第%row_num%%write_way%,从第%begin_column_name%列开始写入内容%content%", + "inputs": { + "workbook": { + "value": "11:excel_instance", + "display": "excel_instance" + }, + "write_range": { + "value": "10:row", + "display": "行" + }, + "write_way": { + "value": "10:override", + "display": "覆盖一行" + }, + "write_column_way": { + "value": "10:override", + "display": "覆盖一列" + }, + "row_num": { + "value": "10:1" + }, + "column_name": { + "value": "10:" + }, + "begin_row_num": { + "value": "10:0" + }, + "begin_column_name": { + "value": "10:A" + }, + "content": { + "value": "13:['时间','店铺信息', '错误原因']" + }, + "sheet_name": { + "value": "10:" + }, + "write_as_text_cols": { + "value": null + } + }, + "outputs": {} + }, + { + "id": "3b5519d1-7a82-453a-bf63-090a95060077", + "name": "excel.close", + "isEnabled": true, + "inputs": { + "operation": { + "value": "10:close_specified", + "display": "关闭指定Excel文件" + }, + "excel_instance": { + "value": "11:excel_instance" + }, + "close_way": { + "value": "10:save", + "display": "保存" + }, + "filename": { + "value": null + }, + "overwrite_file": { + "value": "13:True" + }, + "close_process": { + "value": "10:office", + "display": "office" + }, + "task_kill": { + "value": "13:True" + } + }, + "outputs": {} + }, + { + "id": "bb23b5ba-b3e3-4b96-9491-72380939f9d3", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "be2fffd5-12df-4162-9b10-a7d0efccb052", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:info", + "display": "信息" + }, + "text": { + "value": "10:文件配置成功" + } + }, + "outputs": {} + } + ], + "parameters": [] + }, + { + "name": "A账号登录", + "memo": "process2", + "kind": "visual", + "blocks": [ + { + "id": "87b21e81-eb76-4163-b20d-6ff6a93a180a", + "name": "web.get", + "isEnabled": true, + "comment": "在%web_type%中匹配当前选中的网页,将网页对象保存到%browser%,网页加载超时后重试此指令", + "inputs": { + "web_type": { + "value": "10:ziniaobrowser", + "display": "ziniaobrowser" + }, + "mode": { + "value": "10:activated", + "display": "匹配当前选中的网页" + }, + "value": { + "value": "10:" + }, + "use_wildcard": { + "value": "13:False" + }, + "silent_running": { + "value": "13:False" + }, + "wait_load_completed": { + "value": "13:True" + }, + "load_timeout": { + "value": "10:20" + }, + "stop_load_if_load_timeout": { + "value": "10:handleExcept", + "display": "执行\"错误处理\"" + }, + "open_page": { + "value": "13:False" + }, + "url": { + "value": null + } + }, + "outputs": { + "browser": { + "name": "web_page", + "isEnable": true + } + }, + "exception_handling": { + "logging": true, + "mode": "retry", + "retryTime": 3, + "retryInterval": 3 + } + }, + { + "id": "0b2c905a-80ac-4b23-bdcd-7f5b63b45d3b", + "name": "web.browser.get_details", + "isEnabled": true, + "inputs": { + "browser": { + "value": "11:web_page", + "display": "web_page" + }, + "operation": { + "value": "10:url", + "display": "获取网址" + } + }, + "outputs": { + "webpage_attribute": { + "name": "web_page_attribute", + "variableLabel": "网页地址", + "isEnable": true + } + } + }, + { + "id": "4b31a9ff-e5bf-4bbf-ae19-beb55ced5ec0", + "name": "workflow.if", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "operand1": { + "value": "11:web_page_attribute" + }, + "operator": { + "value": "10:in", + "display": "包含" + }, + "operand2": { + "value": "13:'login'" + }, + "operator_options": { + "value": "10:{\"ignoreCase\":\"False\"}" + } + }, + "outputs": {} + }, + { + "id": "c73f265d-e6a5-4c3b-a01f-aa5a618242f2", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:点击同意复选框" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "7c7b5841-6dfe-4cf4-a9d6-519ff6d740ff", + "name": "web.element.click", + "isEnabled": true, + "inputs": { + "browser": { + "value": "11:web_page", + "display": "web_page" + }, + "element": { + "value": "12:登录页面_同意按钮", + "display": "登录页面_同意按钮" + }, + "simulate": { + "value": "13:True" + }, + "move_mouse": { + "value": "13:False" + }, + "clicks": { + "value": "10:click", + "display": "单击" + }, + "button": { + "value": "10:left", + "display": "鼠标左键" + }, + "keys": { + "value": "10:null", + "display": "无" + }, + "delay_after": { + "value": "10:1" + }, + "anchor_type": { + "value": "10:center", + "display": "中心点" + }, + "sudoku_part": { + "value": "10:MiddleCenter" + }, + "offset_x": { + "value": "10:0" + }, + "offset_y": { + "value": "10:0" + }, + "timeout": { + "value": "10:20" + } + }, + "outputs": {} + }, + { + "id": "e72918a2-583d-4c29-9370-4f549f19ce1c", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:点击登录" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "b9eaea24-017d-43e9-8960-d61e3fcb1851", + "name": "web.element.click", + "isEnabled": true, + "inputs": { + "browser": { + "value": "11:web_page", + "display": "web_page" + }, + "element": { + "value": "12:登录_按钮", + "display": "登录_按钮" + }, + "simulate": { + "value": "13:True" + }, + "move_mouse": { + "value": "13:False" + }, + "clicks": { + "value": "10:click", + "display": "单击" + }, + "button": { + "value": "10:left", + "display": "鼠标左键" + }, + "keys": { + "value": "10:null", + "display": "无" + }, + "delay_after": { + "value": "10:1" + }, + "anchor_type": { + "value": "10:center", + "display": "中心点" + }, + "sudoku_part": { + "value": "10:MiddleCenter" + }, + "offset_x": { + "value": "10:0" + }, + "offset_y": { + "value": "10:0" + }, + "timeout": { + "value": "10:20" + } + }, + "outputs": {} + }, + { + "id": "5d82120a-2938-4bc1-82d0-bd95dddc3dff", + "name": "web.browser.element_display", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "browser": { + "value": "11:web_page", + "display": "web_page" + }, + "content_type": { + "value": "10:display", + "display": "可见" + }, + "selector": { + "value": "12:授权_勾选框", + "display": "授权_勾选框" + } + }, + "outputs": {} + }, + { + "id": "2b93a1c0-4e01-4e3f-abd1-27b7fb9d9c7e", + "name": "web.element.click", + "isEnabled": true, + "inputs": { + "browser": { + "value": "11:web_page", + "display": "web_page" + }, + "element": { + "value": "12:授权_勾选框", + "display": "授权_勾选框" + }, + "simulate": { + "value": "13:True" + }, + "move_mouse": { + "value": "13:False" + }, + "clicks": { + "value": "10:click", + "display": "单击" + }, + "button": { + "value": "10:left", + "display": "鼠标左键" + }, + "keys": { + "value": "10:null", + "display": "无" + }, + "delay_after": { + "value": "10:1" + }, + "anchor_type": { + "value": "10:center", + "display": "中心点" + }, + "sudoku_part": { + "value": "10:MiddleCenter" + }, + "offset_x": { + "value": "10:0" + }, + "offset_y": { + "value": "10:0" + }, + "timeout": { + "value": "10:20" + } + }, + "outputs": {} + }, + { + "id": "6d869ab1-03b8-48a3-a5e7-9f6332a895a8", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + }, + { + "id": "e30ae832-a456-4b66-bb5b-fd75aababe5d", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:进行站点登录" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "5e482386-31eb-4e07-8c7a-3a01cd762206", + "name": "web.element.click", + "isEnabled": true, + "inputs": { + "browser": { + "value": "11:web_page", + "display": "web_page" + }, + "element": { + "value": "12:跨境Temu商家中心", + "display": "跨境Temu商家中心" + }, + "simulate": { + "value": "13:True" + }, + "move_mouse": { + "value": "13:False" + }, + "clicks": { + "value": "10:click", + "display": "单击" + }, + "button": { + "value": "10:left", + "display": "鼠标左键" + }, + "keys": { + "value": "10:null", + "display": "无" + }, + "delay_after": { + "value": "10:1" + }, + "anchor_type": { + "value": "10:center", + "display": "中心点" + }, + "sudoku_part": { + "value": "10:MiddleCenter" + }, + "offset_x": { + "value": "10:0" + }, + "offset_y": { + "value": "10:0" + }, + "timeout": { + "value": "10:20" + } + }, + "outputs": {} + }, + { + "id": "a2ecb0a4-ed16-4ee5-b012-efb7890c2552", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + } + ], + "parameters": [] + }, + { + "name": "B切换店铺", + "memo": "process3", + "kind": "visual", + "blocks": [ + { + "id": "88f7a385-595e-4354-be7b-bdfbdfeeca79", + "name": "web.get", + "isEnabled": true, + "comment": "在%web_type%中匹配当前选中的网页,将网页对象保存到%browser%,网页加载超时后重试此指令", + "inputs": { + "web_type": { + "value": "10:ziniaobrowser", + "display": "ziniaobrowser" + }, + "mode": { + "value": "10:activated", + "display": "匹配当前选中的网页" + }, + "value": { + "value": "10:" + }, + "use_wildcard": { + "value": "13:False" + }, + "silent_running": { + "value": "13:False" + }, + "wait_load_completed": { + "value": "13:True" + }, + "load_timeout": { + "value": "10:20" + }, + "stop_load_if_load_timeout": { + "value": "10:handleExcept", + "display": "执行\"错误处理\"" + }, + "open_page": { + "value": "13:False" + }, + "url": { + "value": null + } + }, + "outputs": { + "browser": { + "name": "web_page", + "isEnable": true + } + }, + "exception_handling": { + "logging": true, + "mode": "retry", + "retryTime": 3, + "retryInterval": 3 + } + }, + { + "id": "7af8ecc4-f6bf-4d94-b14b-cab6a59c8cf9", + "name": "xbot_extensions.activity_temu_shop.switch_store", + "isEnabled": true, + "inputs": { + "web_page": { + "value": "11:web_page", + "display": "web_page" + }, + "store_name": { + "value": "11:店铺名称" + } + }, + "outputs": {}, + "block_title": "temu 商家后台扩展/Temu-切换店铺" + } + ], + "parameters": [ + { + "name": "店铺名称", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + } + ] + }, + { + "name": "C切换站点数据导出", + "memo": "process4", + "kind": "visual", + "blocks": [ + { + "id": "69630f85-cdcb-4d2d-89e4-9d67d3530e1f", + "name": "web.get", + "isEnabled": true, + "comment": "在%web_type%中匹配当前选中的网页,将网页对象保存到%browser%,网页加载超时后重试此指令", + "inputs": { + "web_type": { + "value": "10:ziniaobrowser", + "display": "ziniaobrowser" + }, + "mode": { + "value": "10:activated", + "display": "匹配当前选中的网页" + }, + "value": { + "value": "10:" + }, + "use_wildcard": { + "value": "13:False" + }, + "silent_running": { + "value": "13:False" + }, + "wait_load_completed": { + "value": "13:True" + }, + "load_timeout": { + "value": "10:20" + }, + "stop_load_if_load_timeout": { + "value": "10:handleExcept", + "display": "执行\"错误处理\"" + }, + "open_page": { + "value": "13:False" + }, + "url": { + "value": null + } + }, + "outputs": { + "browser": { + "name": "web_page", + "isEnable": true + } + }, + "exception_handling": { + "logging": true, + "mode": "retry", + "retryTime": 3, + "retryInterval": 3 + } + }, + { + "id": "8ef6359f-944f-4a87-962f-47f0bce2b5ea", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:获取全局变量" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "94b36c07-24ab-4e16-8851-d884212550fb", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:glv['config_start_time']" + } + }, + "outputs": { + "variable": { + "name": "start_time", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "b809a1f6-63c8-4d5f-a33f-dea0bb94151a", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:glv['config_end_time']" + } + }, + "outputs": { + "variable": { + "name": "end_time", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "4f3b811b-b291-4910-8328-a8379081b2f8", + "name": "datetime.to_string", + "isEnabled": true, + "inputs": { + "datetime": { + "value": "11:start_time" + }, + "format": { + "value": "10:%Y-%m-%d" + } + }, + "outputs": { + "text": { + "name": "start_time", + "isEnable": true + } + } + }, + { + "id": "d486f1aa-85b1-40f5-b3f5-a1c9c23fcf72", + "name": "datetime.to_string", + "isEnabled": true, + "inputs": { + "datetime": { + "value": "11:end_time" + }, + "format": { + "value": "10:%Y-%m-%d" + } + }, + "outputs": { + "text": { + "name": "end_time", + "isEnable": true + } + } + }, + { + "id": "111de464-fa98-42be-a0ef-39e26480efc6", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:f'{start_time}~{end_time}'" + } + }, + "outputs": { + "variable": { + "name": "time", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "4b2d47ef-3d48-44f4-b67a-906f29c71f41", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:glv['config_save_dir']" + } + }, + "outputs": { + "variable": { + "name": "save_dir", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "2603acaf-c619-4cef-aa82-9bd361283369", + "name": "datetime.now", + "isEnabled": true, + "inputs": {}, + "outputs": { + "datetime_instance": { + "name": "current_datetime", + "isEnable": true + } + } + }, + { + "id": "265813c0-e32e-42e9-a9d6-a98b4e0bcb1e", + "name": "datetime.to_string", + "isEnabled": true, + "inputs": { + "datetime": { + "value": "11:current_datetime" + }, + "format": { + "value": "10:%Y-%m-%d" + } + }, + "outputs": { + "text": { + "name": "current_day", + "isEnable": true + } + } + }, + { + "id": "58b08baf-0d73-40d2-bedf-fa3b47ddfe18", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:f'{temu店铺名称}-{站点}-{current_day}.xlsx'" + } + }, + "outputs": { + "variable": { + "name": "file_name", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "78f2790c-461d-4bb2-92c5-919c7b51d530", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:进行站点切换" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "b8b327b3-f2f7-47ea-b94d-68fe2ba53731", + "name": "xbot_extensions.activity_temu_shop.switch_area", + "isEnabled": true, + "inputs": { + "web_page": { + "value": "11:web_page", + "display": "web_page" + }, + "area": { + "value": "11:站点" + } + }, + "outputs": {}, + "block_title": "temu 商家后台扩展/Temu-卖家中心-切换区域" + }, + { + "id": "08f61eb4-426c-42e3-8d4f-958aa2b3ff61", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:判断店铺是全托还是半托" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "bd295035-fddb-4d6d-bb59-c85789592b40", + "name": "programing.log", + "isEnabled": true, + "inputs": { + "type": { + "value": "10:info", + "display": "信息" + }, + "text": { + "value": "11:店铺状态" + } + }, + "outputs": {} + }, + { + "id": "0bc10f44-bd3f-4eb4-bf4e-df741d806779", + "name": "workflow.if", + "isEnabled": true, + "foldState": "UnFold", + "inputs": { + "operand1": { + "value": "11:店铺状态" + }, + "operator": { + "value": "10:in", + "display": "包含" + }, + "operand2": { + "value": "13:'全托'" + }, + "operator_options": { + "value": "10:{\"ignoreCase\":\"False\"}" + } + }, + "outputs": {} + }, + { + "id": "98c60045-f892-45ed-b379-16033a65171c", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:进行全托店铺的数据导出" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "a57f1f6e-4398-42b7-bcb3-d7dc2f9f0ca1", + "name": "web.get", + "isEnabled": true, + "comment": "在%web_type%中匹配当前选中的网页,将网页对象保存到%browser%,网页加载超时后重试此指令", + "inputs": { + "web_type": { + "value": "10:ziniaobrowser", + "display": "ziniaobrowser" + }, + "mode": { + "value": "10:activated", + "display": "匹配当前选中的网页" + }, + "value": { + "value": "10:" + }, + "use_wildcard": { + "value": "13:False" + }, + "silent_running": { + "value": "13:False" + }, + "wait_load_completed": { + "value": "13:True" + }, + "load_timeout": { + "value": "10:20" + }, + "stop_load_if_load_timeout": { + "value": "10:handleExcept", + "display": "执行\"错误处理\"" + }, + "open_page": { + "value": "13:False" + }, + "url": { + "value": null + } + }, + "outputs": { + "browser": { + "name": "web_page", + "isEnable": true + } + }, + "exception_handling": { + "logging": true, + "mode": "retry", + "retryTime": 3, + "retryInterval": 3 + } + }, + { + "id": "d0217630-9805-4aff-9800-4fb726483bd2", + "name": "xbot_extensions.activity_temu_shop.active_data_export", + "isEnabled": true, + "inputs": { + "web_page": { + "value": "11:web_page", + "display": "web_page" + }, + "time_range": { + "value": "11:time" + }, + "file_folder": { + "value": "11:save_dir" + }, + "file_name": { + "value": "11:file_name" + } + }, + "outputs": { + "file_path": { + "name": "file_path", + "isEnable": true + } + }, + "block_title": "temu 商家后台扩展/Temu-数据中心-活动数据导出(全托)" + }, + { + "id": "89442ceb-36ce-4e27-982c-81d3fbadc6cd", + "name": "workflow.else", + "isEnabled": true, + "foldState": "UnFold", + "inputs": {}, + "outputs": {} + }, + { + "id": "709c7983-926b-462e-9af1-1103394f7b9a", + "name": "programing.comment", + "isEnabled": true, + "inputs": { + "content": { + "value": "10:进行半托店铺数据导出" + } + }, + "outputs": {}, + "isCommentBlockExpanded": true + }, + { + "id": "c4486439-0a74-4bdf-b11c-93f72f64a164", + "name": "web.get", + "isEnabled": true, + "comment": "在%web_type%中匹配当前选中的网页,将网页对象保存到%browser%,网页加载超时后重试此指令", + "inputs": { + "web_type": { + "value": "10:ziniaobrowser", + "display": "ziniaobrowser" + }, + "mode": { + "value": "10:activated", + "display": "匹配当前选中的网页" + }, + "value": { + "value": "10:" + }, + "use_wildcard": { + "value": "13:False" + }, + "silent_running": { + "value": "13:False" + }, + "wait_load_completed": { + "value": "13:True" + }, + "load_timeout": { + "value": "10:20" + }, + "stop_load_if_load_timeout": { + "value": "10:handleExcept", + "display": "执行\"错误处理\"" + }, + "open_page": { + "value": "13:False" + }, + "url": { + "value": null + } + }, + "outputs": { + "browser": { + "name": "web_page", + "isEnable": true + } + }, + "exception_handling": { + "logging": true, + "mode": "retry", + "retryTime": 3, + "retryInterval": 3 + } + }, + { + "id": "78520fcf-8c41-407c-936d-4b98c017489a", + "name": "xbot_extensions.activity_temu_shop.active_data_export_half", + "isEnabled": true, + "inputs": { + "web_page": { + "value": "11:web_page", + "display": "web_page" + }, + "time_range": { + "value": "11:time" + }, + "file_folder": { + "value": "11:save_dir" + }, + "file_name": { + "value": "11:file_name" + } + }, + "outputs": { + "file_path": { + "name": "file_path2", + "isEnable": true + } + }, + "block_title": "temu 商家后台扩展/Temu-数据中心-活动数据导出(半托)" + }, + { + "id": "e407a9e8-21c9-4432-9e0b-4b80754c40a8", + "name": "workflow.endif", + "isEnabled": true, + "inputs": {}, + "outputs": {} + } + ], + "parameters": [ + { + "name": "站点", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + }, + { + "name": "店铺状态", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + }, + { + "name": "temu店铺名称", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + } + ] + }, + { + "name": "D错误文件", + "memo": "process5", + "kind": "visual", + "blocks": [ + { + "id": "d520efe6-61a8-4fa0-b293-35ab6f8baee2", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "13:glv['config_error_path']" + } + }, + "outputs": { + "variable": { + "name": "error_path", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "6e883b1e-7be2-4a84-b21d-9d4a3cd275ff", + "name": "datetime.now", + "isEnabled": true, + "inputs": {}, + "outputs": { + "datetime_instance": { + "name": "current_datetime", + "isEnable": true + } + } + }, + { + "id": "ae93432d-21a9-4ebe-8ce6-a9d15bcc1363", + "name": "datetime.to_string", + "isEnabled": true, + "inputs": { + "datetime": { + "value": "11:current_datetime" + }, + "format": { + "value": "10:%Y年%m月%d日 %H:%M:%S" + } + }, + "outputs": { + "text": { + "name": "current_time", + "isEnable": true + } + } + }, + { + "id": "8b861421-99f9-4a0d-a5ab-b9f2c7dcdd68", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "11:店铺信息" + } + }, + "outputs": { + "variable": { + "name": "shop_info", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "16938ecf-e052-4ed2-a160-75d8515cd00b", + "name": "programing.variable", + "isEnabled": true, + "comment": "设置字符串变量%variable%=%value%", + "inputs": { + "value_type": { + "value": "10:str" + }, + "value": { + "value": "11:错误日志" + } + }, + "outputs": { + "variable": { + "name": "error_info", + "variableLabel": "字符串", + "type": "str", + "isEnable": true + } + } + }, + { + "id": "86808c30-38d1-49f7-b017-7af12b7f18ec", + "name": "excel.launch", + "isEnabled": true, + "inputs": { + "launch_way": { + "value": "10:open", + "display": "打开已有的Excel" + }, + "driver_way": { + "value": "10:auto_check", + "display": "自动检测" + }, + "open_filename": { + "value": "11:error_path" + }, + "save_filename": { + "value": "10:" + }, + "isvisible": { + "value": "13:True" + }, + "ignoreformula": { + "value": "13:False" + }, + "password": { + "value": null + }, + "write_password": { + "value": null + }, + "update_links": { + "value": "13:False" + } + }, + "outputs": { + "excel_instance": { + "name": "excel_instance", + "variableLabel": "打开的Excel对象", + "isEnable": true + } + } + }, + { + "id": "487c2cda-a5aa-46a0-8e6e-fc7d3a94ce53", + "name": "excel.write_data_to_workbook", + "isEnabled": true, + "comment": "在Excel对象%workbook%中%write_way%,从第%begin_column_name%列开始写入内容%content%", + "inputs": { + "workbook": { + "value": "11:excel_instance", + "display": "excel_instance" + }, + "write_range": { + "value": "10:row", + "display": "行" + }, + "write_way": { + "value": "10:append", + "display": "追加一行" + }, + "write_column_way": { + "value": "10:override", + "display": "覆盖一列" + }, + "row_num": { + "value": "10:0" + }, + "column_name": { + "value": "10:" + }, + "begin_row_num": { + "value": "10:0" + }, + "begin_column_name": { + "value": "10:A" + }, + "content": { + "value": "13:[f'{current_time}',f'{shop_info}',f'{error_info}']" + }, + "sheet_name": { + "value": "10:" + }, + "write_as_text_cols": { + "value": null + } + }, + "outputs": {} + }, + { + "id": "c2dbbec9-2f37-4e05-b469-3ce7fefc9c6c", + "name": "excel.close", + "isEnabled": true, + "inputs": { + "operation": { + "value": "10:close_specified", + "display": "关闭指定Excel文件" + }, + "excel_instance": { + "value": "11:excel_instance" + }, + "close_way": { + "value": "10:save", + "display": "保存" + }, + "filename": { + "value": null + }, + "overwrite_file": { + "value": "13:True" + }, + "close_process": { + "value": "10:office", + "display": "office" + }, + "task_kill": { + "value": "13:True" + } + }, + "outputs": {} + } + ], + "parameters": [ + { + "name": "店铺信息", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + }, + { + "name": "错误日志", + "direction": "In", + "type": "str", + "value": "", + "description": "", + "kind": "Text" + } + ] + } + ] +} \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e69de29 diff --git a/src/Converter/__pycache__/utils.cpython-310.pyc b/src/Converter/__pycache__/utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de8312b30c92e1cd2e5563fd2e965030920654a8 GIT binary patch literal 1019 zcmZWn%}yIJ5cYVz`Gph(sum$tfGUwi4K2r3{S~N(9=LD|8?BPqz^Y-FdYu%aaDqMs zs+1i227QEH`U38;r`&tWrJdOg5^cTmcs|cJp7rO6=jTfd$FJ`{j=l=UeiFDnaF4yl zne3vGOhT76vK1PTV&34AOXrF;94VBLt`dhr=4Ad#G+bFg#AQ*I5alH7Gp{_slh|Gd zXqgT29h^Hj(@H}&!dhd{3+Ta(M|D2&Wwy`KxWM>o8lQQ$<5*r*)+KMA@7b3jvYT}Eijr|0H4j)G1smCb2odOG?~0T-F6 z0`Jg~Fl2qux#7)i`52`0Ug*09MqHxKLpF9USd^b(WD-tMUKTP$*jJ8e~87oY9qHLaQ5GDAc ztw_cvB(st>PY78a*Nd3gD5bP8Lgv3ZRE|^>WXS>Ea1H4RHPI4O;34P-XB$p%h5~AfpHnSXtA79suJI@U literal 0 HcmV?d00001 diff --git a/src/Converter/utils.py b/src/Converter/utils.py new file mode 100644 index 0000000..a4578d0 --- /dev/null +++ b/src/Converter/utils.py @@ -0,0 +1,36 @@ +import random +import re +import time + + +def clear_quote(s): + if s.startswith("'") and s.endswith("'"): + return s[1:-1] + elif s.startswith('"') and s.endswith('"'): + return s[1:-1] + else: + return s + + +def convert_self_to_glv(python_code: str) -> str: + if 'self' not in python_code: + return python_code + + # 第一步:替换属性访问 self.xxx → glv['xxx'] or self.xxx -> glv["xxx"] + # NOTE(huifu.zc) 这里无法完全避免 rf'glv['abc']' 这样的问题, 只能尽力避免 + if python_code.find('"') > 0: + python_code = re.sub(r'\bself\.([a-zA-Z_][a-zA-Z0-9_]*)', r"glv['\1']", python_code) + else: + python_code = re.sub(r'\bself\.([a-zA-Z_][a-zA-Z0-9_]*)', r'glv["\1"]', python_code) + + # 第二步:替换函数参数中的self → glv + # 增强的正则表达式,处理赋值情况 (project=self) + python_code = re.sub(r'([(,=]\s*)\bself\b(?!\.)', r'\1glv', python_code) + + return python_code + + +def gen_random_var(var_base: str): + time_in_ns = str(int(time.time_ns()/100)) + random.seed(time.time_ns()) + return f"{var_base}_{time_in_ns[-6:]}_{random.randint(100, 200)}" diff --git a/src/Xbot/Blockly/BlockManager.py b/src/Xbot/Blockly/BlockManager.py new file mode 100644 index 0000000..09c9d0b --- /dev/null +++ b/src/Xbot/Blockly/BlockManager.py @@ -0,0 +1,193 @@ +import json +import os +import sys +from typing import Dict, Any, Optional, List +import logging +import glob +from .BlockPrototype import BlockPrototype, FieldPrototype +from .Variable import VariablePrototype + +class BlockManager: + """块定义管理器""" + _instance = None + _component_configs: Dict[str, Dict] = {} # 存储每个组件的配置,键为组件名称 + _block_prototypes: Dict[str, BlockPrototype] = {} # 缓存已加载的块原型 + + def __new__(cls): + if cls._instance is None: + cls._instance = super(BlockManager, cls).__new__(cls) + cls._instance._load_block_configs() + return cls._instance + + def _get_resource_path(self, relative_path): + """获取资源文件的路径,支持普通运行和打包环境""" + # 检查是否在PyInstaller环境中运行 + if hasattr(sys, '_MEIPASS'): + # PyInstaller创建的临时文件夹 + base_path = sys._MEIPASS + else: + # 普通Python环境 + base_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + return os.path.join(base_path, relative_path) + + def _load_block_configs(self): + """加载所有块定义配置文件""" + try: + # 获取块配置文件目录 + config_dir = self._get_resource_path("assert/block_settings") + + if not os.path.exists(config_dir): + logging.warning(f"找不到块配置目录: {config_dir}") + # 在打包环境中尝试其他可能的路径 + if hasattr(sys, '_MEIPASS'): + alt_paths = [ + os.path.join(sys._MEIPASS, "block_settings"), + os.path.join(sys._MEIPASS, "assert", "block_settings"), + ] + for alt_path in alt_paths: + if os.path.exists(alt_path): + config_dir = alt_path + logging.info(f"找到替代块配置目录: {config_dir}") + break + else: + # 输出更详细的诊断信息 + logging.error(f"无法找到块配置目录,已尝试以下路径:") + for path in [config_dir] + alt_paths: + logging.error(f" - {path}") + if hasattr(sys, '_MEIPASS'): + logging.error(f"PyInstaller临时目录内容: {os.listdir(sys._MEIPASS)}") + return + else: + return + + # 查找所有 .blocks.json 文件 + config_files = glob.glob(os.path.join(config_dir, "*.blocks.json")) + + if not config_files: + logging.warning(f"未找到块配置文件: {config_dir}") + # 列出目录内容以进行诊断 + if os.path.exists(config_dir): + logging.warning(f"目录内容: {os.listdir(config_dir)}") + return + + # 加载每个文件 + for config_file in config_files: + try: + with open(config_file, 'r', encoding='utf-8-sig') as f: + config_data = json.load(f) + # 从文件名获取组件名称 + component_name = os.path.basename(config_file).split('.')[0] + self._component_configs[component_name] = config_data + + # 预加载所有块原型 + for block_data in config_data.get('blocks', []): + block_name = block_data.get('name') + if block_name: + prototype = BlockPrototype.from_dict(block_data) + self._block_prototypes[block_name] = prototype + + logging.info(f"已加载组件 {component_name} 的块定义") + except Exception as e: + logging.error(f"加载块配置文件失败 {config_file}: {e}") + logging.exception(e) + + logging.info(f"总共加载了 {len(self._component_configs)} 个组件的块定义") + logging.info(f"总共加载了 {len(self._block_prototypes)} 个块原型") + + except Exception as e: + logging.error(f"加载块配置失败: {e}") + logging.exception(e) + + def get_block_prototype(self, block_name: str) -> Optional[BlockPrototype]: + """获取块原型定义 + + Args: + block_name: 块名称 (如 'programing.log') + + Returns: + Optional[BlockPrototype]: 块原型定义,如果不存在则返回None + """ + if block_name is None: + raise ValueError("block_name 不能为空") + + # 首先从缓存中查找 + if block_name in self._block_prototypes: + return self._block_prototypes[block_name] + + # 解析命名空间和块名 + if '.' in block_name: + namespace, block_short_name = block_name.split('.', 1) + else: + # 在转换失败情况下,会添加一个无效的 block,此时不需要警告 + if 'EnumWidget_' in block_name: + return None + print(f"不规范的块名称格式: {block_name},应为'namespace.name'格式.....") + return None + + # 查找对应的组件配置 + component_config = self._component_configs.get(namespace) + if not component_config: + # if 'xbot_extensions' in namespace: + # return None + print(f"找不到组件配置: {namespace}") + return None + + # 在该组件的块列表中查找指定名称的块 + blocks = component_config.get('blocks', []) + for block_data in blocks: + if block_data.get('name') == block_name: + # 创建并缓存块原型 + prototype = BlockPrototype.from_dict(block_data) + self._block_prototypes[block_name] = prototype + return prototype + + print(f"在组件 {namespace} 中找不到块定义: {block_short_name}") + return None + + def get_input_definitions(self, block_name: str) -> Dict[str, FieldPrototype]: + """获取块的输入字段定义 + + Args: + block_name: 块名称 + + Returns: + Dict[str, FieldPrototype]: 字段名到定义的映射 + """ + prototype = self.get_block_prototype(block_name) + if not prototype: + return {} + + # 将输入字段定义转换为字段名到定义的映射 + return {input_def.name: input_def for input_def in prototype.inputs} + + def get_output_definitions(self, block_name: str) -> Dict[str, VariablePrototype]: + """获取块的输出变量定义 + + Args: + block_name: 块名称 + + Returns: + Dict[str, VariablePrototype]: 变量名到定义的映射 + """ + prototype = self.get_block_prototype(block_name) + if not prototype: + return {} + + # 将输出变量定义转换为变量名到定义的映射 + return {output_def.name: output_def for output_def in prototype.outputs} + + def get_required_inputs(self, block_name: str) -> List[str]: + """获取块的必填输入字段名称 + + Args: + block_name: 块名称 + + Returns: + List[str]: 必填字段名列表 + """ + prototype = self.get_block_prototype(block_name) + if not prototype: + return [] + + return prototype.get_required_inputs() diff --git a/src/Xbot/Blockly/BlockPrototype.py b/src/Xbot/Blockly/BlockPrototype.py new file mode 100644 index 0000000..bb14d06 --- /dev/null +++ b/src/Xbot/Blockly/BlockPrototype.py @@ -0,0 +1,196 @@ +from dataclasses import dataclass, field +from typing import List, Dict, Any, Optional +from .Variable import VariablePrototype # 导入自 Variable 模块 + +@dataclass +class FieldPrototype: + name: str + label: str + type: str = "str" + required: bool = False + tips: str = "" + default: Optional[Any] = None + defaultDisplay: Optional[str] = None + editor: Dict[str, Any] = field(default_factory=dict) + category: str = "normal" + + def to_dict(self) -> Dict[str, Any]: + """转换为字典表示""" + result = { + "name": self.name, + "label": self.label, + "type": self.type, + "required": self.required, + "tips": self.tips, + "category": self.category + } + + # 添加可选字段 + if self.default is not None: + result["default"] = self.default + if self.defaultDisplay: + result["defaultDisplay"] = self.defaultDisplay + if self.editor: + result["editor"] = self.editor + + return result + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> 'FieldPrototype': + """从字典创建字段原型""" + return cls( + name=data.get("name"), + label=data.get("label", ""), + type=data.get("type"), + required=data.get("required", False), + tips=data.get("tips", ""), + default=data.get("default", None), + defaultDisplay=data.get("defaultDisplay"), + editor=data.get("editor", {}), + category=data.get("category", "normal") + ) + +@dataclass +class VariablePrototype: + name: str + id: str + type: str + label: str = "" + variableLabel: Optional[str] = None + tips: str = "" + + def to_dict(self) -> Dict[str, Any]: + """转换为字典表示""" + result = { + "name": self.name, + "type": self.type, + } + + if self.label: + result["label"] = self.label + if self.variableLabel: + result["variableLabel"] = self.variableLabel + if self.tips: + result["tips"] = self.tips + + + return result + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> 'VariablePrototype': + """从字典创建变量原型""" + return cls( + name=data.get("name"), + type=data.get("type"), + id=data.get("id"), + label=data.get("label", ""), + variableLabel=data.get("variableLabel", ""), + tips=data.get("tips", "") + ) + +@dataclass +class BlockPrototype: + """块原型定义""" + name: str + title: str + description: str = "" + comment: str = "" + icon: str = "" + function: str = "" + helpUrl: str = "" + extension: str = "" + hidden: bool = False + canDebug: bool = True + isCondition: bool = False + isLoop: bool = False + isPseudo: bool = False + statement: bool = False + keywords: List[str] = field(default_factory=list) + inputs: List[FieldPrototype] = field(default_factory=list) + outputs: List[VariablePrototype] = field(default_factory=list) # 更新为 VariablePrototype + exceptionHandling: Optional[str] = None + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> 'BlockPrototype': + """从字典创建块原型""" + # 处理输入字段 + inputs = [] + for input_data in data.get("inputs", []): + inputs.append(FieldPrototype.from_dict(input_data)) + + # 处理输出变量 + outputs = [] + for output_data in data.get("outputs", []): + outputs.append(VariablePrototype.from_dict(output_data)) # 使用 VariablePrototype + + # 处理关键词 + keywords = [] + keywords_str = data.get("keywords", "") + if keywords_str: + keywords = keywords_str.split(";") + + return cls( + name=data.get("name", ""), + title=data.get("title", ""), + description=data.get("description", ""), + comment=data.get("comment", ""), + icon=data.get("icon", ""), + function=data.get("function", ""), + helpUrl=data.get("helpUrl", ""), + extension=data.get("extension", ""), + hidden=data.get("hidden", False), + canDebug=data.get("canDebug", True), + isCondition=data.get("isCondition", False), + isLoop=data.get("isLoop", False), + isPseudo=data.get("isPseudo", False), + statement=data.get("statement", False), + keywords=keywords, + inputs=inputs, + outputs=outputs, + exceptionHandling=data.get("exception_handling") + ) + + def to_dict(self) -> Dict[str, Any]: + """转换为字典表示""" + result = { + "name": self.name, + "statement": self.statement, + "title": self.title, + "keywords": ";".join(self.keywords) if self.keywords else None, + "description": self.description, + "comment": self.comment, + "icon": self.icon, + "function": self.function, + "helpUrl": self.helpUrl, + "extension": self.extension, + "hidden": self.hidden, + "canDebug": self.canDebug, + "isCondition": self.isCondition, + "isLoop": self.isLoop, + "isPseudo": self.isPseudo, + "inputs": [input.to_dict() for input in self.inputs], + "outputs": [output.to_dict() for output in self.outputs] + } + + if self.exceptionHandling: + result["exception_handling"] = self.exceptionHandling + + return result + + def get_input_by_name(self, name: str) -> Optional[FieldPrototype]: + """通过名称获取输入字段定义""" + for input_def in self.inputs: + if input_def.name == name: + return input_def + return None + + def get_output_by_name(self, name: str) -> Optional[VariablePrototype]: + """通过名称获取输出变量定义""" + for output_def in self.outputs: + if output_def.name == name: + return output_def + return None + + def get_required_inputs(self) -> List[str]: + """获取所有必填输入字段名称""" + return [input_def.name for input_def in self.inputs if input_def.required] diff --git a/src/Xbot/Blockly/Field.py b/src/Xbot/Blockly/Field.py new file mode 100644 index 0000000..129a085 --- /dev/null +++ b/src/Xbot/Blockly/Field.py @@ -0,0 +1,111 @@ +from dataclasses import dataclass +from typing import Dict, Any, Optional, Union, List +from enum import Enum + +from .BlockPrototype import FieldPrototype +from .FieldValue import FieldValue, FieldValueKind, FieldValueFactory + + +@dataclass +class Field: + """块的输入字段定义""" + + label: str + displayValue: str + prototype: FieldPrototype = None + value: Optional["FieldValue"] = None # 引用 FieldValue 类型 + + def __post_init__(self): + """初始化后处理""" + # 如果没有设置值,但有原型,则从原型创建默认值 + if self.value is None and self.prototype is not None: + if self.prototype.default: + self.value = FieldValueFactory.create(self.prototype.default) + + def reset_value(self): + self.value = None + if self.prototype.default: + self.value = FieldValueFactory.create(self.prototype.default) + + def set_text_value(self, content): + self.value = FieldValue(FieldValueKind.TEXT, content) + + def set_image_value(self, content): + self.value = FieldValue(FieldValueKind.IMAGE, content) + + def no_inputbox_text_value(self, content): + self.value = FieldValue(FieldValueKind.TEXT, content) + for item in self.prototype.editor["options"]: + if item["value"].lower() == content.lower(): + self.displayValue = item["display"] + return + + + def set_display_value(self, display_value): + self.displayValue = display_value + + def set_group_array_value(self, value): + self.value = FieldValue(FieldValueKind.GROUPARRAY, value) + + def set_expression_value(self, content): + from Converter.utils import convert_self_to_glv + + if content is not None and "self" in content: + content = convert_self_to_glv(content) + self.value = FieldValue(FieldValueKind.EXPRESSION, content) + + def set_global_var(self, global_var_name): + self.value = FieldValue(FieldValueKind.VARIABLE, f"glv['{global_var_name}']") + + def set_flow_arg(self, flow_var_name): + self.value = FieldValue(FieldValueKind.VARIABLE, flow_var_name) + + def set_flow_var(self, local_var_name): + self.value = FieldValue(FieldValueKind.VARIABLE, local_var_name) + + def to_dict(self) -> Dict[str, Any]: + """转换为字典表示""" + result = {} + + if self.value: + result["value"] = str(self.value) + else: + result["value"] = None + + if self.displayValue: + result["display"] = self.displayValue + + # if self.label: + # result["label"] = self.label + + # 如果 result 是一个空字典,则返回 None + if not result: + return None + + return result + + def not_inputbox_filed(self): + return ( + self.prototype.editor["kind"] != "textbox" + and self.prototype.editor["kind"].lower() != "memoedit" + and self.prototype.editor["kind"] != "select" + ) + + @classmethod + def from_prototype(cls, prototype: FieldPrototype) -> "Field": + """从字段原型创建Field实例""" + field = cls( + label=prototype.label, + displayValue=prototype.defaultDisplay or "", + prototype=prototype, + ) + + return field + + @classmethod + def from_value_string(cls, label: str, value_string: str) -> "Field": + """从值字符串创建Field实例""" + + field = cls(label=label, displayValue="") + + return field diff --git a/src/Xbot/Blockly/FieldValue.py b/src/Xbot/Blockly/FieldValue.py new file mode 100644 index 0000000..81b1871 --- /dev/null +++ b/src/Xbot/Blockly/FieldValue.py @@ -0,0 +1,191 @@ +from typing import List, Dict, Any, Optional, Union +import json +from enum import Enum + +class FieldValueKind(str, Enum): + """字段值类型枚举""" + TEXT = "10" # Text = 10 + VARIABLE = "11" # Variable = 11 + SELECTOR = "12" # Selector = 12 + EXPRESSION = "13" # Expression = 13 + IMAGE = "14" # Image = 14 + ARRAY = "15" # Array = 15 + GROUPARRAY = "16" # GroupArray = 16 + OPERATOR = "17" # Operator = 17 + APEXPR = "18" # APExpr = 18 + + +class FieldValue: + """字段值基类""" + def __init__(self, kind: FieldValueKind, content: str): + """初始化字段值 + + Args: + kind: 字段值类型 + content: 字段内容 + """ + self.kind = kind + self._content = content or "" + + @property + def content(self) -> str: + """获取字段内容""" + return self._content + + @content.setter + def content(self, value: str): + """设置字段内容""" + self._content = value or "" + + def __str__(self) -> str: + """转换为字符串表示""" + if self._content: + return f"{self.kind.value}:{self._content}" + else: + return f"{self.kind.value}:" + + +class FieldValueArray(FieldValue): + """数组类型字段值""" + def __init__(self, content: str = ""): + """初始化数组字段值""" + super().__init__(FieldValueKind.ARRAY, content) + self._items: List[str] = [] + # 解析初始内容 + self._parse_content() + + def _parse_content(self): + """解析内容字符串为数组项""" + if not self._content: + self._items = [] + return + + try: + self._items = json.loads(self._content) + if not isinstance(self._items, list): + self._items = [] + except json.JSONDecodeError: + self._items = [] + + @property + def items(self) -> List[str]: + """获取数组项列表""" + return self._items + + @items.setter + def items(self, values: List[str]): + """设置数组项列表""" + self._items = values or [] + self._content = json.dumps(self._items) + + @property + def content(self) -> str: + """获取字段内容,确保是JSON格式""" + return self._content + + @content.setter + def content(self, value: str): + """设置字段内容并解析""" + self._content = value or "" + self._parse_content() + + +class FieldValueGroupArray(FieldValue): + """分组数组类型字段值""" + def __init__(self, content: str = ""): + """初始化分组数组字段值""" + super().__init__(FieldValueKind.GROUPARRAY, content) + self._groups: List[Dict[str, Any]] = [] + # 解析初始内容 + self._parse_content() + + def _parse_content(self): + """解析内容字符串为分组项""" + if not self._content: + self._groups = [] + return + + try: + self._groups = json.loads(self._content) + if not isinstance(self._groups, list): + self._groups = [] + except json.JSONDecodeError: + self._groups = [] + + @property + def groups(self) -> List[Dict[str, Any]]: + """获取分组列表""" + return self._groups + + @groups.setter + def groups(self, values: List[Dict[str, Any]]): + """设置分组列表""" + self._groups = values or [] + self._content = json.dumps(self._groups) + + @property + def content(self) -> str: + """获取字段内容,确保是JSON格式""" + return self._content + + @content.setter + def content(self, value: str): + """设置字段内容并解析""" + self._content = value or "" + self._parse_content() + + def __str__(self) -> str: + """转换为字符串表示""" + def __str__(self) -> str: + """转换为字符串表示""" + result = {} + for name, value in self._groups.items(): + result[name] = [str(item) for item in value] + return f"{self.kind.value}:{json.dumps(result)}" + +class FieldValueFactory: + """字段值工厂类,用于创建和解析字段值""" + + @staticmethod + def create(value_string: str) -> FieldValue: + """从值字符串创建字段值实例 + + Args: + value_string: 格式为 "kind:content" 的字符串 + + Returns: + FieldValue: 字段值实例 + """ + # 解析值字符串 + parts = value_string.split(':', 1) + if len(parts) != 2: + # 格式不正确,默认为文本类型 + return FieldValue(FieldValueKind.TEXT, value_string) + + kind_str, content = parts + + try: + kind = FieldValueKind(kind_str) + except ValueError: + # 无效的类型,默认为文本 + return FieldValue(FieldValueKind.TEXT, value_string) + + return FieldValueFactory.create_by_kind(kind, content) + + @staticmethod + def create_by_kind(kind: FieldValueKind, content: str = "") -> FieldValue: + """根据类型和内容创建字段值实例 + + Args: + kind: 字段值类型 + content: 字段内容 + + Returns: + FieldValue: 字段值实例 + """ + if kind == FieldValueKind.ARRAY: + return FieldValueArray(content) + elif kind == FieldValueKind.GROUPARRAY: + return FieldValueGroupArray(content) + else: + return FieldValue(kind, content) \ No newline at end of file diff --git a/src/Xbot/Blockly/Variable.py b/src/Xbot/Blockly/Variable.py new file mode 100644 index 0000000..4a217a5 --- /dev/null +++ b/src/Xbot/Blockly/Variable.py @@ -0,0 +1,93 @@ +from dataclasses import dataclass +from typing import Dict, Any, Optional + +from Xbot.Blockly.FieldValue import FieldValueKind + +@dataclass +class VariablePrototype: + """变量原型定义""" + name: str + type: str = "any" + id: Optional[str] = None + label: Optional[str] = None + variableLabel: Optional[str] = None + tips: Optional[str] = None + + def to_dict(self) -> Dict[str, Any]: + """转换为字典表示""" + result = { + "name": self.name, + "type": self.type, + } + + # 添加可选字段 + if self.id: + result["id"] = self.id + if self.label: + result["label"] = self.label + if self.variableLabel: + result["variableLabel"] = self.variableLabel + if self.tips: + result["tips"] = self.tips + + return result + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> 'VariablePrototype': + """从字典创建变量原型""" + return cls( + name=data.get("name"), + type=data.get("type"), + id=data.get("id", None), + label=data.get("label", None), + variableLabel=data.get("variableLabel", None), + tips=data.get("tips", None) + ) + +@dataclass +class Variable: + """块的输出变量定义""" + name: str + isEnable: bool = True + variableLabel: Optional[str] = None + type: Optional[str] = None + defaultValue: Optional[Any] = None + prototype: Optional[VariablePrototype] = None + id: Optional[str] = None + + def to_dict(self) -> Dict[str, Any]: + """转换为字典表示""" + result = { + "name": self.name, + "isEnable": self.isEnable + } + + # if self.variableLabel: + # result["variableLabel"] = self.variableLabel + + # if self.type: + # result["type"] = self.type + + # if self.defaultValue: + # result["defaultValue"] = self.defaultValue + + return result + + def set_name(self, name): + self.name = name + + def set_type(self, field_type:FieldValueKind): + self.type = field_type.value.lower() + + @classmethod + def from_prototype(cls, prototype: VariablePrototype) -> 'Variable': + """从变量原型创建Variable实例""" + return cls( + name=prototype.name, + isEnable=True, + variableLabel=prototype.variableLabel, + type=prototype.type, + defaultValue=None, + prototype=prototype, + id=prototype.id + ) diff --git a/src/Xbot/Blockly/XbotBlock.py b/src/Xbot/Blockly/XbotBlock.py new file mode 100644 index 0000000..5b4ec6f --- /dev/null +++ b/src/Xbot/Blockly/XbotBlock.py @@ -0,0 +1,198 @@ +import enum +from dataclasses import dataclass, field +from typing import Optional, Dict, Any, List +import uuid +import logging +from .Field import Field, FieldValueKind +from .Variable import Variable +from .BlockManager import BlockManager +from .BlockPrototype import BlockPrototype, FieldPrototype +from .FieldValue import FieldValueFactory + +# 创建全局单例 +_block_manager = BlockManager() + + +class XbotExceptionKind(str, enum.Enum): + Default = "default" + Abort = "exit" + Contine = "continue" + Retry = "retry" + + +@dataclass +class XbotBlock: + """Xbot流程块定义""" + id: str + name: str # 块类型名称 + fields: Dict[str, Field] = field(default_factory=dict) + variables: Dict[str, Variable] = field(default_factory=dict) + isEnabled: bool = True + block_title: Optional[str] = None + comment: Optional[str] = None + fold_state: Optional[str] = None + block_prototype: BlockPrototype = None + _exception_mode: Optional[XbotExceptionKind] = XbotExceptionKind.Default + + def __post_init__(self): + """初始化后处理""" + if not self.fields: + self.fields = {} + + # 如果没有提供ID则自动生成 + if not self.id: + self.id = str(uuid.uuid4()) + + if not self.fields: + self.fields = {} + + if not self.variables: + self.variables = {} + + self.prepareDefaultInputOutput() + if not self.block_prototype: + # if 'xbot_extensions' in self.name: + # return + print(f"未找到块定义: {self.name}") + return + + if not self.comment: + self.comment = self.block_prototype.comment + + def set_exception_mode_continue(self): + self._exception_mode = XbotExceptionKind.Contine + + def prepareDefaultInputOutput(self): + """加载块定义并创建默认输入输出""" + self.block_prototype = _block_manager.get_block_prototype(self.name) + if not self.block_prototype: + return + + # 为每个输入字段创建对应的 Field 实例 + for field_prototype in self.block_prototype.inputs: + # 如果该字段已经存在,则跳过 + print(f"输入字段: {field_prototype.name}") + print(self.fields) + if field_prototype.name in self.fields: + continue + + field = Field.from_prototype(field_prototype) + + self.fields[field_prototype.name] = field + + for var_prototype in self.block_prototype.outputs: + if var_prototype.name in self.variables: + continue + + variable = Variable.from_prototype(var_prototype) + + self.variables[var_prototype.id] = variable + + @property + def local_variables(self) -> List[str]: + """获取块定义的局部变量列表""" + return [name for name, var in self.variables.items() if var.isEnable] + + @property + def component_namespace(self) -> str: + """获取组件命名空间""" + return self.name.split('.')[0] if '.' in self.name else '' + + @property + def component_name(self) -> str: + """获取组件基础名称""" + return self.name.split('.')[-1] if '.' in self.name else self.name + + def validate(self) -> List[str]: + """验证块配置 + + Returns: + List[str]: 错误信息列表,如果没有错误则为空列表 + """ + errors = [] + + # 验证必填字段 + required_fields = _block_manager.get_required_fields(self.name) + for field_name in required_fields: + if field_name not in self.fields: + errors.append(f"缺少必填字段: {field_name}") + elif not self.fields[field_name].value: + errors.append(f"必填字段值为空: {field_name}") + + return errors + + def to_dict(self) -> Dict[str, Any]: + """转换为字典格式""" + result = { + "id": self.id, + "name": self.name, + "isEnabled": self.isEnabled, + "inputs": {}, + "outputs": {} + } + + # 添加可选字段 + if self.comment: + result["comment"] = self.comment + + if self.fold_state: + result["foldState"] = self.fold_state + + if self.block_title: + result["block_title"] = self.block_title + + # 处理输入字段 + print(f"输入字段: {self.fields}") + for name, field in self.fields.items(): + result["inputs"][name] = field.to_dict() + + # 处理输出变量 + for name, variable in self.variables.items(): + result["outputs"][name] = variable.to_dict() + + # 错误处理 - 部分模式没有支持, 需要的时候再支持 + if self._exception_mode == XbotExceptionKind.Contine: + result["exception_handling"] = { + "logging": True, + "mode": "continue", + "retryTime": 1, + "retryInterval": 1 + } + return result + + @classmethod + def from_dict(cls, data: Dict[str, Any]) -> 'XbotBlock': + """从字典创建Block实例""" + block = cls( + id=data.get('id', str(uuid.uuid4())), + name=data.get('name', ''), + isEnabled=data.get('isEnabled', True), + comment=data.get('comment'), + fold_state=data.get('foldState') + ) + + if 'block_title' in data: + block.block_title = data['block_title'] + + # 处理输入字段 + for name, input_data in data.get('inputs', {}).items(): + if "value" in input_data: + # 使用 Field.from_value_string 方法创建字段 + field = Field.from_value_string( + label=input_data.get("label", name), + value_string=input_data["value"] + ) + field.displayValue = input_data.get("display", "") + block.fields[name] = field + + # 处理输出变量 + for name, output_data in data.get('outputs', {}).items(): + variable = Variable( + name=name, + isEnable=output_data.get("isEnable", True), + variableLabel=output_data.get("variableLabel"), + type=output_data.get("type", "any") + ) + block.variables[name] = variable + + return block diff --git a/src/Xbot/Blockly/__init__.py b/src/Xbot/Blockly/__init__.py new file mode 100644 index 0000000..fbce87c --- /dev/null +++ b/src/Xbot/Blockly/__init__.py @@ -0,0 +1,4 @@ +from .BlockManager import BlockManager +from .XbotBlock import XbotBlock +from .Field import Field, FieldValueKind +from .Variable import Variable \ No newline at end of file diff --git a/src/Xbot/Blockly/__pycache__/BlockManager.cpython-310.pyc b/src/Xbot/Blockly/__pycache__/BlockManager.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ccfa26746cf215a57271879c311a7b536d4d49d GIT binary patch literal 5608 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 literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/BlockManager.cpython-313.pyc b/src/Xbot/Blockly/__pycache__/BlockManager.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5addfeb7db195b8c1bfe72329eb06925e9141ef4 GIT binary patch literal 9312 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 literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-310.pyc b/src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d595c6c8a16123b1887dd2457d31b19e06b6f183 GIT binary patch literal 5847 zcmbtY|Bo9-72lm*uh;9f&%Q6dFG-V2nowLs8osnZdxW%&(h8z$QNIY86ytdIE>8XB zGHaLK=^|AmRjE*tqDmA>fgA!s)Kc{a5Tykwq5j5yFuzi#$uATLr4XRy^WN^+cfPw8 z30w2#y*IP7GxOg2%$sdxGM<6oOE3Ike*ctV{E>vUKO4e9l&}dR4QbYmhFLNjq9ja` zMcr!HCA*O*B^pl2X(UTY=q+j2-A1aEGL68z%a94_oH3+xTAVgZ9&3`)g~nw~iZvs zSWhXzIvaeVBWrD2q&zhy7ActqtbAnqk z=$S3$d6XgWxqj=Mka;Y5low2c>qcVlPD(LKC+L_*3wcV^V z0-dN=js9v6+JnQ|Rl&(lO$AaLP}LT~S)G)@T%}WQ>uk&%s)Y;n%Hl;+55=1D zT&3D>sYUGsvIa&w&6a9Z>e{VV+QB@xsG!|Z%_{Bx>Q8`4qTGoRJ_xdGoSBOlb+X+m zOZYR*EZh!aTei9ScdmJ!XF6t7Y_U{WZ|{Ba!`kLxp?zQd5uZU}8yp3*j6J)6SY9!? z7SdV~%-OL9@fvHAy*5{-Vx1TFO4p27EF%|kpwe!x>#K3O%9xRS&w_K)JE0?ubE;m}TQzzap zmrr&o^{7SB{_CM~xzcR5+7$w-uw3phUE9Z6t$Kg`ieg4NMA$DadfX=GU>8*cT+zl% zQ%jn`u@SV7x1^$_tXU{8nO3U^>FL1`KyP@4D_qm(f6mOAQ{W0hj7^)|Z)>RhIv(B{ zDjCQSw9<|t69Fo5FaRm=4dfweTb;iOwd1NQprAQ+G%@RDiRK`@Ae+lp&jCgLD>dR&q?>7FG!q&5xr z^WVAh#QC-1&WqiL*F`YQhU)J~jL-v}dhKdAJ-CO+`T%BMzX$q|2BgrXe-ygTwWVzv z_oW}VS#<*q_+cVNA{3(PMk0NCaTxMR!4by+IZa(YN@UAOBiFncg-sSk8pT>Jim^Om zjCyPxV~^kn?Z=ojOGrq91i2vBQG7YfQ+(MaBqV63l*C3#LVOfwDds6Xv5|O@KE-^R zc}i2#B_F9tLi*q{r7ZJV)(l{^y*kS$bnj&D z48c_0?>`fHbN9t(-}v>D5$q(|wRSyFU{8MHQ;I8U1`dCtvMf^ zgp7r2fx*Q{R2Uc@gaghSr=qODoX0tT$au&*Wi5*fW?NjamH`hdrfHmX(F^E@Y(n&U zC6;aUve7FM_u7VD$mY-sH-i;%D!H6gH!mkIBmg8PS`0Z^!!f}<9P073DUt1=e=?Sk z>p^m3DaBGMmOPfcSW2^$jwPQZKbA5qWnwAIQdSP}`*JMhWS*sAmWJcD5tc?`X_TeW zSQ=w#ES9Wg2Xi-kxvpKm{GS7`4o{)gB(_$0li<{N{ZWv%nB#*e4XvZ(uexX% zH<8Uy{3LpXUjec0oH=aTRz!Uyz(~V{Z;JPPA>Q>Z@gLt7|MnB&U%n%*`AP9l-xdGx zQ{o-p6My&9;%(m-fAcfqs-G2qwTHxC?40Ky7U>OATp)WdQ_j-H`3C3na;O*0vjg;qWc}9c*XdZI4SOn z&hm?p1MlOt|#a!C*H%_rU%xx;h`;8sb*;|@3)30Ug<`OZ*L6; z@d(d*-5R`Ac-**%VVY0e9IxV48sm!~OS?9i`})4?d>m)EL9s$6;sjaZOk&`Gp-z)Q zEH+4FgiB98cImk%yRSXoU3q?;LD*312BtyD_7vVBon{=~E`|3ALm_E6VXg^rn37Vc zXd48_mZF?}zPvHCY4-=ew77TR=Ae`1vTRjxpYLBGKKPVYAEBAiNj(Us49&E^+9m{x5&?qKC?v?C zBWR#QnNRfSa{=E;`u7yRolH}gdx?;-)cr*ITf!Xei`ozJWt5PT3eT|dZD955K=h4Z zEiIVz&zVAOHw!luwiS|vB#$s#^pOd#eyj~bMW$4|6bBz4Df#4e^e0IdEbXq|)1o^) kFOVj**-W)N6MbSiK<*vVcb}Xwfs2(8n9xlqdq>Ux0%_qbiU0rr literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-312.pyc b/src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be00659c72b79a7c256321a61c7462985813496d GIT binary patch literal 9515 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 literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-313.pyc b/src/Xbot/Blockly/__pycache__/BlockPrototype.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c7cba15ec236d4c2a0c839587ddd659818ba9c7 GIT binary patch literal 9735 zcmd5?YiwIbcD^Jp-%s%^Qj+zw#MrS_KV>!{aTszARL5Y+^hbEP|RM&cip5-@T`v-4?SI!R18M&CoVk}z zlU26;(}6vl^O(n-Idi@rbrrdL4} zy-K2NL|S=D)yopLS54Ht8lvgd5-spm9D7RFt0($KCaCZ-%?zjZF`Qp#1V9Ij$#Q{!!dhU&WY0e zTDUkDagP`RZozUKXD~k}kFi66O@uE+1$8_;7>x@mK1Bo;C+xVOBhk0UVTA6_Q zsSApa{^?g=|Kt~6ee&u0-_5PR`^lr*%fJ7dPXihPV_*n2LF|}0FhhM(hnX8Q4`$#z zn1KF|QvXmXuzWN=ENDoS2ZP~p-5MK(BgeXf1ALV5!QHz$_wNn%B!8HQC&Ljwc!hr} z7~{!UICy?AnF=0_Cx_mQUy*+E7Q18Yil9v;LlNBi?ow;sA@ggXC;kRx6O5=~T(xs2 zXHRC~=k?jwvraFiymgD_1#>C&#H_U&CN-jyG1;bHn0g^?Y{@pZeqg$7nmj&pAZ@D8 z8m()_2Kbk4-?rA?oo?@*Jbus7k~X!1WcuLr!R(fn#j6WfLA@(&s(Wa4O`11g7_fQJ zhkaRWxw!7s+Ph?HZ-({iFWwJW5fZ1^D|4&Jm7FT)K&xo5o3x-VxbG@0XgBRc$LTj2 zg<+FX7(1CwS}<|uoCaq(pa<)=KJ~*Cef8OUl3lM){^j~-Xyadh^bhOrEw2CdkBdy! z37Q2nKQ7rhns{Hq#wEMQHvcDUFWnck4!A$nNHhgTuNsQ;1UI>C@T3*Wf_|7JFG)u0 zEi>A@WGhzs5o8n06Afc?WNTb=-dXSb)=W)P*6yC`nC+O~zjQQXZ!eL6VV|EpKYww# zE#vCUOO~25HEn3$CuUE~Usz@{&gZlKEsI?XUH4k|Wc+)x4$oZIY}fpWrNN9NfV)F# zq$A_n{lsCg8AQgQHxTqAA2I=tpbLc%B|;&=5DHyNM#ke#|WQ_ z#}d&*G87`X5e49e6NzLhi~!98H}7f$b}*TY7Z!q`VCvse&5Rd%~g~F*6i4BgYqS)astcPDh*MgX_gc*V#|4YbjG7k;r z8z-|y%Z=Ww%{9?8*^*&hS(k6(#AGDH`m#1V@^18H>zgLNH+g<$XzB+Uwkg}%G0``3 zVxF5lonbq^sBd1`ldkWYI6m1kY6;uMHMj5G!@1HgQO&2K=(;q=zl@sj|&(8 z*p(F6(ZtG989-OiC<6Ej0Y+K<3K~TKj}~8+%Ia6pCJzn!qNf4TvwONb+t9ptap59h;r^*J z6glhHjP=>A&#i6kN^k7~{-Ly~1%dOx^a0pcix(Cy0CV3|A7Hl4J!zKg9cQBiIE}!d zt9~B}xa$9V;M@d|RGY|IPMw3JDzK^9R6|?P;B*Hx0BQP)kTyO4_~vvmq|t>w1XCb| zZ*=b*MiRrfTx3_Kl$Vq3sJR2OlEtS!)c@?_=Mm}*)_4Q5N(fbqR#wOK<*Cc_?2oUP z0hg~~v16fQ>Cnp2jBkG_SV8!OsH2rphkEURjqJvu?!k<@jD1)_Tp{~0E0{X&6Uk9f zn4lCCDoMoJlEuWzE1bapin zbI=0y%v1(moKjXwnc(b-GU<$JA~lq%k!5yD*=5Q>DF;$PC!BpRZI07IA3rJd`qK*S)89DQ(Xx%HF5r89l*7E zifhfB3eN9-Xp@csPSp*R-;(Fk{(--R@>@Yy{uXGXk@DKOCbD(J8)z0R^gNS4$2|T% zeDYH~f35%3oV2mmKl=Gs|2QRqqB<2z#iInbwP1`y`5_Xc7aW3iD0%5pGy#_%v7ux_ z&<&3#hA^-aw4>4Z*Z_$O`sn3UG{FP!xS$!0MIzC}Sv-0tdZL5lBZ4u;A4?|SV2+hE zG5(cga!k<0_*ePpcqA$4F@TC<55$X|>)woB`C*boc+gFZji-1)n;cJJp--rZULK0l zVVwvkA`tbB(7=~aq%J<}=%FR*vp<6T7PFH{D64o(#m@X8z`>k=B}}LWl>Jz@EPX$Z z%l+Ci5s(9U-<|W}jm+r)!x))H?47OByRxKrfS!bUfUVej9+fLyF#sZ|bN%Liq5tRd z{cEc94|i)hL`i4|w1|C}!r<=)wEc*DWeLzjJ{%@Ah=iQC6Yk=ww5}<%9#U}HDq7kS zEnO8YU5S>yik7}a%TPtjP@-k5qGc@6GF8zsm1vo(Xqij2ELF5DoHe%^FkiMRS~jkx zNXuSD%U;r!ql%WJM9W!4%UPo3s-op8(NYa);2RVJO30N1EadJg^*lL?3Muv}AReiG zihiK{h@JCU1l<@3V)i;_)L|(ON)hL2NfdhFJv)3@|$Be`5EM&*Y0OV)MIb{4P zX6G@xfY}cq6YP0E6B^Aq8ia8ObDl@JCOkG4O+=)F9YuOXQ$YLmE)eS<^Bi0&dJ`a$v%C0>h$|N)_l9tzFjNb8Q)6}OoyJR82_I@6^Cn5E1%Yv zPA-!N{#}!&vL?rL-&EhKfBTw$-+lkSm8%*5u?MCes8hEa>Nwq#x~#`PcX{^ml41F1 z#y-S5U4xw~2aW8W^ZfuPc_Cu|*>?O^n+oUo14Qx}F!! z$h4GIw<6QVz}QD;N9V6DA6<3t6l;)aXW(oh-BLtX9ot0*GM$AsTUT8>MHe#Ng>kA^ zz57HDGQDNhYmw{TLnzK#ej##D`jAoC%QK)UT}j%1$FY6 zSEvaR79H|1$~>eTEjaa66SHkmx{C;rbgSdXQAO*anFK zB(}1qfCPyVB=(9D6G+gnlqINR1_@rql_ii^K!Sd&EP=!d61>hXOCYg<1n<4e5=d%5 z(on_*5+rtzG(IbFFy|CJL=(Icq8Rw9WKDm|vs!rM!1Su}G<+Y%COq6qK&uXDwN;W8 z=g_LMq}Ar{+$#8eh@_bQt;Ow0<-DChFj`q-K*c#RnjTQK!U&~N4(CeBVJ6_BcMy`( zr*4~iehLU-sMq%$K!9REIRq5IWe}PPI4kuauosiD#Q&*>HfUVJFoc@`OPb+FP*a!? zG!i%vTt6N+AOeAe0$5LQm!W|C2C;zZS0xN!?REor{FxqndJt7WJv4ddor?_%4Wb$- z@Umv-%vpS&5Vc6_7_(<(&)paAzBsR<-q-m-{q6cy@6O*uL_I1P7_)DF&zgT*+P_US zBFDs--7~4VYqQrxGtw5u?2tROB5i{v=UII85NnXO7xW!SI~lWA9+C@bH)D3qMCRU{ zeN*%x?Jd-=McP+90zY!<3N`AHZYb2)f^;LuS92#T1nl#cIR5g({tzA^0`IJg5`m?t#=}In=&?V#l4RpoT zt`A}R!UGr_SCkds9TnXWszku8pLW6afX&&+w9<_{q6jFT;ud~9@$*N&zPUd0liz=^ z^60(0>(f7b^v^$CfA^R2BLzM3^}+2OHFZ1=22|AisHqEjIaG-b^ElL;-wKKex7JJ&pHmjZf5!uMKbD zob+De|ILiu{B&Kq1Iy1C4LYBhF+(nvE1xnuPKYeb%~?~0IV)B9tZ338hTH!Bb_m|A zwbSoRy|dK%xpiyS({$g~1e4}(FPb#i_W6V^gPPfOC{#DIBD`p#cmYOLo^qZ#Z*YoA z5dok{O94%aJ$67rO;R$$ucs!yet&BH*YB?1{@W6hq^1g1NG;LB>5Xg!z z4Fw0zYwqs^B%9=g<_Z&Art>e@5FClo96R^iHQq61to?V4O9$2tz4rN`*M4f5(a%}_ z!t${(ZSB9O>;Lw?wVwv!)6Q=816wyM-4C``x*rs@p-?0_BtJk&7loT2Lr52XA09=@ zVTeK+uA{)l;qOkQlMY@zNpplxG7@}XoJ5Z-(o0r1l7-tydNQF{!=vB|W@r=@?M> zmX1%H>6Vx1!&gJv)RSw?*_hnQ3bJ2QCoV$3Z%GCt#&RAi46QKkFH!#?>PPx%c2GOyu`nJ zuj^!bXRj7`)k{>s?q( zJQE7KbMiw8y+M}FpLF4NVRiJiG*A$9FGw$@FOheFhu(o7giKT^6pG(69lvF^XPE8( z!L&bA7`{Bk+ literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/Field.cpython-310.pyc b/src/Xbot/Blockly/__pycache__/Field.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80d4b01a644927ec7d1a6910c5fbd3e5cbd31546 GIT binary patch literal 3938 zcmb7HS#KNH6`ngAM-)lzvLwrnou+Zv#Yy)CZfZGJ9HXghNO9^;l@3O{BZblohq*IU zEr9|GSSeDtHc}L5fCNtMAYBBcekf4Db=v%aKK5;1E5^=q-U=k?ckYnlBC9}2%w5l& zd(L;(3G?}^g5R(I_0N~TT~L&N)1>pKV{#f#w2Fo+ocT(?Y{qD;`f8xrTA>1-rl$kDXI^hFjYTx2~#JnLWV! z7L;Q4BiyGHS<=Vd*e&^P6cvp`KU*%vi8fQ&NURIhxExkoKQS&%JC1%6`l;W_nvi2aVR!Q#6{;XgUM+; z(JmTKu^Crv^%8KgHBa{puAWk4ubqPAw&`WCX2`MS^>K4j!90Vx#rw7uJIk}YAALX1 z@jUt*FYp2Mc|OR8&=>eHA3;CBNBJ1~K|an8p&#NCd=mXIpW=tnkML=J1pO#K>W$(4 z@nv;VSyuTY{Mfc`AL7UPqu8DBCb{8d_))Gb>-=;4v27iAPhnN{bpClfv}5we`3bpm znCsBQ6Nw>VsZBuQ#?3eGzq$S3gWoh>{e9!lZ+v*?uZ=rz?*8qUiQ&6To}c7+IjZ{Z zhQxF(>8rMo7yUS$80&<4iImg&(OARt44&u|n!2(IIBSZSz=&bQ#1xHIRWTiFxAb&; zo7EKubPHWiQLPQ*6^++!HvV|6@vGl9Ucb?Jcl-Y9znI%G1nr0+G)abg%Wln&MV@A6 zNqBDT?Z9**&tKlb%~<}=Q)j=s=vCI8*t-%hURerbXQ@{9`IC_-EndcS@r)mq*8Gh{ ziO$LDMv`}&Y8b^%xl)cDhpvmrxkfdMjWX*~oo$Y!v|V%uqwzQnbKv0+CM5sRKKT{M zk7tL?i4jnXacYSDw3);x=@(w)#g2rY79tCc$%rZav(41zPj=9hRP48YG;XQqV-hJ= zVz5$YS5+{k(dFVWmW#U7u*hMY=r7D(enH~Bql!bck|~9i*sH|7ycLKuLO5mbC}=;X zD~H+UXo^)g!GXMqBRI966XX03XU@&0s(*widaxOw*Ovo##Y-7DPBf3A*&J(M-?86y zKjA|0QJU^^7<6L;rRl2%XOqfV<)zUrwXSk_jr`yJs*goB-t&M0W+>3{ta`j z&eoypIyoNOVzC-)t9sK3ji$+nX3iUdudRC`b|{)Tap(UI0rakaXy61_LwYcm@ z;v{iQu{rhJ?Cj->^Ro*J=P%5q5Of$&O520ODB<8;sUm(v$igWMU&Z@ml*zF{)nahw zsWu$F#9e5RMh!gDYNjwqU5c|hdkY1}O|2bvirU~Zs7GAnT$nkn(vSh#LrY$ENT<%W4xutwt0!K;C$=;{4yN# zz}s^Kq@-}g3gyAnj)vR7wKo6Xdke@@|3mEd#Q^5}2VRWL#1vj!6P2!vMF_P7kDkV) ztZc#4R~3HfR-q(#mNN{a|=l#CKBikp$HnP|XbM47$EOfzr;j@t1I4n=fQS50-0 zS!lCNH+80~oB0&#CS{k9Vv`jLcyEKZ!JrpF|QB)6R`mO&K} zTR9!(*vxACsEX5x<;Vc$I7!xVf{@pI596HUyi#+03T>EW9EXP`#}VJc3zGrIaVszc zm%f=ItV%1Rw47!)G5|sGR!mbP%OI)XfA~j#8<|%5vMh$s^_y#outRS`pg-k)Q zE9sYCY=IZQ9C9&3%j7y85J)hn8WmJ!^x=sp6=mU=7E%Th2b|N&ScawHZ^<@8?YL%* zshLrxW~Z4vJ69Y``u9E(y-1LwCMG`jp!E*sq=+W=1bxFLx`)q1L8Wj~kd^%2N1~9h j?BzuHksxn+82gEJDpkPK6eDEGlvAd`e@+FD+9>-kNbQ#R literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/Field.cpython-312.pyc b/src/Xbot/Blockly/__pycache__/Field.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dfc5bd430d23f1223f1b8c94836d8097642551a3 GIT binary patch literal 8997 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 Vr#q!%9cv6iz+7j(Pb( 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 gX2PB0QX~l1Rdp)l#Q5 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 literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/FieldValue.cpython-312.pyc b/src/Xbot/Blockly/__pycache__/FieldValue.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..040fc9fb9e185d7e4fbb9aff4ad64bfcb351e7bd GIT binary patch literal 9245 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 aA7E;khLO5?0`veI6+2tn5JxPbdN+7&@<>W?bs z_Qr|YZL&5OC?m&1XxGfYJxFqs^_li9or=)j)6@P<#k!?uNAFHG zE$-Oa+0%~oE$ut8g;L`8%h5nI)b9^OqcrsVNHi$>{S*X=B;g}U+ol#@uN?bRAEcxDMx=QaPYr8dZB+0{2oNv2*u-!gO zGcO5cK10#)p`Jth8}GoGWJ2c*P&R` zv%Xghy`)?~3{i=nzYfx(@CQMXl!E@DNHiFU-qsEY8xxNa{!Z2dnIL;^UJ}-Yoxs5{r@Em+eC)^Zi^t>Re`AbmwYJkixy4!y0mp8sHi}f~WhELv zM&T$RP@MC=!Z-pt{rRQKx6( z8p}wIl7y3#EFUkNE3G>3h&7J!uQ}KrD;64zj?l<$V{%X%(`;$VATdFDNe{%ip_X{L z6fXST6TgU`)K`GbaT&W)*<}+@iZeLXrs;tyNhc6s)Iy4uo;-5w$dp*2 zvM78Db;4~;??EL(jLoZsAHX4(cf(j!By7VNuU9|1^UJH+mM~sv6O?yT)L)lPj9
WC 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 GMg9RU>N~&y literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/Variable.cpython-312.pyc b/src/Xbot/Blockly/__pycache__/Variable.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09a4829581dabf64d001cdd1be1a83435f87566e GIT binary patch literal 3750 zcmai1-ESMm5#RgbH$_q+Wl6Rr+fpb|jaAETBiT(F#8%uGb>yIRf`$-E(7cmF^++mr zWMUdBK%fdj+DIfJ52TVdQiD9ykP{?8P`D17e;_Yb`JlrAMN`yloHyD^5Fk&T*}J1o zvRo~|x!K>$?Cs9Y?r-^}-|r#NKE3(n<-daVAM997FqKUilqwO4$jBta#2E&4R%SC? zoXhZWJ|n~higB_dKVPb9@<}@*n4Re{8*M_+% z=8=3bx__F*5vN(vJI}}4q=4wN;X1&*h7= zQlTBjX)M&fd2^xh_DbXZ>y3}!z5BO{&S#SuN#~M~ARhfDbv7;Pf}Ff0$-4hFbC~nA z%jeUxs_syvd_l>k7#PrM94PqP3<6pub7aP{*q(rzpVbCJR{zNUo&g(gM-5#G?2gYd z#y0?~;}KE2;1I=OZXwF`h^Sp~h@xK@qG;J~kEAo)1&1hszKi)ai8;QDK-9gz-~8`e zAKbllyYW%A@y4xtfBwtYAKs3!3PvkF6n+$KC;}*gAZ|GJu(LX^O7b**6}2GeRm||A zLqGiN%&DmtRY_5&P8>fr_S30}-0N96mlV~hqWbDoT2*F~Q@^>C%TJw_bE)6S#VM;` zMrMn;GoMR{uy3w*TWG6{MobgVO)Y>Zk*0%0x~u1w&S~K;eB2kfc2C*S^buchVeHzN zw!d#>YFiW0eblZFmp$Xln-BSsMR^lO8Vbr?*bj@i`}x~ODK*OPH9o&>-`qQj zW^zYWDPahQW01Qn!4-q$G9Yj61ndn!454H zsdg=O)uQ##;ca@LW8q5WN{z3H^+3PY-dP=58mf)0PSo3DT2JrF(DKmg)1OS#drr2Z zRtM^#!EgP}pr=WkZjaIfZ;6F;S0aIjRwAK$5{XPsEXb()5{Xv}N!heG6A3Yw0+>_t ziXKQLlG$u7pF{#s6A9aP!=&!a4xU5`(tv`8ukNK}l9BSSMdEnG{jo~XUD+`CDj+l&%NsL8qoPwnDr|Ejt= zwEWv9f$p7SXCB~llLLqQ=wQqfXP1IstFa~EC-1t-V>v!kxeeq7?O>2`-?xUOJqV7to&t{P;Cyiqlk7C^?O4CU= zPw5pwch6chYMjv_aM_*z#%V%$qbL<3^>h>w=E>+6YZF#kI_ZYFD^AMq85tayWM45lfO=qBcrtub*z-!0uvpEeh zIGf$FIfL`v(X3k#%)Yg{B2kWk8{7qj*YLgvcbnYnl0uIFYc~;mZ$*nmJXDBPa&<{GYh5hem9{o?w?$(Yk%4qAKk5<)K~KZ1DWaTIt( ziSdThmYt%k(rdYG%Vis-iq;Ogy3cy)$acf8AX>%!(;||dYVT677U|Y{`Zsz;*Ly~_ zkO6fc)H?gLK-a=tW$xR63;Dri@xwml5KiMTiX$j+@yY;-$57zXbpBE9J3jiXY9`?wESI=af;@Ftf@ND55BE%E}-LfMzTJr#%_-=-$@!_vq4}VR z!sO}u@FF>4UL;4(w*FZeiK1zw`PiN#-Swow-9J~Jf>H1~rs95Yaty=#lN|mRiLR4q mgB<^g@qEul8TiH^V6v>YNxLsFpnlIDMGFXOxsP4CjQ;_?VJYMQ literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/Variable.cpython-313.pyc b/src/Xbot/Blockly/__pycache__/Variable.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a00305b202501f48ae6147c4479f614bf1a508e GIT binary patch literal 3870 zcmbVPZ%kX)6~FKK`M-^Az{HS*5MTzg!b1KG$ktU&XjMo?s=N@jleMP@Hq_aRP49cO zLFxxf+Z3ay1vEvNPAjbHhehhD?aP#fePJ^&53#q-thJQmMi!}D6aKn>5w zc>ZJ%W^X#n4)nO4aM4RVbiLep5F4K%WqoiM_ zIW4CxEu^2gV7~okAmx?fliMrh4>rpm-6? z3AJ3a-*2(x5WzVQ(U|5$9-RkLJY_>`us=it?Ag_Vy{Ew#h7IP8*KPdlpz5Mh0kAMA}uRnQkkEcP9QE&vIVI&bG zc&W4n$UWC{p-e%lO{K^T}y7P1WR?)2BwxCC78`W|f?rQj<&S z+sTYd7v$s{GdV4JLCMYjL|IB+w<2O_Vaaf7IVpt?uHEKVV{XV2;a1f}AbC=8k!bt+ z#M*@38pF@7)6wiJxGDh>2(OH+jOa&CY>sS<6kc6DyL?&qhgQz7oYylCk4A*Wl&0VbxXf%W-a_21WGvxepVyYDC(VN@W``7x5 zBU|I8=7iqSx!J$bzxC4Z#!DSzRjaMuQlxJ;=nnfT#O?LbE?DIrNwgRqNy5Y?Nrq37 zZst;p3ibn%^!B2xSdx$=&1I;nDVc0Kn**_1l2W-@=r~l38X%Ul*_2 zG&&5E6UEF;JAoK}21z&5+FQ94#SCFYB}v7}W+hqEXl7S*!e8jSkDabVNGdS-dBBy?7Uh_kKOTAbZFQ+#WqbDzMl5+|-mh4(sr#cNwVTk2N- z#*ZrmhF_k#xQE|82Po{Jg1JxJ;zRhawrUmdcVPVw5b6QAv?0`+^gRWk{u-VQp#k6p zEvU62vEL1m;JOONZ-^*4vd~;azNm$ezzLN`J0iNUzt5vSz zUK^TSY)uoT3MTV}z6@$mdOF|1@)9bi+`DPYa)o`CaZq^rEV!?RvmomVDq~FHSvq%G zd$(JAcUlLwTL((5FBAmpaCHa5_sCp(13FbSgMMQZIXG-}>jzTc3I`**C-T#%e@M|J zI>y`(Ou~K-=px3{mX!=??7%61_R*s+?p&KnxJ|ra5yy%aR>+KjJ;k76L7xyzr2{#} z3V1PYtJQh2i2+RY-55vgMThDIc)cnvT!o*G_0F|UJ=(5!^z3vDZ+8sq5tG$^TyHy} zhhi)5Ex)%L@*t{sEL5R*Cy91CfP48ik{6H+A{j!0$$*|hf@>MVOfILG&z+&g!Fd@* zutVd;na>^F&)yuxprjbfbOOmRk|`voku-n>MkGaoi>sdiL9pmH!6Mq8f31)z3GM$4 z5cKYN{_<*n@yr^)LtGym&QBC>eHlw^hXzW*a6Qaagm680!0_L_oU^^+;+%t9L;D0i zP~{<-_y9ioMk@rq_kXm99}7jGXQBvhdn(~G{MFxYX_aCa8!mVUne04ePGR0c4;n|X z4jr=U(4m80bf&kMFPT5;ePnpPZ^Hi%=rx!Ht2q^YTybz5_cwC#A0)m_;$?FBE6(=~ fALro8fxu>Ye}xTS=b-xyKZp__OtOnZc8vc3`eHK^ literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/XbotBlock.cpython-310.pyc b/src/Xbot/Blockly/__pycache__/XbotBlock.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9927f50e17c43c1a386dd5fea3a6f6819dbb86bf GIT binary patch literal 5310 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 YWhm620pG039P{!2kdN literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/XbotBlock.cpython-312.pyc b/src/Xbot/Blockly/__pycache__/XbotBlock.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f519f4b9f94581ffec8fa5076882c47c45eff0f6 GIT binary patch literal 8621 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 JSOq(q{{!6`cV7Si literal 0 HcmV?d00001 diff --git a/src/Xbot/Blockly/__pycache__/__init__.cpython-310.pyc b/src/Xbot/Blockly/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf9c476c6a107509d7ff3f95691c771c95eb65a3 GIT binary patch literal 286 zcmYk0!Ab)$5QdX%wyv@*zQ%g!xrmhF!HeicC=vo8HK7D2yCu67`x?H5;KBFs4ffiT zui&XOIXT08^Z!G_OgEigFpTf7pX~?sBbomp(5$ff1;R1MfkmbmCoOkBzyxJ{wg57wGo&!2Fy=7iGDI;jg4j$sjJb?aj9@l% z4pS~u6jLs96f>C5lEaeA62-#EP|2#v_L32(U6b(^k5f*5a<*?`USfJ`5s=Rrk(6Ho z7Sm+9#p;%snv-&i4@`w6=9H#-XXd2p^PSP)2jU}j`wyvv|=mqFn^gT_4uxgt)W FC;kBzyxJ{wg57wG6XXOGkP<4F%&Tf_L32(U6b(^k5f*5a<*?`USfJ`5s=Rrk(6Ho z7Sm+9#p;%snv-&i4@`w6=9H#-XXd2p^PSP)2jU}j`wyvv|=mqFn^gT_4uxgt)W FC;&~XPE`N^ literal 0 HcmV?d00001 diff --git a/src/Xbot/CodeFlow.py b/src/Xbot/CodeFlow.py new file mode 100644 index 0000000..1070f7b --- /dev/null +++ b/src/Xbot/CodeFlow.py @@ -0,0 +1,93 @@ +from dataclasses import dataclass +from typing import Dict, Any, Optional +import json +import os.path +from .XbotFlow import XbotFlow, FlowKind +from .FlowParameter import FlowParameter, FieldValueKind + + + +DEFAULT_CODE_TEMPLATE = '''# 使用提醒: +# 1. xbot包提供软件自动化、数据表格、Excel、日志、AI等功能 +# 2. package包提供访问当前应用数据的功能,如获取元素、访问全局变量、获取资源文件等功能 +# 3. 当此模块作为流程独立运行时执行main函数 +# 4. 可视化流程中可以通过"调用模块"的指令使用此模块 + +import xbot +from xbot import print, sleep +from .import package +from .package import variables as glv + +def main(args): + pass +''' + +@dataclass +class CodeFlow(XbotFlow): + """代码类型流程""" + code: str = "" + + def load_flow_json(self, project_dir: str) -> None: + """从flow.json文件加载流程定义""" + dev_dir = os.path.join(project_dir, ".dev") + flow_path = os.path.join(dev_dir, f"{self.filename}.flow.json") + + if not os.path.exists(flow_path): + print(f"警告: 流程文件不存在: {flow_path}") + return + + with open(flow_path, 'r', encoding='utf-8') as f: + data = json.load(f) + + # 加载parameters + self.parameters = [] + for param_data in data.get('parameters', []): + param = FlowParameter( + name=param_data.get('name', ''), + direction=param_data.get('direction', 'In'), + type=param_data.get('type', 'any'), + value=param_data.get('value', ''), + description=param_data.get('description', ''), + kind=FieldValueKind(param_data.get('kind', 'Expression')) + ) + self.parameters.append(param) + + # 从Python文件加载代码内容 + code_path = os.path.join(project_dir, f"{self.filename}.py") + if os.path.exists(code_path): + with open(code_path, 'r', encoding='utf-8') as code_file: + self.code = code_file.read() + else: + print(f"警告: 代码文件不存在: {code_path}, 使用默认模板") + self.code = DEFAULT_CODE_TEMPLATE + + def to_disk(self) -> Dict[str, Any]: + """将流程转换为字典格式 (flow.json内容)""" + return { + 'name': self.name, + 'kind': self.kind.lower(), + 'parameters': [param.to_dict() for param in self.parameters] + } + + def save_flow_json(self, project_dir: str) -> None: + """保存流程定义到flow.json和Python文件 + + Args: + project_dir: 项目根目录 + """ + # 先调用父类方法保存flow.json + super().save_flow_json(project_dir) + + # 然后保存Python代码文件 + code_path = os.path.join(project_dir, f"{self.filename}.py") + print(f"保存代码文件: {code_path}") + with open(code_path, 'w', encoding='utf-8') as f: + f.write(self.code or DEFAULT_CODE_TEMPLATE) + + def set_code(self, code: str): + """设置代码内容""" + self.code = code + + def get_code(self) -> str: + """获取代码内容""" + return self.code diff --git a/src/Xbot/FlowParameter.py b/src/Xbot/FlowParameter.py new file mode 100644 index 0000000..604d3b9 --- /dev/null +++ b/src/Xbot/FlowParameter.py @@ -0,0 +1,89 @@ +from dataclasses import dataclass +import enum +from typing import Dict, Any + +class DirectionKind(str, enum.Enum): + IN = "In" + OUT = "Out" + +class FieldValueKind(str, enum.Enum): + """字段值类型枚举 + + 对应关系: + 10: 文本值 (TEXT) + 11: 变量引用 (VARIABLE) + 12: 选择器 (SELECTOR) + 13: 表达式 (EXPRESSION) + 14: 图片 (IMAGE) + 15: 数组 (ARRAY) + 16: 分组数组 (GROUPARRAY) + 17: 运算符 (OPERATOR) + 18: AI表达式 (APEXPR) + """ + TEXT = "10" # Text = 10 + VARIABLE = "11" # Variable = 11 + SELECTOR = "12" # Selector = 12 + EXPRESSION = "13" # Expression = 13 + IMAGE = "14" # Image = 14 + ARRAY = "15" # Array = 15 + GROUPARRAY = "16" # GroupArray = 16 + OPERATOR = "17" # Operator = 17 + APEXPR = "18" # APExpr = 18 + + @classmethod + def from_string(cls, value: str) -> 'FieldValueKind': + """从字符串创建枚举值 + + 支持字符串名称 (如 "TEXT") 和实际值 (如 "10") + """ + # 尝试将输入当作枚举成员名称处理 + name_map = { + "TEXT": cls.TEXT, + "VARIABLE": cls.VARIABLE, + "SELECTOR": cls.SELECTOR, + "EXPRESSION": cls.EXPRESSION, + "IMAGE": cls.IMAGE, + "ARRAY": cls.ARRAY, + "GROUPARRAY": cls.GROUPARRAY, + "OPERATOR": cls.OPERATOR, + "APEXPR": cls.APEXPR, + } + + # 处理忽略大小写的情况 + if value.upper() in name_map: + return name_map[value.upper()] + + # 尝试直接用值创建 + try: + return cls(value) + except ValueError: + # 如果都失败,返回默认值 + return cls.TEXT + +@dataclass +class FlowParameter: + """流程参数定义""" + name: str = "" + direction: DirectionKind = DirectionKind.IN + value: str = "" + type: str = "" + description: str = "" + kind: FieldValueKind = FieldValueKind.TEXT + + def __post_init__(self): + self._name = self.name + self._direction = self.direction + self._value = self.value + self._description = self.description + self._kind = self.kind + + def to_dict(self) -> Dict[str, Any]: + """转换为字典表示""" + return { + "name": self.name, + "direction": self.direction.value, + "value": self.value, + "type": self.type, + "description": self.description, + "kind": self.kind.value + } diff --git a/src/Xbot/ShadowBotPaths.py b/src/Xbot/ShadowBotPaths.py new file mode 100644 index 0000000..cf5418f --- /dev/null +++ b/src/Xbot/ShadowBotPaths.py @@ -0,0 +1,32 @@ +import os +import glob + + +class ShadowBotPaths: + @staticmethod + def get_shadowbot_root(): + """获取ShadowBot安装根目录""" + return os.path.join(os.environ["LOCALAPPDATA"], "ShadowBot") + + @staticmethod + def get_first_user_dir(): + """获取第一个用户目录""" + users_dir = os.path.join(ShadowBotPaths.get_shadowbot_root(), "users") + user_dirs = glob.glob(os.path.join(users_dir, "*")) + if not user_dirs: + raise FileNotFoundError("未找到ShadowBot用户目录") + + # NOTE(huifu.zc) 为多账户的用户方便指定账号 + env_defined_id = os.environ.get("__XBOT_YSQ_CONV_USR_ID__", "") + if env_defined_id is not None and len(env_defined_id) > 0: + for user_dir in user_dirs: + user_id = os.path.basename(user_dir) + if user_id == env_defined_id: + return user_dir + + return user_dirs[0] + + @staticmethod + def get_apps_dir(): + """获取应用目录""" + return os.path.join(ShadowBotPaths.get_first_user_dir(), "apps") diff --git a/src/Xbot/VisualFlow.py b/src/Xbot/VisualFlow.py new file mode 100644 index 0000000..574677d --- /dev/null +++ b/src/Xbot/VisualFlow.py @@ -0,0 +1,75 @@ +from dataclasses import dataclass, field +from typing import Optional, List, Dict, Any +import json +import os.path +from .XbotFlow import XbotFlow, FlowKind +from .Blockly import XbotBlock +from .FlowParameter import FlowParameter, DirectionKind, FieldValueKind + +@dataclass +class VisualFlow(XbotFlow): + """可视化流程""" + blocks: List[XbotBlock] = field(default_factory=list) + connections: List[Dict[str, str]] = field(default_factory=list) + + def load_flow_json(self, project_dir: str) -> None: + """从flow.json文件加载流程定义""" + dev_dir = os.path.join(project_dir, ".dev") + flow_path = os.path.join(dev_dir, f"{self.filename}.flow.json") + + if not os.path.exists(flow_path): + print(f"警告: 流程文件不存在: {flow_path}") + return + + with open(flow_path, 'r', encoding='utf-8') as f: + data = json.load(f) + self.memo = data.get('memo', '') + + # 加载blocks + self.blocks = [] + for block_data in data.get('blocks', []): + block = XbotBlock.from_dict(block_data) + self.blocks.append(block) + + # 加载parameters + self.parameters = [] + for param_data in data.get('parameters', []): + param = FlowParameter( + name=param_data.get('name', ''), + direction=param_data.get('direction', 'In'), + type=param_data.get('type', 'any'), + value=param_data.get('value', ''), + description=param_data.get('description', ''), + kind=FieldValueKind(param_data.get('kind', 'Expression')) + ) + self.parameters.append(param) + + # 加载connections (如果有) + self.connections = data.get('connections', []) + + def to_disk(self) -> Dict[str, Any]: + """将流程转换为字典格式""" + return { + 'name': self.name, + 'memo': self.memo, + 'kind': self.kind.lower(), + 'blocks': [block.to_dict() for block in self.blocks], + 'parameters': [param.to_dict() for param in self.parameters], + } + + def create_new_block(self, block_id: str, block_name: str, + inputs: Dict[str, Dict[str, Any]] = None, + outputs: Dict[str, Any] = None, + is_enabled: bool = True, + block_title: Optional[str] = None) -> XbotBlock: + """添加新的代码块""" + block = XbotBlock( + id=block_id, + name=block_name, + inputs=inputs or {}, + outputs=outputs or {}, + isEnabled=is_enabled, + block_title=block_title + ) + self.blocks.append(block) + return block diff --git a/src/Xbot/XBotHelper.py b/src/Xbot/XBotHelper.py new file mode 100644 index 0000000..428fb7f --- /dev/null +++ b/src/Xbot/XBotHelper.py @@ -0,0 +1,47 @@ +from Xbot import XbotProject, XbotBlock + + +class XBotGlobalVariable(object): + @classmethod + def build_glv_var(cls, var_name: str): + assert isinstance(var_name, str) + return f"glv['{var_name}']" + + +class XBotVariableUtil(object): + self_prefix_string = "self." + + @classmethod + def is_self_var(cls, var_name: str): + return var_name.startswith(cls.self_prefix_string) + + @classmethod + def trim_self(cls, var_name): + return var_name[len(cls.self_prefix_string):] + + @classmethod + def create_comment_block(cls, comment): + comment_block = XbotBlock(id="", name="programing.comment") + comment_block.fields["content"].set_text_value(comment) + return comment_block + + @classmethod + def create_var_block(cls, project: XbotProject, var_name: str, var_value: str): + set_var_block = XbotBlock(id="", name="programing.variable") + # 绑定的变量 = ret_name (any) + set_var_block.fields["value_type"].set_text_value("any") + + if cls.is_self_var(var_name): + var_value_without_self = cls.trim_self(var_name) + cls.add_global_if_not_existed(project, var_value_without_self) + set_var_block.variables["variable"].set_name(var_value_without_self) + else: + set_var_block.variables["variable"].set_name(var_name) + + set_var_block.fields["value"].set_expression_value(var_value) + return set_var_block + + @classmethod + def add_global_if_not_existed(cls, project: XbotProject, var_name: str) -> None: + if not project.global_variable_exist(var_name): + project.add_global_variable(var_name, value=None) \ No newline at end of file diff --git a/src/Xbot/XbotApp.py b/src/Xbot/XbotApp.py new file mode 100644 index 0000000..e6b8481 --- /dev/null +++ b/src/Xbot/XbotApp.py @@ -0,0 +1,46 @@ +import json +import os +import shutil +import uuid +from Xbot.XbotProject import XbotProject +from Xbot.XbotFlow import XbotFlow + + + +class XbotApp: + def __init__(self, app_root: str, app_id: str, app_name: str): + self.project = XbotProject(app_root, app_id, app_name) + self.main_flow = XbotFlow(self.project.dev_dir) + self.main_flow.project = self.project + + def create(self): + """创建完整的Xbot应用程序结构""" + if not os.path.exists(self.project.template_dir): + raise FileNotFoundError(f"模板目录不存在: {self.project.template_dir}") + + self.project.create_project_structure() + self.main_flow.create_flow() + self._create_python_modules() + self._update_package_json() + + def _create_python_modules(self): + """创建Python模块文件""" + with open(os.path.join(self.project.robot_dir, "main.py"), "w", encoding="utf-8") as f: + f.write("# main.py implementation\n") + + def _update_package_json(self): + """更新package.json文件""" + package_file = os.path.join(self.project.robot_dir, "package.json") + with open(package_file, 'r', encoding="utf-8") as f: + package_data = json.load(f) + + package_data.update({ + "uuid": self.project.app_id, + "name": self.project.app_name, + "flows": [XbotFlow.get_flow_config("main")] + }) + + with open(package_file, 'w', encoding="utf-8") as f: + json.dump(package_data, f, indent=2, ensure_ascii=False) + + diff --git a/src/Xbot/XbotAppCreator.py b/src/Xbot/XbotAppCreator.py new file mode 100644 index 0000000..8782792 --- /dev/null +++ b/src/Xbot/XbotAppCreator.py @@ -0,0 +1,317 @@ +import os +import shutil +import sys +import uuid + +from .ShadowBotPaths import ShadowBotPaths +from .XbotProject import XbotProject +from Xbot.Blockly import Variable, Field +import json + +# 添加项目根目录到Python路径 +project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if project_root not in sys.path: + sys.path.append(project_root) + +from .bot_import import insert_new_app + +def _get_template_dir(): + """获取模板目录,适用于普通运行和PyInstaller打包的情况""" + # 检查是否在PyInstaller环境中运行 + if hasattr(sys, '_MEIPASS'): + # PyInstaller创建的临时文件夹 + base_path = sys._MEIPASS + else: + # 普通Python环境 + base_path = os.path.dirname(os.path.abspath(__file__)) + + template_path = os.path.join(base_path, "Xbot", "XbotAppTemplate", "xbot_robot") + + # 如果路径不存在,尝试其他可能的路径 + if not os.path.exists(template_path): + template_path = os.path.join(base_path, "XbotAppTemplate", "xbot_robot") + + return template_path + +class XbotAppCreator: + def __init__(self, app_root: str, app_id: str, app_name: str): + """初始化应用创建器 + + Args: + app_root: 应用根目录 + app_id: 应用唯一标识 + app_name: 应用名称 + """ + self.app_root = app_root + self.app_id = app_id + self.app_name = app_name + self.app_dir = os.path.join(app_root, app_id) + self.robot_dir = os.path.join(self.app_dir, "xbot_robot") + self.template_dir = _get_template_dir() # 使用辅助函数获取模板目录 + + def create(self) -> XbotProject: + """创建新的Xbot应用 + + Returns: + XbotProject: 创建的项目实例 + """ + # 验证模板目录 + if not os.path.exists(self.template_dir): + # 输出更多诊断信息 + print(f"模板目录不存在: {self.template_dir}") + print(f"当前工作目录: {os.getcwd()}") + print(f"Python路径: {sys.path}") + + if hasattr(sys, '_MEIPASS'): + print(f"PyInstaller临时目录: {sys._MEIPASS}") + print(f"临时目录内容: {os.listdir(sys._MEIPASS)}") + + if os.path.exists(os.path.join(sys._MEIPASS, 'Xbot')): + print(f"Xbot目录内容: {os.listdir(os.path.join(sys._MEIPASS, 'Xbot'))}") + + raise FileNotFoundError(f"模板目录不存在: {self.template_dir}") + + # 创建应用目录 + os.makedirs(self.app_dir, exist_ok=True) + + # 复制机器人模板 + self._copy_robot_template() + + # 加载并更新项目 + return self._init_project() + + def _copy_robot_template(self): + """从模板目录复制xbot_robot内容到目标目录""" + if os.path.exists(self.robot_dir): + shutil.rmtree(self.robot_dir) + + print(f"正在从模板创建机器人: {self.template_dir} -> {self.robot_dir}") + shutil.copytree(self.template_dir, self.robot_dir) + + def _init_project(self) -> XbotProject: + """初始化项目配置""" + # 加载项目 + project = XbotProject.load(self.robot_dir) + + # 更新基本信息 + project.uuid = self.app_id + project.name = self.app_name + + # 保存更新后的配置和流程 + project.save_all(self.robot_dir) + + print(f"已初始化项目:") + print(f"- 名称: {project.name}") + print(f"- UUID: {project.uuid}") + print(f"- 位置: {self.robot_dir}") + + return project + +def create_and_import_app(app_name: str, temp_path: str) -> tuple[str, str]: + """创建并导入新的Xbot应用 + + Returns: + tuple[str, str]: (app_id, app_path) + """ + try: + output_dir = ShadowBotPaths.get_apps_dir() + app_id = str(uuid.uuid4()) + + # 创建应用 + creator = XbotAppCreator(output_dir, app_id, app_name) + project = creator.create() + + # 加载扩展 + project.add_internal_dependency('super_browser==25.9.3') + project.add_internal_dependency('activity_f4d5de04==23.11.1') + # code = project.create_code_flow('module1', '') + code = project.create_new_flow('module1', '') + code.add_input_parameter('参数一', 'str', '参数1的默认值', '参数1的描述', 'TEXT') + code.add_output_parameter('结果', 'str', '结果的默认值', '结果的描述', 'TEXT') + + # project.add_global_variable('全局变量1', 'str', '全局变量1的默认值', '全局变量1的描述', 'TEXT') + # project.add_global_variable('全局变量2', 'any', '0', '全局变量2的描述', 'Expression') + + main = project.main + main.add_input_parameter('参数一', 'str', '参数1的默认值', '参数1的描述', 'TEXT') + main.add_output_parameter('结果', 'str', '结果的默认值', '结果的描述', 'TEXT') + block = main.add_block('dialog.show_custom_dialog') + block.fields['dialog_title'].set_text_value('Hello, World!') + block.variables['dialog_result'].set_name('1111') + # block = main.add_block('programing.log') + + # 创建脚手架 + # # 打开excel + # block = main.add_block('excel.launch') + # file_path = r"D:\env_text\万相台\批量报表下载.xlsx" + # block.fields['open_filename'].set_text_value(file_path) + # block.fields['save_filename'].set_text_value("excel_instance") + # block.fields['driver_way'].set_text_value("office") + # # 关闭excel + # block = main.add_block('excel.close') + # block.fields['operation'].set_text_value("close_specified") + # block.fields['excel_instance'].set_text_value("excel_instance") + # block.fields['close_way'].set_text_value("save") + # 打开紫鸟登录 + block = main.add_block('xbot_extensions.super_browser.A2 打开店铺') + # block.fields['紫鸟版本'].set_text_value("V5") + + + + project.save_all(creator.robot_dir) + + app_path = os.path.join(output_dir, app_id) + + # 导入应用到数据库 + print("\n=== 开始导入数据库 ===") + user_dir = ShadowBotPaths.get_first_user_dir() + user_id = os.path.basename(user_dir) + insert_new_app(app_id, user_id, app_name) + + return app_id, app_path + + except Exception as e: + print(f"\n错误: 创建或导入失败") + print(f"详细信息: {str(e)}") + raise + +def create_and_import_app_test(app_name: str, temp_path: str) -> tuple[str, str]: + """ + 根据json配置文件创建并导入新的Xbot应用脚手架 + """ + try: + output_dir = ShadowBotPaths.get_apps_dir() + app_id = str(uuid.uuid4()) + + # 1. 创建应用基本结构 + creator = XbotAppCreator(output_dir, app_id, app_name) + project = creator.create() + + + print(f"正在从配置文件创建脚手架: {temp_path}") + with open(temp_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + # 3. 添加依赖 + if 'dependency' in config: + for dep in config['dependency']: + print(f"添加依赖: {dep}") + project.add_internal_dependency(dep) + + # 4. 创建和配置流程 + if 'flow' in config: + for flow_data in config['flow']: + flow_name = flow_data['name'] + + if flow_name == 'main': + flow = project.main + print("配置主流程 (main)...") + else: + if flow_data.get('kind') == 'visual': + flow = project.create_new_flow(flow_name, flow_data.get('memo')) + print(f"创建新可视化流程: {flow_name}") + else: + flow = project.create_code_flow(flow_name, flow_data.get('memo', '')) + print(f"创建新代码流程: {flow_name}") + + if 'parameters' in flow_data: + for param in flow_data['parameters']: + if param.get('direction') == 'In': + flow.add_input_parameter(param['name'], param.get('type', 'str'), param.get('value', ''), param.get('description', ''), param.get('kind', 'Text')) + + if 'blocks' in flow_data: + for block_data in flow_data['blocks']: + print(f" -> 添加积木块: {block_data['name']}") + block = flow.add_block(block_data['name']) + if 'inputs' in block_data: + for input_name, input_info in block_data['inputs'].items(): + value = input_info.get('value') + display = input_info.get('display', '') + if value is None: + continue + value_str = str(value) + if value_str.startswith('10:'): + block.fields[input_name].set_text_value(value_str[3:]) + elif value_str.startswith('11:'): + block.fields[input_name].set_expression_value(value_str[3:]) + elif value_str.startswith('13:'): + block.fields[input_name].set_text_value(value_str[3:]) + elif value_str.startswith('16:'): + block.fields[input_name].set_text_value(value_str[3:]) + else: + block.fields[input_name].set_text_value(value_str) + + if display: + block.fields[input_name].set_display_value(display) + + # **错误修复逻辑** + if 'outputs' in block_data: + for output_name, output_info in block_data['outputs'].items(): + if output_info.get('isEnable'): + var_name = output_info.get('name') + if var_name: + # 检查指定的 output_name 是否存在 + if output_name in block.fields: + block.variables[output_name].set_name(var_name) + # 如果不存在,并且只有一个输出,尝试使用通用的 'output' 字段 + elif len(block_data['outputs']) == 1 and 'output' in block.fields: + print(f" [警告] 字段 '{output_name}' 未找到. 尝试使用通用字段 'output'.") + block.variables['output'].set_name(var_name) + else: + # 如果还是找不到,则打印一个更明确的错误信息 + print(f" [错误] 无法为积木块 '{block_data['name']}' 设置输出变量 '{var_name}'. " + f"字段 '{output_name}' 或备用字段 'output' 均不存在。 " + f"可用字段: {list(block.fields.keys())}") + + + # 5. 保存所有更改 + print("\n保存项目所有更改...") + project.save_all(creator.robot_dir) + + # 6. 导入应用到数据库 + app_path = os.path.join(output_dir, app_id) + print("\n=== 开始导入数据库 ===") + user_dir = ShadowBotPaths.get_first_user_dir() + user_id = os.path.basename(user_dir) + insert_new_app(app_id, user_id, app_name) + + return app_id, app_path + + except Exception as e: + import traceback + print(f"\n错误: 创建或导入失败") + print(f"详细信息: {str(e)}") + traceback.print_exc() + raise + +def create_and_import_app_for_convert(app_name: str) -> tuple[str, str]: + """创建并导入新的Xbot应用 + + Returns: + tuple[str, str]: (app_id, app_path) + """ + try: + output_dir = ShadowBotPaths.get_apps_dir() + app_id = str(uuid.uuid4()) + + # 创建应用 + creator = XbotAppCreator(output_dir, app_id, app_name) + project = creator.create() + + project.save_all(creator.robot_dir) + + app_path = os.path.join(output_dir, app_id) + + # 导入应用到数据库 + print("\n=== 开始导入数据库 ===") + user_dir = ShadowBotPaths.get_first_user_dir() + user_id = os.path.basename(user_dir) + insert_new_app(app_id, user_id, app_name) + + return app_id, app_path + + except Exception as e: + print(f"\n错误: 创建或导入失败") + print(f"详细信息: {str(e)}") + raise + diff --git a/src/Xbot/XbotAppTemplate/xbot_robot/.dev/main.flow.json b/src/Xbot/XbotAppTemplate/xbot_robot/.dev/main.flow.json new file mode 100644 index 0000000..60a78f7 --- /dev/null +++ b/src/Xbot/XbotAppTemplate/xbot_robot/.dev/main.flow.json @@ -0,0 +1,8 @@ +{ + "name": "main", + "memo": "测试_jc", + "kind": "visual", + "blocks": [ + ], + "parameters": [] +} \ No newline at end of file diff --git a/src/Xbot/XbotAppTemplate/xbot_robot/__init__.py b/src/Xbot/XbotAppTemplate/xbot_robot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/Xbot/XbotAppTemplate/xbot_robot/imagesV2.xml b/src/Xbot/XbotAppTemplate/xbot_robot/imagesV2.xml new file mode 100644 index 0000000..d246e95 --- /dev/null +++ b/src/Xbot/XbotAppTemplate/xbot_robot/imagesV2.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/Xbot/XbotAppTemplate/xbot_robot/main.py b/src/Xbot/XbotAppTemplate/xbot_robot/main.py new file mode 100644 index 0000000..62bcacf --- /dev/null +++ b/src/Xbot/XbotAppTemplate/xbot_robot/main.py @@ -0,0 +1,7 @@ +import xbot +import xbot_visual +from . import package +import time + +def main(args): + pass diff --git a/src/Xbot/XbotAppTemplate/xbot_robot/package.json b/src/Xbot/XbotAppTemplate/xbot_robot/package.json new file mode 100644 index 0000000..7258619 --- /dev/null +++ b/src/Xbot/XbotAppTemplate/xbot_robot/package.json @@ -0,0 +1,13 @@ +{ + "version": "1", + "name": "浦发-新应用测试11", + "package_version": 2, + "startup": "main", + "flows": [{ + "name": "main", + "filename": "main", + "kind": "visual" + }], + "variables": [], + "external_dependencies": [] +} diff --git a/src/Xbot/XbotAppTemplate/xbot_robot/package.py b/src/Xbot/XbotAppTemplate/xbot_robot/package.py new file mode 100644 index 0000000..2d649c4 --- /dev/null +++ b/src/Xbot/XbotAppTemplate/xbot_robot/package.py @@ -0,0 +1,49 @@ +""" +提供访问应用数据的功能,如获取元素、访问全局变量、获取资源文件等功能 + +```python +# 获取名称为Button的选择器 +package.selector('Button') +# 获取名称为Img的图像选择器 +package.image_selector('Img') +# 以文本形式获取名称为names.txt的资源文件 +package.resources.get_text('names.txt') +# 以二进制形式获取名称为users.xlsx的资源文件 +package.resources.get_bytes('users.xlsx') +# 设置全局变量 +package.variables['g_var1'] = 123 +# 获取全局变量 +package.variables['g_var1'] +``` +""" + +from xbot.selector import SelectorStore, ImageSelectorStore +from xbot.primitives import VariableDict, ResourceReader, _sdmodules + +import os + + +_path = os.path.dirname(__file__) +_sdmodules[_path] = globals() +_selector_store = SelectorStore(_path) +_image_selector_store = ImageSelectorStore(_path) + + +def selector(name): + """ + 从元素库中获取指定名称的选择器 + * @param name, 元素名称 + * @return `Selector`、`TableSelector`, 返回选择器对象 + """ + return _selector_store(name) + +def image_selector(name): + """ + 从图像库中获取指定名称的图像选择器 + * @param name, 元素名称 + * @return `ImageSelector`, 返回图像选择器对象 + """ + return _image_selector_store(name) + +resources = ResourceReader(__loader__, _path) +variables = VariableDict() \ No newline at end of file diff --git a/src/Xbot/XbotAppTemplate/xbot_robot/resources/aocc.yaml b/src/Xbot/XbotAppTemplate/xbot_robot/resources/aocc.yaml new file mode 100644 index 0000000..37eb1d3 --- /dev/null +++ b/src/Xbot/XbotAppTemplate/xbot_robot/resources/aocc.yaml @@ -0,0 +1,22 @@ +# 如果配置中必填项有一个为空, 以流程代码传递的参数为准 +# 如果Config目录下有此配置文件, aocc模块流程参数以配置文件为准 + +# 流程编号(必填) +Processid: "87df5e45-1a63-4d1a-97b5-baffeab20851" +# 流程名称(必填) +ProcessName: "test - jianxin" +#管理端类型(必填) AA或i-search,默认为 yingdao +Software: "yingdao" +#管理端地址(必填) +CR: "21.64.212.172" +# 机器人名称为空则自动获取用户和机器名拼接机器人名称 +RobotName: "uat_test6@yd" +#机器人ip为空则自动获取本机IP地址 +Robotip: "" +# AOCC接口开关(必填): 为True表示与AOCC通信,为False表示流程不与AOCC交互,默认为True +Switch: True +#AOCC通信超时重试次数(必填--超时重试):当AOCC接口调用超时,尝试重发多少次,默认为3次 +TimeoutRetry: 3 +#AOCC通信失败重试次数 (必填--失败重试):当AOCC接口不通时,尝试重发多少次,默认为3次 +failedRetry: 3 + diff --git a/src/Xbot/XbotAppTemplate/xbot_robot/selectorsV2.xml b/src/Xbot/XbotAppTemplate/xbot_robot/selectorsV2.xml new file mode 100644 index 0000000..a4228f5 --- /dev/null +++ b/src/Xbot/XbotAppTemplate/xbot_robot/selectorsV2.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/Xbot/XbotFlow.py b/src/Xbot/XbotFlow.py new file mode 100644 index 0000000..0610547 --- /dev/null +++ b/src/Xbot/XbotFlow.py @@ -0,0 +1,248 @@ +from abc import abstractmethod +from dataclasses import dataclass, field +from typing import Optional, List, Dict, Any, Union, Literal +import json +import os.path +import re +import enum +import uuid + +from Xbot.Blockly.Field import Field +from Xbot.FlowParameter import FieldValueKind, DirectionKind +from Xbot.Blockly import Variable, XbotBlock + +class FlowKind(enum.Enum): + VISUAL = "Visual" + CODE = "Code" + +class ParameterDirection(str, enum.Enum): + IN = "In" + OUT = "Out" + +class ParameterKind(str, enum.Enum): + TEXT = "Text" + EXPRESSION = "Expression" + +@dataclass +class FlowParameter: + name: str + direction: str # "In" 或 "Out" + type: str # 数据类型,如 "str", "int", "bool" 等 + value: str = "" # 默认值 + description: str = "" + kind: str = "Text" # "Text" 或 "Expression" + + def to_dict(self) -> Dict[str, Any]: + """转换为字典表示""" + return { + "name": self.name, + "direction": self.direction, + "type": self.type, + "value": self.value, + "description": self.description, + "kind": self.kind + } + +@dataclass +class XbotFlow: + name: str + filename: str + kind: str = "Visual" + opened: bool = False + groupName: Optional[str] = None + memo: Optional[str] = None + blocks: List[XbotBlock] = field(default_factory=list) + parameters: List[FlowParameter] = field(default_factory=list) + dev_dir: Optional[str] = None + local_vars: list[str] = field(default_factory=list) + project = None + + block_imports: list[str] = field(default_factory=list) + + def load_flow_json(self, project_dir: str) -> None: + """从flow.json文件加载流程定义 + + Args: + project_dir: 项目根目录 + """ + # 在.dev目录下查找flow.json + dev_dir = os.path.join(project_dir, ".dev") + flow_path = os.path.join(dev_dir, f"{self.filename}.flow.json") + + if not os.path.exists(flow_path): + print(f"警告: 流程文件不存在: {flow_path}") + return + + with open(flow_path, 'r', encoding='utf-8') as f: + data = json.load(f) + self.memo = data.get('memo', '') + + # 加载blocks + self.blocks = [] + for block_data in data.get('blocks', []): + block = XbotBlock.from_dict(block_data) + self.blocks.append(block) + + # 加载parameters + self.parameters = [] + for param_data in data.get('parameters', []): + param = FlowParameter( + name=param_data.get('name', ''), + direction=param_data.get('direction', 'In'), + type=param_data.get('type', 'str'), + value=param_data.get('value', ''), + description=param_data.get('description', ''), + kind=param_data.get('kind', 'Text') + ) + self.parameters.append(param) + + def add_block(self, block_name: str, + inputs: Dict[str, Field] = None, + outputs: Dict[str, Variable]= None, + is_enabled: bool = True, + block_title: Optional[str] = None) -> XbotBlock: + """添加新的代码块""" + block = XbotBlock( + id=str(uuid.uuid4()), + name=block_name, + fields=inputs, + variables=outputs, + isEnabled=is_enabled, + block_title=block_title + ) + self.blocks.append(block) + return block + + def add_parameter(self, name: str, param_type: str = "str", + direction: str = "In", value: str = "", + description: str = "", kind: str = "Text") -> FlowParameter: + """添加流程参数 + + Args: + name: 参数名称 + param_type: 参数类型,如 "str", "int", "bool" 等 + direction: 参数方向,"In"表示输入参数,"Out"表示输出参数 + value: 参数默认值 + description: 参数描述 + kind: 参数种类,"Text"或"Expression" + + Returns: + FlowParameter: 新添加的参数 + """ + param = FlowParameter( + name=name, + direction=DirectionKind(direction), + type=param_type, + value=value, + description=description, + kind=kind + ) + self.parameters.append(param) + return param + + def add_input_parameter(self, name: str, param_type: str = "str", + value: str = "", description: str = "", + kind: str = "Text") -> FlowParameter: + """添加输入参数(便捷方法)""" + return self.add_parameter(name, param_type, "In", value, description, kind) + + def add_output_parameter(self, name: str, param_type: str = "str", + value: str = "", description: str = "", + kind: str = "Text") -> FlowParameter: + """添加输出参数(便捷方法)""" + return self.add_parameter(name, param_type, "Out", value, description, kind) + + def get_parameter_by_name(self, name: str) -> Optional[FlowParameter]: + """通过名称获取参数 + + Args: + name: 参数名称 + + Returns: + Optional[FlowParameter]: 找到的参数,如果不存在则返回None + """ + for param in self.parameters: + if param.name == name: + return param + return None + + def add_block_import(self, import_content: str): + for import_line in import_content.split('\n'): + import_line = import_line.strip("\r") + if import_line is not None and len(import_line) > 0: + self.block_imports.append(import_line) + + def get_block_import(self) -> list[str]: + return self.block_imports + + def get_input_parameters(self) -> List[FlowParameter]: + """获取所有输入参数""" + return [param for param in self.parameters if param.direction == "In"] + + def get_output_parameters(self) -> List[FlowParameter]: + """获取所有输出参数""" + return [param for param in self.parameters if param.direction == "Out"] + + def get_block_by_id(self, block_id: str) -> Optional[XbotBlock]: + """通过ID获取代码块 + + Args: + block_id: 块ID + + Returns: + Optional[Block]: 找到的代码块,如果不存在则返回None + """ + for block in self.blocks: + if block.id == block_id: + return block + return None + + def to_dict(self) -> Dict[str, Any]: + """将流程转换为字典格式""" + return { + 'name': self.name, + 'filename': self.filename, + 'memo': self.memo, + 'kind': self.kind.lower(), + 'groupName': self.groupName, + } + + @abstractmethod + def to_disk(self) -> Dict[str, Any]: + """转换为保存到磁盘的字典格式""" + pass + + def save_flow_json(self, project_dir: str) -> None: + """保存流程定义到flow.json文件 + + Args: + project_dir: 项目根目录 + """ + dev_dir = os.path.join(project_dir, ".dev") + if not os.path.exists(dev_dir): + os.makedirs(dev_dir, exist_ok=True) + + flow_path = os.path.join(dev_dir, f"{self.filename}.flow.json") + print(f"保存流程: {flow_path}") + with open(flow_path, 'w', encoding='utf-8') as f: + json.dump(self.to_disk(), f, indent=2, ensure_ascii=False) + + def create_flow(self): + """创建流程文件""" + if not self.dev_dir: + raise ValueError("dev_dir不能为空") + + template = self.to_dict() + flow_file = os.path.join(self.dev_dir, f"{self.filename}.flow.json") + with open(flow_file, "w", encoding="utf-8") as f: + json.dump(template, f, indent=2, ensure_ascii=False) + + @classmethod + def create(cls, name: str, filename: str, kind: str, **kwargs): + """创建合适类型的流程对象""" + if kind.lower() == FlowKind.CODE.value.lower(): + from .CodeFlow import CodeFlow + return CodeFlow(name=name, filename=filename, kind=FlowKind.CODE.value, **kwargs) + else: + from .VisualFlow import VisualFlow + return VisualFlow(name=name, filename=filename, kind=FlowKind.VISUAL.value, **kwargs) \ No newline at end of file diff --git a/src/Xbot/XbotProject.py b/src/Xbot/XbotProject.py new file mode 100644 index 0000000..f1a5a87 --- /dev/null +++ b/src/Xbot/XbotProject.py @@ -0,0 +1,405 @@ +from dataclasses import dataclass, field +from typing import List, Optional, Dict, Any +from enum import Enum +import json +import uuid +import os.path +from .XbotFlow import XbotFlow +from .XbotFlow import FlowKind + + +class FlowKind(Enum): + VISUAL = "Visual" + CODE = "Code" + + +@dataclass +class FlowGroup: + name: str + + +@dataclass +class CustomItems: + gifUrl: Optional[str] = None + videoUrl: str = "" + imageUrl: str = "" + imageName: str = "" + + +@dataclass +class XbotProject: + name: str + uuid: str = field(default_factory=lambda: str(uuid.uuid4())) + icon: Optional[str] = None + version: str = "1" + tags: str = "" + software: Optional[str] = None + software_title: Optional[str] = None + package_version: int = 2 + description: Optional[str] = None + instruction: str = "" + use_latest_pip: bool = False + videoName: str = "" + startup: str = "main" + robot_type: str = "app" + activity_code: Optional[str] = None + main: Optional[XbotFlow] = None # 添加main流程属性 + flows: List[XbotFlow] = field(default_factory=list) + flow_groups: List[FlowGroup] = field(default_factory=list) # 修复这行 + variables: List[Any] = field(default_factory=list) + external_dependencies: List[str] = field(default_factory=list) + internaldependencies: List[Any] = field(default_factory=list) + selectordependencies: List[Any] = field(default_factory=list) + internalautodependencies: List[Any] = field(default_factory=list) + databook_columns: List[Any] = field(default_factory=list) + authority: str = "use" + internalautoupgrade: bool = False + isbrief: bool = False + uia_type: str = "PC" + persist_databook: bool = False + customItems: CustomItems = field(default_factory=CustomItems) + _project_dir: Optional[str] = None + + images: Dict[str, Any] = field(default_factory=dict) + + + def _post_init(self): + """初始化后处理""" + if self.main: + self.main.project = self + + for flow in self.flows: + flow.project = self + + def create_new_flow( + self, + name: str, + filename: str, + kind: str = FlowKind.VISUAL.value, + groupName: Optional[str] = None, + ) -> XbotFlow: + """添加新的流程""" + flow = XbotFlow.create( + name=name, filename=filename, kind=kind, groupName=groupName + ) + flow.project = self + if name == "main": + self.main = flow + else: + self.flows.append(flow) + + return flow + + def add_exist_flow(self, flow: XbotFlow) -> XbotFlow: + """添加已存在的流程""" + if flow.name == "main": + self.main = flow + else: + self.flows.append(flow) + flow.project = self + return flow + + def create_code_flow( + self, name: str, code: str = "", groupName: Optional[str] = None + ) -> XbotFlow: + """创建代码类型流程(便捷方法)""" + flow = self.create_new_flow( + name=name, filename=name, kind=FlowKind.CODE.value, groupName=groupName + ) + flow.set_code(code) + return flow + + def add_flow_group(self, name: str) -> None: + """添加新的流程组""" + group = FlowGroup(name=name) + self.flow_groups.append(group) + + def add_global_variable( + self, + name: str, + type="any", + value: str = "", + desc: str = "any", + kind: str = "Expression", + ) -> None: + """添加全局变量""" + self.variables.append( + {"name": name, "value": value, "kind": kind, "type": type, "desc": desc} + ) + + def global_variable_exist(self, name: str) -> bool: + for i in self.variables: + if i['name'] == name: + return True + return False + + + def add_external_dependency(self, dependency: str) -> None: + """添加外部依赖""" + if dependency not in self.external_dependencies: + self.external_dependencies.append(dependency) + + def add_internal_dependency(self, dependency: str) -> None: + """添加内部组件依赖 + + Args: + dependency: 依赖标识符,格式如 'activity_f4d5de04==23.11.1' + """ + if dependency not in self.internaldependencies: + self.internaldependencies.append(dependency) + # 添加自动更新依赖 + component_name = dependency.split("==")[0] + if component_name not in self.internalautodependencies: + self.internalautodependencies.append(component_name) + + def remove_internal_dependency(self, component_name: str) -> None: + """移除内部组件依赖 + + Args: + component_name: 组件名称,如 'activity_f4d5de04' + """ + # 移除指定版本的依赖 + self.internaldependencies = [ + dep + for dep in self.internaldependencies + if not dep.startswith(component_name + "==") + ] + # 移除自动更新依赖 + if component_name in self.internalautodependencies: + self.internalautodependencies.remove(component_name) + + def get_internal_dependencies(self) -> Dict[str, str]: + """获取内部组件依赖的版本映射 + + Returns: + Dict[str, str]: 组件名称到版本号的映射 + """ + result = {} + for dep in self.internaldependencies: + if "==" in dep: + name, version = dep.split("==") + result[name] = version + return result + + def add_image(self, image_name: str, image_file: str) -> None: + self.images[image_file] = { + "filepath" : fr'resources\images\{image_file}', + "similarity": "85", + "scalingfactor": "1.0", + "adaptive": "True", + "graying": "False", + "sourcetype": "screenshot", + "name": image_name, + 'filename': image_file + } + + def get_images(self) -> dict[Any]: + return self.images + + def project_dir(self) -> str: + return self._project_dir + + def to_dict(self) -> dict: + """将项目配置转换为字典格式""" + flows_data = [] + if self.main: + flows_data.append(self.main.to_dict()) + flows_data.extend([flow.to_dict() for flow in self.flows]) + + return { + "uuid": self.uuid, + "name": self.name, + "icon": self.icon, + "version": self.version, + "tags": self.tags, + "software": self.software, + "software_title": self.software_title, + "package_version": self.package_version, + "description": self.description, + "instruction": self.instruction, + "use_latest_pip": self.use_latest_pip, + "videoName": self.videoName, + "startup": self.startup, + "robot_type": self.robot_type, + "activity_code": self.activity_code, + "flows": flows_data, + "flow_groups": [vars(group) for group in self.flow_groups], + "variables": self.variables, + "external_dependencies": self.external_dependencies, + "internaldependencies": self.internaldependencies, + "selectordependencies": self.selectordependencies, + "internalautodependencies": self.internalautodependencies, + "databook_columns": self.databook_columns, + "authority": self.authority, + "internalautoupgrade": self.internalautoupgrade, + "isbrief": self.isbrief, + "uia_type": self.uia_type, + "persist_databook": self.persist_databook, + "customItems": vars(self.customItems), + } + + def save(self, filepath: str) -> None: + """保存项目配置到package.json""" + with open(filepath, "w", encoding="utf-8") as f: + json.dump(self.to_dict(), f, indent=2, ensure_ascii=False) + + def save_all(self, project_dir: str) -> None: + """保存项目所有内容,包括配置文件和所有流程 + + Args: + project_dir: 项目根目录 + """ + # 保存package.json + package_json = os.path.join(project_dir, "package.json") + self.save(package_json) + + # 保存所有流程 + if self.main: + self.main.save_flow_json(project_dir) + + for flow in self.flows: + flow.save_flow_json(project_dir) + + # 为全局变量生成初始化代码并保存到package.py + self._save_variables_init_code(project_dir) + self._save_image_v2_file() + + def _save_variables_init_code(self, project_dir: str) -> None: + """生成全局变量初始化代码,并保存到package.py文件末尾 + + Args: + project_dir: 项目根目录 + + Raises: + FileNotFoundError: 当package.py文件不存在时抛出异常 + """ + package_py = os.path.join(project_dir, "package.py") + + # 检查package.py文件是否存在 + if not os.path.exists(package_py): + raise FileNotFoundError(f"package.py文件不存在: {package_py}") + + # 生成变量初始化代码 + var_init_lines = [] + for var in self.variables: + var_name = var.get("name", "") + var_value = var.get("value", "") + + # 根据变量类型格式化值 + var_type = var.get("type", "any").lower() + if var_type in ["string", "str"] and not ( + var_value.startswith("'") or var_value.startswith('"') + ): + # 字符串类型需要加引号 + var_value = f"'{var_value}'" + + var_init_lines.append(f"variables['{var_name}'] = {var_value}") + + # 读取现有文件内容 + with open(package_py, "r", encoding="utf-8") as f: + content = f.read() + + # 添加变量初始化代码 + if var_init_lines: + # 在文件末尾添加变量初始化代码 + content += "\n\n# 全局变量初始化\n" + for line in var_init_lines: + content += f"{line}\n" + + # 写回文件 + with open(package_py, "w", encoding="utf-8") as f: + f.write(content) + + print(f"已将 {len(var_init_lines)} 个全局变量的初始化代码添加到 package.py") + + @classmethod + def load(cls, project_dir: str) -> "XbotProject": + """从项目目录加载 XBot 项目配置""" + package_json = os.path.join(project_dir, "package.json") + + if not os.path.exists(package_json): + raise FileNotFoundError(f"项目配置文件不存在: {package_json}") + + try: + with open(package_json, "r", encoding="utf-8") as f: + data = json.load(f) + + # 确保必需的字段存在 + if "name" not in data: + raise ValueError("项目配置缺少必需的name字段") + + # 修改流程加载逻辑 + flows = [] + main_flow = None + for flow_data in data.pop("flows", []): + kind = flow_data.get("kind", FlowKind.VISUAL.value) + flow = XbotFlow.create(**flow_data) + flow.load_flow_json(project_dir) + + if flow.name == "main": + main_flow = flow + else: + flows.append(flow) + + flow_groups = [ + FlowGroup(**group) for group in data.pop("flow_groups", []) + ] + custom_items = CustomItems(**data.pop("customItems", {})) + + # 创建项目实例 + project = cls( + name=data.pop("name"), + flows=flows, + main=main_flow, # 设置main流程 + flow_groups=flow_groups, + customItems=custom_items, + **data, + ) + project._project_dir = project_dir + print(f"已加载项目 '{project.name}' (UUID: {project.uuid})") + print(f"包含主流程: {project.main.name if project.main else 'None'}") + print(f"包含 {len(project.flows)} 个子流程:") + for flow in project.flows: + print( + f" - {flow.name} ({flow.kind})" + + (f" [组: {flow.groupName}]" if flow.groupName else "") + ) + + return project + + except json.JSONDecodeError as e: + raise ValueError(f"项目配置文件格式错误: {e}") + except Exception as e: + raise RuntimeError(f"加载项目失败: {e}") + + def _save_image_v2_file(self): + image_v2_path = os.path.join(self._project_dir, "imagesV2.xml") + + image_content = [] + image_content.append('') + image_content.append('') + image_content.append(' ') + for image in self.images.values(): + image_name = image["name"] + image_path = image["filepath"] + image_similarity = image["similarity"] + image_content.append(f' ') + image_content.append(' ') + image_content.append('') + + with open(image_v2_path, 'w', encoding='utf-8') as f: + f.write("\n".join(image_content)) + pass + + def get_image_name(self, image_file_name: str) -> str: + if image_file_name in self.images: + return self.images[image_file_name]['name'] + return "" + + def set_image_fuzzy(self, image_file_name: str, fuzzy: str) -> None: + '''设置相似度''' + try: + if image_file_name in self.images: + self.images[image_file_name]['similarity'] = int(float(fuzzy) * 100) + except Exception as e: + pass diff --git a/src/Xbot/__init__.py b/src/Xbot/__init__.py new file mode 100644 index 0000000..d116973 --- /dev/null +++ b/src/Xbot/__init__.py @@ -0,0 +1,5 @@ +from .XbotProject import XbotProject +from .XbotFlow import XbotFlow +from .Blockly.XbotBlock import XbotBlock + +__all__ = ['XbotProject', 'XbotFlow', 'XbotBlock', 'ValueRef', 'BlockInput'] \ No newline at end of file diff --git a/src/Xbot/__pycache__/CodeFlow.cpython-310.pyc b/src/Xbot/__pycache__/CodeFlow.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2885cdfbc4698a23b12373c47f842b55b26f2be6 GIT binary patch literal 3468 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 literal 0 HcmV?d00001 diff --git a/src/Xbot/__pycache__/FlowParameter.cpython-310.pyc b/src/Xbot/__pycache__/FlowParameter.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..385d29a097c40d18afff33a11b1d589cf3a754b1 GIT binary patch literal 2538 zcmb6bYi|@)bnfiz?Ck8L6-y%EW2qn9Rje&<8=|bZkSexKTM#BqCd=L_Zrzu6W`Q;} z0a^qC2r(e?2oYnDCbgi1q_nmE0RO@LYG;>z@}mhKjOX0lZFi|(oXI(R=ALuUJ@32u zP)L{Hc{ugQ(c?hxi()cU<;Y##Ab((BQeq)EM4)GzXy>4n zJ7zl831{%ck-TFbDW)@Y@DPxLdo%gty-5a&9gDRUMi|Bs!Bzojl0q~h)>gT*9Pp1o zaJ4&zmnw!zy@rpfhDLpcpK1^~zY(Ci5wt=yV1;RrN<#__(eQ)glesw}S3l3+3}? zBhju;;`?eUw}CC!9+u}OBGGtXU;J=YdOJv;`wEt8%zb@52YTxzcEEAJUnx&tFHhZz zM0}{Cb5lU)vt9@ zzcdQ6V`Q9s3bZ0Q`UqqeU)U+B(qULVF2&?x0S;T7`x;UXJ}=Jv>Ylsh&dpX*4yhD5 zT+TcarK=B07f-FoU%6EN>0u=5-a8#>#k9A^BJMXA-RV0^H_nJ!5S)(o)=H#MMa<6? z6y;j27PwYRJl9vU%)KJ3+$(a#^_6^at(F|FR`U>G8^9IzGNM-yy^82HL=i+A5w#+E z9T4{x3k8dDT~vO8u{?`;xF?md**ahwnrQNDvar(IER6dCLoA;)ZHJ|EM^UAXDiuv3 zjj#H5Fcc)RM<+p|%kn>?>l^#5txipMteI(`h4~R-8E~Iz(tOG^|DR6*F&SaHe3qx& z12(cZP~-A+s!-?#YXXGF+3Nw}?$216Gdub=~hRs|gtv=4TKhQmga6@ncaaQsxCkc?)SUN3;e znjv|eG$g|u3r#4-i!==LtBHpihH7yQSX6p^s(k-~d-*iTMMq zm5XaZ@ab<;rAt37&dkDuaL>%Zye$7XJE@8Y2-ij6**hRAd==iYo%p#8(Mquj$9zs6 zB9(G_foJ22;!&%urV{np=-NiNs?y!DmghQ(MNv7XfxQWcH<@NKm&-dz%()GXhBqt= zAj14SZzQ%$r57<7YzHC_B5VcrE}|8~1%pP`WU?t4Nl_048wJ z3wqH*i5De=cmqxJZ}7ZVX~BQNi@uqyD_@(;n>RCWe*50<_r_^%Zbb04-25>)t|9bO zE{=W_7Pn!zm%wnuaS55xj7@wOal+{;;&g?WgyTHQYQG>3<;JBw`o%ccVb?+?=Ex)# z<(QLIw1Q0ye9ATD>)`7=q5K3-0;&M^LaHy|muxEI4Bs zT1Xr>)aKylp*HQ<o-%5M~4pLy1TS6CQxJT~UrC0-Z>w-BSL z60XfX4>OaN$6QsJj1`XKC1eoA#=YdwVO;B!=EFn*? z=+SPVc-h2DIKXa)mjDg%GKRBc#o!v(A({k)Cwwfry@r6SV4j@OM0bGu(UX=Xs!$pO z3J6-D1!RVZu7DDRQ69}-2_U)yysY7OLLw3C2ix2GdoT9)whlHv*4B3GlBoZG85`{#8exy~_gUXi?h$*Kf57hbGZvzp!0@MRlb|pO*$+Yz zA|#ih0Zgb(mYlJ$b-*rJIma7t{4&2Igd>C`Eu_G1NJ~~ZG{%aqRW8n2S>0?<*)eX5 z$d#UJrlrQ*ny||jXEqNF86}Uxr1EV3zbAwt(UsB@aMxr1Vw+&!Z3mN~ZCJwwPQz^A z6bu8CKgQYmAICVRKR}`Q9b{l}Qh(5c`0^mqqxy9N$gRtu73b#MtbQhY=ithbf>gV! zs#3BeYRg=*b<#S86 MlPg=pKnBjxze5RMEdT%j literal 0 HcmV?d00001 diff --git a/src/Xbot/__pycache__/VisualFlow.cpython-310.pyc b/src/Xbot/__pycache__/VisualFlow.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39dc78b62e36e6626a70baf43564fd5b62775e03 GIT binary patch literal 2811 zcmZ`5YmXd9vAd^dc6Ro8=SMgqf|DSmMd5fzKrpAnn6pC^bU|_wVB}~tx7};zJdbtH ztnEAPNkl$^2pm=<gsxT zRn26LhDYGJ`R?D(jcbJb12+dB8#X6kx?hKLE}XcLH2tQ*D{(7n`K_ewx04xvh7w7iBEl8b zO(LqYcE!3v{aIn1Asz1n@Pc%hu8Ob-yK$K3+U`X%79FnLXZuBzrD3f3_oKYfd@1S{ z+WJnqw)_Dt#oQmQWX0(?yQE!&&qS%{P+djp$vEqt?^wEl2R{f^n8-pZ-B^m0?4n*| z*3Hvs?1eBMNZfbPor6ycHYZ@^?*Wj+r-JzGc}SaYNiJ={wy5vOigf3QtO{#^>{C6U z)?{7Qdu)!FQ@%iiE$hM&l^!?g;C@3mhO3EOJtjO++vI+$T7h4^S`kM?10F(RVgtWDU?1h842zp_+$kdv4RxpRTu646CEt3YDzRFf%6NpG@N6BKK(&a7# zjnfAUumS74u=20NO%-I7j@Xb2I%XSeZ^wpY)%qTP?6vHMX8NR*s?-@No8r5EUn!T(QddzC!ZfTmql)_hVQXbLXMK=OBaI zw}0J(JDXq4vvlX$&$n;?W%9~s_s*U2+9rQ|WBYHvSm*OXUR?L)_c;fj1<~Cbzn{GN z%JE|*Ybm^aYin}j^~sxWA3wINsam%OMemDG!tJ{B-2FAfC}yPr>&D~ zo$|>9KfLHt0;xBko6_Ff%(xq z&O)KBbFxqmp)L$T!5AdE+EZBqH478O3Hu-+)Epkx5i}7PyPoE`jC<-3%2Xh!rp&9D z*T6VKdz#~{(w=FKz~HvQ_j0vIGI@K4s3$?wy^c73R;Cw&LS8P;UWVxutPG-9oW((P z_CaIL_t$h2LkNsP3<+B`|0;kcJ4)-UNjYsZk2a}ewdwSq0XF@?$-SoAwjSGEpF5!W zqguN-Kc^4k4lL8JXbLJ97lp+}))=OpV4FzcO9ZOh+S}P?$KSM}R_(zfAUL`Ca#?G; zci!FEdTaaEdy^ZlO@4N3XY~H${i`1_iUWhgIs@y&!vL@uUvxI;kdDZhyvi=HGiCDL zp}JCJ=IY=@!REiLz6R_juO;{?!Q!R}1 zML?z^|JOD3t$kYyfOVK!M8Y@rsc1~02kP4Z3~~aHj$Kx{sX|lMrWCQ{rVX%vq;04! zsmfwC98`S?7(X6jnT7m3UQv#9%Pme_CMMJ&4&urhsIKyaBdc><7v4C#;!t-ceHA@5fK+CxWB7=Act zapappJH!_d8yo?Voxk3O>9uq1=G`|ow{QRM?&zh-_18L%W|1iKbqbi&X#lz!<)=!Q z)c0WDu}mMANt#E3TP6wJQA-H+Wz|!-MX66Lm3CLju#iD2F9jx8yxAOUkU5Mp>cG$Z z->bWvu0MPru^*T0@a5&_mSI}CL4c_Z0__Dsl8Hf#cs&R%z&m&Eq!I)o>jr_cz!Z!s zD84cr{3a`>R4WL=G|h?-KTvXD#i69IIkg4c>NsxkQq)PL@s%u#6}FLj27xKY2f$P# z4v;FW{0jg)!eNX<B00$5{=7WVC*Nma_kNjQyKg>|YLN_Ze^AS11R8)%HKkWUjEO zO79(*`tYtOZ5#j5$j}jmd zp!N==$T_&QzAKU}wfbgTq6e7Rv62~+YHCX|Wl7V{WZF*tfzJIJ9!UPw=@0&;O_P4! z9(epBc^YtTZ*TYQ+ugTs-}}7BVq;@i!cVLH?!d;)lJtA}Sp3uQ@iHFck0_YL7GBT)5J( zsEp{1Rhj-$Q9Y_Fx$uz8x6-@Pq(`f=;2Oxs2AWgNs0W#LOiHzUUt%E^J|?m7Q6<&N z8uU1e;Azy`^tc}HS30Hs0E@DwV`{4X8+v1`8ND5%ckwutwXjz7tYGpkDH)%G45S@% zGRmZEM|T~_u;TD5MRRAyJYb-u;jMl6;KiKYXC@U}`$>jpGyC$o?SCz+=NXO377U%6 z>4H9-&I}Ir5ySbPf=U3-_wX2Rp)e&=X7W*mhfF!Al%+!0^ySowUz7neNP;R$;!Cqg z;6A2S)v_#FLKb?Br@db4^Oa?bHsUXRAM9t}yX~C6QoB*DjX#*VHsRd6{GVT)of|tc zbLqzP)O)oLCg#RIoPBU%wtCk2hqF6JwigUDlh5nCcKV`o_V~<)$7)B9J14%dwe*j+ zZQr?d*DhP7{im9!+&Vb8TOSzAXH4A=A4Wr(7f~j|cJM&P$e1R#ea48vNxy8RXxQo? zglGp@mKQPux*g2yGenD)PWNZ?dOB^Zxnj0p2lT^P!!#h?(7ueJr->-lXx8TvpTClL z8`%DL&#S$A^ukcu)DN3`#2WUMvU&E5!Ta{m8byJHevj)Jv&g##N9^YGe%-_XcjalU zrUjggD2lL8Q{uiBCE|<8s=_x}BGza1=ns$I{S?0Eo-1<~ZJpZFQ zJwl;gM#YjXDJ@wFO4;(ERD^o?(XLdfHBkSSaseibmY}H}mCzGn3fAH)RlvqMHST$6` zSgmq$cJjnSWVBn4@WQ#7Pj7l8oJ`t|WSDp2&AX^rNkt z9pJiI;)Oo4Df2(7)4dSq_8+L2QckYmd~!Zq={=^(aE>|OHECQqD$5eS6;rDCtJ0zt zpBc!>-gnT1-ocRU2CW}Gn%4t8#MltERTt>Rd}7ux^{`-7smfxsCa9@@QIE&1Ve!h2 z$lwscN*hVL&nYtWs1mJ8;@wo0pid2@pJ98h0@beEgiRqixf-&dO+OYQTBcA$SU0s$ z1EGQ#K35fLHSy8({WG3El<2N5wsX^W&N-jG?_9spn<&L;0rxICr_VXJKbgLF-PKBT zkfQ7yF%J|Av$rRm`^S0{!dR6^sTNto={uj-uHN!S5xd1r&WYpB#FrQwLPv>=2`$_u zpYPiZ$Dj$bmM$Jl#un*mE9m)Z6t;hmXA8LSFi(BMjFW=#1}cOB4d!7JNq=bqyZJR3 z%pFDZwPLBjwsBtMwlSQz*t2%Eq;q6?t zhnmAAp&q;jPghre)m8rryk9OT=%8fG2gOoLw7}`R?=3!d=i_tEsauC3e|P7u{GC%b zaU8HR?xBy}CJQAf8#ri3GWc!W$DD!8&F zIb31*e;5u+POEss?56{kTp`J!4-(dZHr%&j$+>`ctu=-*Id#!DjaTNs>zIOe`$^-V)jAO$kR>ZwOV}lz8Kf?XTkQxgFE@XmoD^VkS3ctNCJv zaT2jG>b6=cWtlMTwkkk_W@Lu+G(d_Fc~TJyYzONKy3kO|-k44UvBmNQbWlO&=Zj{EvJb4HSp}Iy}kf89M%| zR8~xQ`-)nXj>=`9=?4k`0yyd`tCm^`pxh^q*F#RrEDh%Mx1kOj6DaofCN>cM$g+(B8xf363Xe6~W|RhXp5Dic!-y5O zYgVcN+(a!|A?~VHO8~s;DUyao=e(Yv%RQ#vkbUd~svq%_7gUwW-E> zC)bTq-b|@I_?0$c0%5Cx-t~f!Ef$RKC6ejh`doryk*~&_sjG7rr@kgf8Q!vGOM;pJ zP~FqHe6x0L!kN05K#xl@cj<%K$;o-tP&;+SrF1_2$Jx(6`I`Lx?Bp+J?w*)_P_4ZS zx*f@toD8ZRq2K_gW(cfEvgOZGyPpivX7`5D4YxZojKP_jI)a&en(2djf$4?55xdFt zfg=9v&liX7R+n+2-+L3qFpiY*p7f1bY7z9Q54HmdsFRg37w4eh+Cf}(~%M%EYE zL;JrNoAkl%rB7$d}KmiPm7f~nySZ%V~a@ZG^BY+|;a==ezSlID!EaHzU!nT7h zte}oQMb^fY|K&dcgC*8;6&mRLh4tJBr*lCb{jWdQewwhJmS;Ci&63@a{G9K6V>w`k zDq$-CdlY;V*$@@>hwM>7>yeDj!?0)c_ftG9UCjfD5%mR`|2yb4qQ4;TEtEr6h=n>~2QAp=g9^`E{#*o>FvuFn$`z7UsM5$H zRhc!S_ZT=vt*~fAmId~dD4VSCyn`<^g96_!1&bjXaA}$sXjqFC!n*$jGq;F!KT(cY z5zNwxS>l-GpRI;U%z~fjltg7}9{&xzy9Dn) zlpC?al@=n4PA}>K|7N!ZQjW4!R-+j8GqkOOH)*MoG>7*n<)(7XiqX8FYZkS~Xx?&* z)y(`QiT~lyEPOyS{A8=uT4`mgt1@P9wW7JW)dWs$Rx4Y>{Kt`5qEjer6;ug9^^`}| zzKp6{P^}eIFL+eTd94&wj|-~TzmZB?+#`Hs3s#u+T01P^BM;58b#*EHE2OZ_lfv7O zLcH8&wLuC`h`D|%>LEy^-D(G~-&%3vCM0+cwG~zzqdTp3n(cyo=%Cry`M;b>Q*i*|m1XT%q#{wOo=q3u>+sALp^8%5F*?82w30vl) z{*u|h>AND5EWqYw3;TE2;RVkl!r9vGyUx!m)Az?`zqo=?DtRE@gK30;7Llzx&-9(U zwJ+YCxp5}3ft*gVySv*~4`vH26&T7IK)1F!pbr#FWbo_3(UqId`N`Q&ParMi4n@q{ zi*6Bodoecb>owdp^&wL+~KTo5H`?%Jzb-nj=6#(&~WZuIf2a6y16 zfCY9yxD=yAo+3dZnY+W8PbX{FZ#d&uvB^NT05@t-X3;=8a%9xk^K9=NxpUNddQm)2 z#dmt`pzF!tG_%IG0_ANvA!|F}wwDN^C-8fF_Oo9)fB*Bn3Fot`wTUkh>r2m|XMLh} z{nxeA_YqEZC!Cw(vy+#n?>#_z3|Ul4lGSNlUhBI{gxm!;7me&q)UH-)|8#l!&Xl)$ zaHfr|Ps~o-M<6tN|Dtnp$~pi3+{yFkqUe7;rkY>G3+^I-Wl2u{-CTd5GRzz68TUm>Dc-PIFhNDJL0Kg=mDVEeNO zdJH>^95gqL;jDRpQx2QcjkDu~a`eN4z>kCz>oBO9TI;9oHu3E=2pm7)p!;$qlgq2Gdp{|(wxVWG_e(aqPhh5jPX&?Nmt z0q_S5m_~?^YN$gqV(Wbnxvc>qy0GxaG;kLcyQz4CiXkdQKq9R=sSI~kKM^yfftc-vihfpqWw`D(*ocNL?~86i78+{LVbek znDRgT@37cD(&hOd1x;Sm{A+xS_SR9KyeMi`5H%xHE}~|iJs#y3>Ks_dnjqHXO!vDw+lSY`E-;FRI zybrwKJRXDBQOnvpn(#V)PB-7ZpWfBnk!=2R?&dctJzZM<2+c<-Mx@doq2ByasaVBBst&edi&c><#}83_h_3ufs`4v;Qni1>1HfNOMX7QXBTM;u z=5FtSlcU_#^v?G5%=Gkh_w@7@Iy)l@e)_-u)AN5AQk4Iom&RWJFWXR@{{mnNQ?p7= zwN#brT2{;HmYy>#L%i$RK+d$xT+j;ULRKgjw!*oH70Gp29irXHMy)9N8QD%NCZ1hZ zmw3jlxOjG3-FODFJ-JoZD$&Qx_U2Ywt8;x;pLh>u*W~)G{@hw?t*U%mVIdYiuCTBj zpIkSmTkC;|unu54>;Zu@tXqJKvQFSSecT3H2R6pKfbE*o=2Yuefr+zjV7dinkQsZF zM9&SZTS=&1EH&=9Je78Hw)=d6B{VP0Qf?}pO*xJin8?^!mN320?rAqu$fvTN@kGXP zJ!3SJc0GN2{)iXYmq&{id?Mr8Je3{8n1P+5o94wtWq&GLw7-+dGp}8Uhv*7#HLvJK_aUI1IMRHj%OQ!Slomcewa#_&QrvxP%q z4s(CTDH5ZP7nnVk2za4nGM~!X$)p!aCUXT=%u+p?OuhiJYKysl*PeabpFpSGqdP7r zd@W`Y;O5<^^fCJSNABnJl}{;pu0HWdUgN;prp18{J~WsR3bE9a{T^Z}r0%+h!7+gs;T*47cl06-5_ z*4N(t&*?k;>4gZ5y;!Ul*>QN9+m3_XYQuuDcgNFvLG$#JPwm*VXV>nrw!9321>#up zLT@X0F@W5L;yedX+uePNt=k4ux5%efed=3aWmZ761w`ExbrW@1r>KWe58ENs!xP$C zWkM5{V^|Rug{E|RowQm0dOd?Q06Je&OwVwSOxvE~1rCzhdL7Jm(mW&7pKk<xL&y%>`dS6= zq!K|Z;=hNXP91iXMdnqj(~j9)f~und8wa*qV56dMkKebmfohc)86^0c%}&AiN=bD|?)&=sk$C5oHMFHWUM;+wPu-u}$oDP_M62kNVWDlu@>s-2uvh zuRwVxOMvngF;+KtgOsqYyV%`W*9LZvt;68%Wy5&86|tPr*dv1fFzpIP{u=u_u(yGZWVESj(vPw~1NL@%a|?ciedD-+WABaznQvj= z1nr${EBn@Q#Y)(B3Enj+sR@&9W7|cayIBx6xx)*QTPF(<7U+d0GFh9P1Q$+~jBlrB z7N+gI&Bna&0bVFhkC6{Ca(1qO)31x!6RBd>O-|rcE$}0rIZnr#<3*-xPTui?%svPk zqOyamCI({$aO~VxYAH_FO6ya<(!S%RsG-a)% zGIc?l)v9m8?VLqSb6x{h7g(dDFR0E&H^B6gepWe;H~}#Tq5{_}=`6rZ7M#~lJvVE( z!E&f%EU2@AQlK2Bm}CLtB_jvm)RG+nhx&pxsyy2{Yr4^LXUPP05H7Bx94iGEFzyRm z1$CF8?x<4VH5+o{r4Yu9iZQ9y$zm9tYF#W|t#$jYJ$`K!>s`>;>UncEjCr~+Pgu;e z@4Hxop%}`XE?4t_;=FPQ9MJ!JC?f9ZE9M}x>z7}hpd)+IDdZQ=ynOxg?9`=gGL5#EPS+d_Wi{&!OGRsKH*Jc7@K`F zGVD)TycIkwzxVUX>pvVBlygchu3wz5y!U41+`A)#W1h-y28!;)y^q4phwOa1z%uy* z{84n}2?8SozCoaVQrtqX;<$K_YAt659be+$NOXHz!SRggl>5AAOcpYE{s`JU(>{#o z4sqW!&*Ty1k(Q$!Qu2&!A;moXfbB{a#O&mxz3>Dtxl@zpCZYP-8395;*g6GLrIcpk{H~I!5vz3EZC<; zwHVI3xE4`ks;S4-+EYWV{x@&NLfRjO{(ELk&Ekif$3%Q1ITJC0naNKVA)H{L=!!}t z<0Ro35WO<5LlU|fH*2RU`m6oubfm*km?=3AS8-KWE9(o&oLW*#T1hV%B}4>JXp`cD za)69TRZ8^;Ve!Mu(9gv)A1u9f{QBjeEtOxaoPPsRxt3wlN0}28a64WYZbXFBjup;0 zJ0x%X`fj2XtQ;T0C)PsD5P_Y8u>sc}hgh zEpC(!TR$R)M?CX^+#jfW%UY!OGDOJ8JF)N5)d=+sN%a-ZaGaV%?Ck5044d~+LyHb~ zl1ln#vkMBT$8k+HTlKiFNss+bO(sv~UsFzTXDumZsAmaxR%z@D(zG{$PA;^0M^9Y; z_}b$9huHbWU!VTu%1L1(7gSCbhI@f%hz6(R=xb{hm})j zT2#+h;s3W^@O!pZ{#s_``%PBxEX?5K$CVT0@_kE(7g>D!oF61qPW)u~+TT^qzCBjR z+x{eD39TL#B=iP#X{YfC0z%QVOLm_qyK|?QYtJ+cHk27n1IkeKR$ORC0V#(wYNE5-jiUgTt?mi$_@IbPa zp@ii0mmqS;R!y~G=2of|GgA*?194OsgnPVd33H_Jda)m9spX3&k1n1&+30|p2BU#! z=k}m{N+&)=^UsE7VM>$8mBO5G<9JpOV)%&%T3olXcc2W`M zzG95u5&2)!WX(ptg3t?9b(5_yZynu91j)vdkA${tuQK@NuS8-D&a;m>=F@X z0cQG}wooojkTfX@X&E^R;W0=<$YY@R*~7B2K<|`248Yv9A`w+S_<_7Zwxkgk%U3E_ zP9b$HB85jlDerA`1>s)@z>T0ylNUfNW^+N&PJ={_@1N0KI7XRQ4B@V2{?AO@Uu89+ zxMFp_KO~P*J$uPl_^e;QcAoCPIQ4$^;?mhS>Fg6ZQMs6Ein*O$%Z#Tp^>4(PusFSy zA7`pbX9J+D1!>M1ytGN5=yd2fy=cMl!!)MPYif;-5-R~DR*Y(5#bkkcGQ|xdk%BY| z3n7uxi$qFj63L2k1p8;OFeRkt@o5POi>RNlKyn%hi_xZpg-BS-goO}HV|oHY^79EY zdElFcUs-8ZUnyb1w?Q0xk;w{)bU?B&#kT`fq)f8hA<4+dpr;<+7s{okY}|Srk%8cUK@Hy_@C3CQteBhT zbEra-Md0ga68K*d)l&qT{ihdmQU~pNX5imJ;?Ox5Go#1{^dUD8SNqkWFBu*5Ehw|9tBb3>Kf?g3Tx zkZKV2)gUa?;Grfp04@v2>6nQ4IJblI0+;FgmOT=V!`~173i>7tu@hd%wR6+ilxtgIk%gf= zY1{qiNOK!xVn-G+fcPX~(l-FDA6wB&ThZ$~j|Sp2$-edrqGF;DGtP4WCB3XHAel0$ zAwEP6u?W)A_XN} zb;ydXQ)jwb1dUjFY%hJ^dyporXJh=747OV|2}B)xPs_I=N%Rm6B954^q2?Ks=>CjTZ82CFVh#?1Q(Pny6x2#`nODFSH%2MA;c zOc8Jhkj3&@0)Io`MFM2bQrpR83HQQ(M72`@UWfShEkB3z(}b=|SJWsB<_`nVH#nyZ zAU|o*2dy~%efSeJ;A?s`ZL>^%Y2DNs{T%QMQK(&% z$miPnc5T3$?eTqPEY@T8=siZC(HGMq{c4X9>e3X2999 literal 0 HcmV?d00001 diff --git a/src/Xbot/__pycache__/XbotProject.cpython-310.pyc b/src/Xbot/__pycache__/XbotProject.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d730ec579cd693790009f26d41a08d61ac0c7e0 GIT binary patch literal 12910 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 RBr{P}0x?<9@B};L{{!e^AGZJi literal 0 HcmV?d00001 diff --git a/src/Xbot/__pycache__/__init__.cpython-310.pyc b/src/Xbot/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c5beb17d7a4f4e4072a89aae4885443b944649cb GIT binary patch literal 306 zcmd1j<>g`kf(>g~MrY#{SM#4q&}tC-ZhviOqJijtTLpuO=)rI|S?F(AD$@$s2?nI-Y@ edIgoYIBatBQ%ZAE?Lh7?<^U2r3_OfL$OHhSB}z;H literal 0 HcmV?d00001 diff --git a/src/Xbot/__pycache__/bot_import.cpython-310.pyc b/src/Xbot/__pycache__/bot_import.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b2279d9c4b27bb176b67714564746f64dd2ed86 GIT binary patch literal 1229 zcmZWo&2Aev5GMCuvg`y-o8}a3Z`r^}16z#|qiCwcJ{T~RAaaUgA%IvdnVRWpsgRT- z3+qeVwV!)3uK$K8Du@PO{E>cpdfg&E21OyW8EnyWM*`cf0qt@9b=s z*dBcx9_R?OeTaD zx_E=+8l>>=t^K_rTql~%^l&y3nvABrqCY8F4*!7d(3<#oBBZ`OIWynG3&gp(xGox( zEn5*Z2zBr#mg}%6eV9HCTXYQK3V#3#jT(G`&wUN$H$IdfG{M4OqVuo`7Xif$YM^b@ ze-BBvv(DRSVr~`)JH0WTa=Mk) z#h7iSQb0AwXA@X*H2}90K#k8C&C=g{M^6t1>5cna?#ql15u|Nj7MshTtEMCJj91LW z>P5vh+c9w|>YA0>MCDW}A@i8cSUJ@!k4iBfb7)mr3B|I=L>4VhrRB6q?8atgIu6NC zfdd;)Zi0*J&uZ$}8ymcaR%%kSm$teMuqk_x;5JV1cOV@suYutk(%H^9?C-#0MLG>6 zyTCv_&ruIs>MgOlszd5Ect!qKxB-f1et(|W6mQef&iu!+sMA{L)S{3o$Hx>vP3g#) z_R=hp_P3OYoh&gNA56q%Txn%GPo}lzV|E~=keTPekXNmnrQ?@!cN=x{+z`2_zRuN~INM7r&5_GA$rX;_N1)WyxSIZP-(NCZu2@d?kPr{^?#5VEk HIQZ{>ZwEC9 literal 0 HcmV?d00001 diff --git a/src/Xbot/bot_import.py b/src/Xbot/bot_import.py new file mode 100644 index 0000000..22b3e4e --- /dev/null +++ b/src/Xbot/bot_import.py @@ -0,0 +1,33 @@ +import os +import sqlite3 +import uuid + +#TODO(huifu): 演示的用用户ID +USER_ID = "757424674936492032" + + +def get_xbot_user_app_dir(user_id): + local_app_data = os.environ.get('LOCALAPPDATA') + return os.path.join(local_app_data, "ShadowBot", "users", user_id) + + +def insert_new_app(app_id, user_id, app_name): + user_db_file = get_xbot_db_file(user_id) + conn = sqlite3.connect(user_db_file) + cursor = conn.cursor() + cursor.execute('INSERT INTO developmentsync_apps_v2 (uuid, name, robotType, isSynchronized) VALUES (?,?,?,?)', (app_id, app_name, "app", 0)) + conn.commit() + conn.close() + + +def get_xbot_db_file(user_id): + user_db_file = os.path.join(get_xbot_user_app_dir(user_id), "user.db3") + if not os.path.exists(user_db_file): + raise RuntimeError(f"can not file shadow bot db file: {user_db_file}") + return user_db_file + + +if __name__ == "__main__": + uuid_str = str(uuid.uuid4()) + print(f"start insert app : {uuid_str}") + insert_new_app(str(uuid.uuid4()), USER_ID, f"test-{uuid_str}") diff --git a/src/assert/block_settings/asset.blocks.json b/src/assert/block_settings/asset.blocks.json new file mode 100644 index 0000000..4129512 --- /dev/null +++ b/src/assert/block_settings/asset.blocks.json @@ -0,0 +1,77 @@ +{ + "types": [], + "blocks": [ + { + "name": "asset.get_asset", + "title": "获取资产", + "icon": "BlockIcons/36-1.png", + "comment": "获取%asset_name%的资产值", + "description": "获取资产信息", + "function": "xbot_visual.asset.get_asset", + "settingsControl": "ShadowBot.Shell.Console.BlockSettings.Controls.Asset.GetAssetControl, ShadowBot.Shell.Console", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/获取资产.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Asset.GetAssetHandler" + } + ], + "inputs": [ + { + "name": "asset_name", + "label": "资产名称", + "required": true, + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "asset_type", + "label": "资产类型", + "required": true, + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "encrypt_flag", + "label": "资产值加密标志", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "value", + "label": "保存普通资产值至", + "variableLabel": "资产值", + "tips": "输入一个变量用来保存普通资产的资产值", + "name": "value", + "type": "str" + }, + { + "id": "user_name", + "label": "保存凭证资产用户名至", + "variableLabel": "凭证用户名", + "tips": "输入一个变量用来保存凭证资产的用户名", + "name": "user_name", + "type": "str" + }, + { + "id": "password", + "label": "保存凭证资产密码至", + "variableLabel": "凭证密码", + "tips": "输入一个变量用来保存凭证资产的密码,获取的凭证资产密码为加密文本,会在使用填写密码框指令时被自动解密", + "name": "password", + "type": "str" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/base64.blocks.json b/src/assert/block_settings/base64.blocks.json new file mode 100644 index 0000000..91ff6c9 --- /dev/null +++ b/src/assert/block_settings/base64.blocks.json @@ -0,0 +1,101 @@ +{ + "types": [], + "blocks": [ + { + "name": "base64.encode", + "function": "xbot_visual.base64.encode", + "title": "Base64编码", + "description": "Base64编码", + "comment": "Base64编码%source%,将编码结果保存到%base64_encode_result%", + "icon": "BlockIcons/15-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/base64编解码/base64编码.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Base64.EncodeHandler" + } + ], + "inputs": [ + { + "name": "source", + "label": "内容", + "required": true, + "tips": "输入待编码的内容", + "type": "any", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "output_string", + "label": "", + "required": true, + "tips": "输出字符串", + "type": "bool", + "default": "13:True", + "editor": { + "label": "输出字符串", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "base64_encode_result", + "label": "保存编码结果至", + "variableLabel": "Base64编码结果", + "tips": "输入一个名字,用来保存Base64编码结果", + "type": "any", + "name": "base64_encode_result" + } + ] + }, + { + "name": "base64.decode", + "function": "xbot_visual.base64.decode", + "title": "Base64解码", + "description": "Base64解码", + "comment": "Base64解码%source%,将解码结果保存到%base64_decode_result%", + "icon": "BlockIcons/15-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/base64编解码/base64解码.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Base64.DecodeHandler" + } + ], + "inputs": [ + { + "name": "source", + "label": "待解码内容", + "required": true, + "tips": "输入待解码的内容", + "type": "any", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "output_string", + "label": "", + "required": true, + "tips": "输出字符串", + "type": "bool", + "default": "13:True", + "editor": { + "label": "输出字符串", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "base64_decode_result", + "label": "保存解码结果至", + "variableLabel": "base64解码结果", + "tips": "输入一个名字,用来保存base64解码结果", + "type": "any", + "name": "base64_decode_result" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/buildin_types.json b/src/assert/block_settings/buildin_types.json new file mode 100644 index 0000000..7c024cc --- /dev/null +++ b/src/assert/block_settings/buildin_types.json @@ -0,0 +1,142 @@ +[ + { + "name": "any", + "localName": "任意类型", + "group_order": "6" + }, + { + "name": "int", + "localName": "整数", + "pythonName": "int", + "group": "Common", + "group_order": "2", + "methods": [ + { + "display": "转字符串", + "function": "str($0)", + "type": "str" + } + ] + }, + { + "name": "float", + "localName": "小数", + "pythonName": "float", + "group_order": "7", + "methods": [ + { + "display": "转字符串", + "function": "str($0)", + "type": "str" + }, + { + "display": "取整数部分", + "function": "int($0)", + "type": "int" + } + ] + }, + { + "name": "bool", + "localName": "布尔值", + "pythonName": "bool", + "group": "Common", + "group_order": "3" + }, + { + "name": "str", + "localName": "字符串", + "pythonName": "str", + "group": "Common", + "group_order": "1", + "methods": [ + { + "display": "删除两端空格", + "function": "$0.strip()", + "type": "str" + }, + { + "display": "转数字(整数)", + "function": "int($0)", + "type": "int" + }, + { + "display": "转数字(小数)", + "function": "float($0)", + "type": "float" + } + ] + }, + { + "name": "list", + "localName": "列表", + "pythonName": "list,set,tuple", + "group": "Common", + "group_order": "4", + "methods": [ + { + "display": "列表第$1项", + "function": "$0[--$1]", + "type": "any", + "params": [ + { + "name": "$1", + "default": "1" + } + ], + "editor": "spin" + }, + { + "display": "列表倒数第$1项", + "function": "$0[-$1]", + "type": "any", + "params": [ + { + "name": "$1", + "default": "1" + } + ], + "editor": "spin" + }, + { + "display": "列表长度", + "function": "len($0)", + "type": "int" + } + ] + }, + { + "name": "dict", + "localName": "字典", + "group": "Common", + "pythonName": "dict", + "group_order": "5" + }, + { + "name": "file", + "localName": "文件路径", + "pythonName": "str" + }, + { + "name": "directory", + "localName": "文件夹路径", + "pythonName": "str" + }, + { + "name": "bytes", + "localName": "二进制数据", + "pythonName": "bytes", + "methods": [ + { + "display": "转字符串", + "function": "str($0)", + "type": "str" + } + ] + }, + { + "name": "datetime", + "localName": "日期时间", + "pythonName": "datetime.datetime" + } +] \ No newline at end of file diff --git a/src/assert/block_settings/chatgpt.blocks.json b/src/assert/block_settings/chatgpt.blocks.json new file mode 100644 index 0000000..84c4860 --- /dev/null +++ b/src/assert/block_settings/chatgpt.blocks.json @@ -0,0 +1,212 @@ +{ + "types": [], + "blocks": [ + { + "name": "chatgpt.completions", + "icon": "BlockIcons/23-8.png", + "description": "可通过自然语言对话让AI完成原创写作、检查纠错、客服对话、翻译等任务", + "comment": "通过%ai_engine%GPT引擎,提问内容%question%,将结果保存到%chatgpt_result%", + "title": "影刀GPT", + "keywords": "Chat", + "function": "xbot_visual.chatgpt.completions", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/chatgpt.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.ChatGPT.ChatGPTControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.ChatGPT.ChatGPTHandler" + } + ], + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择AI引擎类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "model", + "label": "模型", + "required": false, + "tips": "调用的AI模型版本,请仔细确认价格后切换", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀GPT-3.5", + "value": "gpt35_turbo" + }, + { + "display": "影刀GPT-4.0", + "value": "gpt-4" + } + ] + } + }, + { + "name": "use_knowledge", + "label": "扩展能力", + "required": false, + "tips": "选择知识库,让GPT生成更懂业务的回答", + "type": "bool", + "default": "13:False", + "editor": { + "kind": "checkbox", + "label": "知识库" + } + }, + { + "name": "knowledge", + "label": "知识库", + "required": false, + "tips": "选择知识库,让GPT生成更懂业务的回答", + "type": "str", + "editor": { + "kind": "select" + } + }, + { + "name": "prompt", + "label": "角色定义", + "tips": "定义GPT的角色和回答要求。如:扮演影刀客服,回答要专业", + "type": "str", + "required": false, + "editor": { + "kind": "textbox", + "placeholder": "选填,定义角色与回答要求" + } + }, + { + "name": "question", + "label": "提问", + "tips": "最多可输入1600字,请勿包含敏感词", + "type": "str", + "required": true, + "editor": { + "kind": "textbox", + "placeholder": "最多可输入1600字,请勿包含敏感词" + } + }, + { + "name": "maxWords", + "label": "最大回答字数", + "required": false, + "category": "advanced", + "tips": "默认值为 -1,代表不限制", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认不限制" + } + }, + { + "name": "temperature", + "label": "创意性参数", + "required": false, + "category": "advanced", + "tips": "在0-2之间值越高越有创意性", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "选填,范围0-2,默认为1,值越高越有创意性" + } + } + ], + "outputs": [ + { + "id": "chatgpt_result", + "label": "返回结果保存至", + "variableLabel": "gpt文本", + "tips": "指定一个变量,该变量用于保存返回的文本", + "type": "str", + "name": "gpt_result" + } + ] + }, + { + "name": "dynamic.magic", + "icon": "Png/Magic/icon_magicaction2.png", + "statement": "programing.empty", + "description": "通过文字描述生成处理类指令,包括列表、文本、时间日期、逻辑等", + "comment": "", + "title": "魔法指令", + "function": "", + "helpUrl": "yddoc/language/zh-cn/指令文档/魔法指令/魔法指令说明.html", + "inputs": [], + "outputs": [], + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Magic.MagicHandler" + } + ] + }, + { + "name": "ai.power", + "statement": "ai.power", + "icon": "BlockIcons/ai_power.png", + "description": "在影刀中调用并执行AI Power应用,增强AI自动化的场景与能力", + "comment": "执行AI应用%flowId%,将结果保存到%ai_power_result%", + "title": "AI应用", + "keywords": "", + "function": "xbot_visual.chatgpt.ai_power", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能AI/AI应用.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.AIPower.AIPowerControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.AIPower.AIPowerBlockHandler" + } + ], + "inputs": [ + { + "name": "flowId", + "label": "选择应用", + "required": true, + "tips": "从“我的AI应用”列表中选择一个应用", + "type": "str", + "editor": { + "kind": "select" + } + }, + { + "name": "inputs", + "label": "输入参数", + "required": false, + "tips": "输入参数列表", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "outputs", + "label": "输出参数", + "required": false, + "tips": "输出参数列表", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "ai_power_result", + "label": "输出结果保存至", + "tips": "", + "name": "ai_power_result", + "type": "dict" + } + ] + } + ] +} diff --git a/src/assert/block_settings/clipboard.blocks.json b/src/assert/block_settings/clipboard.blocks.json new file mode 100644 index 0000000..4918a37 --- /dev/null +++ b/src/assert/block_settings/clipboard.blocks.json @@ -0,0 +1,83 @@ +{ + "types": [], + "blocks": [ + { + "name": "clipboard.get_text", + "function": "xbot_visual.win32.clipboard_get_text", + "title": "获取剪切板文本", + "keywords": "剪贴板", + "description": "这个指令用来获取剪切板文本内容", + "comment": "获取剪切板中的文本内容,将结果保存到%clipboard_text%", + "icon": "BlockIcons/24-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/剪切板/获取剪切板内容.html", + "outputs": [ + { + "id": "clipboard_text", + "label": "保存剪切板文本至", + "variableLabel": "剪切板文本", + "tips": "获取剪切板中文本内容", + "type": "str", + "name": "clipboard_text" + } + ] + }, + { + "name": "clipboard.set_text", + "function": "xbot_visual.win32.clipboard_set_text", + "title": "设置剪切板内容", + "keywords": "剪贴板", + "description": "这个指令用来设置剪切板内容", + "comment": "将内容源%text%设置到剪切板中", + "icon": "BlockIcons/24-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/剪切板/设置剪切板内容.html", + "inputs": [ + { + "name": "text", + "label": "内容源", + "required": true, + "tips": "请输入要设置到剪切板中的文本内容", + "type": "str", + "editor": { + "kind": "memoedit" + } + } + ] + }, + { + "name": "clipboard.clear", + "function": "xbot_visual.win32.clipboard_clear", + "title": "清空剪切板", + "keywords": "剪贴板", + "description": "这个指令用来清空剪切板内容", + "comment": "清空当前剪切板中的内容", + "icon": "BlockIcons/24-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/剪切板/清空剪切板.html" + }, + { + "name": "clipboard.set_file", + "function": "xbot_visual.win32.clipboard_set_file", + "title": "将文件添加到剪切板", + "keywords": "剪贴板", + "description": "这个指令用来将文件添加到剪切板中,可用于文件的快捷发送", + "comment": "将文件%file_path%添加到剪切板中", + "icon": "BlockIcons/24-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/剪切板/将文件添加到剪切板.html", + "inputs": [ + { + "name": "file_path", + "label": "文件路径", + "required": true, + "tips": "请输入资源文件名或文件名列表", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件(.*)|*.*" + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/code.template.py b/src/assert/block_settings/code.template.py new file mode 100644 index 0000000..86f9e3c --- /dev/null +++ b/src/assert/block_settings/code.template.py @@ -0,0 +1,13 @@ +# 使用提醒: +# 1. xbot包提供软件自动化、数据表格、Excel、日志、AI等功能 +# 2. package包提供访问当前应用数据的功能,如获取元素、访问全局变量、获取资源文件等功能 +# 3. 当此模块作为流程独立运行时执行main函数 +# 4. 可视化流程中可以通过"调用模块"的指令使用此模块 + +import xbot +from xbot import print, sleep +from .import package +from .package import variables as glv + +def main(args): + pass \ No newline at end of file diff --git a/src/assert/block_settings/csv.blocks.json b/src/assert/block_settings/csv.blocks.json new file mode 100644 index 0000000..ddbf0ce --- /dev/null +++ b/src/assert/block_settings/csv.blocks.json @@ -0,0 +1,176 @@ +{ + "types": [], + "blocks": [ + { + "name": "csv.read", + "function": "xbot_visual.csv.read", + "title": "读取CSV数据", + "description": "读取CSV数据", + "comment": "读取%csv_path%文件,并将读取结果保存到%row_values%", + "icon": "BlockIcons/29-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/csv读写/读取csv数据.html", + "inputs": [ + { + "name": "csv_path", + "label": "CSV文件路径", + "required": true, + "tips": "输入CSV文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "CSV文件 (.csv)|*.csv" + } + } + }, + { + "name": "encoding", + "label": "文件编码", + "required": true, + "default": "10:UTF-8", + "defaultDisplay": "UTF-8", + "tips": "选择文本编码格式,UTF-8-SIG为带有 BOM 的 UTF-8", + "type": "str", + "editor": { + "kind": "editselect", + "options": [ + "ANSI", + "UTF-8", + "UTF-8-SIG" + ] + } + }, + { + "name": "delimiter", + "label": "内容分隔符", + "required": false, + "tips": "选择内容分隔符,默认为逗号", + "type": "str", + "defaultDisplay": "逗号", + "editor": { + "kind": "select", + "options": [ + { + "display": "逗号", + "value": "," + }, + { + "display": "分号", + "value": ";" + }, + { + "display": "冒号", + "value": ":" + }, + { + "display": "空格", + "value": " " + }, + { + "display": "Tab键", + "value": "\t" + } + ] + } + }, + { + "name": "first_row_is_header", + "label": "", + "required": true, + "tips": "CSV文件首行是否是列头", + "type": "bool", + "default": "13:False", + "editor": { + "label": "首行是列头", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "row_values", + "label": "保存行数据至", + "variableLabel": "CSV数据", + "tips": "输入一个名字,用来保存读取的行数据", + "type": "list>", + "name": "row_values" + } + ] + }, + { + "name": "csv.write", + "function": "xbot_visual.csv.write", + "title": "数据写入CSV", + "description": "数据写入CSV", + "comment": "将%values%通过%write_way%方式写入到%csv_path%", + "icon": "BlockIcons/29-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/csv读写/数据写入csv.html", + "inputs": [ + { + "name": "csv_path", + "label": "CSV文件路径", + "required": true, + "tips": "输入CSV文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "CSV文件 (.csv)|*.csv" + } + } + }, + { + "name": "encoding", + "label": "文件编码", + "required": true, + "default": "10:UTF-8", + "defaultDisplay": "UTF-8", + "tips": "选择文本编码格式", + "type": "str", + "editor": { + "kind": "editselect", + "options": [ + "ANSI", + "UTF-8", + "UTF-8-SIG" + ] + } + }, + { + "name": "write_way", + "label": "写入方式", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖写入", + "tips": "选择写入方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "追加写入", + "value": "append" + }, + { + "display": "覆盖写入", + "value": "overwrite" + } + ] + } + }, + { + "name": "values", + "label": "行数据", + "required": true, + "tips": "输入待写入CSV文件的行数据", + "type": "list>", + "editor": { + "kind": "textbox" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/database.blocks.json b/src/assert/block_settings/database.blocks.json new file mode 100644 index 0000000..e061d8a --- /dev/null +++ b/src/assert/block_settings/database.blocks.json @@ -0,0 +1,250 @@ +{ + "types": [ + { + "name": "xbot.database", + "localName": "数据库连接", + "pythonName": "xbot.ado.Database", + "props": [] + } + ], + "blocks": [ + { + "name": "database.connect", + "icon": "BlockIcons/25-1.png", + "description": "使用数据库连接字符串连接到数据库", + "comment": "使用%conn_str%数据库连接字符串创建数据库连接对象,并保存到%database%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Database.ConnectControl, ShadowBot.Shell.Development", + "title": "连接数据库", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/数据库/连接数据库.html", + "function": "xbot_visual.database.connect", + "inputs": [ + { + "name": "conn_str", + "label": "连接字符串", + "required": true, + "tips": "输入数据库连接字符串", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "Custom" + } + } + } + ], + "outputs": [ + { + "id": "database", + "label": "保存数据库连接对象至", + "variableLabel": "数据库连接", + "tips": "指定一个变量名称,该变量用于存储数据库连接对象", + "type": "xbot.database", + "name": "database" + } + ] + }, + { + "name": "database.close", + "icon": "BlockIcons/25-3.png", + "description": "关闭数据库", + "comment": "关闭数据库连接%database%", + "title": "关闭数据库", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/数据库/关闭数据库.html", + "function": "xbot_visual.database.close", + "inputs": [ + { + "name": "database", + "label": "数据库连接对象", + "required": true, + "tips": "输入数据库连接对象", + "type": "xbot.database", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ] + }, + { + "name": "database.exec", + "icon": "BlockIcons/25-2.png", + "description": "在指定数据库中,执行Insert、Update、Delete、Select等SQL语句", + "comment": "在%database%中执行SQL:%sql%,结果保存到%recordset%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Database.ExecControl, ShadowBot.Shell.Development", + "title": "执行SQL语句", + "keywords": "查询;修改;删除;插入;Insert;Update;Delete;Select", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/数据库/查询数据库.html", + "function": "xbot_visual.database.exec", + "inputs": [ + { + "name": "connect_way", + "label": "连接方式", + "required": true, + "default": "10:database", + "defaultDisplay": "数据库连接对象", + "tips": "选择一个数据库连接方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "数据库连接对象", + "value": "database" + }, + { + "display": "数据库连接字符串", + "value": "conn_str" + } + ] + } + }, + { + "name": "database", + "label": "数据库连接对象", + "required": false, + "tips": "选择数据库连接对象", + "type": "xbot.database", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "conn_str", + "label": "数据库连接字符串", + "required": false, + "tips": "请输入数据库连接字符串", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "Custom" + } + } + }, + { + "name": "sql", + "label": "数据库查询语句", + "required": true, + "tips": "请输入数据库查询语句", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "timeout_seconds", + "label": "超时秒数", + "required": true, + "tips": "请输入数据库查询超时秒数", + "type": "int", + "default": "10:30", + "editor": { + "kind": "textbox" + } + }, + { + "name": "result_toString", + "label": "", + "category": "advanced", + "type": "bool", + "tips": "若勾选,查询结果的每一个值会转成文本格式输出,否则保留原格式输出", + "default": "13:True", + "editor": { + "label": "以文本格式输出", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "recordset", + "label": "保存查询结果至", + "variableLabel": "数据库查询结果", + "tips": "指定一个变量名称,该变量用于存储数据库查询结果", + "type": "list>", + "name": "recordset" + } + ] + }, + { + "name": "database.batch_insert", + "icon": "BlockIcons/25-4.png", + "description": "将多组数据一次性插入到一张表中,结果为全部正确或全部失败", + "comment": "在%database%中执行批量插入%sql%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Database.BatchInsertControl, ShadowBot.Shell.Development", + "title": "数据库批量插入数据", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/数据库/数据库批量插入数据.html", + "function": "xbot_visual.database.batch_insert", + "inputs": [ + { + "name": "connect_way", + "label": "连接方式", + "required": true, + "default": "10:database", + "defaultDisplay": "数据库连接对象", + "tips": "选择一个数据库连接方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "数据库连接对象", + "value": "database" + }, + { + "display": "数据库连接字符串", + "value": "conn_str" + } + ] + } + }, + { + "name": "database", + "label": "数据库连接对象", + "required": false, + "tips": "选择数据库连接对象", + "type": "xbot.database", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "conn_str", + "label": "数据库连接字符串", + "required": false, + "tips": "请输入数据库连接字符串", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "Custom" + } + } + }, + { + "name": "sql", + "label": "数据库插入语句", + "required": true, + "tips": "请输入数据库插入语句", + "type": "str", + "editor": { + "kind": "memoedit", + "placeholder": "例:INSERT INTO `test` 或 INSERT INTO `test` (`id`, `name`)" + } + }, + { + "name": "data", + "label": "待插入数据", + "required": true, + "tips": "请输入需要批量插入的数据,格式为二维列表", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/datetime.blocks.json b/src/assert/block_settings/datetime.blocks.json new file mode 100644 index 0000000..36c4e50 --- /dev/null +++ b/src/assert/block_settings/datetime.blocks.json @@ -0,0 +1,583 @@ +{ + "types": [ + { + "name": "xbot_visual.datetime.DateTimeParts", + "localName": "日期时间详情", + "props": [ + { + "name": "year", + "type": "int", + "label": "年份" + }, + { + "name": "month", + "type": "int", + "label": "月份" + }, + { + "name": "day", + "type": "int", + "label": "天数" + }, + { + "name": "hour", + "type": "int", + "label": "小时" + }, + { + "name": "minute", + "type": "int", + "label": "分钟" + }, + { + "name": "second", + "type": "int", + "label": "秒数" + }, + { + "name": "weekday", + "type": "int", + "label": "星期" + }, + { + "name": "lastday_of_month", + "type": "int", + "label": "当月最后一天" + }, + { + "name": "week_of_year", + "type": "int", + "label": "当年第几周" + }, + { + "name": "day_of_year", + "type": "int", + "label": "当年第几天" + } + ] + } + ], + "blocks": [ + { + "name": "datetime.now", + "function": "xbot_visual.datetime.now", + "title": "获取当前日期时间", + "description": "获取当前日期时间", + "comment": "获取当前日期时间,将结果保存到%datetime_instance%", + "icon": "BlockIcons/17-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/日期时间/获取当前时间.html", + "outputs": [ + { + "id": "datetime_instance", + "label": "保存当前日期时间至", + "variableLabel": "当前的日期时间对象", + "tips": "输入一个变量,用来保存当前日期时间", + "type": "datetime", + "name": "current_datetime" + } + ] + }, + { + "name": "datetime.difference", + "function": "xbot_visual.datetime.difference", + "title": "获取时间间隔", + "description": "获取时间间隔", + "comment": "获取%begin_datetime%到%end_datetime%间隔的%unit%数,将结果保存至%datetime_difference%", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Datetime.DifferenceHandler" + } + ], + "icon": "BlockIcons/17-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/日期时间/获取时间间隔.html", + "inputs": [ + { + "name": "begin_datetime", + "label": "开始时间", + "required": false, + "tips": "输入开始时间。若日期是文本,只支持常用格式,如:2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等", + "type": "any", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本。若空,则为系统的当前时间" + } + }, + { + "name": "end_datetime", + "label": "结束时间", + "required": false, + "tips": "输入结束时间。若日期是文本,只支持常用格式,如:2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等", + "type": "datetime", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本。若空,则为系统的当前时间" + } + }, + { + "name": "unit", + "label": "时间间隔单位", + "required": true, + "default": "10:second", + "defaultDisplay": "秒", + "tips": "选择时间间隔的时间单位", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "秒", + "value": "second" + }, + { + "display": "分钟", + "value": "minute" + }, + { + "display": "小时", + "value": "hour" + }, + { + "display": "天", + "value": "day" + } + ] + } + } + ], + "outputs": [ + { + "id": "datetime_difference", + "label": "保存时间间隔至", + "variableLabel": "时间间隔", + "tips": "输入一个变量,用来保存时间间隔", + "type": "int", + "name": "datetime_difference" + } + ] + }, + { + "name": "datetime.add", + "function": "xbot_visual.datetime.add", + "title": "增加/减少时间", + "description": "在指定日期时间上进行时间增加或者减少,支持文本格式的日期", + "comment": "将%datetime%%timeway%%duration%%unit%,将结果保存到%datetime_instance%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Datetime.AddControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Datetime.AddHandler" + } + ], + "icon": "BlockIcons/17-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/日期时间/增加时间.html", + "inputs": [ + { + "name": "datetime", + "label": "原日期时间", + "required": false, + "tips": "输入日期时间。若日期是文本,只支持常用格式,如: 2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等", + "type": "any", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本。若空,为系统的当前时间" + } + }, + { + "name": "timeway", + "label": "调整方式", + "required": true, + "default": "10:increase", + "defaultDisplay": "增加", + "tips": "选择增加时间或者减少时间", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "增加", + "value": "increase" + }, + { + "display": "减少", + "value": "decrease" + } + ] + } + }, + { + "name": "duration", + "label": "时间长度", + "required": true, + "tips": "输入时间长度", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "unit", + "label": "时间单位", + "required": true, + "default": "10:second", + "defaultDisplay": "秒", + "tips": "选择时间单位", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "秒", + "value": "second" + }, + { + "display": "分钟", + "value": "minute" + }, + { + "display": "小时", + "value": "hour" + }, + { + "display": "天", + "value": "day" + }, + { + "display": "月", + "value": "month" + }, + { + "display": "年", + "value": "year" + } + ] + } + }, + { + "name": "output_text", + "label": "", + "required": false, + "default": "13:False", + "tips": "若勾选,指明该指令的输出为新日期的文本格式,否则为日期时间对象", + "type": "bool", + "editor": { + "label": "输出日期时间的文本", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "datetime_instance", + "label": "保存新的日期时间至", + "variableLabel": "更改时间后的日期时间对象", + "tips": "输入一个名字,用来保存更改后的日期时间", + "type": "datetime", + "name": "datetime_instance" + }, + { + "id": "datetime_text", + "label": "保存新的日期文本至", + "variableLabel": "更改时间后的日期时间文本", + "tips": "输入一个名字,用来保存更改后的日期时间的文本", + "type": "str", + "name": "datetime_text" + } + ] + }, + { + "name": "datetime.from_string", + "function": "xbot_visual.datetime.from_string", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Datetime.FromStringControl, ShadowBot.Shell.Development", + "title": "转换到日期时间", + "keywords": "文本转换", + "description": "将文本转换成日期时间,默认采用%Y-%m-%d的时间格式", + "comment": "将%text%按%format%格式转换成日期时间,并将结果保存到%datetime_instance%", + "icon": "BlockIcons/17-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/日期时间/转换到日期时间.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Datetime.FromStringHandler" + } + ], + "inputs": [ + { + "name": "text", + "label": "文本", + "required": true, + "tips": "输入待转换到日期时间的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_custom_format", + "label": "", + "required": true, + "tips": "是否使用自定义格式", + "type": "bool", + "default": "13:False", + "editor": { + "label": "使用自定义格式", + "kind": "checkbox" + } + }, + { + "name": "format", + "label": "时间格式", + "required": false, + "tips": "设置待转换文本的日期时间格式。自定义的时间格式请参考Python日期时间相关文档。", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "datetime_instance", + "label": "保存日期时间至", + "variableLabel": "文本转换后的日期时间对象", + "tips": "输入一个名字,用来保存转换后的日期时间", + "type": "datetime", + "name": "datetime_instance" + } + ] + }, + { + "name": "datetime.to_string", + "function": "xbot_visual.datetime.to_string", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Datetime.ToStringControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Datetime.ToStringHandler" + } + ], + "title": "日期时间转换为文本", + "keywords": "星期;格式化", + "description": "将日期时间转换到文本", + "comment": "将%datetime%按%format%格式转换成文本,将结果保存到%text%", + "icon": "BlockIcons/17-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/日期时间/时间转换到文本.html", + "inputs": [ + { + "name": "datetime", + "label": "日期时间", + "required": false, + "tips": "输入待转换日期。若日期是文本,只支持常用格式,如: 2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等", + "type": "any", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本。若空,为系统的当前时间" + } + }, + { + "name": "format", + "label": "时间格式", + "required": true, + "tips": "设置待转换文本的日期时间格式。自定义的时间格式请参考Python日期时间相关文档。", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "text", + "label": "保存文本至", + "variableLabel": "日期时间转换后的文本", + "tips": "输入一个名字,用来保存转换后的文本", + "type": "str", + "name": "text" + } + ] + }, + { + "name": "datetime.get_parts", + "function": "xbot_visual.datetime.get_parts", + "title": "获取时间详细信息", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Datetime.DetailHandler" + } + ], + "keywords": "日期时间;年月日时分秒;星期;当月最后一天;当年第几周;当年第几天", + "description": "获取日期时间的年、月、日、时、分、秒、星期、当月最后一天、当年第几周、当年第几天", + "comment": "获取%datetime%的时间详细信息,将结果保存到%datetime_parts%", + "icon": "BlockIcons/17-6.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/日期时间/获取时间详细信息.html", + "inputs": [ + { + "name": "datetime", + "label": "日期时间", + "required": false, + "tips": "输入日期时间。若日期是文本,只支持常用格式,如: 2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等", + "type": "any", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本。若空,为系统的当前时间" + } + } + ], + "outputs": [ + { + "id": "datetime_parts", + "label": "保存日期时间数据至", + "variableLabel": "时间的详情数据", + "tips": "输入一个名字,用来保存获得的年月日时分秒数据", + "required": true, + "type": "xbot_visual.datetime.DateTimeParts", + "name": "datetime_parts" + } + ] + }, + { + "name": "datetime.to_timestamp", + "function": "xbot_visual.datetime.to_timestamp", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Datetime.ToTimestampControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Datetime.ToTimestampHandler" + } + ], + "title": "日期时间转换为时间戳", + "keywords": "星期;格式化", + "description": "将日期时间转换为时间戳", + "comment": "将%datetime%转换成%timestamp_level%时间戳,将结果保存到%timestamp%", + "icon": "BlockIcons/17-7.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/日期时间/日期时间转换为时间戳.html", + "inputs": [ + { + "name": "datetime", + "label": "日期时间", + "required": false, + "tips": "输入待转换日期。若日期是文本,只支持常用格式,如: 2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等", + "type": "any", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本。若空,为系统的当前时间" + } + }, + { + "name": "timestamp_level", + "label": "时间戳级别", + "required": true, + "default": "10:second", + "defaultDisplay": "秒级", + "tips": "选择时间戳级别,分别为秒级,毫秒级,微秒级", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "秒级", + "value": "second" + }, + { + "display": "毫秒级", + "value": "millisecond" + }, + { + "display": "微秒级", + "value": "microsecond" + } + ] + } + } + ], + "outputs": [ + { + "id": "timestamp", + "label": "保存时间戳至", + "variableLabel": "日期时间转换后的时间戳", + "tips": "输入一个变量名,用来保存转换后的时间戳", + "type": "str", + "name": "timestamp" + } + ] + }, + { + "name": "datetime.from_timestamp", + "function": "xbot_visual.datetime.from_timestamp", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Datetime.FromTimestampControl, ShadowBot.Shell.Development", + "title": "时间戳转换为日期时间", + "description": "将时间戳转换为日期时间,默认采用秒级时间戳", + "comment": "将%timestamp%按%timestamp_level%时间戳转换成日期时间,将结果保存到%datetime_instance%", + "icon": "BlockIcons/17-8.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/日期时间/时间戳转换为日期时间.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Datetime.FromTimestampHandler" + } + ], + "inputs": [ + { + "name": "timestamp", + "label": "时间戳", + "required": true, + "tips": "输入待转换到日期时间的时间戳", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timestamp_level", + "label": "时间戳级别", + "required": true, + "default": "10:second", + "defaultDisplay": "秒级", + "tips": "选择时间戳级别,分别为秒级,毫秒级,微秒级", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "秒级", + "value": "second" + }, + { + "display": "毫秒级", + "value": "millisecond" + }, + { + "display": "微秒级", + "value": "microsecond" + } + ] + } + }, + { + "name": "output_text", + "label": "", + "required": false, + "default": "13:False", + "tips": "若勾选,指明该指令的输出为日期时间文本格式(采用默认格式%Y-%m-%d %H:%M:%S),否则为日期时间对象", + "type": "bool", + "editor": { + "label": "输出日期时间的文本", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "datetime_instance", + "label": "保存日期时间至", + "variableLabel": "时间戳转换后的日期时间对象", + "tips": "输入一个变量名,用来保存转换后的日期时间", + "type": "datetime", + "name": "datetime_instance" + }, + { + "id": "datetime_text", + "label": "保存日期文本至", + "variableLabel": "时间戳转换后的日期时间文本", + "tips": "输入一个变量名,用来保存转换后的日期时间的文本", + "type": "str", + "name": "datetime_text" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/dialog.blocks.json b/src/assert/block_settings/dialog.blocks.json new file mode 100644 index 0000000..80c25e4 --- /dev/null +++ b/src/assert/block_settings/dialog.blocks.json @@ -0,0 +1,926 @@ +{ + "types": [], + "blocks": [ + { + "name": "dialog.show_alert", + "icon": "BlockIcons/11-1.png", + "description": "打开消息对话框", + "comment": "打开消息对话框%message%", + "title": "打开消息对话框", + "function": "xbot_visual.dialog.show_alert", + "inputs": [ + { + "name": "title", + "label": "对话框标题", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "message", + "label": "对话框内容", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "dialog.show_confirm", + "icon": "BlockIcons/11-2.png", + "description": "打开确认对话框", + "comment": "打开确认对话框%message%", + "title": "打开确认对话框", + "function": "xbot_visual.dialog.show_confirm", + "inputs": [ + { + "name": "title", + "label": "对话框标题", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "message", + "label": "对话框内容", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "confirm_result", + "label": "确认结果", + "tips": "指定一个变量名称,该变量用于保存确认结果,bool类型", + "name": "confirm_result", + "type": "bool" + } + ] + }, + { + "name": "dialog.show_custom_message_box", + "icon": "BlockIcons/11-2.png", + "description": "打开信息对话框", + "comment": "打开信息对话框%message%,将点击按钮名保存到%button_result%", + "title": "打开信息对话框", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/打开信息对话框.html", + "video": { + "time": "05:32" + }, + "function": "xbot_visual.dialog.show_message_box", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.MessageBox.CustomMessageBox, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dialog.ShowCustomMessageBoxHandler" + } + ], + "inputs": [ + { + "name": "title", + "label": "对话框标题", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "message", + "label": "对话框内容", + "required": true, + "type": "str", + "editor": { + "kind": "memoEdit" + } + }, + { + "name": "buttons", + "label": "对话框按钮", + "required": true, + "default": "10:确定", + "defaultDisplay": "确定", + "tips": "选择对话框按钮", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "确定", + "value": "确定" + }, + { + "display": "是-否", + "value": "是|否" + }, + { + "display": "确定-取消", + "value": "确定|取消" + }, + { + "display": "是-否-取消", + "value": "是|否|取消" + } + ] + } + }, + { + "name": "default_button", + "label": "默认选中按钮", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_wait_timeout", + "label": "", + "required": false, + "tips": "当对话框超过设定时间没有点击按钮时,自动点击默认按钮", + "type": "bool", + "default": "13:False", + "editor": { + "label": "超时自动点击默认按钮", + "kind": "checkbox" + } + }, + { + "name": "wait_seconds", + "label": "超时秒数", + "required": false, + "tips": "设置对话框在没有用户点击时,自动关闭的超时秒数", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "button_result", + "label": "按钮名称", + "tips": "指定一个变量名称,该变量用于保存点击的按钮名称", + "variableLabel": "按钮名称", + "name": "pressed_button", + "type": "str" + } + ] + }, + { + "name": "dialog.show_custom_dialog", + "icon": "BlockIcons/11-3.png", + "description": "打开自定义对话框", + "comment": "打开自定义对话框,将输入结果保存到%dialog_result%", + "title": "打开自定义对话框", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/打开自定义对话框.html", + "video": { + "time": "08:39" + }, + "function": "xbot_visual.dialog.show_custom_dialog", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Dialog.CustomDialogControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dialog.ShowCustomDialogBlockHandler" + } + ], + "inputs": [ + { + "name": "settings", + "label": "对话框配置", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "dialog_title", + "label": "对话框标题", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "default_btn", + "label": "默认选中按钮", + "required": true, + "default": "10:确定", + "defaultDisplay": "确定", + "tips": "超时自动点击时默认点击的按钮", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "确定", + "value": "确定" + }, + { + "display": "取消", + "value": "取消" + } + ] + } + }, + { + "name": "is_auto_click", + "label": "", + "required": false, + "tips": "当对话框超过设定时间没有点击按钮时,自动点击默认按钮", + "type": "bool", + "default": "13:False", + "editor": { + "label": "超时自动点击默认按钮", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "超时秒数", + "required": false, + "tips": "设置对话框在没有用户点击时,自动关闭的超时秒数", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "globals", + "label": "全局变量集合", + "default": "13:globals()", + "type": "dict", + "editor": { + "kind": "textbox" + } + }, + { + "name": "locals", + "label": "局部变量集合", + "default": "13:locals()", + "type": "dict", + "editor": { + "kind": "textbox" + } + }, + { + "name": "storage_key", + "label": "指令ID", + "default": "13:`block_id`", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "dialog_result", + "label": "保存用户输入结果至", + "tips": "指定一个变量名称,该变量用于保存用户输入结果,如果用户取消对话框则返回None否则返回dict对象", + "name": "dialog_result", + "type": "dict" + } + ] + }, + { + "name": "dialog.show_workbook_dialog", + "icon": "BlockIcons/11-2.png", + "description": "弹出数据表格,可对数据表格进行填写或Excel导入操作", + "comment": "打开标题为%title%的数据表格对话框,将输入结果保存到数据表格中,将点击按钮名保存到%button_result%", + "title": "打开数据表格对话框", + "keywords": "Excel导入", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/打开数据表格对话框.html", + "video": { + "time": "02:49" + }, + "function": "xbot_visual.dialog.show_workbook_dialog", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.MessageBox.DataBookDialog, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "title", + "label": "对话框标题", + "tips": "对话框的标题", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "message", + "label": "提示说明", + "tips": "为数据表格的使用方法进行说明,让使用者更加容易理解", + "type": "str", + "editor": { + "kind": "memoEdit" + } + } + ], + "outputs": [ + { + "id": "button_result", + "label": "按钮名称", + "tips": "指定一个变量名称,该变量用于保存点击的按钮名称", + "variableLabel": "按钮名称", + "name": "pressed_button", + "type": "str" + } + ] + }, + { + "name": "dialog.show_input_dialog", + "icon": "BlockIcons/11-4.png", + "description": "打开输入对话框", + "comment": "打开标题为%title%的输入对话框,将输入结果保存到%input_dialog%", + "title": "打开输入对话框", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/打开输入对话框.html", + "function": "xbot_visual.dialog.show_input_dialog", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.MessageBox.InputDialog, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dialog.ShowInputDialogBlockHandler" + } + ], + "inputs": [ + { + "name": "title", + "label": "对话框标题", + "tips": "对话框标题", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "label", + "label": "对话框说明", + "tips": "对话框说明", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "type", + "label": "输入框类型", + "tips": "输入框类型", + "required": true, + "type": "str", + "default": "10:input", + "defaultDisplay": "文本框", + "editor": { + "kind": "select", + "options": [ + { + "display": "文本框", + "value": "input" + }, + { + "display": "密码框", + "value": "password" + }, + { + "display": "多行文本框", + "value": "multiInput" + } + ] + } + }, + { + "name": "value", + "label": "默认值", + "tips": "默认值", + "type": "str", + "category": "advanced", + "editor": { + "kind": "textbox" + } + }, + { + "name": "storage_key", + "label": "指令ID", + "default": "13:`block_id`", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "input_dialog", + "label": "保存用户输入结果至", + "tips": "指定一个变量名称,该变量用于保存用户输入结果,如果用户取消对话框则返回None否则返回dict对象", + "name": "input_dialog", + "type": "dict" + } + ] + }, + { + "name": "dialog.show_datetime_dialog", + "icon": "BlockIcons/11-5.png", + "description": "打开日期时间对话框", + "comment": "打开标题为%title%的日期时间对话框,将输入的日期时间保存到%datetime_dialog%", + "title": "打开日期时间对话框", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/打开日期时间对话框.html", + "function": "xbot_visual.dialog.show_datetime_dialog", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.MessageBox.DatetimeDialog, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dialog.ShowDateTimeDialogBlockHandler" + } + ], + "inputs": [ + { + "name": "title", + "tips": "对话框标题", + "label": "对话框标题", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "label", + "label": "对话框说明", + "tips": "对话框说明", + "type": "str", + "category": "advanced", + "editor": { + "kind": "textbox" + } + }, + { + "name": "kind", + "tips": "时间类型", + "label": "时间类型", + "required": true, + "default": "10:date", + "defaultDisplay": "时间", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "时间", + "value": "date" + }, + { + "display": "时间段", + "value": "dateRange" + } + ] + } + }, + { + "name": "format", + "label": "时间格式", + "tips": "时间格式", + "required": true, + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "value": "yyyy-MM-dd", + "display": "年-月-日" + }, + { + "value": "yyyy-MM-dd HH:mm:ss", + "display": "年-月-日 时:分:秒" + }, + { + "value": "yyyy/MM/dd", + "display": "年/月/日" + }, + { + "value": "yyyy/MM/dd HH:mm:ss", + "display": "年/月/日 时:分:秒" + }, + { + "value": "MM-dd-yyyy", + "display": "月-日-年" + }, + { + "value": "MM-dd-yyyy HH:mm:ss", + "display": "月-日-年 时:分:秒" + }, + { + "value": "MM/dd/yyyy", + "display": "月/日/年" + }, + { + "value": "MM/dd/yyyy HH:mm:ss", + "display": "月/日/年 时:分:秒" + } + ] + } + }, + { + "name": "begin_date", + "label": "默认时间", + "tips": "如果输入的数据无法转为时间格式则取当前时间日期", + "type": "datetime", + "editor": { + "kind": "textbox" + } + }, + { + "name": "end_date", + "label": "结束时间", + "tips": "如果输入的数据无法转为时间格式则取当前时间日期", + "type": "datetime", + "editor": { + "kind": "textbox" + } + }, + { + "name": "storage_key", + "label": "指令ID", + "default": "13:`block_id`", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "datetime_dialog", + "label": "保存时间设置结果至", + "tips": "指定一个变量名称,该变量用于保存时间设置结果,如果用户取消对话框则返回None否则返回dict对象", + "name": "datetime_dialog", + "type": "dict" + } + ] + }, + { + "name": "dialog.show_select_dialog", + "icon": "BlockIcons/11-6.png", + "description": "打开选择对话框", + "comment": "打开标题为%title%的%select_model%对话框,将选择结果保存到%select_dialog%", + "title": "打开选择对话框", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/打开选择对话框.html", + "function": "xbot_visual.dialog.show_select_dialog", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.MessageBox.SelectDialog, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dialog.ShowSelectDialogBlockHandler" + } + ], + "inputs": [ + { + "name": "title", + "label": "对话框标题", + "tips": "对话框标题", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "label", + "label": "对话框说明", + "tips": "对话框说明", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "select_type", + "label": "选择框类型", + "tips": "选择框类型", + "required": true, + "default": "10:combobox", + "defaultDisplay": "下拉框", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "下拉框", + "value": "combobox" + }, + { + "display": "列表", + "value": "list" + } + ] + } + }, + { + "name": "select_model", + "label": "选择模式", + "tips": "选择模式", + "required": true, + "default": "10:single", + "defaultDisplay": "单选", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单选", + "value": "single" + }, + { + "display": "多选", + "value": "multi" + } + ] + } + }, + { + "name": "values", + "label": "选项列表", + "tips": "选项列表,每行代表一个选项", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "is_selected_first", + "label": "", + "tips": "默认选中第一项", + "required": true, + "default": "13:True", + "type": "bool", + "editor": { + "kind": "checkbox", + "label": "默认选中第一项" + } + }, + { + "name": "storage_key", + "label": "指令ID", + "default": "13:`block_id`", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "select_dialog", + "label": "保存用户选择结果至", + "tips": "指定一个变量名称,该变量用于保存用户选择结果,如果用户取消对话框则返回None否则返回dict对象", + "name": "select_dialog", + "type": "dict" + } + ] + }, + { + "name": "dialog.show_select_file_dialog", + "icon": "BlockIcons/11-7.png", + "description": "打开选择文件对话框", + "comment": "打开标题为%title%的选择文件对话框,将文件路径保存到%select_file_dialog%", + "title": "打开选择文件对话框", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/打开选择文件对话框.html", + "function": "xbot_visual.dialog.show_select_file_dialog", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dialog.ShowSelectFileBlockHandler" + } + ], + "inputs": [ + { + "name": "title", + "label": "对话框标题", + "tips": "对话框标题", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "folder", + "label": "默认文件夹", + "tips": "默认打开的文件夹路径", + "type": "str", + "category": "advanced", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "filter", + "label": "文件类型", + "tips": "文件类型", + "default": "10:所有文件 (.*)|*.*", + "type": "str", + "editor": { + "kind": "editselect", + "options": [ + "所有文件|*.*", + "Excel文件|*.xls;*.xlsx", + "Word文件|*.doc;*.docx", + "文本文件|*.txt", + "图像文件|*.png;*.jpg;*.bmp", + "PPT文件|*.ppt;*.pptx", + "压缩文件|*.zip;*.rar" + ] + } + }, + { + "name": "is_multi", + "label": "", + "tips": "允许选择多个文件", + "type": "bool", + "default": "13:False", + "editor": { + "kind": "checkbox", + "label": "允许多选" + } + }, + { + "name": "is_checked_exists", + "label": "", + "tips": "检查文件是否存在", + "type": "bool", + "default": "13:False", + "editor": { + "kind": "checkbox", + "label": "检查文件是否存在" + } + } + ], + "outputs": [ + { + "id": "select_file_dialog", + "label": "保存文件选择结果至", + "tips": "指定一个变量名称,该变量用于保存文件选择结果,如果用户取消对话框则返回None否则返回dict对象", + "name": "select_file_dialog", + "type": "dict" + } + ] + }, + { + "name": "dialog.show_select_folder_dialog", + "icon": "BlockIcons/11-8.png", + "description": "打开选择文件夹对话框", + "comment": "打开标题为%title%的选择文件夹对话框,将文件夹路径保存到%select_folder_dialog%", + "title": "打开选择文件夹对话框", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/打开选择文件夹对话框.html", + "function": "xbot_visual.dialog.show_select_folder_dialog", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dialog.ShowSelectFolderBlockHandler" + } + ], + "inputs": [ + { + "name": "title", + "label": "对话框标题", + "tips": "对话框标题", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "folder", + "label": "默认路径", + "tips": "默认打开的文件夹路径", + "type": "str", + "category": "advanced", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + } + ], + "outputs": [ + { + "id": "select_folder_dialog", + "label": "保存文件夹选择结果至", + "tips": "指定一个变量名称,该变量用于保存文件夹选择结果,如果用户取消对话框则返回None否则返回dict对象", + "name": "select_folder_dialog", + "type": "dict" + } + ] + }, + { + "name": "dialog.show_notifycation", + "icon": "BlockIcons/11-5.png", + "description": "打开或关闭消息提示框", + "comment": "在屏幕%placement%打开或关闭%level%信息%message%", + "title": "消息通知", + "keywords": "弹框;消息提示", + "helpUrl": "yddoc/language/zh-cn/指令文档/对话框/消息通知.html", + "function": "xbot_visual.dialog.show_notifycation", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Dialog.NotifycationControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "operation_kind", + "label": "操作", + "default": "10:show", + "defaultDisplay": "打开消息通知", + "tips": "可选择打开消息通知或关闭消息通知", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "打开消息通知", + "value": "show" + }, + { + "display": "关闭消息通知", + "value": "close" + } + ] + } + }, + { + "name": "level", + "label": "消息类型", + "default": "10:info", + "defaultDisplay": "信息", + "tips": "提示框展示的信息的类型,类型有:信息、警告、错误", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "信息", + "value": "info" + }, + { + "display": "警告", + "value": "warning" + }, + { + "display": "错误", + "value": "error" + } + ] + } + }, + { + "name": "placement", + "label": "消息位置", + "default": "10:top", + "defaultDisplay": "顶部", + "tips": "提示框展示时再屏幕上的位置,位置有:顶部、底部、右下", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "顶部", + "value": "top" + }, + { + "display": "底部", + "value": "bottom" + }, + { + "display": "右下角", + "value": "rightBottom" + } + ] + } + }, + { + "name": "message", + "label": "消息内容", + "tips": "提示框要展示给用户的信息", + "type": "str", + "editor": { + "kind": "memoEdit" + } + }, + { + "name": "timeout", + "label": "关闭超时时间(秒)", + "category": "advanced", + "default": "10:3", + "tips": "通知信息展示时长,默认展示3秒", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 1 + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/dictionary.blocks.json b/src/assert/block_settings/dictionary.blocks.json new file mode 100644 index 0000000..1e94745 --- /dev/null +++ b/src/assert/block_settings/dictionary.blocks.json @@ -0,0 +1,239 @@ +{ + "types": [], + "blocks": [ + { + "name": "dictionary.create", + "function": "xbot_visual.dictionary.create", + "title": "新建字典", + "description": "新建空的字典", + "comment": "新建字典,将字典对象保存到%dict_instance%", + "icon": "BlockIcons/28-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/字典操作/新建字典.html", + "outputs": [ + { + "id": "dict_instance", + "label": "保存字典对象至", + "variableLabel": " 新建的字典对象", + "tips": "输入一个名字,用来保存新建的字典", + "type": "dict", + "name": "dict_instance" + } + ] + }, + { + "name": "dictionary.set", + "function": "xbot_visual.dictionary.set", + "title": "设置键值对", + "keywords": "字典", + "description": "这个指令用于在字典中设置一对键值,若键名已存在则修改值", + "comment": "在字典%dict%中设置新的键值对(%key%,%value%)", + "icon": "BlockIcons/28-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/字典操作/设置键值对.html", + "inputs": [ + { + "name": "dict", + "label": "字典", + "required": true, + "tips": "输入字典变量", + "type": "dict", + "editor": { + "kind": "textbox" + } + }, + { + "name": "key", + "label": "键名", + "required": true, + "tips": "输入键名", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "value", + "label": "值", + "required": true, + "tips": "输入键值", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "dictionary.get_value", + "function": "xbot_visual.dictionary.get_value", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Dictionary.GetValueControl, ShadowBot.Shell.Development", + "title": "获取键值", + "keywords": "字典", + "description": "这个指令用于在字典中获取键值", + "comment": "在字典%dict%中获取%key%键的值,将结果保存到%value_instance%", + "icon": "BlockIcons/28-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/字典操作/获取键值.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dictionary.GetValueHandler" + } + ], + "inputs": [ + { + "name": "dict", + "label": "字典", + "required": true, + "tips": "输入字典变量", + "type": "dict", + "editor": { + "kind": "textbox" + } + }, + { + "name": "key", + "label": "键名", + "required": true, + "tips": "输入键名", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "key_not_exist_process_way", + "label": "键不存在时", + "required": true, + "default": "10:raise_error", + "defaultDisplay": "报错", + "tips": "当输入的键不存在时,选择一种处理方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "报错", + "value": "raise_error" + }, + { + "display": "返回默认值", + "value": "return_default_value" + } + ] + } + }, + { + "name": "default_value", + "label": "默认值", + "required": false, + "tips": "输入默认键值", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "value_instance", + "label": "保存键值至", + "variableLabel": "字典的键值", + "tips": "输入一个名字,用来保存查找到的键值", + "type": "any", + "name": "value_instance" + } + ] + }, + { + "name": "dictionary.get_keys", + "function": "xbot_visual.dictionary.get_keys", + "title": "获取字典键名列表", + "description": "这个指令用于在字典中获取键名列表", + "comment": "在字典%dict%中获取键名列表,将结果保存到%key_list%", + "icon": "BlockIcons/28-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/字典操作/获取字典键名列表.html", + "inputs": [ + { + "name": "dict", + "label": "字典", + "required": true, + "tips": "输入字典变量", + "type": "dict", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "key_list", + "label": "保存键名列表至", + "variableLabel": "字典键名列表", + "tips": "输入一个名字,用来保存查找到的键名列表", + "type": "list", + "name": "key_list" + } + ] + }, + { + "name": "dictionary.get_values", + "function": "xbot_visual.dictionary.get_values", + "title": "获取字典值列表", + "description": "这个指令用于在字典中获取值列表", + "comment": "在字典%dict%中获取值列表,将结果保存到%value_list%", + "icon": "BlockIcons/28-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/字典操作/获取字典值列表.html", + "inputs": [ + { + "name": "dict", + "label": "字典", + "required": true, + "tips": "输入字典变量", + "type": "dict", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "value_list", + "label": "保存值列表至", + "variableLabel": "字典键值列表", + "tips": "输入一个名字,用来保存查找到的值列表", + "type": "list", + "name": "value_list" + } + ] + }, + { + "name": "dictionary.pop", + "function": "xbot_visual.dictionary.pop", + "title": "删除字典键值对", + "description": "这个指令用于在字典中删除键值对", + "comment": "在字典%dict%中删除键名为%key%的键值对", + "icon": "BlockIcons/28-6.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/字典操作/删除字典键值对.html", + "inputs": [ + { + "name": "dict", + "label": "字典", + "required": true, + "tips": "输入字典变量", + "type": "dict", + "editor": { + "kind": "textbox" + } + }, + { + "name": "key", + "label": "待删除的键名", + "required": true, + "tips": "输入待删除的键名", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/dir.blocks.json b/src/assert/block_settings/dir.blocks.json new file mode 100644 index 0000000..0249d0b --- /dev/null +++ b/src/assert/block_settings/dir.blocks.json @@ -0,0 +1,747 @@ +{ + "types": [], + "blocks": [ + { + "name": "dir.if_exist", + "statement": "workflow.if", + "function": "xbot_visual.dir.if_exist", + "title": "IF 文件夹存在", + "description": "判断文件夹是否存在", + "comment": "如果文件夹%path%%expect_exist%,则执行以下操作", + "indent": "1", + "scope": "1", + "isCondition": true, + "icon": "BlockIcons/19-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if文件夹存在.html", + "video": { + "time": "00:36" + }, + "inputs": [ + { + "name": "path", + "label": "文件夹路径", + "required": true, + "tips": "输入或选择文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "expect_exist", + "label": "文件夹是否", + "required": true, + "default": "10:exist", + "defaultDisplay": "存在", + "tips": "选择预期的文件夹是否存在", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "存在", + "value": "exist" + }, + { + "display": "不存在", + "value": "no_exist" + } + ] + } + } + ] + }, + { + "name": "dir.make", + "function": "xbot_visual.dir.make", + "title": "创建文件夹", + "description": "创建指定路径的文件夹", + "comment": "创建文件夹%path%", + "icon": "BlockIcons/19-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/创建文件夹.html", + "inputs": [ + { + "name": "path", + "label": "路径", + "required": true, + "tips": "输入或选择文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + } + ] + }, + { + "name": "dir.makedir", + "function": "xbot_visual.dir.makedir", + "title": "创建文件夹", + "description": "创建文件夹", + "comment": "在%parent%下新建文件夹%name%,将新建的文件夹路径保存到%new_folder%", + "icon": "BlockIcons/19-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/创建文件夹.html", + "inputs": [ + { + "name": "parent", + "label": "父文件夹目录", + "required": true, + "tips": "输入或选择要在其中创建新文件夹的文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "name", + "label": "新文件夹名称", + "required": true, + "tips": "要创建的文件夹名称", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "new_folder", + "label": "保存新文件夹路径至", + "variableLabel": "创建的新文件夹路径", + "tips": "输入一个名字,用于保存新建的文件夹路径", + "type": "str", + "name": "new_folder" + } + ] + }, + { + "name": "dir.remove", + "function": "xbot_visual.dir.remove", + "title": "删除文件夹", + "description": "删除文件夹,包括该文件夹下所有的子文件和文件", + "comment": "删除文件夹%path%", + "icon": "BlockIcons/19-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/删除文件夹.html", + "inputs": [ + { + "name": "path", + "label": "要删除的文件夹", + "required": true, + "tips": "输入或选择要删除的文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + } + ] + }, + { + "name": "dir.find_files", + "function": "xbot_visual.dir.find_files", + "title": "获取文件列表", + "keywords": "检索文件", + "description": "在文件夹中检索文件", + "comment": "获取文件夹%path%下符合%patterns%命名规则的文件列表,将文件列表保存到%file_paths%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Dir.FindFilesControl, ShadowBot.Shell.Development", + "icon": "BlockIcons/19-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件/获取文件列表.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dir.FindFilesHandler" + } + ], + "inputs": [ + { + "name": "path", + "label": "文件夹", + "required": true, + "tips": "输入或选择文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "patterns", + "label": "文件名匹配规则", + "required": true, + "tips": "输入文件名匹配规则,允许使用通配符,比如“图片*”或“图片?”,多个规则用逗号分割,比如:规则1,规则2", + "type": "str", + "default": "10:*.*", + "editor": { + "kind": "textbox" + } + }, + { + "name": "find_subdir", + "label": "", + "required": true, + "tips": "是否查找子文件夹下的文件", + "type": "bool", + "default": "13:False", + "editor": { + "label": "查找子文件夹", + "kind": "checkbox" + } + }, + { + "name": "skip_hidden_file", + "label": "", + "required": true, + "tips": "是否忽略隐藏的文件", + "type": "bool", + "default": "13:False", + "editor": { + "label": "忽略隐藏的文件", + "kind": "checkbox" + } + }, + { + "name": "is_sort", + "label": "", + "required": true, + "tips": "指定文件列表排序规则", + "type": "bool", + "default": "13:False", + "editor": { + "label": "指定文件列表排序规则", + "kind": "checkbox" + } + }, + { + "name": "sort_by", + "label": "排序因素", + "required": false, + "default": "10:name", + "defaultDisplay": "文件名称", + "tips": "选择文件列表排序因素", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文件名称", + "value": "name" + }, + { + "display": "文件大小", + "value": "size" + }, + { + "display": "文件创建时间", + "value": "create_time" + }, + { + "display": "文件最后修改时间", + "value": "last_modify_time" + } + ] + } + }, + { + "name": "sort_way", + "label": "排序方式", + "required": false, + "default": "10:increase", + "defaultDisplay": "递增", + "tips": "选择文件列表排序方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "递增", + "value": "increase" + }, + { + "display": "递减", + "value": "decrease" + } + ] + } + } + ], + "outputs": [ + { + "id": "file_paths", + "label": "保存文件列表至", + "variableLabel": "获取的文件列表", + "tips": "输入一个名字,用来保存文件列表", + "type": "list", + "name": "file_paths" + } + ] + }, + { + "name": "dir.find_subdirs", + "function": "xbot_visual.dir.find_subdirs", + "title": "获取文件夹列表", + "keywords": "子文件夹", + "description": "获取指定路径文件夹下的子文件夹", + "comment": "获取文件夹%path%下的子文件夹,将文件夹列表保存到%dir_paths%", + "icon": "BlockIcons/19-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/获取文件夹列表.html", + "inputs": [ + { + "name": "path", + "label": "文件夹路径", + "required": true, + "tips": "输入或选择文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "patterns", + "label": "子文件夹名称匹配规则", + "required": true, + "tips": "输入子文件夹名称匹配规则,允许使用通配符,比如“图片*”或“图片?”,多个规则用逗号分割,比如:规则1,规则2", + "type": "str", + "default": "10:*", + "editor": { + "kind": "textbox" + } + }, + { + "name": "find_subdir", + "label": "", + "required": true, + "tips": "是否递归查找子文件夹", + "type": "bool", + "default": "13:False", + "editor": { + "label": "递归查找子文件夹", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "dir_paths", + "label": "保存文件夹列表至", + "variableLabel": "获取的文件夹列表", + "tips": "输入一个名字,用来保存文件夹列表", + "type": "list", + "name": "dir_paths" + } + ] + }, + { + "name": "dir.selected_dirs_or_files", + "function": "xbot_visual.dir.selected_dirs_or_files", + "title": "获取选中文件(夹)列表", + "description": "获取当前激活文件资源管理器(若激活桌面则目标为桌面)中选中的文件、文件夹列表", + "comment": "获取当前激活的文件夹中选中的文件和文件夹列表,将结果保存到%dir_or_file_paths%", + "icon": "BlockIcons/19-11.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/获取选中文件(夹)列表.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dir.SelectedDirsOrFilesHandler" + } + ], + "inputs": [ + { + "name": "file_type", + "label": "获取类型", + "required": true, + "tips": "选择要获取的选中类型,支持获取选中的文件、文件夹或所有选中项", + "type": "str", + "default": "10:all", + "defaultDisplay": "文件和文件夹", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "文件和文件夹", + "value": "all" + }, + { + "display": "文件", + "value": "file" + }, + { + "display": "文件夹", + "value": "folder" + } + ] + } + } + ], + "outputs": [ + { + "id": "dir_or_file_paths", + "label": "保存文件、文件夹列表至", + "variableLabel": "选中的文件(夹)列表", + "tips": "输入一个名字,用来保存文件、文件夹列表", + "type": "list", + "name": "dir_or_file_paths" + } + ] + }, + { + "name": "dir.open", + "function": "xbot_visual.dir.open", + "title": "打开文件夹", + "description": "打开文件夹,如果为文件路径,会在打开文件夹后选中文件", + "comment": "打开文件夹并选中文件%folder_file_path%", + "icon": "BlockIcons/19-12.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/打开文件夹.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Dir.OpenDirHandler" + } + ], + "inputs": [ + { + "name": "folder_file_path", + "label": "文件(夹)路径", + "required": true, + "tips": "输入要打开的文件夹路径,如果为文件路径,会打开文件夹并选中文件", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + } + ] + }, + { + "name": "dir.empty", + "function": "xbot_visual.dir.empty", + "title": "清空文件夹", + "description": "删除文件夹下的所有文件和子文件夹,但保留文件夹本身", + "comment": "清空文件夹%path%", + "icon": "BlockIcons/19-6.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/清空文件夹.html", + "inputs": [ + { + "name": "path", + "label": "要清空的文件夹", + "required": true, + "tips": "输入或选择要清空的文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + } + ] + }, + { + "name": "dir.copy", + "function": "xbot_visual.dir.copy", + "title": "拷贝文件夹", + "keywords": "复制文件夹", + "description": "将源文件夹拷贝到目标文件夹", + "comment": "将源文件夹%source_dir_path%拷贝到目标文件夹%copyto_dir_path%,将拷贝后的文件夹路径保存到%dir_path%", + "icon": "BlockIcons/19-7.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/拷贝文件夹.html", + "inputs": [ + { + "name": "source_dir_path", + "label": "要拷贝的文件夹", + "required": true, + "tips": "输入或选择要拷贝的文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "copyto_dir_path", + "label": "目标文件夹", + "required": true, + "tips": "输入目标文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "copy_way", + "label": "如果文件存在", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖", + "tips": "对目标文件夹中已存在的文件,选择覆盖还是不执行拷贝", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "不要拷贝", + "value": "not_overwrite" + }, + { + "display": "自动添加后缀", + "value": "save_as" + } + ] + } + } + ], + "outputs": [ + { + "id": "dir_path", + "label": "拷贝后的文件夹路径", + "variableLabel": "拷贝后的文件夹路径", + "tips": "输入一个名字,用来保存拷贝后的文件夹路径", + "type": "str", + "name": "dir_path" + } + ] + }, + { + "name": "dir.move", + "function": "xbot_visual.dir.move", + "title": "移动文件夹", + "description": "将源文件夹移动到目标文件夹下", + "comment": "将源文件夹%source_dir_path%移动到目标文件夹%moveto_dir_path%下,将移动后的文件路径保存到%dir_path%", + "icon": "BlockIcons/19-8.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/移动文件夹.html", + "inputs": [ + { + "name": "source_dir_path", + "label": "要移动的文件夹", + "required": true, + "tips": "输入或选择要移动的文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "moveto_dir_path", + "label": "目标文件夹", + "required": true, + "tips": "输入或选择目标文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + } + ], + "outputs": [ + { + "id": "dir_path", + "label": "移动后的文件夹路径", + "variableLabel": "移动后的文件夹路径", + "tips": "输入一个名字,用来保存移动后的文件夹路径", + "type": "str", + "name": "dir_path" + } + ] + }, + { + "name": "dir.get_special_dir", + "function": "xbot_visual.dir.get_special_dir", + "title": "获取系统文件夹路径", + "description": "获取系统文件夹路径", + "comment": "获取系统文件夹%special_dir_name%路径,将系统文件夹路径保存到%dir_path%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Dir.GetSpecialDirControl, ShadowBot.Shell.Development", + "icon": "BlockIcons/19-9.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/获取系统文件夹路径.html", + "inputs": [ + { + "name": "special_dir_name", + "label": "系统文件夹名称", + "required": true, + "default": "10:DesktopDirectory", + "defaultDisplay": "文件夹名称", + "tips": "选择系统文件夹名称", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "临时", + "value": "TEMP" + }, + { + "display": "桌面", + "value": "DesktopDirectory" + }, + { + "display": "应用程序数据", + "value": "ApplicationData" + }, + { + "display": "常见应用程序数据", + "value": "CommonApplicationData" + }, + { + "display": "本地应用程序数据", + "value": "LocalApplicationData" + }, + { + "display": "Cookies", + "value": "Cookies" + }, + { + "display": "收藏夹", + "value": "Favorites" + }, + { + "display": "历史", + "value": "History" + }, + { + "display": "Internet 缓存", + "value": "InternetCache" + }, + { + "display": "程序", + "value": "Programs" + }, + { + "display": "音乐", + "value": "MyMusic" + }, + { + "display": "图片", + "value": "MyPictures" + }, + { + "display": "最近", + "value": "Recent" + }, + { + "display": "发送到", + "value": "SendTo" + }, + { + "display": "开始菜单", + "value": "StartMenu" + }, + { + "display": "启动", + "value": "Startup" + }, + { + "display": "系统", + "value": "System" + }, + { + "display": "模板", + "value": "Templates" + }, + { + "display": "个人", + "value": "Personal" + }, + { + "display": "程序文件", + "value": "ProgramFiles" + }, + { + "display": "常见程序文件", + "value": "CommonProgramFiles" + }, + { + "display": "系统", + "value": "Windows" + }, + { + "display": "下载", + "value": "Downloads" + } + ] + } + } + ], + "outputs": [ + { + "id": "dir_path", + "label": "系统文件夹路径", + "variableLabel": "系统文件夹路径", + "tips": "输入一个名字,用来保存系统文件夹路径", + "type": "str", + "name": "dir_path" + } + ] + }, + { + "name": "dir.rename", + "function": "xbot_visual.dir.rename", + "title": "文件夹重命名", + "description": "文件夹重命名", + "comment": "将文件夹%path%重命名为%new_name%,将新的文件夹路径保存到%new_dir_path%", + "icon": "BlockIcons/19-10.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件夹/文件夹重命名.html", + "inputs": [ + { + "name": "path", + "label": "要重命名的文件夹", + "required": true, + "tips": "输入或选择要重命名的文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "new_name", + "label": "新文件夹名称", + "required": true, + "tips": "输入新的文件夹名称", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "new_dir_path", + "label": "新的文件夹路径", + "variableLabel": "重命名后的文件夹路径", + "tips": "输入一个名字,用来保存新的文件夹路径", + "type": "str", + "name": "new_dir_path" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/email.blocks.json b/src/assert/block_settings/email.blocks.json new file mode 100644 index 0000000..fea5c5f --- /dev/null +++ b/src/assert/block_settings/email.blocks.json @@ -0,0 +1,519 @@ +{ + "types": [ + { + "name": "xbot_visual_email_mailmessage", + "localName": "邮件", + "pythonName": "xbot_visual._core.xbot_visual_email_mailmessage", + "props": [ + { + "name": "sender", + "type": "str", + "label": "发件人" + }, + { + "name": "receiver", + "type": "str", + "label": "收件人" + }, + { + "name": "subject", + "type": "str", + "label": "主题" + }, + { + "name": "text_body", + "type": "str", + "label": "正文" + }, + { + "name": "html_body", + "type": "str", + "label": "HTML正文" + }, + { + "name": "time", + "type": "str", + "label": "时间" + }, + { + "name": "attachment", + "type": "str", + "label": "附件路径" + } + ] + } + ], + "blocks": [ + { + "name": "email.send_email", + "icon": "BlockIcons/13-1.png", + "description": "发送邮件", + "comment": "发送邮件到%to%", + "title": "发送邮件", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/邮件/发送邮件.html", + "function": "xbot_visual.email.send_email", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Email.SendEmailControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Email.SendEmailHandler" + } + ], + "inputs": [ + { + "name": "sender", + "label": "发件人", + "required": true, + "tips": "邮件发件人", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sender_display_name", + "label": "发件人名称", + "required": false, + "tips": "邮件发送人名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "to", + "label": "收件人", + "required": true, + "tips": "邮件收件人,多个收件人用“;”分隔。", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "cc", + "label": "抄送", + "required": false, + "tips": "邮件抄送,多个抄送用“;”分隔。", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "bcc", + "label": "密送", + "required": false, + "tips": "邮件密送,多个密送用“;”分隔。", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "subject", + "label": "主题", + "required": true, + "tips": "邮件主题", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "body", + "label": "正文", + "required": true, + "tips": "邮件正文", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "body_is_html", + "label": "", + "required": false, + "tips": "正文是HTML格式", + "type": "bool", + "default": "13:False", + "editor": { + "label": "HTML格式", + "kind": "checkbox" + } + }, + { + "name": "attachments", + "label": "邮件附件", + "required": false, + "tips": "邮件附件,多个附件用“;”分隔。", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "All Files (*.*)|*.*" + } + } + }, + { + "name": "select_smtp_server", + "label": "SMTP服务器", + "required": true, + "category": "advanced", + "default": "10:qq_smtp", + "defaultDisplay": "QQ邮箱", + "tips": "选择一个SMTP服务器", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "QQ邮箱", + "value": "qq_smtp" + }, + { + "display": "126邮箱", + "value": "126_smtp" + }, + { + "display": "163邮箱", + "value": "163_smtp" + }, + { + "display": "Google邮箱", + "value": "gmail_smtp" + }, + { + "display": "Outlook邮箱", + "value": "outlook_smtp" + }, + { + "display": "iCloud邮箱", + "value": "iCloud_smtp" + }, + { + "display": "其他", + "value": "other_smtp" + } + ] + } + }, + { + "name": "smtp_server", + "label": "指定的SMTP服务器", + "category": "advanced", + "tips": "输入指定的SMTP服务器地址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "smtp_port", + "label": "指定的SMTP端口", + "default": "10:465", + "category": "advanced", + "tips": "输入指定的SMTP端口", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_ssl", + "label": "", + "required": true, + "category": "advanced", + "tips": "使用SSL连接SMTP服务器", + "type": "bool", + "default": "13:False", + "editor": { + "label": "使用SSL", + "kind": "checkbox" + } + }, + { + "name": "smtp_server_authentication", + "label": "", + "required": false, + "category": "advanced", + "tips": "SMTP服务器需要身份验证", + "type": "bool", + "default": "13:False", + "editor": { + "label": "SMTP服务器需要身份验证", + "kind": "checkbox" + } + }, + { + "name": "user_name", + "label": "用户名", + "required": false, + "category": "advanced", + "tips": "SMTP服务器身份验证的用户名", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "password", + "label": "授权码", + "required": false, + "category": "advanced", + "tips": "SMTP服务器验证身份的授权码", + "type": "str", + "editor": { + "kind": "password" + } + } + ] + }, + { + "name": "email.retrieve_email", + "icon": "BlockIcons/13-2.png", + "description": "从指定的邮箱中获取邮件,收取邮件", + "comment": "获取%mail_kind%%username%中文件夹%folder_name%的前%top%封邮件,将邮件列表保存到%mailmessage_list%", + "title": "获取邮件", + "keywords": "收取邮件;收邮件", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/邮件/获取邮件.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Email.RetrieveEmailControl, ShadowBot.Shell.Development", + "function": "xbot_visual.email.retrieve_email", + "inputs": [ + { + "name": "mail_kind", + "label": "邮箱类型", + "required": true, + "default": "10:163", + "defaultDisplay": "163邮箱", + "tips": "选择一个邮箱类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "163邮箱", + "value": "163" + }, + { + "display": "126邮箱", + "value": "126" + }, + { + "display": "qq邮箱", + "value": "qq" + }, + { + "display": "Google邮箱", + "value": "gmail" + }, + { + "display": "Outlook邮箱", + "value": "outlook" + }, + { + "display": "iCloud邮箱", + "value": "iCloud" + }, + { + "display": "其他", + "value": "other_smtp" + }, + { + "display": "自定义邮箱", + "value": "custom" + } + ] + } + }, + { + "name": "address", + "label": "IMAP服务器", + "tips": "输入指定的IMAP服务器地址", + "type": "str", + "editor": { + "placeholder": "如imap.163.com", + "kind": "textbox" + } + }, + { + "name": "port", + "label": "端口号", + "tips": "输入指定的IMAP端口号", + "default": "10:993", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_ssl", + "label": "", + "tips": "使用SSL连接IMAP服务器", + "type": "bool", + "default": "13:True", + "editor": { + "label": "使用SSL", + "kind": "checkbox" + } + }, + { + "name": "username", + "label": "邮箱账号", + "tips": "IMAP服务器身份验证的用户名,通常是邮箱账号,以具体邮件服务商的规定为准", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "authcode", + "label": "授权码", + "tips": "IMAP服务器验证身份的授权码,一般需要短信认证开通,部分邮箱为账号密码,以具体邮件服务商的规定为准", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "only_unread", + "label": "", + "tips": "仅获取未读邮件或者获取所有邮件", + "type": "bool", + "default": "13:True", + "editor": { + "label": "仅未读邮件", + "kind": "checkbox" + } + }, + { + "name": "top", + "label": "邮件数量", + "tips": "获取前N封邮件", + "default": "10:5", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "save_attachments", + "label": "", + "tips": "是否下载邮件的附件", + "type": "bool", + "default": "13:False", + "editor": { + "label": "保存附件", + "kind": "checkbox" + } + }, + { + "name": "attachments_savefolder", + "label": "保存目录", + "tips": "附件的保存目录", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "folder_name_specifc_mode", + "label": "文件夹指定方式", + "tips": "文件夹指定方式", + "type": "str", + "default": "10:default", + "defaultDisplay": "默认", + "category": "advanced", + "editor": { + "kind": "select", + "options": [ + { + "display": "默认", + "value": "default" + }, + { + "display": "动态指定", + "value": "dynamic" + } + ] + } + }, + { + "name": "folder_name", + "label": "文件夹名称", + "tips": "输入指定文件夹的名称", + "category": "advanced", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "mark_as_read", + "label": "", + "tips": "获取邮件后,将邮件标记为已读状态", + "category": "advanced", + "type": "bool", + "default": "13:True", + "editor": { + "label": "标记为已读", + "kind": "checkbox" + } + }, + { + "name": "keyword_in_from", + "label": "发件人中包含的内容", + "tips": "发件人中包含的内容", + "category": "advanced", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "keyword_in_to", + "label": "收件人中包含的内容", + "tips": "收件人中包含的内容", + "category": "advanced", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "keyword_in_subject", + "label": "主题中包含的内容", + "tips": "主题中包含的内容", + "category": "advanced", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "keyword_in_textBody", + "label": "正文中包含的内容", + "tips": "正文中包含的内容", + "category": "advanced", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "mailmessage_list", + "label": "保存邮件列表至", + "variableLabel": "邮件列表", + "tips": "指定一个变量名称,该变量用于存储获取到的邮件列表", + "type": "list", + "name": "mailmessage_list" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/excel.blocks.json b/src/assert/block_settings/excel.blocks.json new file mode 100644 index 0000000..29a1ad0 --- /dev/null +++ b/src/assert/block_settings/excel.blocks.json @@ -0,0 +1,4149 @@ +{ + "types": [ + { + "name": "openpyxl.Workbook", + "localName": "Excel对象", + "pythonName": "xbot.excel.workbook.officeworkbook.OfficeWorkBook,xbot.excel.workbook.comworkbook.ComWorkBook,xbot.excel.workbook.openpyxlworkbook.OpenPyxlWorkBook", + "methods": [ + { + "display": "总行数", + "function": "$0.get_active_sheet().get_row_count()", + "type": "int" + }, + { + "display": "第一个可用行", + "function": "$0.get_active_sheet().get_first_free_row()", + "type": "int" + }, + { + "display": "文件所在位置", + "function": "$0.get_full_name()", + "type": "str" + } + ] + }, + { + "name": "table.row", + "base": "list", + "localName": "一行数据", + "methods": [ + { + "display": "该行第$1列单元格内容", + "function": "$0[--$1]", + "type": "str", + "params": [ + { + "name": "$1", + "default": "A" + } + ], + "editor": "letterspin" + }, + { + "display": "该行倒数第$1个单元格内容", + "function": "$0[-$1]", + "type": "any", + "params": [ + { + "name": "$1", + "default": "1" + } + ], + "editor": "spin" + } + ] + }, + { + "name": "table.column", + "base": "list", + "localName": "一列数据", + "methods": [ + { + "display": "该列第$1个单元格内容", + "function": "$0[--$1]", + "type": "any", + "params": [ + { + "name": "$1", + "default": "1" + } + ], + "editor": "spin" + }, + { + "display": "该列倒数第$1个单元格内容", + "function": "$0[-$1]", + "type": "any", + "params": [ + { + "name": "$1", + "default": "1" + } + ], + "editor": "spin" + } + ] + } + ], + "blocks": [ + { + "name": "excel.launch", + "title": "打开/新建Excel", + "keywords": "打开Excel文件;新建Excel;启动Excel", + "icon": "BlockIcons/9-1.png", + "comment": "%launch_way% %open_filename%,将Excel对象保存到%excel_instance%", + "description": "打开已有Excel文件,或新建Excel,以实现Excel程序的自动化", + "function": "xbot_visual.excel.launch", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.LaunchExcelControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/启动excel.html", + "video": { + "time": "09:51" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.LaunchExcelHandler" + } + ], + "inputs": [ + { + "name": "launch_way", + "label": "启动方式", + "required": true, + "default": "10:open", + "defaultDisplay": "打开已有的Excel", + "tips": "选择要新建一个Excel文件还是打开一个Excel文件", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "新建Excel", + "value": "create" + }, + { + "display": "打开已有的Excel", + "value": "open" + } + ] + } + }, + { + "name": "driver_way", + "label": "驱动方式", + "required": true, + "tips": "选择新建Excel文件或者打开Excel文件的驱动方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "自动检测", + "value": "auto_check" + }, + { + "display": "office", + "value": "office" + }, + { + "display": "wps", + "value": "wps" + }, + { + "display": "openpyxl", + "value": "openpyxl" + } + ] + } + }, + { + "name": "open_filename", + "label": "Excel文件路径", + "required": false, + "tips": "填写或选择要打开的Excel文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "Excel 工作簿|*.xlsx;*.xls;*.xlsm;*.csv" + } + } + }, + { + "name": "save_filename", + "label": "Excel文件路径", + "required": false, + "tips": "填写打开的Excel路径或保存Excel的路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "defaultFileName": "Workbook", + "filter": "Excel 工作簿|*.xlsx;*.xls;*.csv" + } + } + }, + { + "name": "isvisible", + "label": "", + "default": "13:True", + "tips": "此选项并不会限制Excel自动化的能力,只是用于控制可视化操作是否用户可见,如果是非可视化下操作Excel,保存之后必须要关闭Excel", + "type": "bool", + "editor": { + "label": "是否可视化", + "kind": "checkbox" + } + }, + { + "name": "ignoreformula", + "label": "", + "default": "13:False", + "tips": "忽略Excel中的公式,仅读取公式结果,勾选忽略公式打开文件后不允许保存,以防公式丢失。", + "type": "bool", + "editor": { + "label": "忽略公式", + "kind": "checkbox" + } + }, + { + "name": "password", + "label": "打开密码", + "category": "advanced", + "tips": "用于打开加密Excel文件的密码", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "write_password", + "label": "编辑密码", + "category": "advanced", + "tips": "用于编辑加密Excel文件的密码", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "update_links", + "label": "", + "default": "13:False", + "tips": "自动更新外部链接,建议勾选可视化", + "type": "bool", + "editor": { + "label": "自动更新外部链接", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "excel_instance", + "label": "保存Excel对象至", + "variableLabel": "打开的Excel对象", + "tips": "该变量保存的是Excel对象,使用此Excel对象可以对Excel进行自动化操作", + "name": "excel_instance", + "type": "openpyxl.Workbook" + } + ] + }, + { + "name": "excel.get_active_workbook", + "title": "获取当前激活的Excel对象", + "comment": "获取当前激活的Excel对象,将对象保存到%excel_instance%", + "description": "获取当前激活的Excel对象", + "icon": "BlockIcons/9-30.png", + "function": "xbot_visual.excel.get_active_workbook", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/获取当前激活的excel.html", + "video": { + "time": "03:32" + }, + "inputs": [], + "outputs": [ + { + "id": "excel_instance", + "label": "保存Excel对象至", + "variableLabel": "激活的Excel对象", + "tips": "该变量保存的是Excel对象,使用此Excel对象可以对Excel进行自动化操作", + "name": "excel_instance", + "type": "openpyxl.Workbook" + } + ] + }, + { + "name": "excel.save", + "title": "保存/另存Excel", + "comment": "%save_way%Excel对象%excel_instance%", + "description": "保存或另存Excel", + "keywords": "保存Excel;另存为Excel;导出Excel", + "icon": "BlockIcons/9-3.png", + "function": "xbot_visual.excel.save", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.SaveExcelControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/保存excel.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.SaveExcelHandler" + } + ], + "inputs": [ + { + "name": "excel_instance", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "save_way", + "label": "保存方式", + "required": true, + "default": "10:save", + "defaultDisplay": "保存", + "tips": "保存对Excel的更改或另存为到新的路径", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "保存", + "value": "save" + }, + { + "display": "另存为", + "value": "saveas" + } + ] + } + }, + { + "name": "filename", + "label": "Excel文件路径", + "tips": "填写或选择要打开的Excel文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "defaultFileName": "Workbook", + "filter": "Excel 工作簿 (.xlsx)|*.xlsx" + } + } + }, + { + "name": "overwrite_file", + "label": "", + "default": "13:True", + "tips": "若文件已存在,又选择不覆盖,会报错提示文件已存在", + "type": "bool", + "editor": { + "label": "如果文件存在则覆盖", + "kind": "checkbox" + } + }, + { + "name": "is_close_after_save", + "label": "", + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "保存后关闭", + "kind": "checkbox" + } + } + ] + }, + { + "name": "excel.close", + "title": "关闭Excel", + "comment": "关闭Excel", + "description": "关闭Excel", + "icon": "BlockIcons/9-44.png", + "function": "xbot_visual.excel.close", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.CloseExcelControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/关闭excel.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.CloseExcelHandler" + } + ], + "inputs": [ + { + "name": "operation", + "label": "操作", + "required": true, + "default": "10:close_specified", + "defaultDisplay": "关闭指定Excel文件", + "tips": "选择要关闭一个指定的Excel文件还是关闭所有Excel文件", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "关闭指定Excel文件", + "value": "close_specified" + }, + { + "display": "关闭所有Excel文件", + "value": "close_all" + } + ] + } + }, + { + "name": "excel_instance", + "label": "Excel对象", + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "close_way", + "label": "关闭方式", + "required": true, + "default": "10:save", + "defaultDisplay": "保存", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "不保存", + "value": "notsave" + }, + { + "display": "保存", + "value": "save" + }, + { + "display": "另存为", + "value": "saveas" + } + ] + } + }, + { + "name": "filename", + "label": "文件路径", + "tips": "填写或选择要打开的Excel文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "defaultFileName": "Workbook", + "filter": "Excel 工作簿 (.xlsx)|*.xlsx" + } + } + }, + { + "name": "overwrite_file", + "label": "", + "default": "13:True", + "tips": "若文件已存在,又选择不覆盖,会报错提示文件已存在", + "type": "bool", + "editor": { + "label": "如果文件存在则覆盖", + "kind": "checkbox" + } + }, + { + "name": "close_process", + "label": "关闭进程", + "required": true, + "default": "10:office", + "defaultDisplay": "office", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "office", + "value": "office" + }, + { + "display": "wps", + "value": "wps" + } + ] + } + }, + { + "name": "task_kill", + "label": "", + "required": true, + "default": "13:True", + "tips": "如果勾选, 将强制结束属于当前用户的指定Excel进程和由它启动的所有子进程", + "type": "bool", + "editor": { + "label": "终止Excel进程", + "kind": "checkbox" + } + } + ] + }, + { + "name": "excel.active", + "title": "激活Sheet页", + "comment": "%mode%激活Excel对象%workbook%中的Sheet页%value%", + "description": "根据Sheet页的名称或位置激活指定的Sheet页", + "keywords": "切换;选择", + "icon": "BlockIcons/9-4.png", + "function": "xbot_visual.excel.active", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/sheet页操作/激活sheet页.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "mode", + "label": "激活方式", + "required": true, + "default": "10:name", + "defaultDisplay": "根据Sheet页的名称", + "tips": "可根据名称或Sheet页中的位置(从1开始)", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据Sheet页的名称", + "value": "name" + }, + { + "display": "根据Sheet页的位置", + "value": "index" + } + ] + } + }, + { + "name": "value", + "label": "Sheet页的名称/位置", + "required": true, + "tips": "填写要打开激活的Sheet页的名称或位置(从1开始)", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.create_sheet", + "title": "添加Sheet页", + "comment": "在Excel对象%workbook%中添加一个Sheet页,%create_way%,命名为%sheet_name%", + "description": "在Excel对象中添加一个新的sheet页,可以指定在头部添加或尾部添加", + "icon": "BlockIcons/9-10.png", + "function": "xbot_visual.excel.create_sheet", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/sheet页操作/添加sheet页.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "请选择一个已打开的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "required": true, + "tips": "请输入待添加的Sheet页名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "create_way", + "label": "添加方式", + "required": true, + "default": "10:first", + "defaultDisplay": "作为第一个sheet页", + "tips": "选择添加位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "作为第一个sheet页", + "value": "first" + }, + { + "display": "作为最后一个sheet页", + "value": "last" + } + ] + } + } + ] + }, + { + "name": "excel.remove_row", + "title": "删除Excel行", + "keywords": "删除行", + "comment": "删除Excel对象%workbook%工作表中的第%index%行", + "description": "删除行", + "icon": "BlockIcons/9-20.png", + "function": "xbot_visual.excel.remove_row", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/删除行.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "index", + "label": "行号", + "required": true, + "tips": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.remove_all_rows", + "title": "删除所有行", + "comment": "删除Excel对象%workbook%中的所有行数据", + "description": "删除所有行", + "icon": "BlockIcons/9-11.png", + "function": "xbot_visual.excel.remove_all_rows", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/删除所有行.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.get_row_count", + "title": "读取Excel总行数", + "comment": "读取Excel对象%workbook%中Sheet页%sheet_name%的总行数,将结果保存到%row_count%", + "description": "读取Excel总行数", + "icon": "BlockIcons/9-9.png", + "function": "xbot_visual.excel.get_row_count", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/读取总行数.html", + "video": { + "time": "03:05" + }, + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ], + "outputs": [ + { + "id": "row_count", + "label": "保存总行数至", + "variableLabel": "Excel总行数", + "tips": "指定一个变量名称,该变量用于保存总行数", + "type": "int", + "name": "excel_row_count" + } + ] + }, + { + "name": "excel.write_data_to_workbook", + "title": "写入内容至Excel工作表", + "keywords": "写入Excel", + "icon": "BlockIcons/9-5.png", + "comment": "写入内容到Excel工作表", + "description": "在 Excel 工作表中以写入内容,支持追加、插入或覆盖", + "function": "xbot_visual.excel.write_data_to_workbook", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/写入内容至excel工作表.html", + "video": { + "time": "13:55" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.WriteDataToWorkBookControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.WriteDataToWorkBookHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "write_range", + "label": "写入范围", + "required": true, + "default": "10:area", + "defaultDisplay": "区域", + "tips": "将数据写入到区域(包含单元格)、一行或一列", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "区域", + "value": "area" + }, + { + "display": "行", + "value": "row" + }, + { + "display": "列", + "value": "column" + } + ] + } + }, + { + "name": "write_way", + "label": "写入方式", + "default": "10:append", + "defaultDisplay": "追加一行", + "tips": "支持覆盖、追加、插入", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "追加一行", + "value": "append" + }, + { + "display": "插入一行", + "value": "insert" + }, + { + "display": "覆盖一行", + "value": "override" + } + ] + } + }, + { + "name": "write_column_way", + "label": "写入方式", + "default": "10:override", + "defaultDisplay": "覆盖一列", + "tips": "支持覆盖、追加、插入", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "追加一列", + "value": "append" + }, + { + "display": "插入一列", + "value": "insert" + }, + { + "display": "覆盖一列", + "value": "override" + } + ] + } + }, + { + "name": "row_num", + "label": "行号", + "tips": "输入行号,从1开始,-n表示倒数第n行", + "default": "10:1", + "type": "int", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "column_name", + "label": "列名", + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "begin_row_num", + "label": "起始行号", + "category": "advanced", + "default": "10:1", + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "int", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "begin_column_name", + "label": "起始列名", + "category": "advanced", + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "content", + "label": "写入内容", + "required": true, + "tips": "内容的数据格式需要跟写入范围对应,写入行、列、非单个单元格的区域的内容需要是列表类型", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + }, + { + "name": "write_as_text_cols", + "label": "格式设置为文本的列", + "category": "advanced", + "required": false, + "tips": "纯数字的长文本,写入Excel后会变成科学计数法,比如身份证号码。可在此设置相应列的数字格式为文本。多个列以,分割,比如A,B,C", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "多个列名以,分割,适用于订单号、身份证等纯数字的长文本" + } + } + ] + }, + { + "name": "excel.read_data_from_workbook", + "title": "读取Excel内容", + "keywords": "读取表格内容", + "icon": "BlockIcons/9-12.png", + "comment": "从Excel对象%workbook%中读取单元格(第%cell_row_num%行,第%cell_column_name%列)的内容,将数据保存到%excel_data%", + "description": "从Excel文件中读取内容,支持矩形区域范围读取", + "function": "xbot_visual.excel.read_data_from_workbook", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读取excel内容.html", + "video": { + "time": "05:39" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.ReadDataFromWorkBookControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.ReadDataFromWorkBookHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "read_way", + "label": "读取方式", + "required": true, + "default": "10:cell", + "defaultDisplay": "单元格", + "tips": "可读取单元格、一行、一列、区域内容", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单元格内容", + "value": "cell" + }, + { + "display": "行内容", + "value": "row" + }, + { + "display": "列内容", + "value": "column" + }, + { + "display": "区域内容", + "value": "range" + }, + { + "display": "已使用区域内容", + "value": "used_range" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "cell_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "cell_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "area_begin_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "area_begin_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "area_end_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "area_end_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "row_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "get_display_text", + "label": "", + "required": false, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "获取单元格的值作为纯文本", + "kind": "checkbox" + } + }, + { + "name": "has_header_row", + "label": "", + "required": false, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "区域第一行包含列名", + "kind": "checkbox" + } + }, + { + "name": "column_column_name", + "label": "列名", + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + }, + { + "name": "using_text", + "label": " ", + "category": "advanced", + "required": false, + "default": "13:False", + "tips": "若不勾选,整数会被读成小数,比如1->1.0,日期格式值会被读成日期对象。若勾选此项,返回的内容为肉眼看到的文本", + "type": "str", + "editor": { + "kind": "checkbox", + "label": "读取单元格显示的内容" + } + }, + { + "name": "text_cols", + "label": "显示内容的列", + "category": "advanced", + "default": "10:", + "tips": "选择哪些列需要显示肉眼可见内容。多个列以逗号分割。\r\n注意!这种读取方法较慢,一列一万行数据,需要13秒", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "多个列名以,分割,若空表示所有列,但读取速度会较慢" + } + }, + { + "name": "clear_space", + "label": " ", + "category": "advanced", + "required": false, + "default": "13:False", + "tips": "若勾选,会自动清除读取内容前后的空格、换行符", + "type": "str", + "editor": { + "kind": "checkbox", + "label": "清除单元格前后空格" + } + } + ], + "outputs": [ + { + "id": "excel_data", + "label": "保存Excel数据对象至", + "variableLabel": "Excel数据对象", + "tips": "指定一个变量名称,该变量用于保存区域数据内容", + "type": "any", + "name": "excel_data" + } + ] + }, + { + "name": "excel.loop_data_from_workbook", + "statement": "excel.forin", + "indent": "1", + "scope": "1", + "isLoop": true, + "title": "循环Excel内容", + "keywords": "循环表格内容", + "icon": "BlockIcons/9-13.png", + "comment": "循环Excel对象%workbook中内容,将每次循环项保存到%loop_item%", + "description": "循环Excel对象的内容,并保存循环项", + "function": "xbot_visual.excel.loop_data_from_workbook_with_return_item_location", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/循环excel内容.html", + "video": { + "time": "04:05" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.ExcelLoopControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.ExcelLoopHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "loop_way", + "label": "循环方式", + "required": true, + "default": "10:used_range", + "defaultDisplay": "循环已使用区域", + "tips": "可循环连续的行、列或区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "循环区域", + "value": "loop_range" + }, + { + "display": "循环行", + "value": "loop_row" + }, + { + "display": "循环列", + "value": "loop_column" + }, + { + "display": "循环已使用区域", + "value": "used_range" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "区域", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "begin_row_num", + "label": "起始行号", + "required": false, + "tips": "循环起始行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "起始行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "end_row_num", + "label": "结束行号", + "required": false, + "tips": "循环结束行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "结束行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "begin_column_name", + "label": "起始列名", + "required": false, + "tips": "循环开始列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "起始列名(支持A或1),-n表示倒数第n列数" + } + }, + { + "name": "end_column_name", + "label": "结束列名", + "required": false, + "tips": "循环结束列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "结束列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "has_header_row", + "label": "", + "required": false, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "区域第一行包含列名", + "kind": "checkbox" + } + }, + { + "name": "range_begin_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "range_begin_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "range_end_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "range_end_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + }, + { + "name": "using_text", + "label": " ", + "category": "advanced", + "required": false, + "default": "13:False", + "tips": "若不勾选,整数会被读成小数,比如1->1.0,日期格式值会被读成日期对象。若勾选此项,返回的内容为肉眼看到的文本", + "type": "str", + "editor": { + "kind": "checkbox", + "label": "读取单元格显示的内容" + } + }, + { + "name": "text_cols", + "label": "显示内容的列", + "category": "advanced", + "default": "10:", + "tips": "选择哪些列需要显示肉眼可见内容。多个列以逗号分割。\r\n注意!这种读取方法较慢,一列一万行数据,需要13秒", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "多个列名以,分隔,若空表示所有列,但读取速度会较慢" + } + }, + { + "name": "clear_space", + "label": " ", + "category": "advanced", + "required": false, + "default": "13:False", + "tips": "若勾选,会自动清除读取内容前后的空格、换行符", + "type": "str", + "editor": { + "kind": "checkbox", + "label": "清除单元格前后空格" + } + } + ], + "outputs": [ + { + "id": "loop_item", + "label": "当前循环项保存至", + "variableLabel": "当前循环项数据对象", + "tips": "指定一个变量名称,该变量用于保存Excel循环项", + "type": "table.row", + "name": "loop_excel" + }, + { + "id": "loop_item_rownum", + "label": "当前行号保存至", + "variableLabel": "当前循环行的行号", + "tips": "指定一个变量名称,该变量用于保存Excel当前循环项的行号", + "type": "int", + "name": "loop_item_rownum" + }, + { + "id": "loop_item_columnname", + "label": "当前列名保存至", + "variableLabel": "当前循环列的列名", + "tips": "指定一个变量名称,该变量用于保存Excel当前循环项的列名", + "type": "str", + "name": "loop_item_columnname" + } + ] + }, + { + "name": "excel.execute_macro", + "title": "运行Excel宏", + "comment": "在Excel对象%workbook%中运行宏%macro%", + "description": "运行Excel宏", + "icon": "BlockIcons/9-14.png", + "function": "xbot_visual.excel.execute_macro", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/运行excel宏.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "macro", + "label": "宏", + "required": true, + "tips": "请输入在Excel中运行的宏", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.select_range", + "title": "选中区域", + "icon": "BlockIcons/9-15.png", + "comment": "在Excel对象%workbook%中选中区域:从起始单元格(第%begin_row_num%行,第%begin_column_name%列)到末尾单元格(第%end_row_num%行,第%end_column_name%列)", + "description": "在Excel对象中选中区域", + "function": "xbot_visual.excel.select_range", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/选中区域.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.SelectRangeControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.SelectRangeHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "select_way", + "label": "选中方式", + "required": true, + "default": "10:absolute_range", + "defaultDisplay": "区域", + "tips": "指定需要选中的单元格区域范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "区域", + "value": "absolute_range" + }, + { + "display": "行", + "value": "row" + }, + { + "display": "列", + "value": "column" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "区域", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "begin_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,若选中方式为‘行’,可以填写多行,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "begin_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1)。若选中方式为‘列’,可以填写多列,多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "end_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "end_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "row_num", + "label": "行号", + "required": false, + "tips": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "any", + "editor": { + "placeholder": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.get_sheet_name", + "statement": "excel.get_sheet_name", + "title": "获取Sheet页名称", + "comment": "在Excel对象%workbook%中获取%sheet_scope%,将结果保存到%sheet_name%", + "description": "获取Sheet页名称", + "icon": "BlockIcons/9-25.png", + "function": "xbot_visual.excel.get_sheet_name", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/sheet页操作/获取sheet页名称.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.GetSheetNameControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.GetSheetNameHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_scope", + "label": "Sheet页范围", + "required": true, + "default": "10:active_sheet", + "defaultDisplay": "当前Sheet页名称", + "tips": "当前激活的Sheet页或全部的Sheet页名称列表,注意两者返回的结果数据类型不同", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "当前Sheet页名称", + "value": "active_sheet" + }, + { + "display": "所有Sheet页名称", + "value": "all_sheet" + } + ] + } + } + ], + "outputs": [ + { + "id": "sheet_name", + "label": "Sheet页名称保存至", + "variableLabel": "Sheet页名称", + "tips": "指定一个变量名称,该变量用于保存Sheet页名称", + "type": "any", + "name": "sheet_name" + }, + { + "id": "sheet_name_list", + "label": "Sheet页名称列表保存至", + "variableLabel": "Sheet页名称", + "tips": "指定一个变量名称,该变量用于保存Sheet页名称列表", + "type": "any", + "name": "sheet_name_list", + "isEnable": false + } + ] + }, + { + "name": "excel.delete_sheet", + "title": "删除Sheet页", + "comment": "在Excel对象%workbook%中删除指定的Sheet页%sheet_name%", + "description": "删除指定的Sheet页", + "icon": "BlockIcons/9-21.png", + "function": "xbot_visual.excel.delete_sheet", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/sheet页操作/删除sheet页.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "required": true, + "tips": "输入待删除的Sheet页名称", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.copy_sheet", + "title": "拷贝Sheet页", + "comment": "在Excel对象%workbook%中拷贝Sheet页%sheet_name%到新的Sheet页%new_sheet_name%", + "description": "拷贝指定的Sheet页", + "icon": "BlockIcons/9-17.png", + "function": "xbot_visual.excel.copy_sheet", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/sheet页操作/拷贝sheet页.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.CopySheetControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.CopySheetHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "源Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "源Sheet页名称", + "required": true, + "tips": "输入待拷贝的Sheet页名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "copy_way", + "label": "拷贝方式", + "required": true, + "default": "10:copy_in_current_workbook", + "defaultDisplay": "当前工作簿内拷贝", + "tips": "请选择拷贝方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "当前工作簿内拷贝", + "value": "copy_in_current_workbook" + }, + { + "display": "拷贝到另外的工作簿", + "value": "copy_to_another_workbook" + } + ] + } + }, + { + "name": "dest_workbook", + "label": "目标Excel对象", + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "new_sheet_name", + "label": "新的Sheet页名称", + "required": true, + "tips": "输入新的Sheet页名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_cover", + "label": "", + "default": "13:False", + "required": true, + "tips": "若新的Sheet页名称存在,勾选后会覆盖原Sheet页,若不勾选,则会提示Sheet页名称已存在", + "type": "bool", + "editor": { + "label": "新的Sheet页存在则覆盖", + "kind": "checkbox" + } + } + ] + }, + { + "name": "excel.get_first_free_row", + "title": "获取第一个可用行", + "comment": "在Excel对象%workbook%中的Sheet页%sheet_name%中获取第一个可用行,将行号保存到%row_num%", + "description": "获取第一个可用行", + "icon": "BlockIcons/9-23.png", + "function": "xbot_visual.excel.get_first_free_row", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/获取第一个可用行.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ], + "outputs": [ + { + "id": "row_num", + "label": "行号保存至", + "variableLabel": "第一个可用行号", + "tips": "指定一个变量名称,该变量用于Sheet页第一个可用行号", + "type": "int", + "name": "row_num" + } + ] + }, + { + "name": "excel.get_first_free_column", + "title": "获取第一个可用列", + "comment": "在Excel对象%workbook%中的Sheet页%sheet_name%中获取第一个可用列,将列名保存到%column_name%", + "description": "获取第一个可用列", + "icon": "BlockIcons/9-22.png", + "function": "xbot_visual.excel.get_first_free_column", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/获取第一个可用列.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ], + "outputs": [ + { + "id": "column_name", + "label": "列名保存至", + "variableLabel": "第一个可用列名", + "tips": "指定一个变量名称,该变量用于Sheet页第一个可用列名", + "type": "str", + "name": "column_name" + } + ] + }, + { + "name": "excel.get_last_column", + "title": "获取最后一列", + "comment": "在Excel对象%workbook%中的Sheet页%sheet_name%中获取最后一列,将列名保存到%last_column_name%", + "description": "获取最后一列的列名", + "icon": "BlockIcons/9-22.png", + "function": "xbot_visual.excel.get_last_column", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/获取最后一列.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ], + "outputs": [ + { + "id": "last_column_name", + "label": "列名保存至", + "variableLabel": "Sheet页列名", + "tips": "指定一个变量名称,该变量用于Sheet页最后一列的列名", + "type": "str", + "name": "last_column_name" + } + ] + }, + { + "name": "excel.insert_row", + "title": "插入行", + "comment": "在Excel对象%workbook%中的第%row_num%行插入%values%", + "description": "插入行", + "icon": "BlockIcons/9-28.png", + "function": "xbot_visual.excel.insert_row", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/插入行.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "row_num", + "label": "行号", + "required": true, + "default": "10:1", + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "values", + "label": "行数据", + "required": true, + "tips": "待插入的行数据", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.insert_column", + "title": "插入列", + "comment": "在Excel对象%workbook%中的第%column_name%列插入%values%", + "description": "插入列", + "icon": "BlockIcons/9-27.png", + "function": "xbot_visual.excel.insert_column", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/插入列.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "column_name", + "label": "列名", + "required": true, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "values", + "label": "列数据", + "required": true, + "tips": "待插入的行数据", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.remove_column", + "title": "删除Excel列", + "keywords": "删除列", + "comment": "在Excel对象%workbook%中删除第%column_name%列", + "description": "删除列", + "icon": "BlockIcons/9-19.png", + "function": "xbot_visual.excel.remove_column", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/删除列.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "column_name", + "label": "列名", + "required": true, + "tips": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.get_first_free_row_on_column", + "title": "获取列上第一个可用行", + "comment": "在Excel对象%workbook%中获取第%column_name%列上的第一个可用行,将行号保存到%row_num%", + "description": "获取列上的第一个可用行", + "icon": "BlockIcons/9-24.png", + "function": "xbot_visual.excel.get_first_free_row_on_column", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/获取列上第一个可用行.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "column_name", + "label": "列名", + "required": true, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ], + "outputs": [ + { + "id": "row_num", + "label": "Sheet页行号保存至", + "variableLabel": "列上第一个可用行号", + "tips": "指定一个变量名称,该变量用于Sheet页指定列上的第一个可用行号", + "type": "int", + "name": "row_num" + } + ] + }, + { + "name": "excel.get_first_free_column_on_row", + "title": "获取行上第一个可用列", + "comment": "在Excel对象%workbook%中获取第%row_num%行上的第一个可用列,将列名保存到%column_name%", + "description": "获取行上第一个可用列", + "icon": "BlockIcons/9-24.png", + "function": "xbot_visual.excel.get_first_free_column_on_row", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/获取行上第一个可用列.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "row_num", + "label": "行号", + "required": true, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ], + "outputs": [ + { + "id": "column_name", + "label": "Sheet页列名保存至", + "variableLabel": "行上第一个可用列名", + "tips": "指定一个变量名称,该变量用于Sheet页指定行上的第一个可用列名", + "type": "str", + "name": "column_name" + } + ] + }, + { + "name": "excel.get_selected_range", + "title": "获取选中区域", + "comment": "获取Excel对象%workbook%当前Sheet页选中区域,将起始行号保存到%begin_row_num%,起始列名保存到%beigin_column_name%,结束行号保存到%end_row_num%,结束列名保存到%end_column_name%", + "description": "获取当前Sheet页选中区域", + "icon": "BlockIcons/9-26.png", + "function": "xbot_visual.excel.get_selected_range", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/获取选中区域.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ], + "outputs": [ + { + "id": "begin_row_num", + "label": "起始行号保存至", + "variableLabel": "选中区域起始行号", + "tips": "指定一个变量名称,该变量用于保存选中区域的起始行号", + "type": "int", + "name": "begin_row_num" + }, + { + "id": "beigin_column_name", + "label": "起始列名保存至", + "variableLabel": "选中区域起始列名", + "tips": "指定一个变量名称,该变量用于保存选中区域的起始列名", + "type": "str", + "name": "begin_column_name" + }, + { + "id": "end_row_num", + "label": "结束行号保存至", + "variableLabel": "选中区域结束行号", + "tips": "指定一个变量名称,该变量用于保存选中区域的结束行号", + "type": "int", + "name": "end_row_num" + }, + { + "id": "end_column_name", + "label": "结束列名保存至", + "variableLabel": "选中区域结束列名", + "tips": "指定一个变量名称,该变量用于保存选中区域的结束列名", + "type": "str", + "name": "end_column_name" + } + ] + }, + { + "name": "excel.clear_range", + "title": "清空Excel内容", + "icon": "BlockIcons/9-18.png", + "comment": "从Excel对象%workbook%中清空单元格(第%cell_row_num%行,第%cell_column_name%列)中的内容", + "description": "从Excel文件中清空内容或格式", + "function": "xbot_visual.excel.clear_range", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/清空excel内容.html", + "keywords": "格式,清空表格", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.ClearRangeFromWorkBookControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.ClearRangeFromWorkBookHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "clear_target", + "label": "清除内容", + "default": "13:all", + "tips": "选择清除内容:全部、内容、格式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all" + }, + { + "display": "内容", + "value": "content" + }, + { + "display": "格式", + "value": "format" + } + ] + } + }, + { + "name": "clear_way", + "label": "清空方式", + "required": true, + "default": "10:cell", + "defaultDisplay": "单元格", + "tips": "选择清空的区域,单元格、多行、多列、区域等", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单元格", + "value": "cell" + }, + { + "display": "行内容", + "value": "row" + }, + { + "display": "列内容", + "value": "column" + }, + { + "display": "区域内容", + "value": "range" + }, + { + "display": "已使用区域内容", + "value": "used_range" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "区域", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "cell_row_num", + "label": "行号", + "required": false, + "tips": "行号从1开始。若清空方式为‘行内容’,可以填写多行,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "cell_column_name", + "label": "列名", + "required": false, + "tips": "列名(支持A或1)。若清空方式为‘列内容’,多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "area_begin_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "area_begin_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "area_end_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "area_end_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "row_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "column_column_name", + "label": "列名", + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.copy_range", + "title": "拷贝Excel内容", + "icon": "BlockIcons/9-16.png", + "keywords": "复制Excel", + "comment": "从Excel对象%workbook%中拷贝单元格(第%cell_row_num%行,第%cell_column_name%列)中的内容", + "description": "从Excel文件中拷贝内容", + "function": "xbot_visual.excel.copy_range", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/拷贝excel内容.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.CopyRangeFromWorkBookControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.CopyRangeFromWorkBookHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "copy_way", + "label": "拷贝方式", + "required": true, + "default": "10:cell", + "defaultDisplay": "单元格", + "tips": "可拷贝单元格、多行、多列或区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单元格", + "value": "cell" + }, + { + "display": "行内容", + "value": "row" + }, + { + "display": "列内容", + "value": "column" + }, + { + "display": "区域内容", + "value": "range" + }, + { + "display": "已使用区域内容", + "value": "used_range" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "区域", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "cell_row_num", + "label": "行号", + "required": false, + "tips": "行号从1开始。若拷贝方式为‘行内容’,可以填写多行,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "cell_column_name", + "label": "列名", + "required": false, + "tips": "列名从A或1开始。拷贝方式为‘列内容’,可以填写多列,多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "area_begin_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "area_begin_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "area_end_row_num", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "area_end_column_name", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "row_row_num", + "label": "行号", + "required": false, + "tips": "行号", + "type": "any", + "editor": { + "placeholder": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "column_column_name", + "label": "列名", + "tips": "列名", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.paste_range", + "title": "粘贴Excel内容", + "comment": "在Excel对象%workbook%中单元格(第%row_num%行,第%column_name%列)处粘贴内容", + "description": "将剪切板中内容粘贴到Excel中,内容可通过拷贝Excel指令或者剪切板获取", + "icon": "BlockIcons/9-29.png", + "function": "xbot_visual.excel.paste_range", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/粘贴excel内容.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "row_num", + "label": "单元格行号", + "required": true, + "default": "10:1", + "tips": "待粘贴的单元格行号", + "type": "int", + "editor": { + "placeholder": "输入行号,从1开始", + "kind": "textbox" + } + }, + { + "name": "column_name", + "label": "单元格列名", + "required": true, + "tips": "待粘贴的单元格列名", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1)", + "kind": "textbox" + } + }, + { + "name": "copy_formula", + "label": "", + "default": "13:True", + "tips": "勾选时,表示拷贝单元格公式;未勾选时,表示只拷贝单元格值", + "type": "bool", + "editor": { + "label": "拷贝单元格公式", + "kind": "checkbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.paste_range_ex", + "title": "粘贴Excel内容", + "comment": "在Excel对象%workbook%中单元格(第%row_num%行,第%column_name%列)处粘贴内容", + "description": "粘贴Excel内容", + "icon": "BlockIcons/9-29.png", + "function": "xbot_visual.excel.paste_range_ex", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/粘贴excel内容.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.PasteRangeFromWorkBookHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "row_num", + "label": "单元格行号", + "default": "10:1", + "required": true, + "tips": "待粘贴的单元格行号,从1开始,-n表示倒数第n行", + "type": "int", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "column_name", + "label": "单元格列名", + "required": true, + "tips": "待粘贴的单元格列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "paste_type", + "label": "选择性粘贴", + "required": true, + "default": "10:-4104", + "defaultDisplay": "选择粘贴类型", + "tips": "选择粘贴类型", + "type": "int", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": -4104 + }, + { + "display": "公式", + "value": -4123 + }, + { + "display": "数值", + "value": -4163 + }, + { + "display": "格式", + "value": -4122 + }, + { + "display": "批注", + "value": -4144 + }, + { + "display": "有效性验证", + "value": 6 + }, + { + "display": "所有使用源主题的单元", + "value": 13 + }, + { + "display": "边框除外", + "value": 7 + }, + { + "display": "列宽", + "value": 8 + }, + { + "display": "公式和数字格式", + "value": 11 + }, + { + "display": "值和数字格式", + "value": 12 + }, + { + "display": "所有合并条件格式", + "value": 14 + } + ] + } + }, + { + "name": "paste_special_operation", + "label": "粘贴运算", + "required": true, + "default": "10:-4142", + "defaultDisplay": "选择粘贴运算方式", + "tips": "选择粘贴运算方式", + "type": "int", + "editor": { + "kind": "select", + "options": [ + { + "display": "无", + "value": -4142 + }, + { + "display": "加", + "value": 2 + }, + { + "display": "减", + "value": 3 + }, + { + "display": "乘", + "value": 4 + }, + { + "display": "除", + "value": 5 + } + ] + } + }, + { + "name": "skip_blanks", + "label": "", + "default": "13:False", + "tips": "是否跳过空单元", + "type": "bool", + "editor": { + "label": "跳过空单元", + "kind": "checkbox" + } + }, + { + "name": "transpose", + "label": "", + "default": "13:False", + "tips": "是否转置", + "type": "bool", + "editor": { + "label": "转置", + "kind": "checkbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.remove_duplicate_row", + "title": "删除重复行", + "comment": "在Excel对象%workbook%中根据第%column_name%列删除重复值", + "description": "实现Excel删除重复值功能", + "keywords": "去重", + "icon": "BlockIcons/9-31.png", + "function": "xbot_visual.excel.remove_duplicate_row", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/删除重复行.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "column_name", + "label": "重复值的列名", + "required": false, + "tips": "检查哪些列的重复信息,输入列名(支持A或1),多列用A,B,C或A:C。若不填,表示所有列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),多列用A,B,C或A:C。 若不填,表示所有列" + } + }, + { + "name": "start_row", + "label": "起始的行号", + "required": false, + "tips": "自定义需要删除的起始行号,默认为第一行,-n表示倒数第n行", + "type": "int", + "default": "10:1", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为第一行,-n表示倒数第n行" + } + }, + { + "name": "contain_header", + "label": "", + "default": "13:False", + "tips": "勾选时,表示第一行是标题,不参与重复值计算;不勾选时,表示第一行也参与重复值计算", + "type": "bool", + "editor": { + "label": "数据包含标题", + "kind": "checkbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.rename_sheet", + "title": "重命名Sheet页", + "comment": "在Excel对象%workbook%中将Sheet页%sheet_name%重命名为%new_sheet_name%", + "description": "重命名Sheet页", + "icon": "BlockIcons/9-32.png", + "function": "xbot_visual.excel.rename_sheet", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/sheet页操作/重命名sheet页.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "required": true, + "tips": "输入待修改的Sheet页名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "new_sheet_name", + "label": "新的Sheet页名称", + "required": true, + "tips": "输入新的Sheet页名称", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.refresh_data", + "title": "刷新Excel数据", + "keywords": "刷新表格数据", + "comment": "在Excel对象%workbook%中刷新当前工作簿的所有源,以获取最新的数据", + "description": "刷新Excel数据", + "icon": "BlockIcons/9-33.png", + "function": "xbot_visual.excel.refresh_data", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/刷新excel数据.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ] + }, + { + "name": "excel.insert_row", + "title": "插入空行", + "keywords": "添加行;插入行;新增行", + "comment": "在Excel对象%workbook%中第%row_num%行之前插入%amount%行空行", + "description": "在Excel表格中插入空行", + "icon": "BlockIcons/9-34.png", + "function": "xbot_visual.excel.insert_blank_row", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/插入行.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "row_num", + "label": "在第几行之前", + "required": true, + "default": "10:1", + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "int", + "editor": { + "placeholder": "输入行号,从1开始,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "amount", + "label": "插入几行", + "required": true, + "default": "10:1", + "tips": "插入几行,默认1行", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.insert_column", + "title": "插入空列", + "keywords": "添加列;插入列;新增列", + "comment": "在Excel对象%workbook%中第%column_name%列之前插入%amount%列空列", + "description": "在Excel表格中插入空列", + "icon": "BlockIcons/9-35.png", + "function": "xbot_visual.excel.insert_blank_column", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/插入列.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "column_name", + "label": "在第几列之前", + "required": true, + "tips": "在第几列之前插入,列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "amount", + "label": "插入几列", + "required": true, + "default": "10:1", + "tips": "插入几列,默认1列", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.set_format", + "title": "设置格式", + "icon": "BlockIcons/9-36.png", + "description": "设置单元格格式:数字、对齐、字体、边框、填充、保护", + "comment": "在Excel对象%workbook%中设置单元格格式", + "function": "xbot_visual.excel.set_format", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/设置格式.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.SetFormatControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.SetFormatHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "setting", + "label": "格式设置", + "required": true, + "tips": "可直接在此设置简单的格式,复杂的格式可事先在Excel中设置好,再点击编辑格式内的‘在Excel中指出’提取", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "range_type", + "label": "区域", + "required": true, + "default": "10:cell", + "defaultDisplay": "单元格", + "tips": "指定需要设置格式的区域,单元格、多行、多列、区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单元格", + "value": "cell" + }, + { + "display": "区域", + "value": "range" + }, + { + "display": "行", + "value": "row" + }, + { + "display": "列", + "value": "column" + }, + { + "display": "已使用区域", + "value": "used_range" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "区域", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "start_row", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始。若区域为行,可以填写多行,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "start_column", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1)。若区域为列,可以填写多列,多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "end_row", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "end_column", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.clear_format", + "title": "清空格式", + "icon": "BlockIcons/9-37.png", + "description": "清空单元格格式", + "comment": "在Excel对象%workbook%中清空单元格格式", + "function": "xbot_visual.excel.clear_fomat", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/清空格式.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.ClearFormatControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.ClearFormatHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "range_type", + "label": "区域", + "required": true, + "default": "10:cell", + "defaultDisplay": "单元格", + "tips": "指定清空格式的区域,单元格、多行、多列、区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单元格", + "value": "cell" + }, + { + "display": "区域", + "value": "range" + }, + { + "display": "行", + "value": "row" + }, + { + "display": "列", + "value": "column" + }, + { + "display": "已使用区域", + "value": "used_range" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "区域", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "start_row", + "label": "行号", + "required": false, + "tips": "输入行号从1开始。若区域为行,可以填写多行,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "start_column", + "label": "列名", + "required": false, + "tips": "输入列名从A或1开始。若区域为列,可以填写多列,多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名,从A或1开始,-n表示倒数第n列" + } + }, + { + "name": "end_row", + "label": "行号", + "required": false, + "tips": "输入行号,从1开始,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,从1开始,-n表示倒数第n行" + } + }, + { + "name": "end_column", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n行列" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.set_row_height", + "title": "设置行高", + "icon": "BlockIcons/9-38.png", + "description": "设置行高", + "comment": "在Excel对象%workbook%中设置第%row_num%行的高度为%height%", + "function": "xbot_visual.excel.set_row_height", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/设置行高.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.SetRowHeightControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.SetRowHeightHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "row_num", + "label": "行号", + "required": true, + "tips": "输入行号,多行用1,2,3或1:3", + "type": "any", + "editor": { + "placeholder": "输入行号,多行用1,2,3或1:3", + "kind": "textbox" + } + }, + { + "name": "mode", + "label": "方式", + "required": true, + "default": "10:autoFit", + "defaultDisplay": "根据内容自适应高度", + "tips": "两种方式:根据内容自适应高度、指定行高", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据内容自适应高度", + "value": "autoFit" + }, + { + "display": "指定行高", + "value": "specific" + } + ] + } + }, + { + "name": "height", + "label": "行高", + "required": false, + "tips": "行高", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.set_column_width", + "title": "设置列宽", + "icon": "BlockIcons/9-39.png", + "description": "设置列宽", + "comment": "在Excel对象%workbook%中设置第%column_name%列宽度为%width%", + "function": "xbot_visual.excel.set_column_width", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/设置列宽.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.SetColumnWidthControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.SetColumnWidthHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "column_name", + "label": "列名", + "required": true, + "tips": "输入列名(支持A或1),多列用A,B,C", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),多列用A,B,C" + } + }, + { + "name": "mode", + "label": "方式", + "required": true, + "default": "10:autoFit", + "defaultDisplay": "根据内容自适应宽度", + "tips": "两种方式:根据内容自适应宽度、指定列宽", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据内容自适应宽度", + "value": "autoFit" + }, + { + "display": "指定列宽", + "value": "specific" + } + ] + } + }, + { + "name": "width", + "label": "列宽", + "required": false, + "tips": "列宽", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.create_pivot_table", + "title": "新建数据透视表", + "icon": "BlockIcons/9-40.png", + "description": "新建数据透视表", + "comment": "在Excel对象%workbook%中新建数据透视表", + "function": "xbot_visual.excel.create_pivot_table", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/新建数据透视表.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.CreatePivotTableControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "setting", + "label": "透视表设置", + "required": true, + "tips": "在Excel中完成透视表的设置,再点击此处的‘在Excel中指出’提取透视表的配置信息", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "source", + "label": "数据源", + "required": true, + "tips": "设置透视表的数据源", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.refresh_pivot_table", + "title": "刷新数据透视表", + "icon": "BlockIcons/9-41.png", + "description": "刷新数据透视表", + "comment": "在Excel对象%workbook%中刷新数据透视表", + "function": "xbot_visual.excel.refresh_pivot_table", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/刷新数据透视表.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.RefreshPivotTableControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "所在Sheet页名称", + "tips": "透视所在Sheet页名称", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + }, + { + "name": "name_or_index", + "label": "透视表名称或位置", + "required": true, + "default": "10:1", + "tips": "若一个Sheet页中只有一个数据透视表,填1即可,若有多个,可填写透视表名称或位置(从1开始)", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.filter_pivot_table", + "title": "筛选数据透视表", + "icon": "BlockIcons/9-46.png", + "description": "筛选数据透视表", + "comment": "在Excel对象%workbook%中筛选数据透视表,筛选字段为%field_name%,筛选项为%filter_value_list%", + "function": "xbot_visual.excel.filter_pivot_table", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/筛选数据透视表.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.FilterPivotTableControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.FilterPivotTableHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "所在Sheet页名称", + "tips": "透视所在Sheet页名称", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + }, + { + "name": "name_or_index", + "label": "透视表名称或位置", + "required": true, + "default": "10:1", + "tips": "若一个Sheet页中只有一个数据透视表,填1即可,若有多个,可填写透视表名称或位置(从1开始)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "field_name", + "label": "筛选器名称", + "required": true, + "tips": "输入筛选器字段名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "select_type", + "label": "选择方式", + "required": true, + "default": "10:partial", + "defaultDisplay": "部分选择", + "tips": "可选择全部选择和部分选择", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部选择", + "value": "all" + }, + { + "display": "部分选择", + "value": "partial" + } + ] + } + }, + { + "name": "filter_value_list", + "label": "筛选器内容", + "tips": "输入筛选器内容列表", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "excel.add_validation", + "title": "新增数据验证", + "icon": "BlockIcons/9-42.png", + "description": "新增数据验证", + "comment": "在Excel对象%workbook%中新增数据验证", + "function": "xbot_visual.excel.add_validation", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/新增数据验证.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.AddValidationControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.AddValidationHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "setting", + "label": "数据验证设置", + "required": true, + "tips": "在Excel中将数据验证设置完成后,通过点击此处的‘在Excel内指出’提取设置信息", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "range_type", + "label": "区域", + "required": true, + "default": "10:cell", + "defaultDisplay": "单元格", + "tips": "可选择单元格、多行、多列和区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单元格", + "value": "cell" + }, + { + "display": "区域", + "value": "range" + }, + { + "display": "行", + "value": "row" + }, + { + "display": "列", + "value": "column" + }, + { + "display": "已使用区域", + "value": "used_range" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "区域", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "start_row", + "label": "行号", + "required": false, + "tips": "输入行号,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,-n表示倒数第n行" + } + }, + { + "name": "start_column", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "end_row", + "label": "行号", + "required": false, + "tips": "输入行号,-n表示倒数第n行", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入行号,-n表示倒数第n行" + } + }, + { + "name": "end_column", + "label": "列名", + "required": false, + "tips": "输入列名(支持A或1),-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),-n表示倒数第n列" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.custom_sort", + "title": "Excel排序", + "keywords": "Excel升序;Excel降序;表格排序", + "icon": "BlockIcons/9-45.png", + "description": "对Excel指定列做升序、降序,或者指定区域做自定义排序操作", + "comment": "在Excel对象%workbook%中新增排序", + "function": "xbot_visual.excel.custom_sort", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/高级指令/excel自定义排序.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.CustomSortControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.CustomSortHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sort_way", + "label": "排序方法", + "required": true, + "default": "10:ascending", + "defaultDisplay": "升序", + "tips": "可选择排序方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "升序", + "value": "ascending" + }, + { + "display": "降序", + "value": "descending" + }, + { + "display": "自定义排序", + "value": "custom_sort" + } + ] + } + }, + { + "name": "sort_column", + "label": "排序列", + "default": "10:", + "required": false, + "tips": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "useVariableOptions": false + } + }, + { + "name": "is_expand_selected_area", + "label": "", + "required": false, + "default": "13:True", + "tips": "", + "type": "bool", + "editor": { + "label": "扩展选定区域", + "kind": "checkbox" + } + }, + { + "name": "is_firstline_notsort", + "label": "", + "required": false, + "default": "13:True", + "tips": "", + "type": "bool", + "editor": { + "label": "首行不参与排序", + "kind": "checkbox" + } + }, + { + "name": "sort_setting", + "label": "自定义排序设置", + "required": false, + "tips": "在Excel中将自定义排序设置完成后,通过点击此处的‘在Excel内指出’提取设置信息", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "range_type", + "label": "区域", + "required": false, + "default": "10:used_range", + "defaultDisplay": "已使用区域", + "tips": "可选择区域,行,列和已使用区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "区域", + "value": "range" + }, + { + "display": "行", + "value": "row" + }, + { + "display": "列", + "value": "column" + }, + { + "display": "已使用区域", + "value": "used_range" + } + ] + } + }, + { + "name": "range", + "label": "区域", + "tips": "区域", + "type": "str", + "editor": { + "kind": "excelrange" + } + }, + { + "name": "start_row", + "label": "行号", + "required": false, + "tips": "起始行号从1开始。若区域为行,可以填写多行,多行用1,2,3或1:3", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "起始行号,从1开始" + } + }, + { + "name": "start_column", + "label": "起始列名", + "required": false, + "tips": "起始列名从A或1开始。若区域为列,可以填写多列,多列用A,B,C或A:C", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "列名,从A或1开始" + } + }, + { + "name": "end_row", + "label": "行号", + "required": false, + "tips": "结束行号,从1开始", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "结束行号,从1开始" + } + }, + { + "name": "end_column", + "label": "列名", + "required": false, + "tips": "结束列名(支持A或1)", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "结束列名,从A或1开始" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + }, + { + "name": "excel.export_to_pdf", + "title": "导出为PDF", + "icon": "BlockIcons/9-43.png", + "description": "导出为PDF", + "comment": "将Excel对象%workbook%导出为PDF文件到%pdf_name%", + "function": "xbot_visual.excel.export_to_pdf", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/导出为pdf.html", + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在的工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + }, + { + "name": "all_sheets", + "label": "", + "default": "13:False", + "tips": "若勾选,导出所有工作表", + "type": "bool", + "editor": { + "label": "全部Sheet页", + "kind": "checkbox" + } + }, + { + "name": "pdf_name", + "label": "PDF保存到", + "tips": "填写要导出的PDF保存的文件名", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "filter": "PDF|*.pdf" + } + } + }, + { + "name": "override", + "label": "", + "default": "13:True", + "tips": "如果PDF文件存在则覆盖,PDF保存路径若不存在会自动创建", + "type": "bool", + "editor": { + "label": "如果文件存在则覆盖", + "kind": "checkbox" + } + } + ] + }, + { + "name": "excel.set_hidden", + "title": "设置行列隐藏", + "icon": "BlockIcons/9-44.png", + "comment": "在Excel对象%workbook%中隐藏第%row_num%行", + "description": "隐藏/取消隐藏Excel行列", + "function": "xbot_visual.excel.set_hidden", + "helpUrl": "yddoc/language/zh-cn/指令文档/excel/读写操作/设置行列隐藏.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Excel.SetHiddenControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Excel.SetHiddenHandler" + } + ], + "inputs": [ + { + "name": "workbook", + "label": "Excel对象", + "required": true, + "tips": "输入一个通过\"新建Excel\"或\"打开Excel\"创建的Excel对象", + "type": "openpyxl.Workbook", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "hidden_property", + "label": "状态", + "required": true, + "default": "10:True", + "defaultDisplay": "隐藏", + "tips": "用于设置Excel行列的隐藏属性", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "隐藏", + "value": "True" + }, + { + "display": "取消隐藏", + "value": "False" + } + ] + } + }, + { + "name": "range_type", + "label": "区域", + "required": true, + "default": "10:row", + "defaultDisplay": "行", + "tips": "指定要隐藏/取消隐藏的行或者列", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "行", + "value": "row" + }, + { + "display": "列", + "value": "column" + } + ] + } + }, + { + "name": "row_num", + "label": "行号", + "tips": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "column_name", + "label": "列名", + "tips": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "default": "10:", + "tips": "所在工作表名称,选填,默认为当前激活的Sheet页", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "选填,默认为当前激活的Sheet页" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/file.blocks.json b/src/assert/block_settings/file.blocks.json new file mode 100644 index 0000000..ac29d8b --- /dev/null +++ b/src/assert/block_settings/file.blocks.json @@ -0,0 +1,651 @@ +{ + "types": [ + { + "name": "xbot_visual.file.FileParts", + "localName": "文件路径信息", + "props": [ + { + "name": "drive_name", + "type": "str", + "label": "根目录" + }, + { + "name": "directory", + "type": "str", + "label": "父目录" + }, + { + "name": "file_name", + "type": "str", + "label": "文件名称" + }, + { + "name": "file_name_without_extension", + "type": "str", + "label": "文件名称(不带扩展名)" + }, + { + "name": "file_extension", + "type": "str", + "label": "文件扩展名" + } + ] + } + ], + "blocks": [ + { + "name": "file.if_exist", + "statement": "workflow.if", + "function": "xbot_visual.file.if_exist", + "title": "IF 文件存在", + "description": "判断文件是否存在", + "comment": "如果文件%path%%expect_exist%,则执行以下操作", + "indent": "1", + "scope": "1", + "isCondition": true, + "icon": "BlockIcons/18-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if文件存在.html", + "video": { + "time": "00:47" + }, + "inputs": [ + { + "name": "path", + "label": "文件路径", + "required": true, + "tips": "输入或选择文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "expect_exist", + "label": "文件是否", + "required": true, + "default": "10:exist", + "defaultDisplay": "存在", + "tips": "选择预期的文件是否存在", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "存在", + "value": "exist" + }, + { + "display": "不存在", + "value": "no_exist" + } + ] + } + } + ] + }, + { + "name": "file.remove", + "function": "xbot_visual.file.remove", + "title": "删除文件", + "description": "删除文件,Python模式支持多文件删除,文本模式只支持单文件删除", + "comment": "删除文件%paths%", + "icon": "BlockIcons/18-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件/删除文件.html", + "inputs": [ + { + "name": "paths", + "label": "要删除的文件", + "required": true, + "tips": "输入要删除的文件的路径,若想删除多个文件,切换到Python模式,比如['文件1路径','文件2路径']", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + } + ] + }, + { + "name": "file.read", + "function": "xbot_visual.file.read", + "title": "读取文件", + "description": "读取指定路径文件的内容", + "comment": "读取文件%path%的内容,将内容保存到%file_content%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.File.ReadFile, ShadowBot.Shell.Development", + "icon": "BlockIcons/18-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件/读取文件.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.File.ReadHandler" + } + ], + "inputs": [ + { + "name": "path", + "label": "要读取的文件", + "required": true, + "tips": "输入要读取文件的路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "read_way", + "label": "文件内容保存为", + "required": false, + "default": "10:all_text", + "defaultDisplay": "文本", + "tips": "指定输出的文件内容,可以选择“文本”可以将整个文件保存到一个文本中,选择“列表”按行获取文本内容并存储到列表中,选择“二进制文本”将读取的文本再转为二进制", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文本", + "value": "all_text" + }, + { + "display": "列表(每行保存为列表一项)", + "value": "lines" + }, + { + "display": "二进制文本", + "value": "bin" + } + ] + } + }, + { + "name": "encoding", + "label": "文件编码", + "required": false, + "default": "10:UTF-8", + "defaultDisplay": "UTF-8", + "tips": "选择文本编码", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "默认", + "value": "default" + }, + { + "display": "ANSI", + "value": "ANSI" + }, + { + "display": "UTF-8", + "value": "UTF-8" + }, + { + "display": "UTF-16", + "value": "UTF-16" + }, + { + "display": "UTF-16 BE", + "value": "utf-16-be" + } + ] + } + } + ], + "outputs": [ + { + "id": "file_content", + "label": "保存文件内容至", + "variableLabel": "读取的文件内容", + "tips": "输入一个名字,用来保存文件内容", + "type": "any", + "name": "file_content" + } + ] + }, + { + "name": "file.write", + "function": "xbot_visual.file.write", + "title": "写入文件", + "description": "将文本内容写入到已有文件,若文件不存在,自动创建文件", + "comment": "将内容%content%覆盖写入到文件%path%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.File.WriteFile, ShadowBot.Shell.Development", + "icon": "BlockIcons/18-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件/写入文件.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.File.WriteHandler" + } + ], + "inputs": [ + { + "name": "path", + "label": "要写入的文件", + "required": true, + "tips": "输入文件路径,文件若不存在,会自动创建文件", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "content", + "label": "要写入的内容", + "required": true, + "tips": "待写入文件的内容", + "type": "any", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "write_way", + "label": "如果文件存在", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖写入", + "tips": "指定当要写入的文件存在时要执行的操作", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖写入", + "value": "overwrite" + }, + { + "display": "追加写入", + "value": "append" + } + ] + } + }, + { + "name": "is_text", + "label": "", + "required": true, + "tips": "文件是文本文件", + "type": "bool", + "default": "13:True", + "editor": { + "label": "文件是文本文件", + "kind": "checkbox" + } + }, + { + "name": "new_line", + "label": "", + "required": false, + "tips": "是否要换新行追加,若否,直接在原内容后面追加", + "type": "bool", + "default": "13:False", + "editor": { + "label": "新行追加", + "kind": "checkbox" + } + }, + { + "name": "encoding", + "label": "文件编码", + "required": false, + "default": "10:UTF-8", + "defaultDisplay": "UTF-8", + "tips": "选择文本编码", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "默认", + "value": "default" + }, + { + "display": "ANSI", + "value": "ANSI" + }, + { + "display": "UTF-8", + "value": "UTF-8" + }, + { + "display": "UTF-16", + "value": "UTF-16" + }, + { + "display": "UTF-16 BE", + "value": "utf-16-be" + } + ] + } + } + ] + }, + { + "name": "file.copy", + "function": "xbot_visual.file.copy", + "title": "拷贝文件", + "keywords": "复制文件", + "description": "拷贝文件,Python模式支持多文件拷贝,文本模式只支持单文件拷贝", + "comment": "将文件%source_file_paths%拷贝到文件夹%copyto_dir_path%,将拷贝后的文件路径列表保存到%file_list%", + "icon": "BlockIcons/18-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件/拷贝文件.html", + "inputs": [ + { + "name": "source_file_paths", + "label": "要拷贝的文件", + "required": true, + "tips": "输入要拷贝文件的路径,若想拷贝多个文件,切换到Python模式,比如['D:\\测试\\11.txt','D:\\测试\\22.txt']", + "type": "any", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "copyto_dir_path", + "label": "目标文件夹", + "required": true, + "tips": "输入目标文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "copy_way", + "label": "如果文件存在", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖", + "tips": "指定当目标文件夹下已存在同名文件时要执行的操作", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "不要拷贝", + "value": "not_copy" + }, + { + "display": "自动添加后缀", + "value": "save_as" + } + ] + } + } + ], + "outputs": [ + { + "id": "file_list", + "label": "拷贝后的文件路径列表", + "variableLabel": "拷贝后的文件路径列表", + "tips": "输入一个名字,用来保存拷贝后的文件路径列表", + "type": "list", + "name": "file_list" + } + ] + }, + { + "name": "file.move", + "function": "xbot_visual.file.move", + "title": "移动文件", + "description": "移动文件,Python模式支持多文件移动,文本模式只支持单文件移动", + "comment": "将文件%source_file_paths%移动到文件夹%moveto_dir_path%,将移动后的文件路径列表保存到%file_list%", + "icon": "BlockIcons/18-6.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件/移动文件.html", + "inputs": [ + { + "name": "source_file_paths", + "label": "要移动的文件", + "required": true, + "tips": "输入要移动文件的路径,若想移动多个文件,切换到Python模式,比如['D:\\测试\\11.txt','D:\\测试\\22.txt']", + "type": "any", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "moveto_dir_path", + "label": "目标文件夹", + "required": true, + "tips": "输入目标文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "move_way", + "label": "如果文件存在", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖", + "tips": "指定当目标文件夹下已存在同名文件时要执行的操作", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "不要移动", + "value": "not_copy" + } + ] + } + } + ], + "outputs": [ + { + "id": "file_list", + "label": "移动后的文件路径列表", + "variableLabel": "移动后的文件路径列表", + "tips": "输入一个名字,移动后的文件路径列表", + "type": "list", + "name": "file_list" + } + ] + }, + { + "name": "file.get_file_parts", + "function": "xbot_visual.file.get_file_parts", + "title": "获取文件路径信息", + "description": "获取文件路径的根目录、父目录、文件名、基本文件名和文件扩展名", + "comment": "解析文件%path%信息,将结果保存到%file_parts%", + "icon": "BlockIcons/18-8.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件/获取文件路径信息.html", + "inputs": [ + { + "name": "path", + "label": "文件路径", + "required": true, + "tips": "输入文件路径", + "type": "any", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + } + ], + "outputs": [ + { + "id": "file_parts", + "label": "文件路径信息", + "variableLabel": "文件路径信息", + "tips": "输入一个名字,用来保存文件路径信息", + "type": "xbot_visual.file.FileParts", + "name": "file_parts" + } + ] + }, + { + "name": "file.wait", + "function": "xbot_visual.file.wait", + "title": "等待文件", + "description": "等待文件被创建或者删除", + "comment": "等待文件%path%被%desired_state%,最多等待%timeout%秒", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.File.WaitFileControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.File.WaitFileHandler" + } + ], + "icon": "BlockIcons/18-9.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/等待/等待文件.html", + "video": { + "time": "04:46" + }, + "inputs": [ + { + "name": "path", + "label": "文件路径", + "required": true, + "tips": "输入文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "desired_state", + "label": "等待文件被", + "required": true, + "default": "10:created", + "defaultDisplay": "创建", + "tips": "选择期望的文件状态", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "创建", + "value": "created" + }, + { + "display": "删除", + "value": "deleted" + } + ] + } + }, + { + "name": "is_wait", + "label": "", + "required": true, + "tips": "设置超时时间", + "type": "bool", + "default": "13:True", + "editor": { + "label": "设置超时时间", + "kind": "checkbox" + } + }, + { + "name": "timeout_seconds", + "label": "超时时间(秒)", + "required": false, + "default": "10:20", + "tips": "请输入超时时间(秒),", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "file_wait_result", + "label": "等待结果", + "tips": "如果为True则等待成功,否则等待超时", + "name": "file_wait_result", + "type": "bool" + } + ] + }, + { + "name": "file.rename", + "function": "xbot_visual.file.rename", + "title": "文件重命名", + "description": "文件重命名", + "comment": "将文件%path%重命名为%new_name%,将新的文件路径保存到%new_file_path%", + "icon": "BlockIcons/18-10.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/文件/文件重命名.html", + "inputs": [ + { + "name": "path", + "label": "要重命名的文件", + "required": true, + "tips": "输入或选择要重命名的文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "new_name", + "label": "新的文件名称", + "required": true, + "tips": "新的文件名称", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "new_file_path", + "label": "新的文件路径", + "variableLabel": "重命名后的文件路径", + "tips": "输入一个名字,用来保存新的文件路径", + "type": "str", + "name": "new_file_path" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/ftp.blocks.json b/src/assert/block_settings/ftp.blocks.json new file mode 100644 index 0000000..68ebfcb --- /dev/null +++ b/src/assert/block_settings/ftp.blocks.json @@ -0,0 +1,684 @@ +{ + "types": [ + { + "name": "xbot.ftp.FTPBase", + "localName": "FTP对象" + } + ], + "blocks": [ + { + "name": "ftp.connection", + "function": "xbot_visual.ftp.connection", + "title": "建立FTP连接", + "description": "创建一个文件服务器连接,并返回连接对象", + "comment": "使用输入密码为用户%user_name%建立%server_kind%(%server_ip%:%server_port%)的连接,将连接对象保存到%ftp_instance%", + "icon": "BlockIcons/32-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/建立ftp连接.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.FTP.ConnectionControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.FTP.ConnectionHandler" + } + ], + "inputs": [ + { + "name": "server_kind", + "label": "服务器类型", + "tips": "要创建的连接对象的服务器类型", + "type": "str", + "required": true, + "default": "10:FTP", + "defaultDisplay": "FTP服务器", + "editor": { + "kind": "select", + "options": [ + { + "display": "FTP服务器", + "value": "FTP" + }, + { + "display": "SFTP服务器", + "value": "SFTP" + } + ] + } + }, + { + "name": "server_ip", + "label": "FTP服务器地址", + "required": true, + "tips": "FTP服务器地址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "server_port", + "label": "FTP服务器端口", + "required": true, + "tips": "FTP服务器端口", + "default": "10:21", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "is_active", + "label": "", + "default": "13:False", + "tips": "通常更推荐使用ftp被动模式。但如果FTP服务器配置为仅支持主动模式或者服务端网络配置不允许被动模式的数据连接,此时客户端就需要使用主动模式。", + "type": "bool", + "editor": { + "kind": "checkbox", + "label": "启用主动模式" + } + }, + { + "name": "ispasv", + "label": "", + "default": "13:False", + "tips": "当客户端和服务端之间存在连接安全问题如存在防火墙导致服务端无法主动创建数据传输连接时可以启用主动连接模式", + "type": "bool", + "editor": { + "kind": "checkbox", + "label": "启用主动连接" + } + }, + { + "name": "login_kind", + "label": "连接方式", + "tips": "连接远程服务器的方式,默认使用密码连接", + "type": "str", + "required": true, + "default": "10:usePassword", + "defaultDisplay": "密码连接", + "editor": { + "kind": "select", + "options": [ + { + "display": "密码连接", + "value": "usePassword" + }, + { + "display": "密钥连接", + "value": "usePrivateKey" + } + ] + } + }, + { + "name": "user_name", + "label": "用户名", + "required": true, + "tips": "用于连接到FTP服务器的用户名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "password", + "label": "密码", + "tips": "用于连接到FTP服务器的用户密码", + "type": "str", + "default": "10:", + "editor": { + "kind": "password" + } + }, + { + "name": "private_key", + "label": "密钥文件", + "tips": "用于连接到服务器的密钥文件", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "timeout", + "label": "连接超时时间", + "tips": "FTP连接的超时时间,默认超时时间10s,设置为-1表示一直等待,0表示不等待", + "required": true, + "category": "advanced", + "default": "10:10", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "ftp_instance", + "label": "保存FTP连接对象至", + "tips": "指定一个变量名称,该变量用于保存FTP连接对象", + "name": "ftp_instance", + "type": "xbot.ftp.FTPBase" + } + ] + }, + { + "name": "ftp.disconnection", + "function": "xbot_visual.ftp.disconnection", + "title": "断开FTP连接", + "description": "断开当前FTP连接", + "comment": "断开当前%ftp%连接", + "icon": "BlockIcons/32-12.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/断开ftp连接.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "需要断开连接的FTP对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + } + ] + }, + { + "name": "ftp.get_ftp_files", + "function": "xbot_visual.ftp.get_ftp_files", + "title": "获取全部文件", + "description": "获取FTP服务端当前路径下的全部文件和子文件夹", + "comment": "获取FTP连接%ftp%中当前工作路径下的全部文件和子文件夹,将结果保存到%files_result%", + "icon": "BlockIcons/32-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/获取全部文件.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.FTP.GetFTPFilesBlockHandler" + } + ], + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "需要获取文件和文件夹信息的FTP连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + } + ], + "outputs": [ + { + "id": "files_result", + "label": "保存返回的文件至", + "tips": "指定一个变量名称,该变量用于保存返回的文件和子文件数据", + "name": "files_result", + "type": "dict" + } + ] + }, + { + "name": "ftp.change_workspace_path", + "function": "xbot_visual.ftp.change_workspace_path", + "title": "切换工作路径", + "description": "切换FTP连接的工作路径", + "comment": "切换FTP连接%ftp%中的工作路径到%new_remote_path%", + "icon": "BlockIcons/32-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/切换工作路径.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "需要切换工作路径的ftp连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "new_remote_path", + "label": "工作路径", + "tips": "需要切换到的新工作路径", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "ftp.download_files", + "function": "xbot_visual.ftp.download_files", + "title": "文件下载(ftp)", + "keywords": "下载文件;FTP下载", + "description": "将FTP远程服务器指定路径下的一个或多个文件下载到本地指定的路径下", + "comment": "将FTP连接%ftp%中的文件%download_files%下载到本地路径%local_path%中,如果本地存在同名文件则%download_mode%", + "icon": "BlockIcons/32-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/文件下载.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "要下载的文件的ftp连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "download_files", + "label": "远程文件(文件列表)", + "tips": "需要下载的文件或文件列表", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "local_path", + "label": "本地路径", + "tips": "远程文件将要下载到本地的路径", + "required": true, + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "download_mode", + "label": "下载模式", + "tips": "需要下载的文件在本地文件夹存在时的处理方式", + "type": "str", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "放弃下载", + "value": "notdownload" + }, + { + "display": "自动生成文件名", + "value": "uniquename" + } + ] + } + } + ] + }, + { + "name": "ftp.download_folders", + "function": "xbot_visual.ftp.download_folders", + "title": "文件夹下载(ftp)", + "keywords": "下载文件夹;FTP下载", + "description": "将FTP远程服务器指定路径下的一个或多个文件夹下载到本地指定的路径下", + "comment": "将FTP连接%ftp%中的文件夹%remote_paths%下载到本地路径%local_path%中", + "icon": "BlockIcons/32-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/文件夹下载.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "要下载的文件夹的ftp连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "remote_paths", + "label": "远程文件夹(文件夹列表)", + "tips": "下载文件夹的远程路径,不填则默认下载当前工作路径", + "required": true, + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "local_path", + "label": "本地路径", + "tips": "文件夹下载保存的本地路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "download_mode", + "label": "子文件存在时", + "tips": "需要下载的文件夹中子文件在本地文件夹存在时的处理方式", + "type": "str", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "放弃下载", + "value": "notdownload" + }, + { + "display": "自动生成文件名", + "value": "uniquename" + } + ] + } + } + ] + }, + { + "name": "ftp.uoload_files", + "function": "xbot_visual.ftp.upload_files", + "title": "文件上传(ftp)", + "keywords": "上传文件;FTP上传", + "description": "将本地一个或多个文件上传到FTP远程服务的指定路径下", + "comment": "将本地文件%local_files%上传到FTP连接%ftp%中指定的路径%remote_path%下,如果远程路径下存在同名文件则%upload_mode%", + "icon": "BlockIcons/32-6.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/文件上传.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "文件要上传到的FTP连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "remote_path", + "label": "远程路径", + "tips": "文件要上传到远程服务器的路径,不填则默认上传到当前工作路径", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "local_files", + "label": "本地文件(文件列表)", + "tips": "要上传的本地文件或文件列表", + "required": true, + "type": "any", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "upload_mode", + "label": "上传模式", + "tips": "要上传的文件在远程服务器上存在时的处理方式", + "type": "str", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "放弃上传", + "value": "notupload" + }, + { + "display": "自动生成文件名", + "value": "uniquename" + } + ] + } + } + ] + }, + { + "name": "ftp.upload_folders", + "function": "xbot_visual.ftp.upload_folders", + "title": "文件夹上传(ftp)", + "keywords": "上传文件夹;FTP上传", + "description": "将本地一个或多个文件夹上传到FTP远程服务的指定路径下", + "comment": "将本地文件夹%local_folders%上传到FTP连接%ftp%中", + "icon": "BlockIcons/32-7.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/文件夹上传.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "文件夹要上传到的FTP连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "remote_path", + "label": "远程路径", + "tips": "本地文件夹需要上传到的远程路径,不填则默认上传到当前工作路径", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "local_folders", + "label": "本地文件夹(文件夹列表)", + "tips": "需要上传到远程服务器的本地的一个或多个文件夹", + "required": true, + "type": "any", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "upload_mode", + "label": "子文件存在时", + "tips": "要上传的文件夹中子文件在远程服务器上存在时的处理方式", + "type": "str", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "放弃上传", + "value": "notupload" + }, + { + "display": "自动生成文件名", + "value": "uniquename" + } + ] + } + } + ] + }, + { + "name": "ftp.delete_files", + "function": "xbot_visual.ftp.delete_files", + "title": "文件删除(ftp)", + "keywords": "删除文件", + "description": "删除远程路径指定的一个或多个文件", + "comment": "删除FTP连接%ftp%中的文件%remote_files%", + "icon": "BlockIcons/32-8.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/文件删除.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "需要删除文件的FTP远程连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "remote_files", + "label": "删除的文件(文件列表)", + "tips": "需要删除的远程文件名称", + "required": true, + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "ftp.rename_file", + "function": "xbot_visual.ftp.rename_file", + "title": "文件重命名(ftp)", + "description": "重命名远程服务器的文件", + "comment": "将FTP连接%ftp%中的文件%remote_file%重命名为%new_name%", + "icon": "BlockIcons/32-9.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/文件重命名.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "需要重命名文件的FTP远程连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "remote_file", + "label": "远程文件", + "tips": "需要重命名的远程文件", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "new_name", + "label": "新名称", + "tips": "远程文件重命名后的名称", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "ftp.creat_directory", + "function": "xbot_visual.ftp.creat_directory", + "title": "创建文件夹(ftp)", + "description": "在远程服务器上创建文件夹", + "comment": "在FTP连接%ftp%中创建文件夹%new_remote_path%", + "icon": "BlockIcons/32-10.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/创建文件夹.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "需要创建文件夹的FTP连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "new_remote_path", + "label": "新文件夹", + "tips": "需要创建的文件夹名称", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "ftp.delete_folder", + "function": "xbot_visual.ftp.delete_folder", + "title": "删除文件夹(ftp)", + "description": "删除远程服务器上的文件夹", + "comment": "删除FTP连接%ftp%中的文件夹%remote_path%", + "icon": "BlockIcons/32-11.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/ftp/删除文件夹.html", + "inputs": [ + { + "name": "ftp", + "label": "FTP连接对象", + "tips": "需要删除文件夹的FTP连接对象", + "required": true, + "type": "xbot.ftp.FTPBase", + "editor": { + "useVariableOptions": true, + "kind": "select" + } + }, + { + "name": "remote_path", + "label": "远程文件夹", + "tips": "需要删除的文件夹名称,不填则默认删除当前工作路径", + "required": true, + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/image.blocks.json b/src/assert/block_settings/image.blocks.json new file mode 100644 index 0000000..4cb1709 --- /dev/null +++ b/src/assert/block_settings/image.blocks.json @@ -0,0 +1,628 @@ +{ + "types": [], + "blocks": [ + { + "name": "image.wait", + "icon": "BlockIcons/22-3.png", + "description": "等待目标图像出现或消失,再继续执行流程", + "comment": "等待%window_kind%中图像%template_images%出现,最多等待%timeout%秒", + "title": "等待图像", + "keywords": "等待图片", + "function": "xbot_visual.image.wait", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Image.WaitImageControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Image.WaitImageHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/等待/等待图像.html", + "video": { + "time": "06:01" + }, + "inputs": [ + { + "name": "window_kind", + "label": "搜索范围", + "required": true, + "default": "10:screen", + "defaultDisplay": "整个屏幕", + "tips": "搜索范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "整个屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "currentactivatewindow" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "wait_mode", + "label": "等待方式", + "required": true, + "default": "10:appear", + "defaultDisplay": "等待目标图像出现", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "等待目标图像出现", + "value": "appear" + }, + { + "display": "等待目标图像消失", + "value": "disappear" + } + ] + } + }, + { + "name": "template_images", + "label": "目标图像", + "tips": "可从图像库选择多张图,其中任一张\"出现/消失\",则继续执行流程", + "required": true, + "type": "str", + "editor": { + "kind": "images" + } + }, + { + "name": "is_wait_all_images", + "label": "", + "required": true, + "default": "13:False", + "tips": "等待所有图像或者只等待其中一张", + "type": "bool", + "editor": { + "label": "等待全部图像出现(消失)后再执行", + "kind": "checkbox" + } + }, + { + "name": "iswait", + "label": "", + "required": true, + "default": "13:True", + "tips": "设置等待超时时间,超时后流程将自动往下继续执行", + "type": "bool", + "editor": { + "label": "设置超时时间", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "超时时间(秒)", + "default": "10:20", + "tips": "设置最大等待时间", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "wait_result", + "label": "等待结果", + "tips": "如果为True则等待成功,否则等待超时", + "name": "image_wait_result", + "type": "bool" + } + ] + }, + { + "name": "image.hover", + "icon": "BlockIcons/22-2.png", + "description": "鼠标悬停在图像上", + "comment": "在%window_kind%中搜索图像%template_images%,将鼠标移动到图像%anchor_type%位置", + "title": "鼠标悬停在图像上", + "keywords": "悬浮;图片;图形", + "function": "xbot_visual.image.hover", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/鼠标悬停在图像上.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Image.HoverImageControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Image.HoverImageHandler" + } + ], + "inputs": [ + { + "name": "window_kind", + "label": "搜索范围", + "required": true, + "default": "10:screen", + "defaultDisplay": "整个屏幕", + "tips": "搜索范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "整个屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "currentactivatewindow" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "template_images", + "label": "目标图像", + "tips": "可从图像库选择多张图,其中任一张\"出现/消失\",则继续执行流程", + "required": true, + "type": "str", + "editor": { + "kind": "images" + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": true, + "tips": "支持点击元素中心位置(元素矩形区域的中心点)、随机位置(自动随机指定元素矩形范围内的点)、自定义位置(手动指定目标点)", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "label": "目标图像的部位", + "default": "10:middleCenter", + "tips": "选择你要将鼠标移动到图像的哪个部位上", + "required": true, + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "超时时间(秒)", + "default": "10:5", + "tips": "设置最大等待时间", + "category": "advanced", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "delay_after", + "label": "执行后延迟(秒)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + } + ] + }, + { + "name": "image.click", + "icon": "BlockIcons/22-1.png", + "description": "点击图像", + "keywords": "点击图片", + "comment": "在%window_kind%中搜索图像%template_images%,%button%%clicks%点击%anchor_type%位置", + "title": "点击图像", + "function": "xbot_visual.image.click", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/点击图像.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Image.ClickImageControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Image.ClickImageHandler" + } + ], + "inputs": [ + { + "name": "window_kind", + "label": "搜索范围", + "required": true, + "default": "10:screen", + "defaultDisplay": "整个屏幕", + "tips": "搜索范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "整个屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "currentactivatewindow" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "template_images", + "label": "目标图像", + "tips": "可从图像库选择多张图,其中任一张\"出现/消失\",则继续执行流程", + "required": true, + "type": "str", + "editor": { + "kind": "images" + } + }, + { + "name": "anchor_type", + "label": "目标图像的部位", + "required": true, + "tips": "支持点击元素中心位置(元素矩形区域的中心点)、随机位置(自动随机指定元素矩形范围内的点)、自定义位置(手动指定目标点)", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点位置", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "label": "目标图像的部位", + "default": "10:middleCenter", + "tips": "选择你要将鼠标移动到图像的哪个部位上", + "required": true, + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "clicks", + "label": "点击次数", + "required": true, + "default": "10:click", + "defaultDisplay": "单击", + "tips": "选择点击的方式是单击还是双击", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单击", + "value": "click" + }, + { + "display": "双击", + "value": "dbclick" + } + ] + } + }, + { + "name": "button", + "label": "鼠标", + "required": true, + "default": "10:left", + "defaultDisplay": "鼠标左键", + "tips": "选择用于触发点击的鼠标按键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "鼠标左键", + "value": "left" + }, + { + "display": "鼠标右键", + "value": "right" + } + ] + } + }, + { + "name": "keys", + "label": "键盘", + "required": true, + "default": "10:null", + "defaultDisplay": "无", + "category": "advanced", + "tips": "在点击时需要按下的键盘功能键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "无", + "value": "null" + }, + { + "display": "Alt", + "value": "alt" + }, + { + "display": "Ctrl", + "value": "ctrl" + }, + { + "display": "Shift", + "value": "shift" + }, + { + "display": "Win", + "value": "win" + } + ] + } + }, + { + "name": "move_mouse", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "是否显示鼠标移动轨迹", + "type": "bool", + "editor": { + "label": "显示鼠标移动轨迹", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "超时时间(秒)", + "default": "10:5", + "tips": "设置最大等待时间", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "delay_after", + "label": "执行后延迟(秒)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + } + ] + }, + { + "name": "image.exist", + "statement": "workflow.if", + "icon": "BlockIcons/22-3.png", + "description": "判断目标图像是否存在", + "comment": "在%window_kind%中,是否%exist_mode%目标图像%template_images%", + "title": "IF 图像存在", + "keywords": "图片存在", + "function": "xbot_visual.image.exist", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Image.ExistImageControl, ShadowBot.Shell.Development", + "indent": "1", + "scope": "1", + "isCondition": true, + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if图像存在.html", + "video": { + "time": "02:11" + }, + "inputs": [ + { + "name": "window_kind", + "label": "搜索范围", + "required": true, + "default": "10:screen", + "defaultDisplay": "整个屏幕", + "tips": "可选择整个屏幕或指定的窗口", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "整个屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "currentactivatewindow" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "exist_mode", + "label": "查找方式", + "required": true, + "default": "10:exist", + "defaultDisplay": "存在", + "tips": "指定查找范围内指定的图像存在or不存在", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "存在", + "value": "exist" + }, + { + "display": "不存在", + "value": "notexist" + } + ] + } + }, + { + "name": "template_images", + "label": "目标图像", + "tips": "可从图像库选择多张图像", + "required": true, + "type": "str", + "editor": { + "kind": "images" + } + }, + { + "name": "is_find_all_images", + "label": "", + "required": true, + "default": "13:False", + "tips": "检测所有图像或者只检测其中一张", + "type": "bool", + "editor": { + "label": "全部图像存在(不存在)后再执行", + "kind": "checkbox" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/json.blocks.json b/src/assert/block_settings/json.blocks.json new file mode 100644 index 0000000..7709874 --- /dev/null +++ b/src/assert/block_settings/json.blocks.json @@ -0,0 +1,67 @@ +{ + "types": [], + "blocks": [ + { + "name": "json.to_text", + "function": "xbot_visual.json.to_text", + "title": "Json转换成文本", + "description": "将Json对象转换成文本", + "comment": "将Json对象%json_obj%转换成文本,将结果保存到%text_instance%", + "icon": "BlockIcons/16-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/json转换/转换成文本.html", + "inputs": [ + { + "name": "json_obj", + "label": "Json对象", + "required": true, + "tips": "输入待转换成文本的Json对象", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "text_instance", + "label": "保存文本至", + "variableLabel": "Json转换后的文本", + "tips": "输入一个名字,用来保存Json对象转换成的文本", + "type": "str", + "name": "text_instance" + } + ] + }, + { + "name": "json.to_json", + "function": "xbot_visual.json.to_json", + "title": "转换成Json对象", + "description": "这个指令用于将输入的文本转换成Json对象", + "comment": "将文本%text%转换成Json对象,将对象保存到%json_instance%", + "icon": "BlockIcons/16-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/json转换/转换成json对象.html", + "inputs": [ + { + "name": "text", + "label": "文本", + "required": true, + "tips": "输入待转换成Json对象的文本", + "type": "str", + "editor": { + "kind": "memoedit" + } + } + ], + "outputs": [ + { + "id": "json_instance", + "label": "保存Json对象至", + "variableLabel": "文本转换后的Json对象", + "tips": "输入一个名字,用来保存转换得到的Json对象", + "type": "any", + "name": "json_instance" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/list.blocks.json b/src/assert/block_settings/list.blocks.json new file mode 100644 index 0000000..ff34032 --- /dev/null +++ b/src/assert/block_settings/list.blocks.json @@ -0,0 +1,605 @@ +{ + "types": [], + "blocks": [ + { + "name": "list.create", + "function": "xbot_visual.list.create", + "title": "新建列表", + "description": "新建空的列表,列表为多个数据的数组,例如列表:[\"中国\",\"美国\",\"法国\"]", + "comment": "新建列表,将列表对象保存到%list_instance%", + "icon": "BlockIcons/14-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/新建列表.html", + "outputs": [ + { + "id": "list_instance", + "label": "保存列表对象至", + "variableLabel": "新建的列表对象", + "tips": "输入一个名字,用来保存新建的列表", + "type": "list", + "name": "list_instance" + } + ] + }, + { + "name": "list.clear", + "function": "xbot_visual.list.clear", + "title": "清空列表", + "description": "这个指令用于清空列表", + "comment": "清空列表对象%lst%", + "icon": "BlockIcons/14-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/清空列表.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "list.append_or_insert", + "function": "xbot_visual.list.append_or_insert", + "title": "列表插入一项", + "description": "在列表指定位置插入一项", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.List.ListInsertControl, ShadowBot.Shell.Development", + "comment": "在列表对象%lst%中增加新的一项%elem%", + "icon": "BlockIcons/14-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/列表添加一项.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.List.ListInsertHandler" + } + ], + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "insert_way", + "label": "插入方式", + "required": true, + "default": "10:append", + "defaultDisplay": "末尾追加", + "tips": "在列表的末尾或指定位置插入新的一项", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "末尾追加", + "value": "append" + }, + { + "display": "指定位置", + "value": "insert" + } + ] + } + }, + { + "name": "index", + "label": "插入到", + "required": false, + "default": "10:0", + "tips": "输入待插入的位置。正着数:第一项填写0,第二项填写1,以此类推;倒着数:倒数第一项填写-1,倒数第二项填写-2,以此类推。插入后原项将后移。", + "type": "int", + "editor": { + "placeholder": "0表示第1项,1表示第2项...支持负数,-n表示倒数第n项", + "kind": "textbox" + } + }, + { + "name": "elem", + "label": "插入项内容", + "required": true, + "tips": "输入待插入的项内容", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "list.set_elem", + "function": "xbot_visual.list.set_elem", + "title": "修改列表指定位置项的值", + "description": "这个指令用于修改列表指定位置的值", + "comment": "修改列表对象%lst%中第%index%项的值为%elem%", + "icon": "BlockIcons/14-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/修改列表指定位置的值.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "index", + "label": "项位置", + "required": true, + "tips": "输入项位置。正着数:第一项填写0,第二项填写1,依次类推;倒着数:倒数第一项填写-1;倒数第二项填写-2,依次类推。", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "elem", + "label": "修改项", + "required": true, + "tips": "修改列表指定位置项内容", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "list.get_elem", + "function": "xbot_visual.list.get_elem", + "title": "获取列表指定位置项", + "description": "这个指令用于获取列表中指定位置的一项", + "comment": "获取列表对象%lst%中第%index%项的内容,将结果保存到%list_instance%", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.List.UseOutputTypeByInputListItemTypeHandler", + "settings": { + "inputName": "lst", + "outputName": "list_instance" + } + } + ], + "icon": "BlockIcons/14-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/获取列表指定位置项.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "index", + "label": "项位置", + "required": true, + "tips": "输入项位置。正着数:第一项填写0,第二项填写1,依次类推;倒着数:倒数第一项填写-1;倒数第二项填写-2,依次类推。", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "list_instance", + "label": "保存列表项至", + "variableLabel": "列表项", + "tips": "输入一个名字,用来保存查找到的列表项", + "type": "any", + "name": "element_instance" + } + ] + }, + { + "name": "list.get_index", + "function": "xbot_visual.list.get_index", + "title": "获取列表指定项的位置", + "description": "获取指定项在列表中的位置,列表位置从0开始排序,0为第1项,1为第2项,依次类推", + "comment": "获取列表%lst%中内容为%elem%项的位置,将结果保存到%element_index%", + "icon": "BlockIcons/14-13.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/获取列表指定项的位置.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "elem", + "label": "指定项的值", + "required": true, + "tips": "输入列表指定项的值", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "element_index", + "label": "保存位置至", + "variableLabel": "列表位置", + "tips": "输入一个名字,用来保存查找到的指定项在列表中的位置", + "type": "int", + "name": "element_index" + } + ] + }, + { + "name": "list.remove", + "function": "xbot_visual.list.remove", + "title": "删除列表一项", + "description": "这个指令用于删除列表中指定的一项", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.List.ListRemove, ShadowBot.Shell.Development", + "comment": "删除列表对象%lst%中第%index%项", + "icon": "BlockIcons/14-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/删除列表一项.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.List.ListRemoveHandler" + } + ], + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "remove_way", + "label": "删除方式", + "required": true, + "default": "10:index", + "defaultDisplay": "按位置删除", + "tips": "在'hellow world'中如果要删除第一个字母'o'选择下表删除需要输入下标4(下标从0开始计数),如果要删除全部的‘o’选择按内容删除则输入字母‘o'", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "按位置删除", + "value": "index" + }, + { + "display": "按内容删除", + "value": "elem" + } + ] + } + }, + { + "name": "elem", + "label": "待删除的内容", + "required": false, + "tips": "输入待删除的内容", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "index", + "label": "待删除的位置", + "required": false, + "tips": "输入删除的位置。正着数:第一项填写0,第二项填写1,依次类推;倒着数:倒数第一项填写-1;倒数第二项填写-2,依次类推。", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "list.sort", + "function": "xbot_visual.list.sort", + "title": "列表排序", + "description": "这个指令用于列表排序", + "comment": "按%sort_way%排序列表对象%lst%", + "icon": "BlockIcons/14-7.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/列表排序.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sort_way", + "label": "排序方式", + "required": true, + "default": "10:descend", + "defaultDisplay": "降序", + "tips": "选择升序或者降序排序列表", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "降序", + "value": "descend" + }, + { + "display": "升序", + "value": "ascend" + } + ] + } + } + ] + }, + { + "name": "list.shuffle", + "function": "xbot_visual.list.shuffle", + "title": "列表随机排序", + "description": "这个指令用于列表随机排序", + "comment": "随机排序列表对象%lst%", + "icon": "BlockIcons/14-8.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/列表随机排序.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "list.extend", + "function": "xbot_visual.list.extend", + "title": "合并列表", + "description": "这个指令用于合并列表", + "comment": "合并列表%lst1%和%lst2%到新的列表,将结果保存到%list_instance%", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.List.ExtendBlockHandler", + "settings": { + "inputList1": "lst1", + "inputList2": "lst2", + "outputList": "list_instance" + } + } + ], + "icon": "BlockIcons/14-9.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/合并列表.html", + "inputs": [ + { + "name": "lst1", + "label": "列表1", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "lst2", + "label": "列表2", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "list_instance", + "label": "保存列表对象至", + "variableLabel": "合并后的列表对象", + "tips": "输入一个名字,用来保存新建的列表", + "type": "list", + "name": "list_instance" + } + ] + }, + { + "name": "list.reverse", + "function": "xbot_visual.list.reverse", + "title": "反转列表", + "description": "这个指令用于反转列表", + "comment": "反转列表对象%lst%", + "icon": "BlockIcons/14-10.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/反转列表.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "list.remove_duplicate", + "function": "xbot_visual.list.remove_duplicate", + "title": "列表去重", + "description": "这个指令用于删除列表中重复的项", + "comment": "删除列表对象%lst%中的重复项", + "icon": "BlockIcons/14-11.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/列表去重.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "list.get_duplicate", + "function": "xbot_visual.list.get_duplicate", + "title": "获取两个列表的相同项", + "description": "这个指令用于获取两个列表的相同项", + "comment": "获取列表%lst1%和%lst2%相同的项,将结果保存到%list_instance%", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.List.UseOutputTypeByInputListTypeHandler", + "settings": { + "inputName": "lst1", + "outputName": "list_instance" + } + } + ], + "icon": "BlockIcons/14-12.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/获取两个列表的相同项.html", + "inputs": [ + { + "name": "lst1", + "label": "列表1", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "lst2", + "label": "列表2", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "list_instance", + "label": "保存列表对象至", + "variableLabel": "两列表的相同项", + "tips": "输入一个名字,用来保存新建的列表", + "type": "list", + "name": "list_instance" + } + ] + }, + { + "name": "list.remove_list", + "function": "xbot_visual.list.remove_list", + "title": "过滤列表中的多项", + "description": "这个指令用于过滤列表中的多项", + "comment": "在列表对象%lst1%中过滤列表对象%lst2%所包含的项,将结果保存到新的列表对象%list_instance%", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.List.UseOutputTypeByInputListTypeHandler", + "settings": { + "inputName": "lst1", + "outputName": "list_instance" + } + } + ], + "icon": "BlockIcons/14-6.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/过滤列表中的多项.html", + "inputs": [ + { + "name": "lst1", + "label": "列表1", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "lst2", + "label": "列表2", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "list_instance", + "label": "保存列表对象至", + "variableLabel": "过滤后的列表对象", + "tips": "输入一个名字,用来保存新建的列表", + "type": "list", + "name": "list_instance" + } + ] + }, + { + "name": "list.get_len", + "function": "xbot_visual.list.get_len", + "title": "获取列表长度", + "description": "这个指令用于获取列表长度", + "comment": "获取列表对象%lst%的长度,将结果保存到%list_len%", + "icon": "BlockIcons/14-6.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/列表操作/获取列表长度.html", + "inputs": [ + { + "name": "lst", + "label": "列表", + "required": true, + "tips": "输入列表变量", + "type": "list", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "list_len", + "label": "保存列表长度至", + "variableLabel": "列表长度", + "tips": "输入一个名字,用来保存列表长度", + "type": "int", + "name": "list_len" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/mobile.blocks.json b/src/assert/block_settings/mobile.blocks.json new file mode 100644 index 0000000..ee28fef --- /dev/null +++ b/src/assert/block_settings/mobile.blocks.json @@ -0,0 +1,445 @@ +{ + "types": [ + { + "name": "xbot._mobile.session.DeviceSession", + "localName": "手机连接对象", + "methods": [ + { + "display": "udid", + "function": "$0.get_udid()", + "type": "str" + } + ] + } + ], + "blocks": [ + { + "name": "mobile.connect_device", + "title": "连接手机", + "icon": "BlockIcons/27-3.png", + "comment": "连接指定的手机,将连接对象保存到%session%", + "description": "与指定或者所有手机建立连接", + "function": "xbot_visual.mobile.connect_device", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Mobile.ConnectDeviceControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Mobile.ConnectDeviceHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/手机操作自动化/连接手机.html", + "inputs": [ + { + "name": "connect_source", + "label": "连接对象", + "required": true, + "tips": "", + "type": "str", + "default": "10:specific", + "defaultDisplay": "指定手机", + "editor": { + "kind": "select", + "options": [ + { + "display": "指定手机", + "value": "specific" + }, + { + "display": "运行时手动选择", + "value": "runtime_dynamic" + }, + { + "display": "运行时连接的一台手机", + "value": "runtime_auto" + }, + { + "display": "运行时连接的所有手机", + "value": "all" + } + ] + } + }, + { + "name": "connect_mode", + "label": "连接模式", + "required": true, + "tips": "Appium:某些应用的输入框会无法输入(如“闲鱼”),需借助 AdbKeyBoard 输入法实现\r\nUiautomator2:稳定性高,但不支持安卓9及以上版本读写剪贴板,需借助 Clipper 剪贴板 APP 实现", + "type": "str", + "default": "10:appium", + "defaultDisplay": "Appium", + "editor": { + "kind": "select", + "options": [ + { + "display": "Appium", + "value": "appium" + }, + { + "display": "Uiautomator2", + "value": "u2" + } + ] + } + }, + { + "name": "ingore_failed_device", + "label": "", + "tips": "若勾选,连接失败的手机将添加到连接失败列表中,反之则抛出异常", + "type": "str", + "default": "13:True", + "editor": { + "kind": "checkbox", + "label": "忽略连接失败的手机" + } + }, + { + "name": "auto_unlock", + "label": "", + "category": "advanced", + "type": "bool", + "tips": "若勾选,连接时会自动解锁", + "default": "13:False", + "editor": { + "label": "连接时自动解锁", + "kind": "checkbox" + } + }, + { + "name": "unlockType", + "label": "锁屏方式", + "category": "advanced", + "type": "str", + "tips": "锁屏方式", + "default": "10:pin", + "editor": { + "kind": "select", + "options": [ + { + "display": "数字密码", + "value": "pin" + }, + { + "display": "图案密码", + "value": "pattern" + }, + { + "display": "复杂密码", + "value": "password" + } + ] + } + }, + { + "name": "mobile_password", + "label": "", + "category": "advanced", + "type": "str", + "tips": "手机锁屏密码", + "editor": { + "kind": "password" + } + }, + { + "name": "custom_name", + "label": "自定义手机名称", + "tips": "请先到设备管理器页面配置手机连接信息", + "type": "str", + "editor": { + "kind": "select", + "options": [] + } + } + ], + "outputs": [ + { + "id": "session", + "label": "保存连接对象至", + "variableLabel": "手机连接对象", + "tips": "该变量保存的是手机连接对象,使用此对象可以对移动手机进行自动化操作", + "name": "device_session", + "type": "xbot._mobile.session.DeviceSession" + }, + { + "id": "session_list", + "label": "保存连接对象列表至", + "variableLabel": "手机连接对象列表", + "tips": "该变量保存的是手机连接对象,使用此对象可以对移动手机进行自动化操作", + "name": "device_session_list", + "type": "list" + }, + { + "id": "failed_sessions", + "label": "保存连接失败列表至", + "variableLabel": "手机udid", + "tips": "该变量保存的是连接失败手机编号", + "name": "failed_udid_list", + "type": "list" + } + ] + }, + { + "name": "mobile.connect", + "title": "连接手机", + "icon": "BlockIcons/27-3.png", + "comment": "连接指定的手机,将连接对象保存到%session%", + "description": "与指定手机建立连接", + "function": "xbot_visual.mobile.connect", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Mobile.ConnectControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Mobile.ConnectHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/手机操作自动化/连接手机.html", + "inputs": [ + { + "name": "connect_source", + "label": "连接来源", + "required": true, + "tips": "", + "type": "str", + "default": "10:current", + "defaultDisplay": "当前连接的手机", + "editor": { + "kind": "select", + "options": [ + { + "display": "当前连接的手机", + "value": "current" + }, + { + "display": "指定的手机", + "value": "assign" + } + ] + } + }, + { + "name": "connect_kind", + "label": "连接类型", + "required": true, + "tips": "", + "type": "str", + "default": "10:local", + "defaultDisplay": "本地连接", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地连接", + "value": "local" + }, + { + "display": "动态连接", + "value": "dynamic" + } + ] + } + }, + { + "name": "connect_mode", + "label": "连接模式", + "required": true, + "tips": "Appium:某些应用的输入框会无法输入(如“闲鱼”),需借助 AdbKeyBoard 输入法实现\r\nUiautomator2:稳定性高,但不支持安卓9及以上版本读写剪贴板,需借助 Clipper 剪贴板 APP 实现", + "type": "str", + "default": "10:appium", + "defaultDisplay": "Appium", + "editor": { + "kind": "select", + "options": [ + { + "display": "Appium", + "value": "appium" + }, + { + "display": "Uiautomator2", + "value": "u2" + } + ] + } + }, + { + "name": "auto_unlock", + "label": "", + "category": "advanced", + "type": "bool", + "tips": "若勾选,连接时会自动解锁", + "default": "13:False", + "editor": { + "label": "连接时自动解锁", + "kind": "checkbox" + } + }, + { + "name": "unlockType", + "label": "锁屏方式", + "category": "advanced", + "type": "str", + "tips": "锁屏方式", + "default": "10:pin", + "editor": { + "kind": "select", + "options": [ + { + "display": "数字密码", + "value": "pin" + }, + { + "display": "图案密码", + "value": "pattern" + }, + { + "display": "复杂密码", + "value": "password" + } + ] + } + }, + { + "name": "mobile_password", + "label": "", + "category": "advanced", + "type": "str", + "tips": "手机锁屏密码", + "editor": { + "kind": "password" + } + }, + { + "name": "custom_name", + "label": "自定义手机名称", + "tips": "请先到设备管理器页面配置手机连接信息", + "type": "str", + "editor": { + "kind": "select", + "options": [] + } + } + ], + "outputs": [ + { + "id": "session", + "label": "保存连接对象至", + "variableLabel": "手机连接对象", + "tips": "该变量保存的是手机连接对象,使用此对象可以对移动手机进行自动化操作", + "name": "device_session", + "type": "xbot._mobile.session.DeviceSession" + } + ] + }, + { + "name": "mobile.all_connect", + "title": "连接多台手机", + "icon": "BlockIcons/27-26.png", + "comment": "与PC机连接的所有手机建立自动化连接,将连接对象保存到%sessions%", + "description": "与PC机连接的所有手机建立自动化连接,用于群控场景", + "function": "xbot_visual.mobile.all_connect", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Mobile.MultiConnectHandler" + } + ], + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Mobile.MultiConnectControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/手机操作自动化/连接多台手机.html?", + "inputs": [ + { + "name": "connect_mode", + "label": "连接模式", + "required": true, + "tips": "Appium:某些应用的输入框会无法输入(如“闲鱼”),需借助 AdbKeyBoard 输入法实现\r\nUiautomator2:稳定性高,但不支持安卓9及以上版本读写剪贴板,需借助 Clipper 剪贴板 APP 实现", + "type": "str", + "default": "10:appium", + "defaultDisplay": "Appium", + "editor": { + "kind": "select", + "options": [ + { + "display": "Appium", + "value": "appium" + }, + { + "display": "Uiautomator2", + "value": "u2" + } + ] + } + }, + { + "name": "ingore_failed_device", + "label": "", + "tips": "若勾选,连接失败的手机将添加到连接失败列表中,反之则抛出异常", + "type": "str", + "default": "13:True", + "editor": { + "kind": "checkbox", + "label": "忽略连接失败的手机" + } + }, + { + "name": "unlockType", + "label": "锁屏方式", + "category": "advanced", + "type": "str", + "tips": "锁屏方式", + "default": "10:pin", + "editor": { + "kind": "select", + "options": [ + { + "display": "数字密码", + "value": "pin" + }, + { + "display": "图案密码", + "value": "pattern" + }, + { + "display": "复杂密码", + "value": "password" + } + ] + } + }, + { + "name": "auto_unlock", + "label": "", + "category": "advanced", + "type": "bool", + "tips": "若勾选, 连接时会自动解锁", + "default": "13:False", + "editor": { + "label": "连接时自动解锁", + "kind": "checkbox" + } + }, + { + "name": "mobile_password", + "label": "", + "category": "advanced", + "type": "str", + "tips": "手机锁屏密码", + "editor": { + "kind": "password" + } + } + ], + "outputs": [ + { + "id": "sessions", + "label": "保存连接对象列表至", + "variableLabel": "手机连接对象列表", + "tips": "该变量保存的是手机连接对象,使用此对象可以对移动手机进行自动化操作", + "name": "device_session_list", + "type": "list" + }, + { + "id": "failed_sessions", + "label": "保存连接失败列表至", + "variableLabel": "手机udid", + "tips": "该变量保存的是连接失败手机编号", + "name": "failed_udid_list", + "type": "list" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/nlp.blocks.json b/src/assert/block_settings/nlp.blocks.json new file mode 100644 index 0000000..206442f --- /dev/null +++ b/src/assert/block_settings/nlp.blocks.json @@ -0,0 +1,405 @@ +{ + "types": [ + { + "name": "xbot_visual_ocr_lexical_words", + "localName": "文本分词", + "python": "xbot_visual._core.xbot_visual_ocr_lexical_words", + "props": [ + { + "name": "words", + "type": "list", + "label": "词汇集" + }, + { + "name": "raw_data", + "type": "any", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_lexical_item", + "localName": "实体属性对象", + "python": "xbot_visual._core.xbot_visual_ocr_lexical_item", + "props": [ + { + "name": "word", + "type": "str", + "label": "词汇" + }, + { + "name": "type", + "type": "str", + "label": "实体类型" + }, + { + "name": "pos", + "type": "str", + "label": "词性" + } + ] + }, + { + "name": "list", + "localName": "实体属性对象列表", + "base": "list", + "listItemType": "xbot_visual_ocr_lexical_item" + }, + { + "name": "xbot_visual_ocr_lexical_detail", + "localName": "实体抽取结果", + "pythonName": "xbot_visual._core.xbot_visual_ocr_lexical_detail", + "props": [ + { + "name": "words", + "type": "list", + "label": "属性集" + }, + { + "name": "raw_data", + "type": "any", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_sentiment", + "localName": "情感分析结果", + "python": "xbot_visual._core.xbot_visual_ocr_sentiment", + "props": [ + { + "name": "sentiment", + "type": "str", + "label": "分类结果" + }, + { + "name": "positive", + "type": "float", + "label": "积极类别的概率" + }, + { + "name": "negative", + "type": "float", + "label": "消极类别的概率" + }, + { + "name": "raw_data", + "type": "any", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_similarity", + "localName": "相似度分析结果", + "python": "xbot_visual._core.xbot_visual_ocr_similarity", + "props": [ + { + "name": "score", + "type": "float", + "label": "相似度" + }, + { + "name": "raw_data", + "type": "any", + "label": "原始数据" + } + ] + } + ], + "blocks": [ + { + "name": "nlp.lexical_analysis", + "icon": "BlockIcons/23-6.png", + "description": "将连续的自然语言文本切分成具有语义合理性和完整性的词汇列表", + "comment": "使用%ai_engine%AI引擎对文本%text%进行分词,将分词结果保存到%lexer_result%", + "title": "文本分词", + "function": "xbot_visual.nlp.lexical_analysis", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/自然语言处理nlp/文本分词.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Nlp.LexicalAnalysisControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "default": "10:shadowbot", + "defaultDisplay": "影刀", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "text", + "label": "文本", + "required": true, + "tips": "输入需要进行分词的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "flag", + "label": "分析模式", + "default": "10:common", + "defaultDisplay": "通用识别", + "tips": "选择一种识别模式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "通用模式", + "value": "common" + }, + { + "display": "高精度模式", + "value": "accurate" + } + ] + } + } + ], + "outputs": [ + { + "id": "lexer_result", + "label": "分词结果保存至", + "variableLabel": "文本分词结果", + "tips": "指定一个变量名称,该变量用于存储文本分词结果", + "type": "xbot_visual_ocr_lexical_words", + "name": "lexer_result" + } + ] + }, + { + "name": "nlp.lexical_analysis_include_location", + "icon": "BlockIcons/23-6.png", + "description": "从目标文本中,识别出实体词汇,比如人名、地名、机构名等", + "comment": "使用%ai_engine%AI引擎对文本%text%进行实体抽取,将抽取结果保存到%lexer_deatil_result%", + "title": "实体抽取", + "function": "xbot_visual.nlp.lexical_analysis_include_location", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/自然语言处理nlp/实体抽取.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Nlp.LexicalAnalysisIncludeLocationControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "default": "10:shadowbot", + "defaultDisplay": "影刀", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "text", + "label": "文本", + "required": true, + "tips": "输入需要进行实体抽取的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "flag", + "label": "分析模式", + "default": "10:common", + "defaultDisplay": "通用识别", + "tips": "选择一种识别模式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "通用模式", + "value": "common" + }, + { + "display": "高精度模式", + "value": "accurate" + } + ] + } + }, + { + "name": "pump_type", + "label": "提取目标", + "default": "10:all", + "defaultDisplay": "全部", + "tips": "选择一种需要提取的实体类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all" + }, + { + "display": "人名", + "value": "PER" + }, + { + "display": "地名", + "value": "LOC" + }, + { + "display": "机构团体名", + "value": "ORG" + }, + { + "display": "时间", + "value": "TIME" + }, + { + "display": "产品名", + "value": "PRODUCTION" + } + ] + } + } + ], + "outputs": [ + { + "id": "lexer_deatil_result", + "label": "实体抽取结果保存至", + "variableLabel": "实体抽取结果", + "tips": "指定一个变量名称,该变量用于存储实体抽取结果", + "type": "xbot_visual_ocr_lexical_detail", + "name": "lexer_deatil_result" + } + ] + }, + { + "name": "nlp.sentiment_analysis", + "icon": "BlockIcons/23-6.png", + "description": "从文本中识别出用户的情感倾向,是积极还是消极,并且提供各自概率", + "comment": "使用%ai_engine%AI引擎,对文本%text%进行情感分析,将分析结果保存到%sentiment_result%", + "title": "情感倾向分析", + "function": "xbot_visual.nlp.sentiment_analysis", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/自然语言处理nlp/情感倾向分析.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Nlp.SentimentAnalysisControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "default": "10:shadowbot", + "defaultDisplay": "影刀", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "text", + "label": "文本", + "required": true, + "tips": "输入需要进行情感分析的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "sentiment_result", + "label": "情感分析结果保存至", + "variableLabel": "情感分析结果", + "tips": "指定一个变量名称,该变量用于存储情感分析结果", + "type": "xbot_visual_ocr_sentiment", + "name": "sentiment_result" + } + ] + }, + { + "name": "nlp.text_similarity", + "icon": "BlockIcons/23-6.png", + "description": "分析两个短文本的相似度,相似度结果取值0~1,值越大说明相似度越高", + "comment": "使用%ai_engine%AI引擎比较文本1%src_text%与文本2%target_text%的相似性,将比较结果保存到%similarity_result%", + "title": "文本相似度分析", + "function": "xbot_visual.nlp.text_similarity", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/自然语言处理nlp/文本相似度分析.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Nlp.TextSimilarityControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "default": "10:shadowbot", + "defaultDisplay": "影刀", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "src_text", + "label": "文本1", + "required": true, + "tips": "需要与目标文本计算相似度的源文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "target_text", + "label": "文本2", + "required": true, + "tips": "需要与源文本计算相似度的目标文本", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "similarity_result", + "label": "相似度结果保存至", + "variableLabel": "文本相似度分析结果", + "tips": "指定一个变量名称,该变量用于存储文本相似度分析结果", + "type": "xbot_visual_ocr_similarity", + "name": "similarity_result" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/ocr.blocks.json b/src/assert/block_settings/ocr.blocks.json new file mode 100644 index 0000000..71471d5 --- /dev/null +++ b/src/assert/block_settings/ocr.blocks.json @@ -0,0 +1,4153 @@ +{ + "types": [ + { + "name": "xbot_visual_ocr_general_word", + "localName": "文本项(通用文字识别)", + "pythonName": "xbot_visual._core.xbot_visual_ocr_general_word", + "props": [ + { + "name": "text", + "type": "str", + "label": "文本" + }, + { + "name": "left", + "type": "str", + "label": "左边距" + }, + { + "name": "top", + "type": "str", + "label": "上边距" + }, + { + "name": "width", + "type": "str", + "label": "宽度" + }, + { + "name": "height", + "type": "str", + "label": "高度" + } + ] + }, + { + "name": "xbot_visual_ocr_form_cell", + "localName": "单元格(表格识别)", + "pythonName": "xbot_visual._core.xbot_visual_ocr_form_cell", + "props": [ + { + "name": "content", + "type": "str", + "label": "内容" + }, + { + "name": "start_x", + "type": "int", + "label": "起始位置X" + }, + { + "name": "start_y", + "type": "int", + "label": "起始位置Y" + }, + { + "name": "end_x", + "type": "int", + "label": "结束位置X" + }, + { + "name": "end_y", + "type": "int", + "label": "结束位置Y" + } + ] + }, + { + "name": "xbot_visual_ocr_form", + "localName": "单个表格(表格识别)", + "pythonName": "xbot_visual._core.xbot_visual_ocr_form", + "props": [ + { + "name": "form_cells", + "type": "list", + "label": "多个单元格" + } + ] + }, + { + "name": "list", + "localName": "单元格列表(表格识别)", + "base": "list", + "listItemType": "xbot_visual_ocr_form_cell" + }, + { + "name": "list", + "localName": "文本项列表(通用文字识别)", + "base": "list", + "listItemType": "xbot_visual_ocr_general_word" + }, + { + "name": "list", + "localName": "表格列表(表格识别)", + "base": "list", + "listItemType": "xbot_visual_ocr_form" + }, + { + "name": "xbot.ai.AIEngine", + "localName": "AI引擎", + "props": [] + }, + { + "name": "xbot.ai.BaiduAIEngine", + "localName": "百度AI引擎", + "pythonName": "xbot.ai.baidu.BaiduAI", + "base": "xbot.ai.AIEngine", + "props": [] + }, + { + "name": "xbot.ai.AliyunAIEngine", + "localName": "阿里云AI引擎", + "pythonName": "xbot.ai.aliyun.AliyunAI", + "base": "xbot.ai.AIEngine", + "props": [] + }, + { + "name": "xbot.ai.TencentAIEngine", + "localName": "腾讯AI引擎", + "pythonName": "xbot.ai.tencent.TencentAI", + "base": "xbot.ai.AIEngine", + "props": [] + }, + { + "name": "xbot.ai.ShadowBotAIEngine", + "localName": "影刀AI引擎", + "pythonName": "xbot.ai.shadowbot.ShadowBotAI", + "base": "xbot.ai.AIEngine", + "props": [] + }, + { + "name": "xbot_visual_ocr_vat_invoice", + "localName": "增值税发票信息", + "pythonName": "xbot_visual._core.xbot_visual_ocr_vat_invoice", + "props": [ + { + "name": "invoice_code", + "type": "str", + "label": "发票代码" + }, + { + "name": "invoice_num", + "type": "str", + "label": "发票号码" + }, + { + "name": "invoice_date", + "type": "str", + "label": "开票日期" + }, + { + "name": "check_code", + "type": "str", + "label": "校验码" + }, + { + "name": "total_amount", + "type": "str", + "label": "合计金额" + }, + { + "name": "total_tax", + "type": "str", + "label": "合计税额" + }, + { + "name": "seller_name", + "type": "str", + "label": "销售方名称" + }, + { + "name": "seller_register_num", + "type": "str", + "label": "销售方纳税人识别号" + }, + { + "name": "seller_address", + "type": "str", + "label": "销售方地址及电话" + }, + { + "name": "seller_bank", + "type": "str", + "label": "销售方开户行及账号" + }, + { + "name": "purchaser_name", + "type": "str", + "label": "购方名称" + }, + { + "name": "purchaser_register_num", + "type": "str", + "label": "购方纳税人识别号" + }, + { + "name": "purchaser_address", + "type": "str", + "label": "购方地址及电话" + }, + { + "name": "purchaser_bank", + "type": "str", + "label": "购方开户行及账号" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_id_card", + "localName": "身份证信息", + "pythonName": "xbot_visual._core.xbot_visual_ocr_id_card", + "props": [ + { + "name": "name", + "type": "str", + "label": "姓名" + }, + { + "name": "sex", + "type": "str", + "label": "性别" + }, + { + "name": "nation", + "type": "str", + "label": "民族" + }, + { + "name": "birth", + "type": "str", + "label": "出生" + }, + { + "name": "address", + "type": "str", + "label": "住址" + }, + { + "name": "id_num", + "type": "str", + "label": "公民身份号码" + }, + { + "name": "authority", + "type": "str", + "label": "签发机关" + }, + { + "name": "valid_date", + "type": "str", + "label": "有效期" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_license_plate", + "localName": "车牌信息", + "pythonName": "xbot_visual._core.xbot_visual_ocr_license_plate", + "props": [ + { + "name": "number", + "type": "str", + "label": "车牌号" + }, + { + "name": "left", + "type": "str", + "label": "左边距" + }, + { + "name": "top", + "type": "str", + "label": "上边距" + }, + { + "name": "width", + "type": "str", + "label": "宽度" + }, + { + "name": "height", + "type": "str", + "label": "高度" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_bank_card", + "localName": "银行卡信息", + "pythonName": "xbot_visual._core.xbot_visual_ocr_bank_card", + "props": [ + { + "name": "bank_name", + "type": "str", + "label": "银行名" + }, + { + "name": "card_number", + "type": "str", + "label": "卡号" + }, + { + "name": "valid_date", + "type": "str", + "label": "有效期" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_train_ticket", + "localName": "火车票信息", + "pythonName": "xbot_visual._core.xbot_visual_ocr_train_ticket", + "props": [ + { + "name": "starting_station", + "type": "str", + "label": "始发站" + }, + { + "name": "train_num", + "type": "str", + "label": "车票号" + }, + { + "name": "destination_station", + "type": "str", + "label": "到达站" + }, + { + "name": "date", + "type": "str", + "label": "出发日期" + }, + { + "name": "time", + "type": "str", + "label": "出发时间" + }, + { + "name": "seat_num", + "type": "str", + "label": "座位号" + }, + { + "name": "price", + "type": "str", + "label": "车票金额" + }, + { + "name": "seat_category", + "type": "str", + "label": "席别" + }, + { + "name": "name", + "type": "str", + "label": "乘客姓名" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_taxi_invoice", + "localName": "出租车票信息", + "pythonName": "xbot_visual._core.xbot_visual_ocr_taxi_invoice", + "props": [ + { + "name": "invoice_num", + "type": "str", + "label": "发票号码" + }, + { + "name": "invoice_code", + "type": "str", + "label": "发票代号" + }, + { + "name": "date", + "type": "str", + "label": "日期" + }, + { + "name": "plate_number", + "type": "str", + "label": "车牌号" + }, + { + "name": "geton_time", + "type": "str", + "label": "上车时间" + }, + { + "name": "getoff_time", + "type": "str", + "label": "下车时间" + }, + { + "name": "distance", + "type": "str", + "label": "里程" + }, + { + "name": "fare", + "type": "str", + "label": "总金额" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_general_text_with_location", + "localName": "AI识别结果(含位置)", + "pythonName": "xbot_visual._core.xbot_visual_ocr_general_text_with_location", + "props": [ + { + "name": "words", + "type": "list", + "label": "识别结果集" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_general_text", + "localName": "AI识别结果", + "pythonName": "xbot_visual._core.xbot_visual_ocr_general_text", + "props": [ + { + "name": "text", + "type": "str", + "label": "识别结果" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + }, + { + "name": "xbot_visual_ocr_table", + "localName": "表格信息", + "pythonName": "xbot_visual._core.xbot_visual_ocr_table", + "props": [ + { + "name": "forms", + "type": "list", + "label": "多个表格" + }, + { + "name": "raw_data", + "type": "dict", + "label": "原始数据" + } + ] + } + ], + "blocks": [ + { + "name": "ocr.OCRToText", + "icon": "BlockIcons/23-1.png", + "description": "识别图像文本", + "comment": "使用%ai_engine%AI引擎,识别%image_source%文本,将结果保存到%ocr_text%", + "title": "识别图像文本(OCR)", + "keywords": "文字识别;图像识别;识图;图文识别;图片识别", + "function": "xbot_visual.ocr.ocr_to_text", + "helpUrl": "yddoc/language/zh-cn/指令文档/ocr/识别图像文本(ocr).html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.OCRToTextControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "baidu_ocr_edition", + "label": "AI版本", + "tips": "选择百度AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "general" + }, + { + "display": "高精度版", + "value": "accurate" + } + ] + } + }, + { + "name": "tencent_ocr_edition", + "label": "AI版本", + "tips": "选择腾讯AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "GeneralBasicOCR" + }, + { + "display": "高精度版", + "value": "GeneralAccurateOCR" + }, + { + "display": "精简版", + "value": "GeneralEfficientOCR" + }, + { + "display": "高速版", + "value": "GeneralFastOCR" + } + ] + } + }, + { + "name": "aliyun_ocr_edition", + "label": "AI版本", + "tips": "选择阿里云AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "ocr_general" + }, + { + "display": "高精度版", + "value": "advanced" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "foreground_window" + }, + { + "display": "本地硬盘图片", + "value": "image_on_disk" + }, + { + "display": "剪切板", + "value": "clipboard_image" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_path", + "label": "图片路径", + "required": false, + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png" + } + } + }, + { + "name": "image_region", + "label": "提取区域", + "required": false, + "default": "10:all_region", + "defaultDisplay": "提取区域", + "tips": "选择图片提取区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all_region" + }, + { + "display": "指定部分区域", + "value": "sub_region" + } + ] + } + }, + { + "name": "region_x1", + "label": "X1", + "required": false, + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y1", + "label": "Y1", + "required": false, + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_x2", + "label": "X2", + "required": false, + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y2", + "label": "Y2", + "required": false, + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "ocr_text", + "label": "保存文本至变量", + "variableLabel": "图象文本", + "tips": "指定一个变量名称,该变量用于存储识别出来的文本", + "type": "str", + "name": "ocr_text" + } + ] + }, + { + "name": "ocr.CreateAIEngine", + "icon": "BlockIcons/23-7.png", + "description": "配置一个AI引擎, 用于人工智能类指令引用", + "comment": "创建%engine%AI引擎,将对象保存到%ai_engine%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.CreateAIEngineControl, ShadowBot.Shell.Development", + "title": "配置AI引擎", + "keywords":"创建;创建AI引擎", + "function": "xbot_visual.ocr.create_ai_engine", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/创建ai引擎.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Ocr.CreateAIEngineHandler" + } + ], + "inputs": [ + { + "name": "engine", + "label": "AI引擎", + "required": true, + "default": "10:shadowbot", + "defaultDisplay": "影刀", + "tips": "选择AI引擎类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀", + "value": "shadowbot" + }, + { + "display": "百度", + "value": "baidu" + }, + { + "display": "腾讯", + "value": "tencent" + }, + { + "display": "阿里云", + "value": "aliyun" + } + ] + } + }, + { + "name": "use_custom_account", + "label": "", + "required": true, + "tips": "是否使用自定义AI账号", + "type": "bool", + "default": "13:False", + "editor": { + "label": "使用自定义账号", + "kind": "checkbox" + } + }, + { + "name": "param1", + "label": "认证参数1", + "tips": "请输入AI引擎的认证参数1", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "param2", + "label": "认证参数2", + "tips": "请输入AI引擎的认证参数2", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "ai_engine", + "label": "保存AI引擎至", + "variableLabel": "AI引擎", + "tips": "指定一个变量名称,该变量用于存储创建的AI引擎", + "type": "xbot.ai.AIEngine", + "name": "ai_engine" + } + ] + }, + { + "name": "ocr.general_text_with_location", + "icon": "BlockIcons/23-1.png", + "description": "通用文字识别(含位置)", + "keywords": "文字识别;图像识别;识图;图文识别;图片识别", + "comment": "使用%ai_engine%AI引擎,识别%image_source%文本,将结果保存到%general_text_with_location%", + "title": "通用文字识别(含位置)", + "function": "xbot_visual.ocr.general_text_with_location", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.GeneralTextWithLocationControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/文字识别ocr/通用文字识别(含位置).html", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "baidu_ocr_edition", + "label": "AI版本", + "default": "10:general", + "tips": "选择百度AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "general" + }, + { + "display": "高精度版", + "value": "accurate" + } + ] + } + }, + { + "name": "tencent_ocr_edition", + "label": "AI版本", + "default": "10:GeneralBasicOCR", + "tips": "选择腾讯AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "GeneralBasicOCR" + }, + { + "display": "高精度版", + "value": "GeneralAccurateOCR" + }, + { + "display": "精简版", + "value": "GeneralEfficientOCR" + }, + { + "display": "高速版", + "value": "GeneralFastOCR" + } + ] + } + }, + { + "name": "aliyun_ocr_edition", + "label": "AI版本", + "default": "10:ocr_general", + "tips": "选择阿里云AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "ocr_general" + }, + { + "display": "高精度版", + "value": "advanced" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "foreground_window" + }, + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png;*.pdf)|*.jpg;*.bmp;*.png;*.pdf" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_region", + "label": "提取区域", + "default": "10:all_region", + "defaultDisplay": "提取区域", + "tips": "选择图片提取区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all_region" + }, + { + "display": "指定部分区域", + "value": "sub_region" + } + ] + } + }, + { + "name": "region_x1", + "label": "X1", + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y1", + "label": "Y1", + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_x2", + "label": "X2", + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y2", + "label": "Y2", + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_pdf", + "label": "", + "tips": "是否开启PDF识别,默认值为false,开启后可同时支持图片和PDF的识别", + "type": "bool", + "category": "advanced", + "default": "13:False", + "editor": { + "label": "开启PDF识别", + "kind": "checkbox" + } + }, + { + "name": "pdf_page_number", + "label": "PDF页码", + "default": "10:1", + "category": "advanced", + "tips": "需要识别的PDF页面的对应页码,仅支持PDF单页识别,当上传文件为PDF且IsPdf参数值为true时有效,默认值为1", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "recognize_granularity", + "label": "定位单字符位置", + "default": "10:big", + "category": "advanced", + "tips": "是否定位单字符位置,big:不定位单字符位置,默认值;small:定位单字符位置", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "vertexes_location", + "label": "", + "tips": "是否返回文字外接多边形顶点位置,不支持单字位置。默认为false", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "获取文字外接多边形顶点位置", + "kind": "checkbox" + } + }, + { + "name": "detect_direction", + "label": "", + "tips": "是否检测图像朝向,默认不检测,即:false。朝向是指输入图像是正常方向、逆时针旋转90/180/270度。可选值包括: true:检测朝向, false:不检测朝向", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "检测朝向", + "kind": "checkbox" + } + }, + { + "name": "detect_language", + "label": "", + "tips": "是否检测语言,默认不检测。当前支持(中文、英语、日语、韩语)", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "检测语言", + "kind": "checkbox" + } + }, + { + "name": "paragraph", + "label": "", + "tips": "是否输出段落信息", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "输出段落信息", + "kind": "checkbox" + } + }, + { + "name": "probability", + "label": "", + "tips": "是否返回识别结果中每一行的置信度", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "获取识别结果中每一行的置信度", + "kind": "checkbox" + } + }, + { + "name": "min_size", + "label": "文字最小高度", + "default": "10:16", + "category": "advanced", + "tips": "图片中文字的最小高度,单位像素", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "output_prob", + "label": "", + "tips": "是否输出文字框的概率", + "type": "bool", + "default": "13:True", + "category": "advanced", + "editor": { + "label": "输出文字框的概率", + "kind": "checkbox" + } + }, + { + "name": "output_keypoints", + "label": "", + "tips": "是否输出文字框角点", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "输出文字框角点", + "kind": "checkbox" + } + }, + { + "name": "skip_detection", + "label": "", + "tips": "是否跳过文字检测步骤直接进行文字识别", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "跳过文字检测", + "kind": "checkbox" + } + }, + { + "name": "without_predicting_direction", + "label": "", + "tips": "是否关闭文字行方向预测", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "关闭文字行方向预测", + "kind": "checkbox" + } + }, + { + "name": "prob", + "label": "", + "tips": "是否需要识别结果中每一行的置信度,默认不需要", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "获取每一行的置信度", + "kind": "checkbox" + } + }, + { + "name": "char_info", + "label": "", + "tips": "是否需要单字识别功能,默认不需要", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "单字识别", + "kind": "checkbox" + } + }, + { + "name": "rotate", + "label": "", + "tips": "是否需要自动旋转功能,默认不需要", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "自动旋转", + "kind": "checkbox" + } + }, + { + "name": "table", + "label": "", + "tips": "是否需要表格识别功能,默认不需要", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "表格识别", + "kind": "checkbox" + } + }, + { + "name": "sort_page", + "label": "", + "tips": "字块返回顺序,false表示从左往右,从上到下的顺序,true表示从上到下,从左往右的顺序,默认false", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "字块返回顺序", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "general_text_with_location", + "label": "保存识别结果至变量", + "variableLabel": "通用文字识别结果", + "tips": "指定一个变量名称,该变量用于存储识别出来的通用文字识别结果", + "type": "xbot_visual_ocr_general_text_with_location", + "name": "general_text_with_location" + } + ] + }, + { + "name": "ocr.general_text", + "icon": "BlockIcons/23-1.png", + "description": "通用文字识别", + "keywords": "文字识别;图像识别;识图;图文识别;图片识别", + "comment": "使用%ai_engine%AI引擎,识别%image_source%文本,将结果保存到%general_text%", + "title": "通用文字识别", + "function": "xbot_visual.ocr.general_text", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.GeneralTextControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/文字识别ocr/通用文字识别.html", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "baidu_ocr_edition", + "label": "AI版本", + "default": "10:general_basic", + "tips": "选择百度AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "general_basic" + }, + { + "display": "高精度版", + "value": "accurate_basic" + } + ] + } + }, + { + "name": "tencent_ocr_edition", + "label": "AI版本", + "default": "10:GeneralBasicOCR", + "tips": "选择腾讯AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "GeneralBasicOCR" + }, + { + "display": "高精度版", + "value": "GeneralAccurateOCR" + }, + { + "display": "精简版", + "value": "GeneralEfficientOCR" + }, + { + "display": "高速版", + "value": "GeneralFastOCR" + } + ] + } + }, + { + "name": "aliyun_ocr_edition", + "label": "AI版本", + "default": "10:ocr_general", + "tips": "选择阿里云AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "ocr_general" + }, + { + "display": "高精度版", + "value": "advanced" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "foreground_window" + }, + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png;*.pdf)|*.jpg;*.bmp;*.png;*.pdf" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_region", + "label": "提取区域", + "default": "10:all_region", + "defaultDisplay": "提取区域", + "tips": "选择图片提取区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all_region" + }, + { + "display": "指定部分区域", + "value": "sub_region" + } + ] + } + }, + { + "name": "region_x1", + "label": "X1", + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y1", + "label": "Y1", + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_x2", + "label": "X2", + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y2", + "label": "Y2", + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_pdf", + "label": "", + "tips": "是否开启PDF识别,默认值为false,开启后可同时支持图片和PDF的识别", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "开启PDF识别", + "kind": "checkbox" + } + }, + { + "name": "pdf_page_number", + "label": "PDF页码", + "default": "10:1", + "category": "advanced", + "tips": "需要识别的PDF页面的对应页码,仅支持PDF单页识别,当上传文件为PDF且IsPdf参数值为true时有效,默认值为1", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "detect_direction", + "label": "", + "tips": "是否检测图像朝向,默认不检测,即:false。朝向是指输入图像是正常方向、逆时针旋转90/180/270度。可选值包括: true:检测朝向, false:不检测朝向", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "检测朝向", + "kind": "checkbox" + } + }, + { + "name": "detect_language", + "label": "", + "tips": "是否检测语言,默认不检测。当前支持(中文、英语、日语、韩语)", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "检测语言", + "kind": "checkbox" + } + }, + { + "name": "paragraph", + "label": "", + "tips": "是否输出段落信息", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "输出段落信息", + "kind": "checkbox" + } + }, + { + "name": "probability", + "label": "", + "tips": "是否返回识别结果中每一行的置信度", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "获取识别结果中每一行的置信度", + "kind": "checkbox" + } + }, + { + "name": "min_size", + "label": "文字最小高度", + "default": "10:16", + "category": "advanced", + "tips": "图片中文字的最小高度,单位像素", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "output_prob", + "label": "", + "tips": "是否输出文字框的概率", + "type": "bool", + "default": "13:True", + "category": "advanced", + "editor": { + "label": "输出文字框的概率", + "kind": "checkbox" + } + }, + { + "name": "output_keypoints", + "label": "", + "tips": "是否输出文字框角点", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "输出文字框角点", + "kind": "checkbox" + } + }, + { + "name": "skip_detection", + "label": "", + "tips": "是否跳过文字检测步骤直接进行文字识别", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "跳过文字检测", + "kind": "checkbox" + } + }, + { + "name": "without_predicting_direction", + "label": "", + "tips": "是否关闭文字行方向预测", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "关闭文字行方向预测", + "kind": "checkbox" + } + }, + { + "name": "prob", + "label": "", + "tips": "是否需要识别结果中每一行的置信度,默认不需要", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "获取每一行的置信度", + "kind": "checkbox" + } + }, + { + "name": "char_info", + "label": "", + "tips": "是否需要单字识别功能,默认不需要", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "单字识别", + "kind": "checkbox" + } + }, + { + "name": "rotate", + "label": "", + "tips": "是否需要自动旋转功能,默认不需要", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "自动旋转", + "kind": "checkbox" + } + }, + { + "name": "table", + "label": "", + "tips": "是否需要表格识别功能,默认不需要", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "表格识别", + "kind": "checkbox" + } + }, + { + "name": "sort_page", + "label": "", + "tips": "字块返回顺序,false表示从左往右,从上到下的顺序,true表示从上到下,从左往右的顺序,默认false", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "字块返回顺序", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "general_text", + "label": "保存识别结果至变量", + "variableLabel": "通用文字识别结果", + "tips": "指定一个变量名称,该变量用于存储识别出来的通用文字识别结果", + "type": "xbot_visual_ocr_general_text", + "name": "general_text" + } + ] + }, + { + "name": "ocr.if_text_on_screen", + "statement": "workflow.if", + "icon": "BlockIcons/23-5.png", + "description": "如果屏幕上存在/不存在指定的文本", + "comment": "通过%ai_engine%AI引擎识别%image_source%上是否存在文本%text%", + "indent": "1", + "scope": "1", + "isCondition": true, + "title": "IF 屏幕上存在文本(OCR)", + "function": "xbot_visual.ocr.if_text_on_screen", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if屏幕上存在文本(ocr).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Ocr.IfTextOnScreenHandler" + } + ], + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.IfTextOnScreenControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "baidu_ocr_edition", + "label": "AI版本", + "tips": "选择百度AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "general" + }, + { + "display": "高精度版", + "value": "accurate" + }, + { + "display": "标准版(不含位置)", + "value": "general_basic" + }, + { + "display": "高精度版(不含位置)", + "value": "accurate_basic" + } + ] + } + }, + { + "name": "tencent_ocr_edition", + "label": "AI版本", + "tips": "选择腾讯AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "GeneralBasicOCR" + }, + { + "display": "高精度版", + "value": "GeneralAccurateOCR" + }, + { + "display": "精简版", + "value": "GeneralEfficientOCR" + }, + { + "display": "高速版", + "value": "GeneralFastOCR" + } + ] + } + }, + { + "name": "aliyun_ocr_edition", + "label": "AI版本", + "tips": "选择阿里云AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "ocr_general" + }, + { + "display": "高精度版", + "value": "advanced" + } + ] + } + }, + { + "name": "text", + "label": "待查找文本", + "required": true, + "tips": "请输入待查找的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_regular_expression", + "label": "", + "required": true, + "tips": "输入的文本是正则表达式", + "type": "bool", + "default": "13:False", + "editor": { + "label": "是正则表达式", + "kind": "checkbox" + } + }, + { + "name": "desired_state", + "label": "如果文本", + "required": true, + "default": "10:exist", + "defaultDisplay": "存在", + "tips": "指定查找范围内指定的文本存在or不存在", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "存在", + "value": "exist" + }, + { + "display": "不存在", + "value": "not_exist" + } + ] + } + }, + { + "name": "image_source", + "label": "查找来源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕", + "tips": "可选择整个屏幕或指定的窗口", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "foreground_window" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_region", + "label": "查找区域", + "required": true, + "default": "10:all_region", + "defaultDisplay": "全部", + "tips": "选择整个查找区域or局部区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all_region" + }, + { + "display": "指定部分区域", + "value": "sub_region" + } + ] + } + }, + { + "name": "region_x1", + "label": "X1", + "required": false, + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y1", + "label": "Y1", + "required": false, + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_x2", + "label": "X2", + "required": false, + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y2", + "label": "Y2", + "required": false, + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "ocr.wait_text_on_screen", + "icon": "BlockIcons/23-4.png", + "description": "等待屏幕上出现/消失指定的文本", + "comment": "通过%ai_engine%AI引擎识别%image_source%上是否存在文本%text%", + "title": "等待文本(OCR)", + "function": "xbot_visual.ocr.wait_text_on_screen", + "helpUrl": "yddoc/language/zh-cn/指令文档/等待/等待文本(ocr).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Ocr.WaitTextOnScreenHandler" + } + ], + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.WaitTextOnScreenControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "baidu_ocr_edition", + "label": "AI版本", + "tips": "选择百度AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "general" + }, + { + "display": "高精度版", + "value": "accurate" + }, + { + "display": "标准版(不含位置)", + "value": "general_basic" + }, + { + "display": "高精度版(不含位置)", + "value": "accurate_basic" + } + ] + } + }, + { + "name": "tencent_ocr_edition", + "label": "AI版本", + "tips": "选择腾讯AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "GeneralBasicOCR" + }, + { + "display": "高精度版", + "value": "GeneralAccurateOCR" + }, + { + "display": "精简版", + "value": "GeneralEfficientOCR" + }, + { + "display": "高速版", + "value": "GeneralFastOCR" + } + ] + } + }, + { + "name": "aliyun_ocr_edition", + "label": "AI版本", + "tips": "选择阿里云AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "ocr_general" + }, + { + "display": "高精度版", + "value": "advanced" + } + ] + } + }, + { + "name": "text", + "label": "待查找文本", + "required": true, + "tips": "请输入待查找的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_regular_expression", + "label": "", + "required": true, + "tips": "输入的文本是正则表达式", + "type": "bool", + "default": "13:False", + "editor": { + "label": "是正则表达式", + "kind": "checkbox" + } + }, + { + "name": "desired_state", + "label": "如果文本", + "required": true, + "default": "10:appear", + "defaultDisplay": "出现", + "tips": "选择等待文本出现或消失", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "出现", + "value": "appear" + }, + { + "display": "消失", + "value": "disappear" + } + ] + } + }, + { + "name": "image_source", + "label": "查找来源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕", + "tips": "选择一个查找来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "foreground_window" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_region", + "label": "查找区域", + "required": true, + "default": "10:all_region", + "defaultDisplay": "全部", + "tips": "选择文本查找区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all_region" + }, + { + "display": "指定部分区域", + "value": "sub_region" + } + ] + } + }, + { + "name": "region_x1", + "label": "X1", + "required": false, + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y1", + "label": "Y1", + "required": false, + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_x2", + "label": "X2", + "required": false, + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y2", + "label": "Y2", + "required": false, + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_wait", + "label": "", + "required": true, + "tips": "设置超时时间", + "default": "13:False", + "type": "bool", + "editor": { + "label": "设置超时时间", + "kind": "checkbox" + } + }, + { + "name": "timeout_seconds", + "label": "超时时间(s)", + "required": false, + "default": "10:20", + "tips": "请输入超时时间(秒),", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "text_wait_result", + "label": "等待结果", + "tips": "如果为True则等待成功,否则等待超时", + "name": "text_wait_result", + "type": "bool" + } + ] + }, + { + "name": "ocr.hover_on_text", + "icon": "BlockIcons/23-5.png", + "title": "鼠标悬停在文本上(OCR)", + "description": "鼠标悬停在文本上(OCR)", + "keywords": "悬浮", + "comment": "通过%ai_engine%AI引擎,识别%image_source%上文本%text%的位置,将鼠标移动到图像%anchor_type%位置", + "function": "xbot_visual.ocr.hover_on_text", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/鼠标悬停在文本上(ocr).html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.HoverOnTextControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Ocr.HoverTextHandler" + } + ], + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "baidu_ocr_edition", + "label": "AI版本", + "tips": "选择百度AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "general" + }, + { + "display": "高精度版", + "value": "accurate" + } + ] + } + }, + { + "name": "tencent_ocr_edition", + "label": "AI版本", + "tips": "选择腾讯AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "GeneralBasicOCR" + }, + { + "display": "高精度版", + "value": "GeneralAccurateOCR" + }, + { + "display": "精简版", + "value": "GeneralEfficientOCR" + }, + { + "display": "高速版", + "value": "GeneralFastOCR" + } + ] + } + }, + { + "name": "aliyun_ocr_edition", + "label": "AI版本", + "tips": "选择阿里云AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "ocr_general" + }, + { + "display": "高精度版", + "value": "advanced" + } + ] + } + }, + { + "name": "text", + "label": "待查找文本", + "required": true, + "tips": "请输入待查找的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_source", + "label": "查找来源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕", + "tips": "选择一个查找来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "foreground_window" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": true, + "tips": "支持点击目标中心位置(元素矩形区域的中心点)、随机位置(自动随机指定目标矩形范围内的点)、自定义位置(手动指定目标点)", + "category": "advanced", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "label": "目标文本的部位", + "default": "10:middleCenter", + "tips": "选择你要将鼠标移动到文本的哪个部位上", + "category": "advanced", + "required": true, + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "category": "advanced", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "category": "advanced", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "occurrence", + "label": "相似结果位置", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "如果识别到多个结果, 可以指定位置序号,从1开始。排序规则先从左向右,再从上至下", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 1 + } + } + ] + }, + { + "name": "ocr.click_text", + "icon": "BlockIcons/23-5.png", + "title": "点击文本(OCR)", + "description": "点击文本(OCR)", + "comment": "通过%ai_engine%AI引擎,识别%image_source%上文本%text%的位置,%button%%clicks%文本", + "function": "xbot_visual.ocr.click_text", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/点击文本(ocr).html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.ClickTextControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Ocr.ClickTextHandler" + } + ], + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "baidu_ocr_edition", + "label": "AI版本", + "tips": "选择百度AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "general" + }, + { + "display": "高精度版", + "value": "accurate" + } + ] + } + }, + { + "name": "tencent_ocr_edition", + "label": "AI版本", + "tips": "选择腾讯AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "GeneralBasicOCR" + }, + { + "display": "高精度版", + "value": "GeneralAccurateOCR" + }, + { + "display": "精简版", + "value": "GeneralEfficientOCR" + }, + { + "display": "高速版", + "value": "GeneralFastOCR" + } + ] + } + }, + { + "name": "aliyun_ocr_edition", + "label": "AI版本", + "tips": "选择阿里云AI识别版本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准版", + "value": "ocr_general" + }, + { + "display": "高精度版", + "value": "advanced" + } + ] + } + }, + { + "name": "text", + "label": "待查找文本", + "required": true, + "tips": "请输入待查找的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_source", + "label": "查找来源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕", + "tips": "选择一个查找来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "foreground_window" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": true, + "tips": "支持点击目标中心位置(元素矩形区域的中心点)、随机位置(自动随机指定目标矩形范围内的点)、自定义位置(手动指定目标点)", + "category": "advanced", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "label": "目标文本的部位", + "default": "10:middleCenter", + "tips": "选择你要将鼠标移动到文本的哪个部位上", + "category": "advanced", + "required": true, + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "category": "advanced", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "category": "advanced", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "clicks", + "label": "点击次数", + "required": true, + "default": "10:click", + "defaultDisplay": "单击", + "tips": "选择点击的方式是单击还是双击", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单击", + "value": "click" + }, + { + "display": "双击", + "value": "dbclick" + } + ] + } + }, + { + "name": "button", + "label": "鼠标", + "required": true, + "default": "10:left", + "defaultDisplay": "鼠标左键", + "tips": "选择用于触发点击的鼠标按键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "鼠标左键", + "value": "left" + }, + { + "display": "鼠标右键", + "value": "right" + } + ] + } + }, + { + "name": "keys", + "label": "辅助按键", + "required": true, + "default": "10:null", + "defaultDisplay": "无", + "category": "advanced", + "tips": "在点击时需要按下的键盘功能键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "无", + "value": "null" + }, + { + "display": "Alt", + "value": "alt" + }, + { + "display": "Ctrl", + "value": "ctrl" + }, + { + "display": "Shift", + "value": "shift" + }, + { + "display": "Win", + "value": "win" + } + ] + } + }, + { + "name": "move_mouse", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "是否显示鼠标移动轨迹", + "type": "bool", + "editor": { + "label": "显示鼠标移动轨迹", + "kind": "checkbox" + } + }, + { + "name": "occurrence", + "label": "相似结果位置", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "如果识别到多个结果, 可以指定位置序号,从1开始。排序规则先从左向右,再从上至下", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 1 + } + } + ] + }, + { + "name": "ocr.vat_invoice", + "icon": "BlockIcons/23-1.png", + "description": "增值税发票识别(OCR)", + "comment": "使用%ai_engine%AI引擎,识别增值税发票 %image_source% 中的内容,将结果保存到%vat_invoice%", + "title": "增值税发票识别", + "function": "xbot_visual.ocr.vat_invoice", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/文字识别ocr/票据识别.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.VatInvoiceControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Ocr.VatInvoiceHandler" + } + ], + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png;*.pdf)|*.jpg;*.bmp;*.png;*.pdf" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_pdf", + "label": "", + "tips": "默认值为false,开启后可同时支持图片和PDF的识别", + "type": "bool", + "default": "13:False", + "editor": { + "label": "是否开启PDF识别", + "kind": "checkbox" + } + }, + { + "name": "pdf_page_number", + "label": "PDF页面页码", + "tips": "需要识别的PDF页面的对应页码,仅支持PDF单页识别,当上传文件为PDF且IsPdf参数值为true时有效,默认值为1", + "type": "int", + "default": "10:1", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "vat_invoice", + "label": "保存发票信息至", + "variableLabel": "增值税发票信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的增值税发票信息", + "type": "xbot_visual_ocr_vat_invoice", + "name": "vat_invoice" + } + ] + }, + { + "name": "ocr.id_card", + "icon": "BlockIcons/23-1.png", + "description": "身份证识别(OCR)", + "comment": "使用%ai_engine%AI引擎,识别身份证%image_source%中的内容,将结果保存到%id_card%", + "title": "身份证识别", + "function": "xbot_visual.ocr.id_card", + "helpUrl": "yddoc/language/zh-cn/指令文档/ocr/身份证识别.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.IdCardControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "side", + "label": "正反面", + "required": true, + "default": "10:front", + "defaultDisplay": "正面", + "tips": "选择身份证正反面", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "正面", + "value": "front" + }, + { + "display": "反面", + "value": "back" + } + ] + } + }, + { + "name": "detect_risk", + "label": "", + "tips": "是否开启身份证风险类型(身份证复印件、临时身份证、身份证翻拍、修改过的身份证)功能,默认不开启,请查看返回参数risk_type", + "type": "bool", + "default": "13:False", + "editor": { + "label": "开启身份证风险类型", + "kind": "checkbox" + } + }, + { + "name": "detect_photo", + "label": "", + "tips": "是否检测头像内容,默认不检测。可选值:true-检测头像并返回头像的 base64 编码及位置信息", + "type": "bool", + "default": "13:False", + "editor": { + "label": "检测头像内容", + "kind": "checkbox" + } + }, + { + "name": "crop_idcard", + "label": "", + "tips": "身份证照片裁剪(去掉证件外多余的边缘、自动矫正拍摄角度)", + "type": "bool", + "default": "13:False", + "editor": { + "label": "身份证照片裁剪", + "kind": "checkbox" + } + }, + { + "name": "crop_portrait", + "label": "", + "tips": "人像照片裁剪(自动抠取身份证头像区域)", + "type": "bool", + "default": "13:False", + "editor": { + "label": "人像照片裁剪", + "kind": "checkbox" + } + }, + { + "name": "quality", + "label": "", + "tips": "图片质量分数(评价图片的模糊程度)", + "type": "bool", + "default": "13:False", + "editor": { + "label": "图片质量分数", + "kind": "checkbox" + } + }, + { + "name": "copy_warn", + "label": "", + "tips": "复印件告警", + "type": "bool", + "default": "13:False", + "editor": { + "label": "复印件告警", + "kind": "checkbox" + } + }, + { + "name": "border_check_warn", + "label": "", + "tips": "边框和框内遮挡告警", + "type": "bool", + "default": "13:False", + "editor": { + "label": "边框和框内遮挡告警", + "kind": "checkbox" + } + }, + { + "name": "reshoot_warn", + "label": "", + "tips": "翻拍告警", + "type": "bool", + "default": "13:False", + "editor": { + "label": "翻拍告警", + "kind": "checkbox" + } + }, + { + "name": "detect_ps_warn", + "label": "", + "tips": "PS检测告警", + "type": "bool", + "default": "13:False", + "editor": { + "label": "PS检测告警", + "kind": "checkbox" + } + }, + { + "name": "tempid_warn", + "label": "", + "tips": "临时身份证告警", + "type": "bool", + "default": "13:False", + "editor": { + "label": "临时身份证告警", + "kind": "checkbox" + } + }, + { + "name": "invalid_date_warn", + "label": "", + "tips": "身份证有效日期不合法告警", + "type": "bool", + "default": "13:False", + "editor": { + "label": "身份证有效日期不合法告警", + "kind": "checkbox" + } + }, + { + "name": "reflect_warn", + "label": "", + "tips": "是否开启反光检测", + "type": "bool", + "default": "13:False", + "editor": { + "label": "开启反光检测", + "kind": "checkbox" + } + }, + { + "name": "multi_card_detect", + "label": "", + "tips": "是否开启多卡证检测", + "type": "bool", + "default": "13:False", + "editor": { + "label": "开启多卡证检测", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "id_card", + "label": "保存身份证信息至", + "variableLabel": "身份证信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的身份证信息", + "type": "xbot_visual_ocr_id_card", + "name": "id_card" + } + ] + }, + { + "name": "ocr.license_plate", + "icon": "BlockIcons/23-1.png", + "description": "车牌识别(OCR)", + "comment": "使用%ai_engine%AI引擎,识别图片%image_source%中的车牌信息,将结果保存到%license_plate%", + "title": "车牌识别", + "function": "xbot_visual.ocr.license_plate", + "helpUrl": "yddoc/language/zh-cn/指令文档/ocr/车牌识别.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.LicensePlateControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "multi_crop", + "label": "", + "tips": "当设成true时,会做多crop预测,只有当多crop返回的结果一致,并且置信度>0.9时,才返回结果", + "type": "bool", + "default": "13:False", + "editor": { + "label": "开启多crop预测", + "kind": "checkbox" + } + }, + { + "name": "multi_detect", + "label": "", + "tips": "是否检测多张车牌,默认为false,当置为true的时候可以对一张图片内的多张车牌进行识别", + "type": "bool", + "default": "13:False", + "editor": { + "label": "检测多张车牌", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "license_plate", + "label": "保存车牌信息至", + "variableLabel": "车牌信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的车牌信息", + "type": "xbot_visual_ocr_license_plate", + "name": "license_plate" + } + ] + }, + { + "name": "ocr.bank_card", + "icon": "BlockIcons/23-1.png", + "description": "银行卡识别(OCR)", + "comment": "使用%ai_engine%AI引擎,识别图片%image_source%中的银行卡信息,将结果保存到%bank_card%", + "title": "银行卡识别", + "function": "xbot_visual.ocr.bank_card", + "helpUrl": "yddoc/language/zh-cn/指令文档/ocr/银行卡识别.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.BankCardControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "detect_direction", + "label": "", + "tips": "是否检测图像朝向,默认检测,即:true。可选值包括true - 检测朝向;false - 不检测朝向。朝向是指输入图像是正常方向、逆时针旋转90/180/270度", + "type": "bool", + "default": "13:True", + "editor": { + "label": "检测图像朝向", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "bank_card", + "label": "保存银行卡信息至", + "variableLabel": "银行卡信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的银行卡信息", + "type": "xbot_visual_ocr_bank_card", + "name": "bank_card" + } + ] + }, + { + "name": "ocr.id_license_discern", + "icon": "BlockIcons/23-1.png", + "description": "对身份证、银行卡、车牌号等多种卡证进行识别", + "title": "卡证识别", + "function": "xbot_visual.ocr.id_license_discern", + "comment": "", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/文字识别ocr/卡证识别.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.IdLicenseDiscernControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Ocr.IdLicenseDiscernHandler" + } + ], + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "id_type", + "label": "卡证类型", + "required": true, + "tips": "选择一个卡证类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "身份证", + "value": "id_card" + }, + { + "display": "银行卡", + "value": "blank_card" + }, + { + "display": "车牌", + "value": "license_plate" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "side", + "label": "正反面", + "required": true, + "default": "10:front", + "defaultDisplay": "正面", + "tips": "选择身份证正反面", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "正面", + "value": "front" + }, + { + "display": "反面", + "value": "back" + } + ] + } + }, + { + "name": "detect_risk", + "label": "", + "tips": "是否开启身份证风险类型(身份证复印件、临时身份证、身份证翻拍、修改过的身份证)功能,默认不开启,请查看返回参数risk_type", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "开启身份证风险类型", + "kind": "checkbox" + } + }, + { + "name": "detect_photo", + "label": "", + "tips": "是否检测头像内容,默认不检测。可选值:true-检测头像并返回头像的 base64 编码及位置信息", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "检测头像内容", + "kind": "checkbox" + } + }, + { + "name": "crop_idcard", + "label": "", + "tips": "身份证照片裁剪(去掉证件外多余的边缘、自动矫正拍摄角度)", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "身份证照片裁剪", + "kind": "checkbox" + } + }, + { + "name": "crop_portrait", + "label": "", + "tips": "人像照片裁剪(自动抠取身份证头像区域)", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "人像照片裁剪", + "kind": "checkbox" + } + }, + { + "name": "quality", + "label": "", + "tips": "图片质量分数(评价图片的模糊程度)", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "图片质量分数", + "kind": "checkbox" + } + }, + { + "name": "copy_warn", + "label": "", + "tips": "复印件告警", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "复印件告警", + "kind": "checkbox" + } + }, + { + "name": "border_check_warn", + "label": "", + "tips": "边框和框内遮挡告警", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "边框和框内遮挡告警", + "kind": "checkbox" + } + }, + { + "name": "reshoot_warn", + "label": "", + "tips": "翻拍告警", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "翻拍告警", + "kind": "checkbox" + } + }, + { + "name": "detect_ps_warn", + "label": "", + "tips": "PS检测告警", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "PS检测告警", + "kind": "checkbox" + } + }, + { + "name": "tempid_warn", + "label": "", + "tips": "临时身份证告警", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "临时身份证告警", + "kind": "checkbox" + } + }, + { + "name": "invalid_date_warn", + "label": "", + "tips": "身份证有效日期不合法告警", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "身份证有效日期不合法告警", + "kind": "checkbox" + } + }, + { + "name": "reflect_warn", + "label": "", + "tips": "是否开启反光检测", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "开启反光检测", + "kind": "checkbox" + } + }, + { + "name": "multi_card_detect", + "label": "", + "tips": "是否开启多卡证检测", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "开启多卡证检测", + "kind": "checkbox" + } + }, + { + "name": "detect_direction", + "label": "", + "tips": "是否检测图像朝向,默认检测,即:true。可选值包括true - 检测朝向;false - 不检测朝向。朝向是指输入图像是正常方向、逆时针旋转90/180/270度", + "type": "bool", + "default": "13:True", + "category": "advanced", + "editor": { + "label": "检测图像朝向", + "kind": "checkbox" + } + }, + { + "name": "multi_crop", + "label": "", + "tips": "当设成true时,会做多crop预测,只有当多crop返回的结果一致,并且置信度>0.9时,才返回结果", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "开启多crop预测", + "kind": "checkbox" + } + }, + { + "name": "multi_detect", + "label": "", + "tips": "是否检测多张车牌,默认为false,当置为true的时候可以对一张图片内的多张车牌进行识别", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "检测多张车牌", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "id_license", + "label": "识别结果保存至", + "variableLabel": "卡证信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的卡证信息", + "type": "any", + "name": "id_license" + } + ] + }, + { + "name": "ocr.train_ticket", + "icon": "BlockIcons/23-1.png", + "description": "火车票识别(OCR)", + "comment": "使用%ai_engine%AI引擎,识别图片%image_source%中的火车票信息,将结果保存到%train_ticket%", + "title": "火车票识别", + "function": "xbot_visual.ocr.train_ticket", + "helpUrl": "yddoc/language/zh-cn/指令文档/ocr/火车票识别.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.TrainTicketControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "train_ticket", + "label": "保存火车票信息至", + "variableLabel": "火车票信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的火车票信息", + "type": "xbot_visual_ocr_train_ticket", + "name": "train_ticket" + } + ] + }, + { + "name": "ocr.taxi_invoice", + "icon": "BlockIcons/23-1.png", + "description": "出租车票识别(OCR)", + "comment": "使用%ai_engine%AI引擎,识别图片%image_source%中的出租车票信息,将结果保存到%taxi_invoice%", + "title": "出租车票识别", + "function": "xbot_visual.ocr.taxi_invoice", + "helpUrl": "yddoc/language/zh-cn/指令文档/ocr/出租车票识别.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.TaxiInvoiceControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "taxi_invoice", + "label": "保存出租车票信息至", + "variableLabel": "出租车票信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的出租车票信息", + "type": "xbot_visual_ocr_taxi_invoice", + "name": "taxi_invoice" + } + ] + }, + { + "name": "ocr.note_discern", + "icon": "BlockIcons/23-1.png", + "description": "对增值税发票、火车票、出租车票等各种票据进行识别", + "title": "票据识别", + "function": "xbot_visual.ocr.note_discern", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.NoteDiscernControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/文字识别ocr/票据识别.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Ocr.NoteDiscernHandler" + } + ], + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "note_type", + "label": "票据类型", + "required": true, + "tips": "选择一个票据类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "增值税发票", + "value": "vat_invoice" + }, + { + "display": "出租车票", + "value": "taxi_invoice" + }, + { + "display": "火车票", + "value": "train_ticket" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png;*.pdf)|*.jpg;*.bmp;*.png;*.pdf" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_pdf", + "label": "", + "tips": "默认值为false,开启后可同时支持图片和PDF的识别", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "是否开启PDF识别", + "kind": "checkbox" + } + }, + { + "name": "pdf_page_number", + "label": "PDF页面页码", + "tips": "需要识别的PDF页面的对应页码,仅支持PDF单页识别,当上传文件为PDF且IsPdf参数值为true时有效,默认值为1", + "type": "int", + "default": "10:1", + "category": "advanced", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "note_invoice", + "label": "保存票据信息至", + "variableLabel": "票据信息信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的票据信息", + "type": "any", + "name": "note_invoice" + } + ] + }, + { + "name": "ocr.table", + "icon": "BlockIcons/23-1.png", + "description": "表格识别(OCR)", + "comment": "使用%ai_engine%AI引擎,识别图片%image_source%中的表格信息,将结果保存到%table%", + "title": "表格识别", + "function": "xbot_visual.ocr.table", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Ocr.TableControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/人工智能ai/文字识别ocr/表格识别.html", + "inputs": [ + { + "name": "ai_engine", + "label": "AI引擎", + "required": true, + "tips": "选择一个AI引擎", + "type": "xbot.ai.AIEngine", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "影刀", + "value": "shadowbot" + } + ] + } + }, + { + "name": "image_source", + "label": "图像源", + "required": true, + "default": "10:disk", + "defaultDisplay": "本地硬盘图片", + "tips": "选择一个图像源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地硬盘图片", + "value": "disk" + }, + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "网络图片", + "value": "url" + } + ] + } + }, + { + "name": "path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png;*.pdf)|*.jpg;*.bmp;*.png;*.pdf" + } + } + }, + { + "name": "url", + "label": "图片URL", + "tips": "图片URL", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "save_to_excel", + "label": "", + "required": true, + "tips": "将表格识别结果直接保存到Excel表格", + "type": "bool", + "default": "13:False", + "editor": { + "label": "识别结果保存到Excel", + "kind": "checkbox" + } + }, + { + "name": "excel_path", + "label": "Excel文件路径", + "tips": "填写或选择要打开的Excel文件路径,若不存在将自动创建", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "defaultFileName": "Workbook", + "filter": "Excel 工作簿 (.xlsx)|*.xlsx" + } + } + }, + { + "name": "dir_assure", + "label": "", + "tips": "图片方向是否确定是正向的: true(确定)/false(不确定)", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "图片方向确定为正向", + "kind": "checkbox" + } + }, + { + "name": "line_less", + "label": "", + "tips": "是否无线条: true(无线条,或者只有横线没有竖线)/false(有线条)", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "无线条", + "kind": "checkbox" + } + }, + { + "name": "is_pdf", + "label": "", + "tips": "是否开启PDF识别,默认值为false,开启后可同时支持图片和PDF的识别", + "type": "bool", + "default": "13:False", + "category": "advanced", + "editor": { + "label": "开启PDF识别", + "kind": "checkbox" + } + }, + { + "name": "pdf_page_number", + "label": "PDF页码", + "default": "10:1", + "category": "advanced", + "tips": "需要识别的PDF页面的对应页码,仅支持PDF单页识别,当上传文件为PDF且IsPdf参数值为true时有效,默认值为1", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "table", + "label": "保存表格信息至", + "variableLabel": "表格信息", + "tips": "指定一个变量名称,该变量用于存储识别出来的表格信息", + "type": "xbot_visual_ocr_table", + "name": "table" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/pdf.blocks.json b/src/assert/block_settings/pdf.blocks.json new file mode 100644 index 0000000..2704ff2 --- /dev/null +++ b/src/assert/block_settings/pdf.blocks.json @@ -0,0 +1,687 @@ +{ + "types": [], + "blocks": [ + { + "name": "pdf.extract_text", + "function": "xbot_visual.pdf.extract_text", + "title": "PDF提取文本", + "description": "这个指令用于从PDF文件中提取文本", + "comment": "从%path%文件中提取%page_scope%的文本,将结果保存到%text%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Pdf.ExtractTextControl, ShadowBot.Shell.Development", + "icon": "BlockIcons/26-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/pdf文件/提取文本.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Pdf.ExtractTextHandler" + } + ], + "inputs": [ + { + "name": "path", + "label": "文件路径", + "required": true, + "tips": "请输入PDF文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "PDF文件 (.pdf)|*.pdf" + } + } + }, + { + "name": "page_scope", + "label": "提取范围", + "required": true, + "default": "10:all", + "defaultDisplay": "全部", + "tips": "选择提取页码范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all" + }, + { + "display": "单页", + "value": "single" + }, + { + "display": "部分", + "value": "part" + } + ] + } + }, + { + "name": "page", + "label": "页码", + "required": false, + "tips": "请输入待提取的单页页码", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "from_page", + "label": "起始页码", + "required": false, + "tips": "请输入待提取的起始页码", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "to_page", + "label": "终止页码", + "required": false, + "tips": "请输入待提取的终止页码, 输入-1表示最后一页", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_password", + "label": "", + "required": true, + "category": "advanced", + "tips": "打开文件是否需要输入密码", + "type": "bool", + "default": "13:False", + "editor": { + "label": "使用密码", + "kind": "checkbox" + } + }, + { + "name": "password", + "label": "密码", + "required": false, + "category": "advanced", + "tips": "请输入文件密码", + "type": "str", + "editor": { + "kind": "password" + } + } + ], + "outputs": [ + { + "id": "text", + "label": "保存文本至", + "variableLabel": "PDF中提取的文本", + "tips": "请输入一个名字,用来保存文本", + "type": "str", + "name": "text" + } + ] + }, + { + "name": "pdf.extract_images", + "function": "xbot_visual.pdf.extract_images", + "title": "PDF提取图片", + "description": "这个指令用于从PDF文件中提取图片", + "comment": "从%path%文件中提取%page_scope%的图片,并以%image_name%为名称前缀保存到%save_to_dir%目录下,将图片路径保存到%image_paths%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Pdf.ExtractImageControl, ShadowBot.Shell.Development", + "icon": "BlockIcons/26-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/pdf文件/提取图片.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Pdf.ExtractImageHandler" + } + ], + "inputs": [ + { + "name": "path", + "label": "文件路径", + "required": true, + "tips": "请输入PDF文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "PDF文件 (.pdf)|*.pdf" + } + } + }, + { + "name": "page_scope", + "label": "提取范围", + "required": true, + "default": "10:all", + "defaultDisplay": "全部", + "tips": "选择提取页码范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all" + }, + { + "display": "单页", + "value": "single" + }, + { + "display": "部分", + "value": "part" + } + ] + } + }, + { + "name": "page", + "label": "页码", + "required": false, + "tips": "请输入待提取的单页页码", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "from_page", + "label": "起始页码", + "required": false, + "tips": "请输入待提取的起始页码", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "to_page", + "label": "终止页码", + "required": false, + "tips": "请输入待提取的终止页码, 输入-1表示最后一页", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "name_prefix", + "label": "图片名称前缀", + "required": true, + "tips": "请输入图片名称前缀", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "save_to_dir", + "label": "保存图片至", + "required": true, + "tips": "请输入保存图片的文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "use_password", + "label": "", + "required": true, + "category": "advanced", + "tips": "打开文件是否需要输入密码", + "type": "bool", + "default": "13:False", + "editor": { + "label": "使用密码", + "kind": "checkbox" + } + }, + { + "name": "password", + "label": "密码", + "required": false, + "category": "advanced", + "tips": "请输入文件密码", + "type": "str", + "editor": { + "kind": "password" + } + } + ], + "outputs": [ + { + "id": "image_paths", + "label": "保存图片路径列表至", + "variableLabel": "PDF中提取的图片路径列表", + "tips": "请输入一个名字,用来保存图片路径列表至", + "type": "list", + "name": "image_paths" + } + ] + }, + { + "name": "pdf.extract_pages", + "function": "xbot_visual.pdf.extract_pages", + "title": "导出新PDF文档", + "description": "这个指令用于从当前PDF文件中导出新的PDF文档", + "comment": "从文件%path%中导出部分页,将内容保存到新文件%file_path%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Pdf.ExtractPdfControl, ShadowBot.Shell.Development", + "icon": "BlockIcons/26-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/pdf文件/导出新的pdf文件.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Pdf.ExtractPdfHandler" + } + ], + "inputs": [ + { + "name": "path", + "label": "原始文件路径", + "required": true, + "tips": "请输入原始文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "PDF文件 (.pdf)|*.pdf" + } + } + }, + { + "name": "page_scope", + "label": "提取范围", + "required": true, + "default": "10:single", + "defaultDisplay": "单页", + "tips": "选择提取页码范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单页", + "value": "single" + }, + { + "display": "部分", + "value": "part" + } + ] + } + }, + { + "name": "page", + "label": "页码", + "required": false, + "tips": "请输入待导出的单页页码", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "from_page", + "label": "起始页码", + "required": false, + "tips": "请输入待导出的起始页码", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "to_page", + "label": "终止页码", + "required": false, + "tips": "请输入待导出的终止页码, 输入-1表示最后一页", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "save_to", + "label": "新文件保存到", + "required": true, + "tips": "请输入新文件保存路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "filter": "PDF 文件|*.pdf" + } + } + }, + { + "name": "save_way", + "label": "如果文件存在", + "required": true, + "default": "10:add_sequential_suffix", + "defaultDisplay": "文件名称末尾添加序号", + "tips": "请选择若文件已经存在时,文件保存方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "终止导出新文件", + "value": "stop_extract_if_exist" + }, + { + "display": "文件名称末尾添加序号", + "value": "add_sequential_suffix" + } + ] + } + }, + { + "name": "use_password", + "label": "", + "required": true, + "category": "advanced", + "tips": "打开文件是否需要输入密码", + "type": "bool", + "default": "13:False", + "editor": { + "label": "使用密码", + "kind": "checkbox" + } + }, + { + "name": "password", + "label": "密码", + "required": false, + "category": "advanced", + "tips": "请输入文件密码", + "type": "str", + "editor": { + "kind": "password" + } + } + ], + "outputs": [ + { + "id": "file_path", + "label": "保存新文件路径至", + "variableLabel": "导出的PDF文件路径", + "tips": "请输入一个名字,用来保存新文件路径", + "type": "str", + "name": "file_path" + } + ] + }, + { + "name": "pdf.merge_pdfs", + "function": "xbot_visual.pdf.merge_pdfs", + "title": "合并PDF文档", + "description": "这个指令用于合并PDF文档,并保存到指定的新文档", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Pdf.MergePdfControl, ShadowBot.Shell.Development", + "comment": "合并%paths%这些文件,将结果保存到%save_to%", + "icon": "BlockIcons/26-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/pdf文件/合并pdf文档.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Pdf.MergePdfHandler" + } + ], + "inputs": [ + { + "name": "paths", + "label": "待合并的文件列表", + "required": true, + "tips": "可同时选择多个文件。或切换到Python模式下,输入列表变量,比如: ['文件1路径','文件2路径']", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFiles", + "filter": "PDF文件 (.pdf)|*.pdf" + } + } + }, + { + "name": "save_to", + "label": "合并后保存至", + "required": true, + "tips": "请输入合并后的文件保存路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "filter": "PDF 文件|*.pdf" + } + } + }, + { + "name": "save_way", + "label": "如果文件存在", + "required": true, + "default": "10:add_sequential_suffix", + "defaultDisplay": "文件名称末尾添加序号", + "tips": "请选择若文件已经存在时,文件保存方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "终止合并", + "value": "stop_extract_if_exist" + }, + { + "display": "文件名称末尾添加序号", + "value": "add_sequential_suffix" + } + ] + } + }, + { + "name": "use_password", + "label": "", + "required": true, + "category": "advanced", + "tips": "打开文件是否需要输入密码", + "type": "bool", + "default": "13:False", + "editor": { + "label": "使用密码", + "kind": "checkbox" + } + }, + { + "name": "passwords", + "label": "密码", + "required": false, + "category": "advanced", + "tips": "请输入文件密码,文件密码和文件路径一一对应", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "delimiter", + "label": "分割符", + "required": false, + "category": "advanced", + "tips": "请输入密码分割符", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "file_path", + "label": "保存合并的路径至", + "variableLabel": "合并后的PDF文件路径", + "tips": "请输入一个名字,用来保存新文件路径", + "type": "str", + "name": "file_path" + } + ] + }, + { + "name": "pdf.save_pages_to_images", + "function": "xbot_visual.pdf.save_pages_to_images", + "title": "将PDF指定页另存为图片", + "description": "这个指令用于将指定页另存为图片", + "comment": "将文件%path%的指定页另存为图片,并以%name_prefix%为名称前缀保存到目录%save_to_dir%中,将图片保存路径保存到%page_image_paths%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Pdf.SavePagesToImageControl, ShadowBot.Shell.Development", + "icon": "BlockIcons/26-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/pdf文件/将指定页另存为图片.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Pdf.SavePagesToImagesHandler" + } + ], + "inputs": [ + { + "name": "path", + "label": "文件路径", + "required": true, + "tips": "请输入PDF文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "PDF文件 (.pdf)|*.pdf" + } + } + }, + { + "name": "page_scope", + "label": "提取范围", + "required": true, + "default": "10:all", + "defaultDisplay": "全部", + "tips": "选择提取页码范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all" + }, + { + "display": "单页", + "value": "single" + }, + { + "display": "部分", + "value": "part" + } + ] + } + }, + { + "name": "page", + "label": "页码", + "required": false, + "tips": "请输入待提取的单页页码", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "from_page", + "label": "起始页码", + "required": false, + "tips": "请输入待提取的起始页码", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "to_page", + "label": "终止页码", + "required": false, + "tips": "请输入待提取的终止页码, 输入-1表示最后一页", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "name_prefix", + "label": "图片名称前缀", + "required": true, + "tips": "请输入图片名称前缀", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "save_to_dir", + "label": "保存图片至", + "required": true, + "tips": "请输入保存图片的文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "use_password", + "label": "", + "required": true, + "category": "advanced", + "tips": "打开文件是否需要输入密码", + "type": "bool", + "default": "13:False", + "editor": { + "label": "使用密码", + "kind": "checkbox" + } + }, + { + "name": "password", + "label": "密码", + "required": false, + "category": "advanced", + "tips": "请输入文件密码", + "type": "str", + "editor": { + "kind": "password" + } + } + ], + "outputs": [ + { + "id": "page_image_paths", + "label": "保存图片路径列表至", + "variableLabel": "PDF中另存为的图片路径列表", + "tips": "请输入一个名字,用来保存图片路径列表至", + "type": "list", + "name": "page_image_paths" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/process.blocks.json b/src/assert/block_settings/process.blocks.json new file mode 100644 index 0000000..ae98c3a --- /dev/null +++ b/src/assert/block_settings/process.blocks.json @@ -0,0 +1,258 @@ +{ + "types": [], + "blocks": [ + { + "name": "process.run", + "statement": "process.run", + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/调用流程.html", + "icon": "BlockIcons/21-2.png", + "title": "调用流程", + "keywords": "调用子流程", + "description": "执行指定名称的内部流程", + "comment": "执行流程%process%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.RunProcessControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.RunProcessHandler" + } + ], + "inputs": [ + { + "name": "process", + "label": "模块名称", + "required": true, + "tips": "选择要执行的模块名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "package", + "label": "当前Python包对象", + "required": true, + "tips": "根据当前Python包对象动态导入指定流程", + "default": "11:__name__", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "inputs", + "label": "输入参数列表", + "required": false, + "tips": "输入参数列表", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "outputs", + "label": "输出参数列表", + "required": false, + "tips": "输出参数列表", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "process_result", + "label": "保存流程输出结果至", + "tips": "指定一个变量名称,该变量用于保存用户输入结果,如果用户取消对话框则返回None否则返回dict对象", + "name": "process_result", + "type": "dict" + } + ] + }, + { + "name": "process.invoke_module", + "statement": "process.invoke_module", + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/调用模块.html", + "icon": "BlockIcons/21-4.png", + "title": "调用模块", + "keywords": "调用python", + "description": "调用应用内的其他模块", + "comment": "调用模块%module%中的%function%方法", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.InvokeModule, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.InvokeModuleHandler" + } + ], + "inputs": [ + { + "name": "module", + "label": "模块名称", + "required": true, + "tips": "选择要执行的模块名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "function", + "label": "方法名称", + "required": true, + "tips": "选择要执行的方法名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "params", + "label": "方法参数列表", + "required": false, + "tips": "方法参数列表", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "returnType", + "label": "返回值类型", + "required": false, + "tips": "返回值类型", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "invoke_result", + "label": "模块调用结果", + "variableLabel": "模块调用结果", + "type": "any", + "name": "invoke_result" + } + ] + }, + { + "name": "process.return", + "statement": "process.return", + "canDebug": false, + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/退出流程.html", + "icon": "BlockIcons/21-1.png", + "description": "退出当前流程并继续执行其他流程", + "comment": "退出当前流程并继续执行其他流程", + "title": "退出当前流程" + }, + { + "name": "process.exit", + "statement": "process.exit", + "canDebug": false, + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/应用/终止应用.html", + "icon": "BlockIcons/21-3.png", + "description": "停止整个应用的运行", + "comment": "停止整个应用的运行", + "keywords": "退出应用;结束应用", + "title": "终止应用" + }, + { + "name": "process.get_app_params", + "function": "xbot_visual.process.get_app_params", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Process.GetAppParamsHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/应用/获取应用参数.html", + "icon": "BlockIcons/21-2.png", + "title": "获取应用参数", + "description": "获取应用参数", + "comment": "获取应用参数,将结果保存到%param_value%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.GetAppParams, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "param_name", + "label": "参数类型", + "type": "str", + "editor": { + "kind": "select", + "options": [] + } + } + ], + "outputs": [ + { + "id": "param_value", + "label": "保存参数值至", + "variableLabel": "应用参数值", + "type": "str", + "name": "param_value" + } + ] + }, + { + "name": "process.write_to_storage", + "function": "xbot_visual.process.write_to_storage", + "title": "保存自定义数据", + "description": "可持久保存流程中的用户数据", + "comment": "保存自定义数据%content%到%key%", + "icon": "BlockIcons/12-10.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/应用/保存自定义数据.html", + "inputs": [ + { + "name": "key", + "label": "读取Key", + "required": true, + "tips": "数据读取时需要, 读取只限同一用户、同一应用 \r\n相同Key多次保存,内容会被覆盖", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "content", + "label": "数据内容", + "required": true, + "tips": "需要保存的数据内容,长度不超过20000个字符", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "process.read_from_storage", + "function": "xbot_visual.process.read_from_storage", + "title": "读取自定义数据", + "description": "读取流程中已保存的自定义数据", + "comment": "读取自定义数据%key%,将结果保存到%content%", + "icon": "BlockIcons/12-11.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/应用/读取自定义数据.html", + "inputs": [ + { + "name": "key", + "label": "Key", + "required": true, + "tips": "“保存自定义数据”指令中指定的读取Key", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "content", + "label": "数据内容", + "variableLabel": "自定义数据内容", + "tips": "若根据key未找到,返回None", + "type": "str", + "name": "content" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/programing.blocks.json b/src/assert/block_settings/programing.blocks.json new file mode 100644 index 0000000..5265c8b --- /dev/null +++ b/src/assert/block_settings/programing.blocks.json @@ -0,0 +1,538 @@ +{ + "types": [], + "blocks": [ + { + "name": "programing.log", + "title": "打印日志", + "description": "将变量或者文本打印输出,输出内容可在【运行日志】区查看", + "comment": "打印日志(%type%):%text%", + "icon": "BlockIcons/8-1.png", + "function": "xbot_visual.programing.log", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/打印日志.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.LogHandler" + } + ], + "inputs": [ + { + "name": "type", + "label": "日志类型", + "required": true, + "tips": null, + "type": "str", + "default": "10:info", + "defaultDisplay": "信息", + "editor": { + "kind": "select", + "options": [ + { + "display": "调试", + "value": "debug" + }, + { + "display": "信息", + "value": "info" + }, + { + "display": "警告", + "value": "warning" + }, + { + "display": "错误", + "value": "error" + } + ] + } + }, + { + "name": "text", + "label": "日志内容", + "required": true, + "tips": null, + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "programing.undefined", + "function": "xbot_visual.programing.undefined", + "icon": "BlockIcons/8-11.png", + "canDebug": false, + "description": "指令在应用中未找到,可尝试升级客户端或联系作者解决", + "comment": "%message% 指令在指令库中未找到", + "title": "未找到指令", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.BlockUndefinedControl, ShadowBot.Shell.Development", + "helpUrl": "", + "sourceBlock": "", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.UndefinedHandler" + } + ], + "inputs": [ + { + "name": "message", + "label": "名称", + "required": false, + "tips": "未找到的自定义指令的名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sourceBlock", + "label": "元数据", + "required": false, + "tips": "原指令的元数据,请勿修改", + "type": "str", + "editor": { + "kind": "textbox" + } + } + + ] + }, + { + "name": "programing.exportlog", + "title": "导出日志", + "description": "将日志导出到文件", + "comment": "导出日志至 %custom_folder_path%\\%file_name%", + "icon": "BlockIcons/8-16.png", + "function": "xbot_visual.programing.exportlog", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/导出日志.html", + "inputs": [ + { + "name": "custom_folder_path", + "label": "文件夹路径", + "required": true, + "tips": "指定文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "file_name", + "label": "文件名称", + "required": true, + "default": "10:日志文件.txt", + "tips": "指定文件名称", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "file_path", + "label": "文件路径", + "variableLabel": "导出的文件路径", + "tips": "指定一个变量名称, 该变量用于保存导出文件的位置", + "type": "str", + "name": "file_path" + } + ] + }, + { + "name": "programing.sleep", + "title": "等待", + "description": "让流程等待一段时间", + "comment": "等待%seconds%秒后继续运行", + "icon": "BlockIcons/8-2.png", + "function": "xbot_visual.programing.sleep", + "helpUrl": "yddoc/language/zh-cn/指令文档/等待/等待说明.html", + "keywords": "延迟;延时", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.ProgramingSleep", + "video": { + "time": "05:09" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.ProgramingSleepHandler" + } + ], + "inputs": [ + { + "name": "random_number", + "label": " ", + "required": true, + "default": "13:False", + "tips": "等待时长是随机数", + "type": "bool", + "editor": { + "label": "等待时长随机", + "kind": "checkbox" + } + }, + { + "name": "seconds", + "label": "时长(秒)", + "tips": null, + "type": "float", + "default": "10:1", + "editor": { + "kind": "textbox" + } + }, + { + "name": "start_number", + "label": "最小时长(秒)", + "required": true, + "tips": "随机数从开始数字到结束数字这一段区间中产生,包括开始数字和结束数字", + "type": "int", + "default": "10:1", + "editor": { + "kind": "textbox" + } + }, + { + "name": "stop_number", + "label": "最大时长(秒)", + "required": true, + "tips": "随机数从开始数字到结束数字这一段区间中产生,包括开始数字和结束数字", + "type": "int", + "default": "10:5", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "programing.variable", + "title": "设置变量", + "statement": "programing.variable", + "description": "创建一个新的变量并给它赋值,或对已经存在的变量重新赋值", + "comment": "设置%value_type%变量%variable%=%value%", + "icon": "BlockIcons/8-3.png", + "function": "xbot_visual.programing.variable", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.SetVariableControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/设置变量.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.SetVariableHandler" + } + ], + "inputs": [ + { + "name": "value_type", + "label": "变量类型", + "tips": "选择要执行的流程名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "value", + "label": "变量值", + "required": false, + "tips": "指定变量中保存的值", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "variable", + "label": "变量名", + "variableLabel": "变量", + "type": "str", + "tips": "输入一个名称作为变量名,将变量值保存至此变量中", + "name": "variable" + } + ] + }, + { + "name": "programing.random_int", + "icon": "BlockIcons/8-12.png", + "description": "产生随机数", + "comment": "在最小数%start_number%与最大数%stop_number%之间产生随机数,将随机数保存到%random_number%", + "title": "产生随机数", + "function": "xbot_visual.programing.random_int", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/产生随机数.html", + "inputs": [ + { + "name": "start_number", + "label": "最小数", + "required": true, + "tips": "随机数从开始数字到结束数字这一段区间中产生,包括开始数字和结束数字", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "stop_number", + "label": "最大数", + "required": true, + "tips": "随机数从开始数字到结束数字这一段区间中产生,包括开始数字和结束数字", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "random_number", + "label": "随机数保存至", + "variableLabel": "随机数", + "tips": "输入一个名字,用来保存产生的随机数", + "type": "int", + "name": "random_number" + } + ] + }, + { + "name": "programing.snippet", + "title": "插入代码段(Python)", + "statement": "programing.snippet", + "description": "插入代码段(Python)", + "comment": "执行Python语句:%snippet%", + "icon": "BlockIcons/8-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/插入代码段(python).html", + "inputs": [ + { + "name": "snippet", + "label": "Python代码段", + "required": true, + "tips": null, + "type": "str", + "editor": { + "kind": "code", + "language": "python" + } + } + ] + }, + { + "name": "programing.comment", + "statement": "programing.comment", + "title": "添加备注说明", + "keywords": "注释", + "description": "在流程中插入一条文字说明", + "icon": "BlockIcons/8-5.png", + "comment": "%content%", + "isCommentBlock": true, + "isPseudo": true, + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/添加备注说明.html", + "inputs": [ + { + "name": "content", + "label": "备注说明", + "required": true, + "tips": null, + "type": "str", + "editor": { + "kind": "PlainText" + } + } + ] + }, + { + "name": "programing.region", + "statement": "programing.region", + "title": "折叠开始", + "description": "折叠一组指令,使之更易于阅读,折叠从此处开始", + "comment": "说明:%content%", + "icon": "BlockIcons/8-6.png", + "indent": "1", + "scope": "0", + "isPseudo": true, + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/折叠.html", + "inputs": [ + { + "name": "content", + "label": "折叠区域名称", + "required": true, + "tips": null, + "type": "str", + "editor": { + "kind": "PlainText" + } + } + ] + }, + { + "name": "programing.endregion", + "statement": "programing.endregion", + "title": "折叠结束", + "description": "结束一段指令折叠", + "icon": "BlockIcons/8-7.png", + "indent": "2", + "scope": "0", + "isPseudo": true + }, + { + "name": "programing.try", + "statement": "programing.try", + "canDebug": false, + "icon": "BlockIcons/8-8.png", + "indent": "1", + "scope": "1", + "comment": "尝试执行", + "keywords": "异常", + "description": "尝试执行开始标记", + "title": "Try", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/异常处理/try.html" + }, + { + "name": "programing.catch", + "statement": "programing.catch", + "icon": "BlockIcons/8-9.png", + "indent": "3", + "scope": "3", + "canDebug": false, + "description": "尝试失败时执行", + "comment": "尝试失败时执行, 将错误信息保存到%exception%", + "title": "Catch", + "keywords": "异常", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/异常处理/catch.html", + "outputs": [ + { + "id": "exception", + "label": "错误信息", + "variableLabel": "错误信息", + "type": "str", + "tips": "输入一个名称作为保存错误信息的变量,当指令执行出错的时候错误信息将会保存至此变量中", + "name": "exception" + } + ] + }, + { + "name": "programing.finally", + "statement": "programing.finally", + "icon": "BlockIcons/8-10.png", + "indent": "3", + "scope": "3", + "canDebug": false, + "description": "无论尝试是否成功始终执行", + "comment": "无论尝试是否成功始终执行以下操作", + "title": "Finally", + "keywords": "异常", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/异常处理/finally.html" + }, + { + "name": "programing.endtry", + "statement": "programing.endtry", + "icon": "BlockIcons/8-11.png", + "indent": "2", + "scope": "2", + "isPseudo": true, + "description": "尝试执行结束标记", + "comment": "结束尝试执行", + "title": "End Try", + "keywords": "异常", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/异常处理/endtry.html" + }, + { + "name": "programing.raise", + "statement": "programing.raise", + "icon": "BlockIcons/8-13.png", + "description": "抛出异常", + "comment": "抛出异常:%reason%", + "title": "Raise", + "keywords": "异常", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/异常处理/raise.html", + "inputs": [ + { + "name": "reason", + "label": "异常原因", + "required": true, + "tips": "异常产生的原因", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "programing.onDelayRunSwitch", + "title": "开始批量等待", + "description": "一次为多个鼠标操作指令添加等待时间", + "comment": "从此处开始,每条鼠标操作指令运行后等待%seconds%秒", + "icon": "BlockIcons/8-14.png", + "indent": "1", + "scope": "1", + "function": "xbot_visual.programing.on_delay_run_switch", + "helpUrl": "doc/指令文档/03等待/开始批量等待.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.OnDelayRunSwitchControl", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.OnDelayRunSwitchHandler" + } + ], + "inputs": [ + { + "name": "random_number", + "label": " ", + "required": true, + "default": "13:True", + "tips": "每条指令结束后,根据最小、最大等待时长生成随机等待时长", + "type": "bool", + "editor": { + "label": "等待时长随机", + "kind": "checkbox" + } + }, + { + "name": "seconds", + "label": "时长(秒)", + "required": false, + "tips": "每条指令结束后,等待的固定时长", + "type": "float", + "default": "10:1", + "editor": { + "kind": "textbox" + } + }, + { + "name": "min_number", + "label": "最小时长(秒)", + "required": false, + "tips": "指定最小等待时间", + "type": "int", + "default": "10:1", + "editor": { + "kind": "textbox" + } + }, + { + "name": "max_number", + "label": "最大时长(秒)", + "required": false, + "tips": "指定最大等待时间", + "type": "int", + "default": "10:3", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "programing.offDelayRunSwitch", + "function": "xbot_visual.programing.off_delay_run_switch", + "icon": "BlockIcons/8-15.png", + "indent": "2", + "scope": "2", + "description": "结束批量等待", + "comment": "结束批量等待", + "title": "结束批量等待", + "helpUrl": "doc/指令文档/03等待/结束批量等待.html" + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/programing.databook.blocks.json b/src/assert/block_settings/programing.databook.blocks.json new file mode 100644 index 0000000..7feb6f9 --- /dev/null +++ b/src/assert/block_settings/programing.databook.blocks.json @@ -0,0 +1,1001 @@ +{ + "types": [], + "blocks": [ + { + "name": "programing.databook.foreach", + "statement": "workflow.for", + "title": "循环数据表格", + "description": "循环读取数据表格内容", + "comment": "循环数据表格,从第%start%行到第%stop%行,步长为%step%,将循环的行号保存到%loop_index%", + "icon": "", + "indent": "1", + "scope": "1", + "function": "xbot_visual.programing.databook.foreach", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/循环数据表格内容.html", + "video": { + "time": "06:30" + }, + "inputs": [ + { + "name": "start", + "label": "起始行号", + "required": true, + "tips": "起始行号,从1开始,支持负数,-n表示倒数第n行", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "起始行号,从1开始,支持负数,-n表示倒数第n行" + } + }, + { + "name": "stop", + "label": "结束行号", + "required": true, + "tips": "结束行号,从1开始,支持负数,-n表示倒数第n行", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "结束行号,从1开始,支持负数,-n表示倒数第n行" + } + }, + { + "name": "step", + "label": "递增步长", + "required": true, + "default": "10:1", + "tips": null, + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "loop_index", + "label": "循环索引位置", + "type": "int", + "name": "row_index" + } + ] + }, + { + "name": "programing.databook.active", + "title": "激活Sheet页", + "comment": "%mode%激活%workbook%中的Sheet页%value%", + "description": "根据Sheet页的名称或位置激活指定的Sheet页", + "icon": "BlockIcons/5-7.png", + "function": "xbot_visual.programing.databook.active", + "helpUrl": "", + "inputs": [ + { + "name": "mode", + "label": "激活方式", + "required": true, + "default": "10:name", + "defaultDisplay": "根据Sheet页的名称", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据Sheet页的名称", + "value": "name" + }, + { + "display": "根据Sheet页的位置", + "value": "index" + } + ] + } + }, + { + "name": "value", + "label": "Sheet页的名称/位置", + "required": true, + "tips": "填写要打开激活的Sheet页的名称或位置(从1开始)", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "programing.databook.create_sheet", + "title": "添加Sheet页", + "comment": "添加一个Sheet页,%create_way%,命名为%sheet_name%", + "description": "在数据表格面板中添加一个新的sheet页,可以指定在头部添加或尾部添加", + "icon": "BlockIcons/5-9.png", + "function": "xbot_visual.programing.databook.create_sheet", + "helpUrl": "", + "inputs": [ + { + "name": "sheet_name", + "label": "Sheet页名称", + "required": true, + "tips": "请输入sheet页的名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "create_way", + "label": "添加方式", + "required": true, + "default": "10:first", + "defaultDisplay": "作为第一个sheet页", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "作为第一个sheet页", + "value": "first" + }, + { + "display": "作为最后一个sheet页", + "value": "last" + } + ] + } + } + ] + }, + { + "name": "programing.databook.remove_row", + "title": "删除数据表格行", + "keywords": "删除行", + "comment": "删除数据表格中的第%index%行", + "description": "删除行", + "icon": "BlockIcons/5-2.png", + "function": "xbot_visual.programing.databook.remove_row", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/删除行.html", + "video": { + "time": "06:22" + }, + "inputs": [ + { + "name": "index", + "label": "行号", + "required": true, + "tips": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "type": "str", + "editor": { + "placeholder": "输入行号,多行用1,2,3或1:3,-n表示倒数第n行", + "kind": "textbox" + } + } + ] + }, + { + "name": "programing.databook.remove_column", + "title": "删除数据表格列", + "keywords": "删除列", + "comment": "删除数据表格中的第%column_name%列", + "description": "删除列", + "icon": "BlockIcons/5-13.png", + "function": "xbot_visual.programing.databook.remove_column", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/删除列.html", + "video": { + "time": "06:22" + }, + "inputs": [ + { + "name": "column_name", + "label": "列号", + "required": true, + "tips": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "type": "str", + "editor": { + "placeholder": "输入列名(支持A或1),多列用A,B,C或A:C,-n表示倒数第n列", + "kind": "textbox" + } + } + ] + }, + { + "name": "programing.databook.remove_all_rows", + "title": "清空数据表格", + "comment": "删除数据表格中的所有数据", + "description": "清空数据表格", + "icon": "BlockIcons/5-8.png", + "function": "xbot_visual.programing.databook.remove_all_rows", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/清空数据表格.html", + "video": { + "time": "00:32" + } + }, + { + "name": "programing.databook.get_row_count", + "title": "读取数据表格总行数", + "comment": "读取数据表格总行数,将结果保存到%row_count%", + "description": "读取数据表格总行数", + "icon": "BlockIcons/5-5.png", + "function": "xbot_visual.programing.databook.get_row_count", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/读取数据表格总行数.html", + "video": { + "time": "01:43" + }, + "outputs": [ + { + "id": "row_count", + "label": "保存总行数至", + "variableLabel": "数据表格总行数", + "tips": "指定一个变量名称,该变量用于保存总行数", + "type": "int", + "name": "databook_row_count" + } + ] + }, + { + "name": "programing.databook.write_data_to_workbook", + "title": "写入内容至数据表格", + "icon": "BlockIcons/5-1.png", + "comment": "写入内容到数据表格", + "keywords": "写入内容", + "description": "在数据表格写入内容,支持追加、插入或覆盖", + "function": "xbot_visual.programing.databook.write_data_to_workbook", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/写入内容至数据表格.html", + "video": { + "time": "08:04" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.Databook.WriteDataToWorkBookControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.WriteDataToWorkBookHandler" + } + ], + "inputs": [ + { + "name": "write_range", + "label": "写入范围", + "required": true, + "default": "10:area", + "defaultDisplay": "区域", + "tips": "将数据写入到区域(包含单元格)、一行或一列", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "区域", + "value": "area" + }, + { + "display": "行", + "value": "row" + }, + { + "display": "列", + "value": "column" + } + ] + } + }, + { + "name": "write_way", + "label": "写入方式", + "default": "10:append", + "defaultDisplay": "追加一行", + "tips": "提示", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "追加一行", + "value": "append" + }, + { + "display": "插入一行", + "value": "insert" + }, + { + "display": "覆盖一行", + "value": "override" + } + ] + } + }, + { + "name": "write_column_way", + "label": "写入方式", + "default": "10:override", + "defaultDisplay": "覆盖一列", + "tips": "提示", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "追加一列", + "value": "append" + }, + { + "display": "插入一列", + "value": "insert" + }, + { + "display": "覆盖一列", + "value": "override" + } + ] + } + }, + { + "name": "row_num", + "label": "行号", + "default": "10:1", + "tips": "行号", + "type": "int", + "editor": { + "placeholder": "从1开始,支持负数,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "column_name", + "label": "列号", + "tips": "列", + "type": "str", + "editor": { + "placeholder": "A或1代表A列, 支持负数,-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "begin_row_num", + "label": "起始行号", + "default": "10:1", + "category": "advanced", + "tips": "起始行号", + "type": "int", + "editor": { + "placeholder": "输入行号,从1开始,支持负数,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "begin_column_name", + "label": "起始列号", + "category": "advanced", + "default": "10:", + "tips": "起始列号", + "type": "str", + "editor": { + "placeholder": "输入列号,A或1代表A列,支持负数,-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "content", + "label": "写入内容", + "required": true, + "tips": "写入内容", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "programing.databook.read_data_from_workbook", + "title": "读取数据表格内容", + "icon": "BlockIcons/5-6.png", + "comment": "从数据表格中读取单元格(第%cell_row_num%行,第%cell_column_name%列)中的内容,将数据保存到%datatable%", + "description": "从数据表格中读取内容,支持矩形区域范围读取", + "function": "xbot_visual.programing.databook.read_data_from_workbook", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/读取数据表格内容.html", + "video": { + "time": "04:41" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.Databook.ReadDataFromWorkBookControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.ReadDataFromWorkBookHandler" + } + ], + "inputs": [ + { + "name": "read_way", + "label": "读取方式", + "required": true, + "default": "10:cell", + "defaultDisplay": "单元格", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单元格", + "value": "cell" + }, + { + "display": "区域内容", + "value": "range" + }, + { + "display": "行内容", + "value": "row" + }, + { + "display": "列内容", + "value": "column" + } + ] + } + }, + { + "name": "cell_row_num", + "label": "行号", + "required": false, + "default": "10:1", + "tips": "行号", + "type": "int", + "editor": { + "placeholder": "从1开始,支持负数,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "cell_column_name", + "label": "列号", + "required": false, + "default": "10:", + "tips": "列号", + "type": "str", + "editor": { + "placeholder": "A或1代表A列, 支持负数,-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "area_begin_row_num", + "label": "行号", + "required": false, + "default": "10:1", + "tips": "行号", + "type": "int", + "editor": { + "placeholder": "从1开始,支持负数,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "area_begin_column_name", + "label": "列号", + "default": "10:", + "required": false, + "tips": "列号", + "type": "str", + "editor": { + "placeholder": "A或1代表A列,支持负数,-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "area_end_row_num", + "label": "行号", + "required": false, + "default": "10:1", + "tips": "行号", + "type": "int", + "editor": { + "placeholder": "从1开始,支持负数,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "area_end_column_name", + "label": "列号", + "required": false, + "default": "10:", + "tips": "列号", + "type": "str", + "editor": { + "placeholder": "A或1代表A列,支持负数,-n表示倒数第n列", + "kind": "textbox" + } + }, + { + "name": "row_row_num", + "label": "行号", + "required": false, + "default": "10:1", + "tips": "行号", + "type": "int", + "editor": { + "placeholder": "从1开始,支持负数,-n表示倒数第n行", + "kind": "textbox" + } + }, + { + "name": "get_display_text", + "label": "", + "required": false, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "获取单元格的值作为纯文本", + "kind": "checkbox" + } + }, + { + "name": "has_header_row", + "label": "", + "required": false, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "区域第一行包含列名", + "kind": "checkbox" + } + }, + { + "name": "column_column_name", + "label": "列号", + "tips": "列号", + "type": "str", + "default": "10:", + "editor": { + "placeholder": "A或1代表A列,从1开始,支持负数,-n表示倒数第n列", + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "datatable", + "label": "保存区域内容至", + "variableLabel": "数据表格内容", + "tips": "指定一个变量名称,该变量用于保存区域数据内容", + "type": "any", + "name": "datatable" + } + ] + }, + { + "name": "programing.databook.loop_data_from_workbook", + "statement": "excel.forin", + "indent": "1", + "scope": "1", + "isLoop": true, + "title": "循环数据表格内容", + "icon": "BlockIcons/5-10.png", + "comment": "循环数据表格的内容,将每次循环的项保存到%loop_item%", + "description": "循环数据表格的内容,并保存循环项", + "function": "xbot_visual.programing.databook.loop_data_from_workbook_with_return_item_location", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/循环数据表格内容.html", + "video": { + "time": "06:30" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.Databook.ExcelLoopControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.DataTableLoopHandler" + } + ], + "inputs": [ + { + "name": "loop_way", + "label": "循环方式", + "required": true, + "default": "10:used_range", + "defaultDisplay": "循环已使用区域", + "tips": "循环数据表格的方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "循环区域", + "value": "loop_range" + }, + { + "display": "循环行", + "value": "loop_row" + }, + { + "display": "循环列", + "value": "loop_column" + }, + { + "display": "循环已使用区域", + "value": "used_range" + } + ] + } + }, + { + "name": "begin_row_num", + "label": "起始行号", + "default": "10:1", + "tips": "循环开始行号", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "从1开始,支持负数,-n表示倒数第n行" + } + }, + { + "name": "end_row_num", + "label": "结束行号", + "default": "10:-1", + "tips": "循环结束行号", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "从1开始,支持负数,-n表示倒数第n行" + } + }, + { + "name": "begin_column_name", + "label": "起始列号", + "required": false, + "default": "10:", + "tips": "循环开始列号", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "A或1代表A列, 支持负数,-n表示倒数第n列" + } + }, + { + "name": "end_column_name", + "label": "结束列号", + "required": false, + "default": "10:", + "tips": "循环结束列号", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "A或1代表A列,支持负数,-n表示倒数第n列" + } + }, + { + "name": "has_header_row", + "label": "", + "required": false, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "区域第一行包含列名", + "kind": "checkbox" + } + }, + { + "name": "range_begin_row_num", + "label": "行号", + "default": "10:1", + "tips": "循环开始行号", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "从1开始,支持负数,-n表示倒数第n行" + } + }, + { + "name": "range_begin_column_name", + "label": "列号", + "default": "10:", + "required": false, + "tips": "循环起始列号", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "A或1代表A列,支持负数,-n表示倒数第n列" + } + }, + { + "name": "range_end_row_num", + "label": "行号", + "default": "10:-1", + "tips": "循环结束行号", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "从1开始,支持负数,-n表示倒数第n行" + } + }, + { + "name": "range_end_column_name", + "label": "列号", + "default": "10:", + "required": false, + "tips": "循环结束列号", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "A或1代表A列,支持负数,-n表示倒数第n列" + } + }, + { + "name": "get_display_text", + "label": "", + "required": false, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "获取单元格的值作为纯文本", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "loop_item", + "label": "当前循环项保存至", + "variableLabel": "当前循环项数据对象", + "tips": "指定一个变量名称,该变量用于保存数据表格的当前循环项", + "type": "list", + "name": "loop_datatable" + }, + { + "id": "loop_item_rownum", + "label": "当前行号保存至", + "variableLabel": "当前循环项的行号", + "tips": "指定一个变量名称,该变量用于保存数据表格当前循环项的行号", + "type": "int", + "name": "loop_item_rownum" + }, + { + "id": "loop_item_columnname", + "label": "当前列名保存至", + "variableLabel": "当前循环项的列名", + "tips": "指定一个变量名称,该变量用于保存数据表格当前循环项的列名", + "type": "str", + "name": "loop_item_columnname" + } + ] + }, + { + "name": "programing.databook.export_data", + "title": "数据表格导出", + "keywords": "保存数据表格;保存表格", + "comment": "导出数据表格到%folder_source%\\%file_name%,将文件路径保存到%file_path%", + "description": "将数据表格导出为文件", + "icon": "BlockIcons/5-12.png", + "function": "xbot_visual.programing.databook.export_data", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/数据表格导出.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.Databook.ExportDataControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.DataTableExportHandler" + } + ], + "inputs": [ + { + "name": "folder_source", + "label": "文件夹", + "required": true, + "default": "10:desktop", + "defaultDisplay": "桌面", + "tips": "选择保存路径", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "桌面", + "value": "desktop" + }, + { + "display": "下载目录", + "value": "download" + }, + { + "display": "临时目录", + "value": "tmp" + }, + { + "display": "自定义目录", + "value": "custom" + } + ] + } + }, + { + "name": "custom_folder_path", + "label": "文件夹路径", + "tips": "指定文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "file_name", + "label": "文件名称", + "required": true, + "default": "10:影刀数据表格.xlsx", + "tips": "指定文件名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "export_header", + "label": "", + "required": true, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "导出列头信息", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "file_path", + "label": "文件路径", + "variableLabel": "导出的文件路径", + "tips": "指定一个变量名称, 该变量用于保存导出文件的位置", + "type": "str", + "name": "file_path" + } + ] + }, + { + "name": "programing.databook.import_data", + "title": "数据表格导入", + "comment": "导入文件%file_path%的Sheet页%sheet_name%到数据表格", + "description": "导入数据到数据表格", + "icon": "BlockIcons/5-11.png", + "function": "xbot_visual.programing.databook.import_data", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/数据表格导入.html", + "inputs": [ + { + "name": "file_path", + "label": "文件路径", + "required": true, + "tips": "填写要导入的文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "Excel 工作簿|*.xlsx;*.xls;*.xlsm;*.csv" + } + } + }, + { + "name": "sheet_name", + "label": "Sheet页名称", + "required": true, + "default": "10:Sheet1", + "tips": "指定要导入的sheet页名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "import_header", + "label": "", + "required": true, + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "使用第一行数据作为列头", + "kind": "checkbox" + } + } + ] + }, + { + "name": "programing.databook.get_column_info", + "title": "获取列信息", + "comment": "从数据表格中%access_kind%,将结果保存到%databook_column_info%", + "description": "获取列名称、列描述", + "icon": "BlockIcons/5-5.png", + "function": "xbot_visual.programing.databook.get_column_info", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Programing.Databook.GetColumnInfoControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Programing.GetColumnInfoHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/获取列信息.html", + "inputs": [ + { + "name": "access_kind", + "label": "获取方式", + "required": true, + "default": "10:get_column_desc_by_name", + "defaultDisplay": "根据列名称获取列描述", + "tips": "获取方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据列名称获取列描述", + "value": "get_column_desc_by_name" + }, + { + "display": "根据列描述获取列名称", + "value": "get_column_name_by_desc" + } + ] + } + }, + { + "name": "column_name", + "label": "列名称", + "tips": "支持负数,-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "A或1代表A列,支持负数,-n表示倒数第n列" + } + }, + { + "name": "column_desc", + "label": "列描述", + "tips": "列描述", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "databook_column_info", + "label": "保存列信息至", + "variableLabel": "数据表格列信息", + "tips": "指定一个变量名称,该变量用于保存数据表格列信息", + "type": "str", + "name": "databook_column_info" + } + ] + }, + { + "name": "programing.databook.set_column_info", + "title": "设置列信息", + "comment": "将内容%column_desc%设置到数据表格列%column_name%", + "description": "为数据表格列设置描述信息", + "icon": "BlockIcons/5-14.png", + "function": "xbot_visual.programing.databook.set_column_info", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据表格/设置列信息.html", + "inputs": [ + { + "name": "column_name", + "label": "列名称", + "tips": "支持负数,-n表示倒数第n列", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "A或1代表A列,支持负数,-n表示倒数第n列" + } + }, + { + "name": "column_desc", + "label": "列描述", + "tips": "列描述", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/rdp.blocks.json b/src/assert/block_settings/rdp.blocks.json new file mode 100644 index 0000000..9fd7d77 --- /dev/null +++ b/src/assert/block_settings/rdp.blocks.json @@ -0,0 +1,78 @@ +{ + "types": [], + "blocks": [ + { + "name": "win32.lock_screen", + "function": "xbot_visual.win32.lock_screen", + "title": "屏幕锁屏", + "description": "这个指令用于屏幕锁屏", + "comment": "屏幕锁屏", + "icon": "BlockIcons/31-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/锁屏、解锁/屏幕解锁.html" + }, + { + "name": "win32.rdp_lock_screen", + "function": "xbot_visual.win32.rdp_lock_screen", + "title": "屏幕锁屏", + "description": "锁住系统屏幕,确保后续指令能在锁屏状态下正常运行", + "comment": "使用%user_name%账户锁屏", + "icon": "BlockIcons/31-1.png", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Rdp.RDPLockScreenControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/锁屏、解锁/屏幕锁屏.html", + "inputs": [ + { + "name": "user_name", + "label": "用户名", + "required": true, + "tips": "请输入用户名", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "password", + "label": "登录密码", + "required": false, + "tips": "输入登录密码", + "type": "str", + "editor": { + "kind": "password" + } + } + ] + }, + { + "name": "win32.unlock_screen", + "function": "xbot_visual.win32.unlock_screen", + "title": "屏幕解锁", + "description": "解锁系统屏幕,进入系统屏幕", + "comment": "使用%user_name%账户解锁", + "icon": "BlockIcons/31-2.png", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Rdp.UnlockScreenControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/锁屏、解锁/屏幕解锁.html", + "inputs": [ + { + "name": "user_name", + "label": "用户名", + "required": true, + "tips": "请输入用户名", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "password", + "label": "登录密码", + "required": false, + "tips": "输入登录密码", + "type": "str", + "editor": { + "kind": "password" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/resourcesfile.blocks.json b/src/assert/block_settings/resourcesfile.blocks.json new file mode 100644 index 0000000..9202bf5 --- /dev/null +++ b/src/assert/block_settings/resourcesfile.blocks.json @@ -0,0 +1,210 @@ +{ + "types": [], + "blocks": [ + { + "name": "resourcesfile.read", + "function": "xbot_visual.resourcesfile.read", + "title": "读取资源文件内容", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.ResourcesFile.ReadFileControl, ShadowBot.Shell.Development", + "description": "读取资源文件内容", + "icon": "BlockIcons/18-3.png", + "comment": "获取资源文件%file_name%的%read_way%", + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/资源文件/读取资源文件内容.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.ResourcesFile.ReadFileHandler" + } + ], + "inputs": [ + { + "name": "file_name", + "label": "资源文件名", + "required": true, + "tips": "请选择资源文件", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "read_way", + "label": "读取内容", + "required": true, + "default": "10:text", + "defaultDisplay": "文本内容", + "tips": "选择文件的读取方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文本内容", + "value": "text" + }, + { + "display": "二进制内容", + "value": "binary" + } + ] + } + }, + { + "name": "encoding", + "label": "文件编码", + "default": "10:UTF-8", + "defaultDisplay": "UTF-8", + "tips": "选择文本编码", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "默认", + "value": "default" + }, + { + "display": "ANSI", + "value": "ANSI" + }, + { + "display": "GB2312", + "value": "GB2312" + }, + { + "display": "GBK", + "value": "GBK" + }, + { + "display": "UTF-8", + "value": "UTF-8" + } + ] + } + } + ], + "outputs": [ + { + "id": "file_content", + "label": "保存文件内容至", + "variableLabel": "资源文件内容", + "tips": "输入一个名字,用来保存文件内容", + "type": "any", + "name": "file_content" + } + ] + }, + { + "name": "resourcesfile.copy_to", + "title": "拷贝资源文件", + "keywords": "复制资源文件", + "comment": "将资源文件%file_name%的内容拷贝到%dest_file_name%中", + "description": "将资源文件的内容拷贝到指定文件中", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.ResourcesFile.CopyToControl, ShadowBot.Shell.Development", + "icon": "BlockIcons/18-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/资源文件/拷贝资源文件.html", + "function": "xbot_visual.resourcesfile.copy_to", + "inputs": [ + { + "name": "file_name", + "label": "资源文件名", + "required": true, + "tips": "请选择资源文件", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "dest_file_name", + "label": "资源文件拷贝至", + "required": true, + "tips": "需要将资源文件拷贝到的文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "filter": "所有文件 (.*)|*.*" + } + } + }, + { + "name": "copy_way", + "label": "存在同名文件时", + "required": true, + "default": "10:overwrite", + "defaultDisplay": "覆盖", + "tips": "指定当目标文件夹下已存在同名文件时要执行的操作", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "覆盖", + "value": "overwrite" + }, + { + "display": "不要拷贝", + "value": "not_copy" + } + ] + } + } + ] + }, + { + "name": "resourcesfile.get_resourcesfile_path", + "function": "xbot_visual.resourcesfile.get_resourcesfile_path", + "title": "获取资源文件路径", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.ResourcesFile.GetResourcesFilePath, ShadowBot.Shell.Development", + "description": "这个指令用来获取指定资源文件路径, 可用于资源文件的快速获取", + "comment": "获取资源文件%file_name%的路径,将文件路径保存到%file_path%", + "icon": "BlockIcons/18-7.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/资源文件/获取资源文件路径.html", + "inputs": [ + { + "name": "file_name", + "label": "资源文件名", + "required": true, + "tips": "输入资源文件名", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "file_path", + "label": "保存文件路径至", + "variableLabel": "资源文件路径", + "tips": "输入一个名字,用来保存文件路径", + "type": "str", + "name": "file_path" + } + ] + }, + { + "name": "resourcesfile.copy_to_clipboard", + "function": "xbot_visual.resourcesfile.copy_to_clipboard", + "title": "将资源文件添加到剪切板", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.ResourcesFile.CopyToClipboardControl, ShadowBot.Shell.Development", + "description": "用来将资源文件添加到剪切板中,可用于资源文件的快捷发送", + "comment": "将资源文件%file_name%添加到剪切板中", + "icon": "BlockIcons/18-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/流程、应用/资源文件/将资源文件添加到剪切板.html", + "inputs": [ + { + "name": "file_name", + "label": "资源文件名", + "required": true, + "tips": "输入资源文件名", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/sap.element.blocks.json b/src/assert/block_settings/sap.element.blocks.json new file mode 100644 index 0000000..949bc00 --- /dev/null +++ b/src/assert/block_settings/sap.element.blocks.json @@ -0,0 +1,294 @@ +{ + "types": [], + "blocks": [ + { + "name": "win32.element.expand_tree_and_select_node", + "title": "选中树节点(sap)", + "keywords": "选中目标节点", + "description": "扩展树以显示目标节点,然后选中目标节点", + "comment": "在窗口%window%内,选中树%element%的节点%text_path%", + "icon": "BlockIcons/3-3.png", + "function": "xbot_visual.win32.element.expand_tree_and_select_node", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/sap/选中树节点(sap).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择一棵节点树", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "text_path", + "label": "节点路径", + "tips": "填写目标节点的位置路径,如 SAP 菜单/会计核算/控制", + "type": "str", + "editor": { + "placeholder": "目标节点的位置,如 SAP 菜单/会计核算/控制", + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标树出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "tree_item_element", + "label": "保存选中节点元素至", + "variableLabel": "元素对象", + "tips": "指定一个变量名称, 该变量用于保存选中的sap树节点内的指定元素", + "name": "win_element", + "type": "xbot.win32.element.Win32Element" + } + ] + }, + { + "name": "win32.element.get_table_row_count", + "title": "获取表格总行数(sap)", + "description": "获取数据表格总行数", + "comment": "获取数据表格%element%的总行数,将结果保存到%row_count%", + "icon": "BlockIcons/3-3.png", + "function": "xbot_visual.win32.element.get_table_row_count", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/sap/获取表格总行数(sap).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择数据表格 或者 单元格", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标表格出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "row_count", + "label": "保存总行数至", + "variableLabel": "总行数", + "tips": "指定一个变量名称, 该变量用于保存获取到的总行数", + "name": "row_count", + "type": "int" + } + ] + }, + { + "name": "win32.element.get_table_column_count", + "title": "获取表格总列数(sap)", + "description": "获取数据表格总列数", + "comment": "获取数据表格%element%的总列数,将结果保存到%column_count%", + "icon": "BlockIcons/3-3.png", + "function": "xbot_visual.win32.element.get_table_column_count", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/sap/获取表格总列数(sap).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择数据表格 或者 单元格", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标表格出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "column_count", + "label": "保存总列数至", + "variableLabel": "总列数", + "tips": "指定一个变量名称, 该变量用于保存获取到的总列数", + "name": "column_count", + "type": "int" + } + ] + }, + { + "name": "win32.element.get_table_cell_by_rownum_and_columnnum", + "title": "获取单元格(sap)", + "description": "获取表格指定位置的单元格", + "comment": "获取数据表格%element%位于(第%row_num%行,第%column_num%列)处的单元格对象,将对象保存到%table_cell_element%", + "icon": "BlockIcons/3-3.png", + "function": "xbot_visual.win32.element.get_table_cell_by_rownum_and_columnnum", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/sap/获取单元格(sap).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择数据表格 或者 单元格", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "row_num", + "label": "行号", + "required": true, + "tips": "单元格所在行的行号, 从1开始", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "单元格所在行的行号, 从1开始" + } + }, + { + "name": "column_num", + "label": "列号", + "required": true, + "tips": "单元格所在的列的列号, 从1开始", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "单元格所在列的列号, 从1开始" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标表格出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "table_cell_element", + "label": "保存单元格元素至", + "variableLabel": "单元格元素", + "tips": "指定一个变量名称,该变量用于保存获取到的单元格元素", + "name": "table_cell_element", + "type": "xbot.win32.element.Win32Element" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/system.blocks.json b/src/assert/block_settings/system.blocks.json new file mode 100644 index 0000000..1257e0a --- /dev/null +++ b/src/assert/block_settings/system.blocks.json @@ -0,0 +1,746 @@ +{ + "types": [ + { + "name": "xbot_visual.system.LaunchResult", + "localName": "应用启动信息", + "props": [ + { + "name": "pid", + "type": "int", + "label": "进程唯一标识码" + }, + { + "name": "main_window_handle", + "type": "int", + "label": "主窗口句柄" + }, + { + "name": "exit_code", + "type": "int", + "label": "退出码" + } + ] + } + ], + "blocks": [ + { + "name": "system.run_application", + "function": "xbot_visual.system.run_application", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.SystemOperation.RunApplicationControl, ShadowBot.Shell.Development", + "title": "启动程序", + "description": "这个指令用于执行一个程序或者打开一个文件", + "comment": "运行应用或者打开文件,路径为%application_path%", + "icon": "BlockIcons/10-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/启动程序.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.SystemOperation.RunApplicationHandler" + } + ], + "inputs": [ + { + "name": "application_path", + "label": "应用路径", + "required": true, + "tips": "打开一个程序或者文件", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile" + } + } + }, + { + "name": "command_line_arguments", + "label": "命令行参数", + "required": false, + "tips": "程序执行的额外参数", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "working_folder", + "label": "工作目录", + "required": false, + "tips": "进程中命令的工作目录", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "after_application_launch", + "label": "在应用启动之后", + "required": true, + "default": "10:continue", + "defaultDisplay": "继续执行下一条指令", + "tips": "选择是否继续执行指令,或者等待程序执行结束、文件关闭", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "继续执行下一条指令", + "value": "continue" + }, + { + "display": "等待应用执行完成", + "value": "wait_to_complete" + } + ] + } + }, + { + "name": "is_wait_not_more_than", + "label": "", + "required": false, + "default": "13:False", + "tips": "如果不勾选,表示无限等待", + "type": "bool", + "editor": { + "label": "等待时间不超过", + "kind": "checkbox" + } + }, + { + "name": "wait_time", + "label": "等待时间", + "required": false, + "default": "10:10", + "tips": "等待程序执行结束或者文件关闭的最长时间", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "process_id", + "label": "保存进程id至", + "variableLabel": "进程Id", + "tips": "输入一个名称作为保存进程ID,其类型是整数", + "type": "int", + "name": "process_id" + }, + { + "id": "exit_code", + "label": "保存退出码至", + "variableLabel": "退出码", + "tips": "输入一个名称作为保存应用退出码, 其类型是整数,-1表示非正常退出", + "type": "int", + "name": "exit_code" + } + ] + }, + { + "name": "system.run_dos_command", + "function": "xbot_visual.system.run_dos_command", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.SystemOperation.RunDosCommandControl, ShadowBot.Shell.Development", + "title": "运行DOS命令", + "description": "这个指令用于执行DOS命令并返回结果", + "comment": "运行DOS命令%dos_command%,将执行结果保存到%output_info%,将错误信息保存到%err_info%,将退出代码保存到%exit_code%", + "icon": "BlockIcons/10-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/运行dos命令.html", + "inputs": [ + { + "name": "dos_command", + "label": "DOS命令", + "required": false, + "tips": "输入DOS命令字符串", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile" + } + } + }, + { + "name": "working_folder", + "label": "工作目录", + "required": false, + "tips": "进程中命令的工作目录", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "encoding", + "label": "编码格式", + "required": false, + "tips": "设置命令行的文本格式", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "output_info", + "label": "保存执行结果至", + "variableLabel": "DOS执行结果", + "tips": "输入一个名称作为保存DOS命令执行结果", + "type": "str", + "name": "output_info" + }, + { + "id": "err_info", + "label": "保存错误信息至", + "variableLabel": "DOS错误信息", + "tips": "输入一个名称作为保存错误信息", + "type": "str", + "name": "err_info" + }, + { + "id": "exit_code", + "label": "保存退出代码至", + "variableLabel": "DOS退出代码", + "tips": "输入一个名称作为保存退出代码,其类型是整数", + "type": "int", + "name": "exit_code" + } + ] + }, + { + "name": "system.terminal_process", + "function": "xbot_visual.system.terminal_process", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.SystemOperation.TerminalProcessControl, ShadowBot.Shell.Development", + "title": "终止程序", + "description": "这个指令用于终止一个程序", + "comment": "终止程序", + "icon": "BlockIcons/10-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/终止程序.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.SystemOperation.TerminalProcessHandler" + } + ], + "inputs": [ + { + "name": "terminal_way", + "label": "终止方式", + "required": true, + "default": "10:id", + "defaultDisplay": "进程Id", + "tips": "指定通过进程Id或者进程名称来终止进程", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "进程Id", + "value": "id" + }, + { + "display": "进程名称", + "value": "name" + } + ] + } + }, + { + "name": "process_id", + "label": "进程Id", + "required": false, + "tips": "输入你想要终止的进程的Id号", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "process_name", + "label": "进程名称", + "required": false, + "tips": "输入你想要终止的进程的名称,如xxx.exe,如果有多个同名的进程将会全部被关闭", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "system.take_screenshot", + "icon": "BlockIcons/10-4.png", + "description": "对屏幕或者窗口截图,保存到剪切板或者文件", + "comment": "从%image_source%截屏,将图像保存到%save_to%", + "title": "截屏", + "keywords": "截图", + "function": "xbot_visual.system.take_screenshot", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/截屏.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.SystemOperation.TakeScreenshotHandler" + } + ], + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.SystemOperation.TakeScreenshotControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "image_source", + "label": "截屏来源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕", + "tips": "选择一个截屏来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕", + "value": "screen" + }, + { + "display": "窗口对象", + "value": "window" + }, + { + "display": "当前激活窗口", + "value": "foreground_window" + }, + { + "display": "动态选择", + "value": "dynamic_select" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "required": false, + "tips": "请选择窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_region", + "label": "提取区域", + "default": "10:all_region", + "defaultDisplay": "提取区域", + "tips": "选择图片提取区域", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "all_region" + }, + { + "display": "指定部分区域", + "value": "sub_region" + } + ] + } + }, + { + "name": "region_x1", + "label": "X1", + "tips": "图片左上角X值", + "type": "int", + "default": "10:0", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y1", + "label": "Y1", + "tips": "图片左上角Y值", + "type": "int", + "default": "10:0", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_x2", + "label": "X2", + "tips": "图片右下角X值", + "type": "int", + "default": "10:0", + "editor": { + "kind": "textbox" + } + }, + { + "name": "region_y2", + "label": "Y2", + "tips": "图片右下角Y值", + "type": "int", + "default": "10:0", + "editor": { + "kind": "textbox" + } + }, + { + "name": "save_to", + "label": "保存截屏至", + "required": true, + "default": "10:clipboard", + "defaultDisplay": "剪切板", + "tips": "选择一个保存当前截屏的方法", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "剪切板", + "value": "clipboard" + }, + { + "display": "文件", + "value": "file" + } + ] + } + }, + { + "name": "image_path", + "label": "图片路径", + "required": false, + "tips": "请选择图片保存路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "filter": "图片(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png" + } + } + } + ], + "outputs": [ + { + "id": "is_user_cancel", + "label": "用户是否取消截图", + "variableLabel": "截图操作是否取消", + "tips": "输入一个名称作为保存用户是否取消了截图", + "type": "bool", + "name": "is_user_cancel" + } + ] + }, + { + "name": "win32.set_ime", + "icon": "BlockIcons/20-6.png", + "description": "设置当前激活窗口的输入法", + "comment": "设置当前激活窗口的输入法为%lang%", + "title": "设置输入法", + "function": "xbot_visual.win32.set_ime", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/输入法/设置输入法.html", + "inputs": [ + { + "name": "lang", + "label": "切换到", + "required": true, + "default": "10:english", + "defaultDisplay": "英文输入法", + "tips": "选择一个输入法", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "英文输入法", + "value": "english" + }, + { + "display": "中文输入法", + "value": "chinese" + } + ] + } + } + ] + }, + { + "name": "win32.get_ime", + "icon": "BlockIcons/20-7.png", + "description": "获取当前激活窗口的输入法的中英文输入状态", + "comment": "获取当前激活窗口的输入法的中英文输入状态,将结果保存到%lang_name%", + "title": "获取输入法", + "function": "xbot_visual.win32.get_ime", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/输入法/获取输入法.html", + "inputs": [], + "outputs": [ + { + "id": "lang_name", + "label": "将输入法名称保存至", + "variableLabel": "输入法名称", + "tips": "输入一个名称用来保存输入法名称", + "type": "str", + "name": "lang_name" + } + ] + }, + { + "name": "system.open_screen_saver", + "icon": "BlockIcons/actionicon_mask_show.png", + "description": "可在保护屏幕信息不被窥视的状态下执行指令,并可展示自定义的文字提示", + "comment": "唤起屏幕保护,在屏保上显示文字%default_text%", + "title": "唤起屏幕保护", + "keywords": "屏保", + "function": "xbot_visual.system.open_screen_saver", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/屏幕保护/唤起屏幕保护.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.SystemOperation.CreateScreenSaverControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "settings", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "default_text", + "label": "提示文字", + "default": "10:影刀机器人正在工作中,请勿操作此电脑", + "tips": "设置屏保显示文字", + "type": "str", + "editor": { + "kind": "memoedit" + } + } + ] + }, + { + "name": "system.append_screen_saver_text", + "title": "设置屏保提示", + "icon": "BlockIcons/actionicon_mask_text.png", + "description": "设置显示在屏幕保护上的提示文字", + "comment": "在屏保上显示自定义提示内容%text%", + "function": "xbot_visual.system.append_screen_saver_text", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/屏幕保护/设置屏保提示.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.SystemOperation.SetScreenSaverTextControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "text", + "label": "屏保提示", + "required": true, + "tips": "设置屏保显示文字", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "settings", + "label": "提示内容", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "system.clear_screen_saver_text", + "title": "清空屏保提示", + "icon": "BlockIcons/actionicon_mask_clear.png", + "description": "清空屏保上显示的提示", + "comment": "清空屏保上显示的提示", + "function": "xbot_visual.system.clear_screen_saver_text", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/屏幕保护/清空屏保提示.html" + }, + { + "name": "system.close_screen_saver", + "title": "关闭屏幕保护", + "keywords": "屏保", + "icon": "BlockIcons/actionicon_mask_close.png", + "description": "关闭已唤起的屏保", + "comment": "关闭已唤起的屏保", + "function": "xbot_visual.system.close_screen_saver", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/屏幕保护/关闭屏幕保护.html" + }, + { + "name": "system.run_or_open", + "function": "xbot_visual.system.run_or_open", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.SystemOperation.RunOrOpenControl, ShadowBot.Shell.Development", + "title": "运行或打开", + "keywords": "启动;运行;执行;程序;软件", + "description": "运行软件、打开文件、打开文件夹、打开网址、执行系统命令等", + "comment": "运行或打开%application_path%,将执行结果保存到%process_info%", + "icon": "BlockIcons/10-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/运行或打开.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.SystemOperation.RunOrOpenHandler" + } + ], + "inputs": [ + { + "name": "application_path", + "label": "路径或命令", + "required": true, + "tips": "打开一个程序或者文件", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile" + } + } + }, + { + "name": "command_line_arguments", + "label": "参数(可选)", + "required": false, + "tips": "程序执行的额外参数", + "category": "advanced", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "working_folder", + "label": "工作目录(可选)", + "required": false, + "tips": "进程中命令的工作目录", + "category": "advanced", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "after_application_launch", + "label": "在指令执行之后", + "required": true, + "default": "10:continue", + "defaultDisplay": "继续执行下一条指令", + "tips": "选择是否继续执行指令,或者等待程序执行结束、文件关闭", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "继续执行下一条指令", + "value": "continue" + }, + { + "display": "等待主窗口出现", + "value": "wait_to_mainwindow" + }, + { + "display": "等待应用执行完成", + "value": "wait_to_complete" + } + ] + } + }, + { + "name": "is_waitexit_not_more_than", + "label": "", + "default": "13:False", + "tips": "如果不勾选, 表示无限等待", + "type": "bool", + "editor": { + "label": "等待时间不超过", + "kind": "checkbox" + } + }, + { + "name": "timeout_for_exit", + "label": "等待时间", + "default": "10:10", + "tips": "等待程序执行结束或者文件关闭的最长时间", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_waithwnd_not_more_than", + "label": "", + "default": "13:False", + "tips": "如果不勾选, 表示无限等待", + "type": "bool", + "editor": { + "label": "等待时间不超过", + "kind": "checkbox" + } + }, + { + "name": "timeout_for_hwnd", + "label": "等待时间", + "default": "10:3", + "tips": "等待主窗口出现的最长时间", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "start_as_admin", + "label": "", + "default": "13:False", + "tips": "是否以管理员身份运行", + "category": "advanced", + "type": "bool", + "editor": { + "label": "以管理员身份运行", + "kind": "checkbox" + } + }, + { + "name": "window_style", + "label": "窗口风格", + "default": "10:normal", + "defaultDisplay": "普通", + "tips": "指定新窗口应如何显示:普通、最小化、最大化", + "type": "str", + "category": "advanced", + "editor": { + "kind": "select", + "options": [ + { + "display": "普通", + "value": "normal" + }, + { + "display": "最小化", + "value": "minimized" + }, + { + "display": "最大化", + "value": "maximized" + } + ] + } + } + ], + "outputs": [ + { + "id": "process_info", + "label": "保存执行结果至", + "variableLabel": "执行结果", + "tips": "输入一个名称,用于保存执行结果", + "type": "xbot_visual.system.LaunchResult", + "name": "process_info" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/text.blocks.json b/src/assert/block_settings/text.blocks.json new file mode 100644 index 0000000..bab06c5 --- /dev/null +++ b/src/assert/block_settings/text.blocks.json @@ -0,0 +1,976 @@ +{ + "types": [], + "blocks": [ + { + "name": "text.get_text_length", + "function": "xbot_visual.text.get_text_length", + "title": "获取文本长度", + "description": "这个指令用于获取文本字符串的长度", + "comment": "获取文本%text%的长度,将文本长度保存到%text_length%", + "icon": "BlockIcons/12-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/获取文本长度.html", + "inputs": [ + { + "name": "text", + "label": "文本内容", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "text_length", + "label": "保存文本长度至", + "variableLabel": "文本长度", + "tips": "输入一个名字,用来保存文本内容的长度,其返回是一个数字类型", + "type": "int", + "name": "text_length" + } + ] + }, + { + "name": "text.append_text_in_newline", + "function": "xbot_visual.text.append_text_in_newline", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Text.AppendTextInNewlineControl, ShadowBot.Shell.Development", + "title": "追加新文本", + "keywords": "拼接", + "description": "在原始文本后追加新文本内容,完成文本拼接功能", + "comment": "在原始文本%text%后追加新文本%new_line_text%,将结果保存到%result%", + "icon": "BlockIcons/12-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/追加新文本.html", + "inputs": [ + { + "name": "text", + "label": "原始文本", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "new_line", + "label": "", + "required": true, + "tips": "是否换行追加", + "type": "bool", + "default": "13:False", + "editor": { + "label": "换行追加", + "kind": "checkbox" + } + }, + { + "name": "new_line_text", + "label": "追加文本", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "result", + "label": "保存结果至", + "variableLabel": "追加后的文本", + "tips": "输入一个名字,用来保存结果。当变量名字与原始文本变量名相同的话,就会发生覆盖。", + "type": "str", + "name": "result" + } + ] + }, + { + "name": "text.sub_text", + "function": "xbot_visual.text.sub_text", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Text.GetSubTextControl, ShadowBot.Shell.Development", + "title": "截取一段文本", + "description": "这个指令用于截取一段文本", + "comment": "截取文本%text%的子内容,将结果保存到%sub_text%", + "icon": "BlockIcons/12-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/截取一段文本.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Text.GetSubTextHandler" + } + ], + "inputs": [ + { + "name": "text", + "label": "文本内容", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "start_way", + "label": "起始位置", + "required": true, + "default": "10:begin", + "defaultDisplay": "第一个字符", + "tips": "指定起始字符的位置,如果你想要在文本'Hello中国欢迎你'中提取'中国'两个字',那么起始位置就是5", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "从第一个字符开始截取", + "value": "begin" + }, + { + "display": "从指定位置开始截取", + "value": "positon" + }, + { + "display": "从指定文本开始截取", + "value": "text" + } + ] + } + }, + { + "name": "start_index", + "label": "起始字符的位置", + "required": false, + "default": "10:0", + "tips": "如果你想要在文本'Hello中国欢迎你'中提取'中国'两个字',那么起始位置就是5", + "type": "int", + "editor": { + "kind": "textbox", + "placeholder": "位置从0开始计算" + } + }, + { + "name": "start_text", + "label": "起始文本", + "required": false, + "tips": "如果你想要在文本“购买订单号:1234567890”中提取订单号,那么起始位置就是“:”", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "输入需要截取的起始文本内容" + } + }, + { + "name": "contaion_start_text", + "label": "", + "default": "13:True", + "tips": "勾选时,结果中包含起始文本,例如:“购买订单号:1234567890”,起始文本设置为“:”,勾选后结果为“:1234567890”,不勾选结果为“1234567890”", + "type": "bool", + "editor": { + "label": "结果中包含起始文本", + "kind": "checkbox" + } + }, + { + "name": "sub_way", + "label": "截取方式", + "required": true, + "default": "10:end", + "defaultDisplay": "截取到最后一个字符", + "tips": "如果你想要在文本'Hello中国欢迎你'中提取'中国'两个字',那么起始位置就是5,截取长度为2,代表从第6个字符开始要截取两个字符", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "截取到最后一个字符", + "value": "end" + }, + { + "display": "截取指定长度", + "value": "length" + } + ] + } + }, + { + "name": "sub_length", + "label": "截取长度", + "default": "10:0", + "required": false, + "tips": "输入你要截取的字符数量", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "sub_text", + "label": "保存结果至", + "variableLabel": "截取到的文本内容", + "tips": "输入一个名字,用来保存截取到的文本内容", + "type": "str", + "name": "sub_text" + } + ] + }, + { + "name": "text.pad_text", + "function": "xbot_visual.text.pad_text", + "title": "补齐文本至指定长度", + "description": "这个指令用于补齐文本至指定长度", + "comment": "在原始文本%text%的%pad_way%文本%pad_text%,直至补齐后的总长度为%total_length%,将结果保存到%result_text%", + "icon": "BlockIcons/12-4.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/补齐文本至指定长度.html", + "inputs": [ + { + "name": "text", + "label": "原始文本", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "pad_way", + "label": "补齐方式", + "required": true, + "default": "10:left", + "defaultDisplay": "左端补齐", + "tips": "在原始文本的左端或者右端添加补齐文本", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "左端补齐", + "value": "left" + }, + { + "display": "右端补齐", + "value": "right" + } + ] + } + }, + { + "name": "pad_text", + "label": "用于补齐的文本", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "total_length", + "label": "总长度", + "required": true, + "tips": "如果你要在数字1的左端补齐2个0,那么补齐后的内容就是001,总长度就是3", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "result_text", + "label": "保存结果至", + "variableLabel": "补齐后的文本", + "tips": "输入一个名字,用来保存补齐后的文本内容", + "type": "str", + "name": "result_text" + } + ] + }, + { + "name": "text.trim_text", + "function": "xbot_visual.text.trim_text", + "title": "删除文本两端的空格", + "description": "这个指令用于删除文本两端的空格(还包括换行符、回车符、制表符)", + "comment": "删除文本%text%中%trim_way%,将结果保存到%trim_text%", + "icon": "BlockIcons/12-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/删除文本两端的空格.html", + "inputs": [ + { + "name": "text", + "label": "原始文本", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "trim_way", + "label": "删除方式", + "required": true, + "default": "10:left", + "defaultDisplay": "左端的空格", + "tips": "选择你要删除文本哪一侧的空格", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "左端的空格", + "value": "left" + }, + { + "display": "右端的空格", + "value": "right" + }, + { + "display": "两端的空格", + "value": "both" + } + ] + } + } + ], + "outputs": [ + { + "id": "trim_text", + "label": "保存结果至", + "variableLabel": "删除空格后的文本", + "tips": "输入一个名字,用来保存删除空格后的文本内容", + "type": "str", + "name": "trim_text" + } + ] + }, + { + "name": "text.change_text_case", + "function": "xbot_visual.text.change_text_case", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Text.ChangeTextCaseHandler" + } + ], + "title": "改变文本的大小写", + "description": "这个指令用于改变文本的大小写(全部大写、全部小写、词首字母大写)", + "comment": "将文本%text%转换成%case_type%,将结果保存到%text_case%", + "icon": "BlockIcons/12-6.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/改变文本的大小写.html", + "inputs": [ + { + "name": "text", + "label": "文本内容", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "case_type", + "label": "转换成", + "required": true, + "default": "10:upper", + "defaultDisplay": "全部大写", + "tips": "选择一个转换方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部大写", + "value": "upper" + }, + { + "display": "全部小写", + "value": "lower" + }, + { + "display": "词首字母大写", + "value": "title" + } + ] + } + } + ], + "outputs": [ + { + "id": "text_case", + "label": "保存结果至", + "variableLabel": "转换大小写后的文本", + "tips": "输入一个名字,用来保存转换大小写后的文本内容", + "type": "str", + "name": "text_case" + } + ] + }, + { + "name": "text.text_to_number", + "function": "xbot_visual.text.text_to_number", + "title": "文本转数字", + "description": "这个指令用于将文本形式的数字转换成一个包含数字的变量", + "comment": "将文本%text%转换成数字,将结果保存到%text_number%", + "icon": "BlockIcons/12-7.png", + "helpUrl": "", + "inputs": [ + { + "name": "text", + "label": "文本内容", + "required": true, + "tips": "输入文本字符串或者一个变量", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "text_number", + "label": "保存结果至", + "variableLabel": "文本转换成的数字", + "tips": "输入一个变量名字,用来保存数字结果", + "type": "int", + "name": "text_number" + } + ] + }, + { + "name": "text.number_to_text", + "function": "xbot_visual.text.number_to_text", + "title": "数字转文本", + "description": "这个指令用于将数字转换成指定格式的文本", + "comment": "将数字%num%转换成文本,将结果保存到%formatted_number%", + "icon": "BlockIcons/12-8.png", + "helpUrl": "", + "inputs": [ + { + "name": "num", + "label": "待转换的数字", + "required": true, + "tips": "请输入一个数字或者一个变量", + "type": "float", + "editor": { + "kind": "textbox" + } + }, + { + "name": "float_places", + "label": "小数位数", + "default": "10:2", + "required": true, + "tips": "请输入一个数字或者一个变量", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_1000_separator", + "label": "", + "required": true, + "default": "13:False", + "tips": "例如数字 10000 用千分位分割显示的话就是 10,000", + "type": "bool", + "editor": { + "label": "千分位分割", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "formatted_number", + "label": "保存结果至", + "variableLabel": "数字转换成的文本", + "tips": "输入一个变量名字,用来保存格式化后的结果", + "type": "str", + "name": "formatted_number" + } + ] + }, + { + "name": "text.join_list_to_text", + "function": "xbot_visual.text.join_list_to_text", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Text.JoinListToTextControl, ShadowBot.Shell.Development", + "title": "列表聚合成文本", + "keywords": "列表转文本", + "description": "这个指令用于将列表中的每个元素用指定的符号连接起来,最终转换成一个文本字符串", + "comment": "用连接符连接列表%list_to_join%中的每个元素,将文本结果保存到%joined_text%", + "icon": "BlockIcons/12-7.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/列表聚合成文本.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Text.JoinListToTextHandler" + } + ], + "inputs": [ + { + "name": "list_to_join", + "label": "待转换的列表", + "required": true, + "tips": "请输入一个列表", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "delimiter_way", + "label": "连接符类型", + "required": true, + "default": "10:no", + "defaultDisplay": "无连接符", + "tips": "选择一种连接符类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "无连接符", + "value": "no" + }, + { + "display": "标准连接符", + "value": "standard" + }, + { + "display": "自定义连接符", + "value": "custom" + } + ] + } + }, + { + "name": "standard_delimiter", + "label": "标准连接符", + "required": false, + "default": "10:space", + "defaultDisplay": "空格符", + "tips": "选择一种连接符", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "空格符", + "value": "space" + }, + { + "display": "制表符", + "value": "tab" + }, + { + "display": "换行符", + "value": "new_line" + } + ] + } + }, + { + "name": "num_standard_delimiter", + "label": "连接符的数量", + "required": false, + "default": "10:1", + "tips": "连接符的重复数量", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "custom_delimiter", + "label": "自定义的连接符", + "required": false, + "default": "10:", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "joined_text", + "label": "保存结果至", + "variableLabel": "列表转换成的文本", + "tips": "输入一个变量名字,用来保存列表转换后的文本", + "type": "str", + "name": "joined_text" + } + ] + }, + { + "name": "text.split_text_to_list", + "function": "xbot_visual.text.split_text_to_list", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Text.SplitTextToListControl, ShadowBot.Shell.Development", + "title": "文本分割成列表", + "keywords": "文本转列表", + "description": "这个指令使用指定分隔符号,将目标文本分割成一个列表", + "comment": "用%delimiter_way%分割字符串%text_to_split%,将结果列表保存到%splited_list%", + "icon": "BlockIcons/12-8.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/文本分割成列表.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Text.SplitTextToListHandler" + } + ], + "inputs": [ + { + "name": "text_to_split", + "label": "待转换的文本", + "required": true, + "tips": "请输入文本字符串或者选择一个包含字符串的变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "delimiter_way", + "label": "分隔符类型", + "required": true, + "default": "10:standard", + "defaultDisplay": "标准分隔符", + "tips": "选择一种列表的分隔方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "标准分隔符", + "value": "standard" + }, + { + "display": "自定义分隔符", + "value": "custom" + } + ] + } + }, + { + "name": "standard_delimiter", + "label": "标准分隔符", + "required": false, + "default": "10:space", + "defaultDisplay": "空格符", + "tips": "选择一种列表的分隔方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "空格符", + "value": "space" + }, + { + "display": "制表符", + "value": "tab" + }, + { + "display": "换行符", + "value": "new_line" + } + ] + } + }, + { + "name": "num_standard_delimiter", + "label": "分隔符的数量", + "required": false, + "default": "10:1", + "tips": "分隔符的重复数量", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "custom_delimiter", + "label": "自定义的分隔符", + "required": false, + "default": "10:", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_regular_expression", + "label": "", + "required": false, + "tips": "是否正则表达式", + "type": "bool", + "default": "13:False", + "editor": { + "label": "正则表达式", + "kind": "checkbox" + } + }, + { + "name": "remove_empty", + "label": "", + "required": true, + "tips": "是否过滤空白项", + "type": "bool", + "default": "13:False", + "editor": { + "label": "过滤空白项", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "splited_list", + "label": "保存结果至", + "variableLabel": "文本切割后的列表", + "tips": "输入一个变量名字,用来保存文本转换后的列表", + "type": "list", + "name": "splited_list" + } + ] + }, + { + "name": "text.extract_content_from_text", + "function": "xbot_visual.text.extract_content_from_text", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Text.ExtractContentFromTextControl, ShadowBot.Shell.Development", + "title": "从文本中提取内容", + "keywords": "正则;提取文本;文本提取", + "description": "根据正则表达式从文本中提取指定内容", + "comment": "从文本%text%中%extract_way%,将内容保存到%content%", + "icon": "BlockIcons/12-9.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/从文本中提取内容.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Text.ExtractContentFromTextHandler" + } + ], + "inputs": [ + { + "name": "text", + "label": "文本内容", + "required": true, + "tips": "请输入文本字符串或者选择一个包含字符串的变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "extract_way", + "label": "提取方式", + "required": true, + "default": "10:number", + "defaultDisplay": "提取数字", + "tips": "选择一种内容的提取方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "提取数字", + "value": "number" + }, + { + "display": "提取手机号码", + "value": "mobile_phone" + }, + { + "display": "提取Email地址", + "value": "email" + }, + { + "display": "提取身份证号", + "value": "id_card" + }, + { + "display": "提取自定义内容", + "value": "custom" + } + ] + } + }, + { + "name": "regular_pattern", + "label": "正则表达式", + "required": true, + "tips": "请输入一段正则表达式", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "just_get_first", + "label": "", + "required": true, + "default": "13:True", + "tips": "例如在文本中找到了两个手机号,你可以只取第一个", + "type": "bool", + "editor": { + "label": "只找第一个匹配项", + "kind": "checkbox" + } + }, + { + "name": "ignore_case", + "label": "", + "required": true, + "default": "13:False", + "tips": "在字符串匹配时,是否忽略大小写", + "type": "bool", + "editor": { + "label": "忽略大小写", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "content", + "label": "保存结果至", + "variableLabel": "提取到的内容", + "tips": "输入一个变量名字,用来保存提取到的内容", + "type": "str", + "name": "content" + } + ] + }, + { + "name": "text.replace_content_from_text", + "function": "xbot_visual.text.replace_content_from_text", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Text.ReplaceContentFromText, ShadowBot.Shell.Development", + "title": "文本替换", + "keywords": "正则", + "description": "替换文本中的指定内容", + "comment": "将文本%text%中的内容%replace_text%用%dest_text%替换,将结果保存到%replace_content%", + "icon": "BlockIcons/12-9.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/数据处理/文本操作/文本替换.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Text.ReplaceContentFromTextHandler" + } + ], + "inputs": [ + { + "name": "text", + "label": "内容源", + "required": true, + "tips": "请输入文本字符串或者选择一个包含字符串的变量", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "regular_pattern", + "label": "正则表达式", + "tips": "请输入一段正则表达式", + "type": "str", + "editor": { + "kind": "PlainText" + } + }, + { + "name": "replace_way", + "label": "替换方式", + "required": true, + "default": "10:content", + "defaultDisplay": "替换内容", + "tips": "选择一种内容的提取方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "替换内容", + "value": "content" + }, + { + "display": "替换数字", + "value": "number" + }, + { + "display": "替换手机号", + "value": "mobile_phone" + }, + { + "display": "替换email", + "value": "email" + }, + { + "display": "替换身份证", + "value": "id_card" + }, + { + "display": "自定义正则替换", + "value": "custom" + } + ] + } + }, + { + "name": "replace_text", + "label": "被替换内容", + "tips": "请输入要被替换的内容", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "just_get_first", + "label": "", + "required": true, + "default": "13:True", + "tips": "例如在文本中找到了两个手机号,你可以只替换第一个", + "type": "bool", + "editor": { + "label": "只替换第一个匹配项", + "kind": "checkbox" + } + }, + { + "name": "ignore_case", + "label": "", + "required": true, + "default": "13:False", + "tips": "在字符串匹配时,是否忽略大小写", + "type": "bool", + "editor": { + "label": "忽略大小写", + "kind": "checkbox" + } + }, + { + "name": "dest_text", + "label": "替换为", + "required": false, + "tips": "请输入替换后的值", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "replace_content", + "label": "保存结果至", + "variableLabel": "替换后的文本", + "tips": "输入一个变量名字,用来保存替换后的内容", + "type": "str", + "name": "replace_content" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/visual.activities.xml b/src/assert/block_settings/visual.activities.xml new file mode 100644 index 0000000..d8e866d --- /dev/null +++ b/src/assert/block_settings/visual.activities.xml @@ -0,0 +1,500 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assert/block_settings/web.blocks.json b/src/assert/block_settings/web.blocks.json new file mode 100644 index 0000000..908f429 --- /dev/null +++ b/src/assert/block_settings/web.blocks.json @@ -0,0 +1,1819 @@ +{ + "types": [ + { + "name": "xbot._web.browser.WebBrowser", + "localName": "网页对象", + "pythonName": "xbot.web.chrome.ChromeBrowser,xbot.web.ie.IEBrowser,xbot.web.cef.CEFBrowser", + "methods": [ + { + "display": "该网页的地址", + "function": "$0.get_url()", + "type": "str" + }, + { + "display": "该网页的标题", + "function": "$0.get_title()", + "type": "str" + } + ] + } + ], + "blocks": [ + { + "name": "web.create", + "title": "打开网页", + "keywords": "打开网站;打开网址", + "icon": "BlockIcons/1-1.png", + "comment": "在%web_type%中新建标签页%value%,将网页对象保存到%browser%,网页加载超时后执行%stop_load_if_load_timeout%操作", + "description": "使用指定浏览器打开网页,以实现网页自动化", + "function": "xbot_visual.web.create", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/打开网页.html", + "video": { + "time": "04:47" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.CreateBrowserControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.CreateHandler" + } + ], + "inputs": [ + { + "name": "web_type", + "label": "浏览器类型", + "required": true, + "tips": "选择浏览器类型, Google Chrome 浏览器、Microsoft Edge 浏览器需要安装影刀插件才能实现自动化, 另外, 如 Chrome、Edge 或 IE 安装路径非默认系统盘,需要在\"高级\"选项中设置安装路径", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "value", + "label": "网址", + "required": true, + "tips": "输入需要打开的网页地址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "silent_running", + "label": "运行时不抢占鼠标键盘", + "required": true, + "category": "advanced", + "tips": "对该网页的后续操作采用API方式执行,将提升稳定性并避免占用鼠标和键盘", + "default": "13:False", + "type": "bool", + "editor": { + "label": "运行时不抢占鼠标键盘", + "kind": "checkbox" + } + }, + { + "name": "wait_load_completed", + "label": "", + "required": true, + "category": "advanced", + "default": "13:True", + "tips": "是否等待网页加载完成", + "type": "bool", + "editor": { + "label": "等待网页加载完成", + "kind": "checkbox" + } + }, + { + "name": "load_timeout", + "label": "加载超时时间", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待网页加载完成的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "stop_load_if_load_timeout", + "label": "加载超时后执行", + "required": true, + "category": "advanced", + "tips": "等待网页加载完成超时后希望执行的操作", + "type": "str", + "default": "10:handleExcept", + "defaultDisplay": "执行\"错误处理\"", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "执行\"错误处理\"", + "value": "handleExcept" + }, + { + "display": "停止网页加载", + "value": "stopLoad" + } + ] + } + }, + { + "name": "chrome_file_name", + "label": "chrome执行文件路径", + "required": false, + "category": "advanced", + "tips": "我们会默认在目录C:\\Program Files (x86)\\Google\\Chrome\\Application\\.下启动chrome.exe,也可以在这里手动配置chrome.exe文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "exe files (*.exe)|*.exe" + } + } + }, + { + "name": "edge_file_name", + "label": "edge执行文件路径", + "required": false, + "category": "advanced", + "tips": "我们会默认在目录C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\.下启动msedge.exe,也可以在这里手动配置msedge.exe文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "exe files (*.exe)|*.exe" + } + } + }, + { + "name": "ie_file_name", + "label": "ie执行文件路径", + "required": false, + "category": "advanced", + "tips": "我们会默认在目录C:\\Program Files\\Internet Explorer\\.下启动iexplore.exe,也可以在这里手动配置iexplore.exe文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "exe files (*.exe)|*.exe" + } + } + }, + { + "name": "bro360_file_name", + "label": "360执行文件路径", + "required": false, + "category": "advanced", + "tips": "我们会在默认目录下启动360se.exe, 也可以在这里手动配置360se.exe文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "exe files (*.exe)|*.exe" + } + } + }, + { + "name": "firefox_file_name", + "label": "firefox执行文件路径", + "required": false, + "category": "advanced", + "tips": "我们会在默认目录下启动firefox.exe, 也可以在这里手动配置firefox.exe文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "exe files (*.exe)|*.exe" + } + } + }, + { + "name": "arguments", + "label": "命令行参数", + "tips": "命令行参数, 必须是目标浏览器支持的命令行, 可为空", + "category": "advanced", + "type": "str", + "editor": { + "placeholder": "目标浏览器支持的命令行可空", + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "browser", + "label": "保存网页对象至", + "variableLabel": "新打开网页的对象", + "tips": "该变量保存的是网页对象,使用此网页对象可以对网页进行自动化操作", + "name": "web_page", + "type": "xbot._web.browser.WebBrowser" + } + ] + }, + { + "name": "web.get", + "title": "获取已打开的网页对象", + "icon": "BlockIcons/1-2.png", + "comment": "在%web_type%中获取已打开的网页对象%value%, 并将网页对象保存至变量%browser%, 网页加载超时后执行 %stop_load_if_load_timeout% 操作", + "description": "获取网址或标题匹配已打开的网页,或者获取当前浏览器选中的网页", + "function": "xbot_visual.web.get", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/获取已打开的网页对象.html", + "video": { + "time": "07:16" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetBrowserControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetBrowserHandler" + } + ], + "inputs": [ + { + "name": "web_type", + "label": "浏览器类型", + "required": true, + "tips": "选择浏览器类型, Google Chrome 浏览器、Microsoft Edge 浏览器需要安装影刀插件才能实现自动化", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "mode", + "label": "匹配方式", + "required": true, + "default": "10:activated", + "defaultDisplay": "匹配当前选中的网页", + "tips": "选择获取已打开网页的匹配方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据标题匹配", + "value": "title" + }, + { + "display": "根据网址匹配", + "value": "url" + }, + { + "display": "匹配当前选中的网页", + "value": "activated" + } + ] + } + }, + { + "name": "value", + "label": "标题", + "required": false, + "tips": "填写要匹配的网页标题或地址,支持模糊匹配", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "silent_running", + "label": "运行时不抢占鼠标键盘", + "required": true, + "category": "advanced", + "tips": "对该网页的后续操作采用API方式执行,将提升稳定性并避免占用鼠标和键盘", + "default": "13:True", + "type": "bool", + "editor": { + "label": "运行时不抢占鼠标键盘", + "kind": "checkbox" + } + }, + { + "name": "wait_load_completed", + "label": "", + "required": true, + "category": "advanced", + "default": "13:True", + "tips": "是否等待网页加载完成", + "type": "bool", + "editor": { + "label": "等待网页加载完成", + "kind": "checkbox" + } + }, + { + "name": "load_timeout", + "label": "超时时间(秒)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待网页加载完成的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "stop_load_if_load_timeout", + "label": "超时后执行 ", + "required": true, + "category": "advanced", + "tips": "等待网页加载完成超时后希望执行的操作", + "type": "str", + "default": "10:handleExcept", + "defaultDisplay": "执行\"错误处理\"", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "执行\"错误处理\"", + "value": "handleExcept" + }, + { + "display": "停止网页加载", + "value": "stopLoad" + } + ] + } + }, + { + "name": "open_page", + "label": "", + "required": true, + "category": "advanced", + "default": "13:False", + "tips": "根据网页标题或网址匹配失败时,打开新网页", + "type": "bool", + "editor": { + "label": "匹配失败时打开新网页", + "kind": "checkbox" + } + }, + { + "name": "url", + "label": "新网址", + "required": false, + "category": "advanced", + "tips": "打开新网页的网址", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "browser", + "label": "保存网页对象至", + "variableLabel": "网页对象", + "tips": "该变量保存的是网页对象,使用此网页对象可以对网页进行自动化操作", + "name": "web_page", + "type": "xbot._web.browser.WebBrowser" + } + ], + "exception_handling": { + "logging": true, + "mode": "retry", + "retryTime": 3, + "retryInterval": 3 + } + }, + { + "name": "web.get_all", + "title": "获取网页对象列表", + "icon": "BlockIcons/1-2.png", + "comment": "在%web_type%中获取已打开且满足筛选条件的网页对象列表%value%,将该列表保存到%browser_list%,列表中每一个网页加载超时后执行%stop_load_if_load_timeout%操作", + "description": "获取已打开的网页对象列表,以实现批量对每个网页相关自动化操作", + "function": "xbot_visual.web.get_all", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/网页操作/获取网页对象列表.html", + "video": { + "time": "02:37" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetAllBrowsersControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetALLBrowsersHandler" + } + ], + "inputs": [ + { + "name": "web_type", + "label": "浏览器类型", + "required": true, + "tips": "选择浏览器类型, Google Chrome 浏览器、Microsoft Edge 浏览器需要安装影刀插件才能实现自动化", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "mode", + "label": "匹配方式", + "required": true, + "default": "10:title", + "defaultDisplay": "匹配所有网页", + "tips": "选择获取已打开网页的匹配方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "匹配所有网页", + "value": "all" + }, + { + "display": "根据标题匹配", + "value": "title" + }, + { + "display": "根据网址匹配", + "value": "url" + } + ] + } + }, + { + "name": "value", + "label": "标题", + "required": false, + "tips": "填写要匹配的网页标题或地址,支持模糊匹配,不填则匹配所有网页", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "browser_list", + "label": "保存网页对象列表至", + "variableLabel": "网页对象列表", + "tips": "该变量保存的是网页对象列表,使用此网页对象列表可以对每个网页进行自动化操作", + "name": "web_page_list", + "type": "list" + } + ] + }, + { + "name": "web.get_cookies", + "title": "获取筛选所有Cookie", + "icon": "BlockIcons/3-12.png", + "comment": "从单个 cookie store 中获取与给定信息匹配的所有 cookie 集合", + "description": "从单个 cookie store 中获取与给定信息匹配的所有 cookie 集合", + "function": "xbot_visual.web.get_cookies", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取筛选所有cookie.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetCookiesControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetCookiesHandler" + } + ], + "inputs": [ + { + "name": "url_type", + "label": "url 指定方式", + "required": true, + "default": "10:auto", + "defaultDisplay": "网页对象", + "tips": "用来筛选 cookies 的 url 来源, 可选择手动输入, 如果选择网页对象,则自动使用网页 url 进行筛选", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据网页对象", + "value": "auto" + }, + { + "display": "根据输入的url", + "value": "manual" + } + ] + } + }, + { + "name": "browser", + "label": "网页对象", + "required": false, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "web_type", + "label": "浏览器类型", + "required": false, + "tips": "获取指定类型浏览器 cookie", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "url", + "label": "筛选cookie url", + "required": false, + "tips": "根据是否与给定的 URL 比如 'https://www.winrobot360.com'匹配, 筛选浏览器 cookie (url为必填项)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "name", + "label": "筛选cookie name", + "required": false, + "category": "advanced", + "tips": "根据是否与给定的 name 匹配, 筛选 cookie (值为空则忽略 name筛选条件)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "domain", + "label": "筛选cookie domain", + "required": false, + "category": "advanced", + "tips": "根据是否完全与给定的 domain 比如 '.winrobot360.com'匹配, 或是否是其子域名, 筛选 cookie (浏览器类型为IE或值为空则忽略 domain筛选条件)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "path", + "label": "筛选cookie path", + "required": false, + "category": "advanced", + "tips": "根据是否与给定的 path 比如 '/', 筛选 cookie (浏览器类型为IE或值为空则忽略 path筛选条件)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "filter_secure", + "label": "", + "required": true, + "category": "advanced", + "default": "13:False", + "tips": "筛选 secure=true cookie 或 secure=fasle cookie(浏览器类型为IE则忽略该设置)", + "type": "bool", + "editor": { + "label": "根据 Cookie secure 属性筛选", + "kind": "checkbox" + } + }, + { + "name": "secure", + "label": "", + "required": false, + "category": "advanced", + "default": "13:False", + "tips": "勾选则筛选 secure cookie 集合, 取消勾选则获取非 secure cookie 集合(浏览器类型为IE则忽略该设置)", + "type": "bool", + "editor": { + "label": "仅 secure Cookie", + "kind": "checkbox" + } + }, + { + "name": "filter_session", + "label": "", + "required": true, + "category": "advanced", + "default": "13:False", + "tips": "筛选会话 cookie 或永久性 cookie(浏览器类型为IE则忽略该设置)", + "type": "bool", + "editor": { + "label": "根据 Cookie 生命周期筛选", + "kind": "checkbox" + } + }, + { + "name": "session", + "label": "", + "required": false, + "category": "advanced", + "default": "13:False", + "tips": "勾选则筛选会话 cookie 集合, 取消勾选则筛选永久性 cookie 集合(浏览器类型为IE则忽略该设置)", + "type": "bool", + "editor": { + "label": "仅会话 Cookie", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "cookie_list", + "label": "保存cookie列表至", + "tips": "指定一个变量名称,该变量用于保存获取到的 cookie 列表,列表项键包括'domain'、'expirationDate'、'name'、'value'、'httpOnly'...(ie只包括name, value), 集合中的值可以通过比如 item['value'] 的方式获取", + "name": "cookie_list", + "type": "list" + } + ] + }, + { + "name": "web.get_cookies_v2", + "title": "获取筛选所有Cookie", + "icon": "BlockIcons/3-12.png", + "comment": "从单个 cookie store 中获取与给定信息匹配的所有 cookie 集合", + "description": "从单个 cookie store 中获取与给定信息匹配的所有 cookie 集合", + "function": "xbot_visual.web.get_cookies_v2", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取筛选所有cookie.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetCookiesV2Control, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetCookiesV2Handler" + } + ], + "inputs": [ + { + "name": "web_type", + "label": "浏览器类型", + "required": true, + "tips": "获取指定类型浏览器 cookie", + "type": "str", + "default": "10:chrome", + "defaultDisplay": "Google Chrome浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "url", + "label": "筛选 cookie url", + "required": false, + "tips": "根据给定的 URL 比如 'https://www.winrobot360.com' 筛选cookie, 值为空则忽略 url筛选条件 (IE 不能为空)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "name", + "label": "筛选 cookie name", + "required": false, + "tips": "根据给定的 name 筛选 cookie, 值为空则忽略 name筛选条件", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "domain", + "label": "筛选 cookie domain", + "required": false, + "tips": "根据给定的 domain 比如'.winrobot360.com'筛选 cookie, 值为空则忽略 domain 筛选条件", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "path", + "label": "筛选 cookie path", + "required": false, + "tips": "根据给定的 path 筛选 cookie, 值为空则忽略 path筛选条件", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "partition_key", + "label": "筛选 partition key", + "required": false, + "tips": "根据给定的 paritition_key 筛选 cookie, 值为空则忽略 partition key 筛选条件(仅支持 Chrome/Edge 119、firefox 94 及之后版本)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "filter_secure", + "label": "", + "required": true, + "category": "advanced", + "default": "13:False", + "tips": "筛选 secure=true cookie 或 secure=fasle cookie", + "type": "bool", + "editor": { + "label": "根据 Cookie secure 属性筛选", + "kind": "checkbox" + } + }, + { + "name": "secure", + "label": "", + "required": false, + "category": "advanced", + "default": "13:False", + "tips": "勾选则筛选 secure cookie, 取消勾选则获取非 secure cookie", + "type": "bool", + "editor": { + "label": "仅 secure Cookie", + "kind": "checkbox" + } + }, + { + "name": "filter_session", + "label": "", + "required": true, + "category": "advanced", + "default": "13:False", + "tips": "筛选会话 cookie 或永久性 cookie", + "type": "bool", + "editor": { + "label": "根据 Cookie 生命周期筛选", + "kind": "checkbox" + } + }, + { + "name": "session", + "label": "", + "required": false, + "category": "advanced", + "default": "13:False", + "tips": "勾选则筛选会话 cookie 集合, 取消勾选则筛选永久性 cookie 集合", + "type": "bool", + "editor": { + "label": "仅会话 Cookie", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "cookie_list", + "label": "保存cookie列表至", + "tips": "指定一个变量名称,该变量用于保存获取到的 cookie 列表,列表项键包括'domain'、'expirationDate'、'name'、'value'、'httpOnly'...(ie只包括name, value), 集合中的值可以通过比如 item['value'] 的方式获取", + "name": "cookie_list", + "type": "list" + } + ] + }, + { + "name": "web.get_cookie", + "title": "获取指定Cookie信息", + "icon": "BlockIcons/3-12.png", + "comment": "获取指定 cookie 信息", + "description": "如果指定的 URL 存在多个相同 name 的 cookie,则返回 path 最长的 cookie。若 path 长度相同,返会创建时间较早的 cookie", + "function": "xbot_visual.web.get_cookie", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取指定cookie信息.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetCookieControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetCookieHandler" + } + ], + "inputs": [ + { + "name": "url_type", + "label": "url 指定方式", + "required": true, + "default": "10:auto", + "defaultDisplay": "网页对象", + "tips": "用来指定 cookie 的 url 来源, 可选择手动输入, 如果选择网页对象,则自动使用网页 url 指定", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据网页对象", + "value": "auto" + }, + { + "display": "根据输入的url", + "value": "manual" + } + ] + } + }, + { + "name": "browser", + "label": "网页对象", + "required": false, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "web_type", + "label": "浏览器类型", + "required": false, + "tips": "获取指定类型浏览器 cookie", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "url", + "label": "筛选cookie url", + "required": false, + "tips": "根据是否与给定的 URL 比如 'https://www.winrobot360.com'匹配, 筛选浏览器 cookie (url 为必填项)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "name", + "label": "筛选 cookie name", + "required": true, + "category": "advanced", + "tips": "根据是否与给定的 name 匹配, 筛选 cookie (值为空则忽略 name 筛选条件)", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "cookie", + "label": "保存 cookie 至", + "tips": "指定一个变量名称,该变量用于保存获取到的cookie,cookie 键包括'domain'、'expirationDate'、'name'、'value'、'httpOnly'...(ie只包括name, value), cookie 的值可以通过比如 cookie['value'] 的方式获取", + "name": "cookie", + "type": "dict" + } + ] + }, + { + "name": "web.set_cookie", + "title": "设置Cookie", + "icon": "BlockIcons/3-12.png", + "comment": "根据指定的 cookie 数据设置 cookie,若存在等效 cookie 则覆盖", + "description": "根据指定的 cookie 数据设置 cookie,若存在等效 cookie 则覆盖", + "function": "xbot_visual.web.set_cookie", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/网页操作/设置cookie.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.SetCookieControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.SetCookieHandler" + } + ], + "inputs": [ + { + "name": "url_type", + "label": "url 设置方式", + "required": true, + "default": "10:auto", + "defaultDisplay": "网页对象", + "tips": "cookie url 设置值来源, 可选择手动输入, 如果选择网页对象,则自动使用网页 url 设置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据网页对象", + "value": "auto" + }, + { + "display": "根据输入的url", + "value": "manual" + } + ] + } + }, + { + "name": "browser", + "label": "网页对象", + "required": false, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "web_type", + "label": "浏览器类型", + "required": false, + "tips": "设置指定类型浏览器 cookie", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "url", + "label": "cookie url", + "required": false, + "tips": "cookie url,与 cookie 设置相关联的 url,该值影响创建 cookie 的默认 domain 和 path 值", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "name", + "label": "cookie name", + "required": true, + "tips": "cookie name, 忽略则为空", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "value", + "label": "cookie value", + "required": false, + "tips": "cookie value,忽略则为空", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "sessionCookie", + "label": "", + "required": true, + "default": "13:True", + "tips": "默认设置为会话 cookie,取消勾选则设置为持久化 cookie", + "type": "bool", + "editor": { + "label": "设置为会话 Cookie", + "kind": "checkbox" + } + }, + { + "name": "expires", + "label": "cookie 有效期(秒)", + "required": false, + "default": "10:100", + "tips": "持久化 cookie 需要设置有效期(cookie 生效到失效的时间间隔,单位为秒),默认 100s", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 1 + } + }, + { + "name": "domain", + "label": "cookie domain", + "required": false, + "tips": "cookie domain,默认为 url 的 domain 部分。忽略这该 cookie 为 host-only cookie", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "path", + "label": "cookie path", + "required": false, + "tips": "cookie path,默认为 url 的 path 部分,忽略则为空", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "httpOnly", + "label": "标记为 HttpOnly", + "required": false, + "default": "13:False", + "tips": "设置该 cookie 是否被标记为 HttpOnly,默认为 false", + "type": "bool", + "editor": { + "label": "标记为 HttpOnly", + "kind": "checkbox" + } + }, + { + "name": "secure", + "label": "标记为 Secure", + "required": false, + "default": "13:False", + "tips": "设置该 cookie 是否被标记为 Secure,默认为 false", + "type": "bool", + "editor": { + "label": "标记为 Secure", + "kind": "checkbox" + } + } + ] + }, + { + "name": "web.remove_cookie", + "title": "移除Cookie", + "icon": "BlockIcons/3-12.png", + "comment": "移除网页对象%browser%上名为%name%的cookie", + "description": "移除通过 cookie url、 cookie name 指定的 cookie", + "function": "xbot_visual.web.remove_cookie", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/网页操作/移除指定cookie.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.RemoveCookieControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.RemoveCookieHandler" + } + ], + "inputs": [ + { + "name": "url_type", + "label": "url 指定方式", + "required": true, + "default": "10:auto", + "defaultDisplay": "网页对象", + "tips": "用来指定 cookie 的 url 来源, 可选择手动输入, 如果选择网页对象,则自动使用网页 url 指定", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据网页对象", + "value": "auto" + }, + { + "display": "根据输入的url", + "value": "manual" + } + ] + } + }, + { + "name": "browser", + "label": "网页对象", + "required": false, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "web_type", + "label": "浏览器类型", + "required": false, + "tips": "获取指定类型浏览器 cookie", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "url", + "label": "cookie url", + "required": false, + "tips": "cookie url,将被移除的 cookie url", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "remove_type", + "label": "移除方式", + "required": true, + "tips": "设置cookie的移除方式", + "type": "str", + "default": "10:appoint_cookie", + "defaultDisplay": "移除指定Cookie", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "移除指定Cookie", + "value": "appoint_cookie" + }, + { + "display": "移除所有Cookie", + "value": "all_cookies" + } + ] + } + }, + { + "name": "name", + "label": "cookie name", + "required": false, + "category": "advanced", + "tips": "将被移除的 cookie 名称", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "web.handle_save_dialog", + "title": "处理下载对话框", + "keywords": "弹框", + "description": "处理下载对话框", + "comment": "点击%web_type%中下载对话框的%dialog_result%按钮下载,保存到路径%file_folder%下,将下载的文件路径保存到%download_file_name%", + "icon": "BlockIcons/4-1.png", + "function": "xbot_visual.web.handle_save_dialog", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.HandleSaveDialogControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/对话框处理/处理下载对话框.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.HandleSaveDialogHandler" + } + ], + "inputs": [ + { + "name": "web_type", + "label": "浏览器类型", + "required": true, + "tips": "选择想要操作的浏览器对象", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + } + ] + } + }, + { + "name": "dialog_result", + "label": "点击按钮", + "required": true, + "default": "10:OK", + "defaultDisplay": "确定", + "tips": "当下载对话框出现时要点击的按钮", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "确定", + "value": "OK" + }, + { + "display": "取消", + "value": "Cancle" + } + ] + } + }, + { + "name": "file_folder", + "label": "保存文件夹", + "required": true, + "tips": "保存下载文件的文件夹", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder", + "filter": "All Files (*.*)|*.*" + } + } + }, + { + "name": "use_custom_filename", + "label": "是否自定义文件名", + "required": true, + "default": "13:False", + "tips": "是否自定义保存文件名,不勾选则使用默认文件名,若没有默认文件名,为下载资源自动生成不重复的文件名", + "type": "bool", + "editor": { + "label": "是否自定义保存文件名", + "kind": "checkbox" + } + }, + { + "name": "file_name", + "label": "保存文件名", + "required": false, + "tips": "自定义保存的文件名", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "wait_complete", + "label": "是否等待下载完成", + "required": false, + "default": "13:False", + "tips": "若是,则会在最大超时时间内一直等待,直到文件下载完成", + "type": "bool", + "editor": { + "label": "是否等待下载完成", + "kind": "checkbox" + } + }, + { + "name": "wait_complete_timeout", + "label": "超时时间(s)", + "required": false, + "default": "10:300", + "tips": "等待下载超时时间,单位(秒)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "simulate", + "label": "", + "default": "13:False", + "category": "advanced", + "tips": "如果使用模拟人工输入则通过模拟人工的方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "模拟人工输入", + "kind": "checkbox" + } + }, + { + "name": "clipboard_input", + "label": "", + "default": "13:False", + "category": "advanced", + "tips": "将输入路径和文件名添加到剪切板, 通过Ctrl+V的方式将内容填写到下载对话框的文件名输入框中,避免输入法问题", + "type": "bool", + "editor": { + "label": "剪切板输入", + "kind": "checkbox" + } + }, + { + "name": "input_type", + "label": "输入方式", + "required": true, + "tips": "自动化接口输入: 调用文件名输入框自身实现的自动化接口输入\r\n剪切板输入: 将输入路径和文件名添加到剪切板, 通过Ctrl+V的方式将内容填写到上传对话框的文件名输入框中,避免输入法问题\r\n模拟人工输入: 如果使用模拟人工输入则通过模拟人工的方式触发输入事件(会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题),否则将根据目标元素的自动化接口触发输入", + "type": "str", + "default": "10:automatic", + "defaultDisplay": "自动化接口输入", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "自动化接口输入", + "value": "automatic" + }, + { + "display": "剪切板输入", + "value": "clipboard" + }, + { + "display": "模拟人工输入", + "value": "simulate" + } + ] + } + }, + { + "name": "wait_appear_timeout", + "label": "等待对话框出现(秒)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待下载对话框出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "force_ime_ENG", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "存在不常见的输入法切换英文输入状态不成功的情况\r\n需要指定强制加载美式键盘(ENG), 确保模拟输入不受中文输入法影响", + "type": "bool", + "editor": { + "label": "强制加载美式键盘(ENG)", + "kind": "checkbox" + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(毫秒)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间, 单位是毫秒, 为避免输入错误, 请将该值调大,最大值为1000ms", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 5 + } + }, + { + "name": "focus_timeout", + "label": "焦点超时时间(毫秒)", + "category": "advanced", + "default": "10:1000", + "tips": "设置焦点超时时间(毫秒), 元素获取焦点后暂停指定时间后进行输入操作", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "download_file_name", + "label": "文件保存位置", + "tips": "下载文件所在的位置:文件路径+名称", + "name": "download_file_name", + "type": "str" + } + ] + }, + { + "name": "web.handle_upload_dialog", + "title": "处理上传对话框", + "keywords": "弹框", + "description": "处理上传对话框", + "comment": "点击%web_type%中上传对话框的%dialog_result%按钮上传,上传文件%filename%", + "icon": "BlockIcons/4-2.png", + "function": "xbot_visual.web.handle_upload_dialog", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.HandleUploadDialogControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/对话框处理/处理上传对话框.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.HandleUploadDialogHandler" + } + ], + "inputs": [ + { + "name": "web_type", + "label": "浏览器类型", + "required": true, + "tips": "选择想要操作的浏览器对象", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "dialog_result", + "label": "点击按钮", + "required": true, + "default": "10:OK", + "defaultDisplay": "确定", + "tips": "当上传对话框出现时要点击的按钮", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "确定", + "value": "OK" + }, + { + "display": "取消", + "value": "Cancle" + } + ] + } + }, + { + "name": "filename", + "label": "上传文件路径", + "required": true, + "tips": "要上传文件完整路径; \r\n如果需要多文件上传, 在python模式下, 输入完整路径字符串数组,比如: [r\"C:\\test.txt\",r\"C:\\text1.txt\"]", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "All Files (*.*)|*.*" + } + } + }, + { + "name": "simulate", + "label": "", + "default": "13:False", + "category": "advanced", + "tips": "如果使用模拟人工输入则通过模拟人工的方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "模拟人工输入", + "kind": "checkbox" + } + }, + { + "name": "clipboard_input", + "label": "", + "default": "13:False", + "category": "advanced", + "tips": "将输入路径和文件名添加到剪切板, 通过Ctrl+V的方式将内容填写到上传对话框的文件名输入框中,避免输入法问题", + "type": "bool", + "editor": { + "label": "剪切板输入", + "kind": "checkbox" + } + }, + { + "name": "input_type", + "label": "输入方式", + "required": true, + "tips": "自动化接口输入: 调用文件名输入框自身实现的自动化接口输入\r\n剪切板输入: 将输入路径和文件名添加到剪切板, 通过Ctrl+V的方式将内容填写到上传对话框的文件名输入框中,避免输入法问题\r\n模拟人工输入: 如果使用模拟人工输入则通过模拟人工的方式触发输入事件(会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题),否则将根据目标元素的自动化接口触发输入", + "type": "str", + "default": "10:automatic", + "defaultDisplay": "自动化接口输入", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "自动化接口输入", + "value": "automatic" + }, + { + "display": "剪切板输入", + "value": "clipboard" + }, + { + "display": "模拟人工输入", + "value": "simulate" + } + ] + } + }, + { + "name": "wait_appear_timeout", + "label": "等待对话框出现(秒)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待上传对话框出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "force_ime_ENG", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "存在不常见的输入法切换英文输入状态不成功的情况\r\n需要指定强制加载美式键盘(ENG), 确保模拟输入不受中文输入法影响", + "type": "bool", + "editor": { + "label": "强制加载美式键盘(ENG)", + "kind": "checkbox" + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(毫秒)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间(仅模拟输入有效), 单位是毫秒, 为避免输入错误, 请将该值调大,最大值为1000ms", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 5 + } + }, + { + "name": "focus_timeout", + "label": "焦点超时时间(毫秒)", + "category": "advanced", + "default": "10:1000", + "tips": "设置焦点超时时间(毫秒), 元素获取焦点后暂停指定时间后进行输入操作", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/web.browser.blocks.json b/src/assert/block_settings/web.browser.blocks.json new file mode 100644 index 0000000..c62db04 --- /dev/null +++ b/src/assert/block_settings/web.browser.blocks.json @@ -0,0 +1,1279 @@ +{ + "types": [ + { + "name": "xbot._web.element.WebElement", + "localName": "网页元素", + "pythonName": "xbot.web.chrome.ChromeElement,xbot.web.ie.IEElement,xbot.web.cef.CEFElement", + "methods": [ + { + "display": "该元素的链接", + "function": "$0.get_attribute('href')", + "type": "str" + }, + { + "display": "该元素的文本内容", + "function": "$0.get_text()", + "type": "str" + } + ] + } + ], + "blocks": [ + { + "name": "web.browser.close", + "title": "关闭网页", + "description": "关闭已打开的某个或所有网页", + "comment": "关闭%web_type%中的网页%browser%", + "icon": "BlockIcons/1-3.png", + "function": "xbot_visual.web.browser.close", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.CloseBrowserControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/关闭网页.html", + "video": { + "time": "03:16" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.CloseBrowserBlockHandler" + } + ], + "inputs": [ + { + "name": "operation", + "label": "操作", + "required": true, + "default": "10:close_specified", + "defaultDisplay": "关闭指定网页", + "tips": "选择要关闭一个指定的网页还是关闭所有网页", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "关闭指定网页", + "value": "close_specified" + }, + { + "display": "关闭所有网页", + "value": "close_all" + } + ] + } + }, + { + "name": "browser", + "label": "网页对象", + "required": false, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "web_type", + "label": "操作浏览器", + "required": false, + "tips": "选择想要操作的浏览器对象", + "type": "str", + "default": "10:cef", + "defaultDisplay": "影刀浏览器", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "影刀浏览器", + "value": "cef" + }, + { + "display": "Google Chrome浏览器", + "value": "chrome" + }, + { + "display": "Microsoft Edge浏览器", + "value": "edge" + }, + { + "display": "Internet Explorer浏览器", + "value": "ie" + }, + { + "display": "Mozilla Firefox浏览器", + "value": "firefox" + }, + { + "display": "360安全浏览器", + "value": "360se" + } + ] + } + }, + { + "name": "task_kill", + "label": "", + "required": true, + "default": "13:False", + "tips": "如果勾选, 将强制结束属于当前用户的指定浏览器进程和由它启动的所有子进程", + "type": "bool", + "editor": { + "label": "终止浏览器进程", + "kind": "checkbox" + } + } + ] + }, + { + "name": "web.browser.navigate", + "title": "跳转至新网址", + "keywords": "后退;前进;重新加载;刷新", + "description": "将Web浏览器跳转至新页面、后退、前进、或重新加载(刷新)当前页面", + "comment": "将网页%browser%%mode%", + "icon": "BlockIcons/1-4.png", + "function": "xbot_visual.web.browser.navigate", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/网页操作/跳转至新网址.html", + "video": { + "time": "01:48" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.NavigateBrowserControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.NavigateBrowserHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "mode", + "label": "跳转方式", + "required": true, + "tips": "选择一种跳转方式,可以是跳转至新页面、后退、前进、或重新加载当前页面", + "default": "10:url", + "defaultDisplay": "跳转至新页面", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "跳转至新页面", + "value": "url" + }, + { + "display": "后退", + "value": "back" + }, + { + "display": "前进", + "value": "forward" + }, + { + "display": "重新加载(刷新)", + "value": "reload" + } + ] + } + }, + { + "name": "url", + "label": "新网址", + "tips": "填写要跳转到的目标网址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "ignore_cache", + "label": "", + "category": "advanced", + "tips": "重新加载时是否忽略浏览器缓存", + "default": "13:False", + "type": "bool", + "editor": { + "label": "忽略缓存", + "kind": "checkbox" + } + }, + { + "name": "load_timeout", + "label": "网页加载超时时间(秒)", + "required": true, + "default": "10:20", + "category": "advanced", + "tips": "等待网页加载完成的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.browser.stop_load", + "title": "停止网页加载", + "description": "如果网页尚未加载完毕则强制停止网页加载", + "comment": "停止网页%browser%加载", + "icon": "BlockIcons/1-5.png", + "function": "xbot_visual.web.browser.stop_load", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/网页操作/停止网页加载.html", + "video": { + "time": "00:18" + }, + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ] + }, + { + "name": "web.browser.execute_javascript", + "title": "执行JS脚本", + "keywords": "Javascript", + "description": "在指定的网页中执行一段Javascript脚本,同时获取脚本的执行结果", + "comment": "在网页%browser%中的元素%element%上执行Javascript,将执行结果保存到%js_result%", + "icon": "BlockIcons/1-6.png", + "function": "xbot_visual.web.browser.execute_javascript", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/网页操作/执行js脚本.html", + "video": { + "time": "03:14" + }, + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "elementType": "xbot._web.browser.WebBrowser" + } + }, + { + "name": "argument", + "label": "参数", + "tips": "填写要传入到Javascript脚本中的参数", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "code", + "label": "javascript", + "required": true, + "default": "10:function (element, input) {\r\n // 在此处编写您的Javascript代码\r\n // element表示选择的操作目标(HTML元素)\r\n // input表示输入的参数(字符串)\r\n \r\n return null;\r\n}", + "tips": "编写一段用于执行的Javascript脚本", + "type": "str", + "editor": { + "kind": "code", + "language": "javascript" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "execution_world", + "label": "执行环境", + "required": true, + "category": "advanced", + "default": "10:ISOLATED", + "defaultDisplay": "插件环境", + "tips": "JS脚本的目标执行环境", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "插件环境", + "value": "ISOLATED" + }, + { + "display": "网页环境", + "value": "MAIN" + } + ] + } + } + ], + "outputs": [ + { + "id": "js_result", + "label": "存储脚本执行结果至", + "variableLabel": "脚本执行结果", + "tips": "指定一个变量名称,该变量用于存储脚本执行的结果", + "name": "web_js_result", + "type": "any" + } + ] + }, + { + "name": "web.browser.scroll_to", + "title": "鼠标滚动网页", + "description": "在指定的网页中滚动鼠标,可以设置为滚动到顶部、底部或者指定位置", + "comment": "在指定的网页中滚动鼠标", + "icon": "BlockIcons/2-10.png", + "function": "xbot_visual.web.browser.scroll_to", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.ScrollToElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/网页操作/鼠标滚动网页.html", + "video": { + "time": "03:50" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.ScrollToElementHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "scroll_on_element", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否在指定元素上滚动", + "type": "bool", + "editor": { + "label": "在指定元素上滚动", + "kind": "checkbox" + } + }, + { + "name": "element", + "label": "操作目标", + "autoFill": false, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "elementType": "xbot._web.browser.WebBrowser" + } + }, + { + "name": "search_up", + "label": "", + "required": false, + "default": "13:False", + "tips": "若当前元素无滚动条,自动向上查找有滚动条元素", + "type": "bool", + "editor": { + "label": "元素无滚动条,自动向上查找", + "kind": "checkbox" + } + }, + { + "name": "location", + "label": "滚动位置", + "required": true, + "tips": "指定网页滚动到的目标位置", + "default": "10:bottom", + "defaultDisplay": "滚动到底部", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "滚动到底部", + "value": "bottom" + }, + { + "display": "滚动到顶部", + "value": "top" + }, + { + "display": "滚动到指定位置", + "value": "point" + }, + { + "display": "滚动一屏", + "value": "screen" + } + ] + } + }, + { + "name": "behavior", + "label": "滚动效果", + "required": true, + "tips": "指定鼠标的滚动效果可以是平滑滚动或者瞬间滚动", + "default": "10:smooth", + "defaultDisplay": "平滑滚动", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "平滑滚动", + "value": "smooth" + }, + { + "display": "瞬间滚动", + "value": "instant" + } + ] + } + }, + { + "name": "left", + "label": "横坐标", + "default": "10:0", + "tips": "鼠标移动到的目标位置的横坐标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "top", + "label": "纵坐标", + "default": "10:0", + "tips": "鼠标移动到的目标位置的纵坐标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.browser.handle_javascript_dialog", + "title": "处理网页对话框", + "keywords": "弹框;alert;confirm;prompt;", + "description": "处理网页中alert、confirm、prompt三种弹框", + "comment": "在网页%browser%的对话框中,点击%dialog_result%按钮", + "icon": "BlockIcons/4-3.png", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.HandleJavascriptDialogControl, ShadowBot.Shell.Development", + "function": "xbot_visual.web.browser.handle_javascript_dialog", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/对话框处理/处理网页对话框.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.HandleJavascriptDialogHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "dialog_result", + "label": "对话框按钮", + "required": true, + "default": "10:OK", + "defaultDisplay": "确定", + "tips": "当网页对话框出现时要点击的按钮", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "确定", + "value": "OK" + }, + { + "display": "取消", + "value": "Cancle" + } + ] + } + }, + { + "name": "text", + "label": "输入内容", + "tips": "如果是支持输入的对话框出现时,可以在此填写要输入的内容", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "wait_appear_timeout", + "label": "等待对话框出现(秒)", + "required": true, + "default": "10:20", + "category": "advanced", + "tips": "等待网页对话框出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.browser.get_details", + "title": "获取网页信息", + "description": "获取网页标题、网址、源代码、文本等信息", + "comment": "%operation%,目标网页为%browser%,将结果保存到%webpage_attribute%", + "icon": "BlockIcons/3-1.png", + "function": "xbot_visual.web.browser.get_details", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetBrowserDetailHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取网页信息.html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "operation", + "label": "操作", + "required": true, + "default": "10:url", + "defaultDisplay": "获取网址", + "tips": "选择要获取的网页信息", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "获取网址", + "value": "url" + }, + { + "display": "获取网页标题", + "value": "title" + }, + { + "display": "获取网页源代码", + "value": "html" + }, + { + "display": "获取网页文本内容", + "value": "text" + } + ] + } + } + ], + "outputs": [ + { + "id": "webpage_attribute", + "label": "存储网页信息至", + "variableLabel": "网页信息", + "tips": "指定一个变量名称,该变量用于存储获取到的网页信息", + "name": "web_page_attribute", + "type": "str" + } + ] + }, + { + "name": "web.browser.get_javascript_dialog_text", + "title": "提取网页对话框内容", + "description": "提取网页对话框内容", + "comment": "提取网页%browser%中的对话框内容,将结果保存到%dialog_text%", + "icon": "BlockIcons/3-7.png", + "function": "xbot_visual.web.browser.get_javascript_dialog_text", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/提取网页对话框内容.html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "wait_appear_timeout", + "label": "等待对话框出现(秒)", + "required": true, + "default": "10:20", + "category": "advanced", + "tips": "等待网页对话框出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "dialog_text", + "label": "存储对话框内容至", + "variableLabel": "对话框内容", + "tips": "指定一个变量名称,该变量用于存储获取到的对话框中的文字内容", + "name": "web_dialog_text", + "type": "str" + } + ] + }, + { + "name": "web.browser.start_monitor_network", + "title": "开始监听网页请求", + "description": "开始监听网页请求,根据输入的资源路径Url、资源类型, 筛选网页监听结果,可在开启后获取抓取到的信息", + "comment": "开始抓取网页%browser%中的请求信息", + "icon": "BlockIcons/3-9.png", + "keywords": "http", + "function": "xbot_visual.web.browser.start_monitor_network", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/开始监听网页请求.html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "url", + "label": "资源路径Url", + "default": "10:", + "tips": "根据输入的资源Url,筛选网页监听结果(值为空则忽略url筛选条件)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符筛选Url", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "resource_type", + "label": "筛选资源类型", + "required": true, + "default": "10:All", + "defaultDisplay": "All", + "tips": "选择要获取的网页监听结果类型,可筛选JS,图片,文档等类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "全部", + "value": "All" + }, + { + "display": "Fetch/XHR", + "value": "Fetch|XHR" + }, + { + "display": "JS", + "value": "Script" + }, + { + "display": "CSS", + "value": "Stylesheet" + }, + { + "display": "图片", + "value": "Image" + }, + { + "display": "媒体", + "value": "Media" + }, + { + "display": "字体", + "value": "Font" + }, + { + "display": "文档", + "value": "Document" + }, + { + "display": "WebSocket", + "value": "WebSocket" + }, + { + "display": "其他", + "value": "Other" + } + ] + } + } + ] + }, + { + "name": "web.browser.get_responses", + "title": "获取网页监听结果", + "description": "获取网页监听结果,\r\n列表项键包括'url'、'type'、'headers'、'body'、'base64Encoded'、'status'、'requestHeaders'、'requestBody'、'method' ", + "comment": "获取网页%browser%监听结果列表,将结果保存到%response_body_list%", + "icon": "BlockIcons/3-11.png", + "keywords": "http", + "function": "xbot_visual.web.browser.get_responses", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetResponsesControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取网页监听结果.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetResponsesHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "url", + "label": "资源路径Url", + "default": "10:", + "tips": "根据输入的资源Url,筛选网页监听结果(值为空则忽略url筛选条件)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符筛选Url", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "resource_type", + "label": "筛选资源类型", + "required": true, + "default": "10:All", + "defaultDisplay": "All", + "tips": "选择要获取的网页监听结果类型,可筛选JS,图片,文档等类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "All", + "value": "All" + }, + { + "display": "XHR", + "value": "XHR" + }, + { + "display": "Script", + "value": "Script" + }, + { + "display": "Stylesheet", + "value": "Stylesheet" + }, + { + "display": "Image", + "value": "Image" + }, + { + "display": "Media", + "value": "Media" + }, + { + "display": "Font", + "value": "Font" + }, + { + "display": "Document", + "value": "Document" + }, + { + "display": "WebSocket", + "value": "WebSocket" + }, + { + "display": "Manifest", + "value": "Manifest" + }, + { + "display": "TextTrack", + "value": "TextTrack" + }, + { + "display": "Fetch", + "value": "Fetch" + }, + { + "display": "EventSource", + "value": "EventSource" + }, + { + "display": "Other", + "value": "Other" + } + ] + } + } + ], + "outputs": [ + { + "id": "response_body_list", + "label": "保存网页监听结果列表至", + "tips": "指定一个变量名称,该变量用于保存获取到的网页监听结果列表,列表项键包括'url'、'type'、'body'、'base64Encoded',集合中的值可以通过比如 item['body'] 的方式获取", + "name": "response_body_list", + "type": "list" + } + ] + }, + { + "name": "web.browser.stop_monitor_network", + "title": "停止监听网页请求", + "description": "停止监听网页请求", + "comment": "结束抓取网页%browser%中的请求信息", + "icon": "BlockIcons/3-10.png", + "keywords": "http", + "function": "xbot_visual.web.browser.stop_monitor_network", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/停止监听网页请求.html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ] + }, + { + "name": "web.browser.contains_element_or_text", + "statement": "workflow.if", + "title": "IF 网页包含", + "description": "检测指定的文本或元素是否出现在网页中", + "comment": "检测指定的文本或元素是否出现在网页中", + "indent": "1", + "scope": "1", + "isCondition": true, + "icon": "BlockIcons/6-4.png", + "function": "xbot_visual.web.browser.contains_element_or_text", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.ContainsElementOrTextControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if网页包含.html", + "video": { + "time": "01:18" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.ContainsElementOrTextHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "content_type", + "label": "检测网页是否", + "required": true, + "default": "10:contains_element", + "defaultDisplay": "包含元素", + "tips": "指定你想要检测的内容类型,检测文本还是检测元素", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "包含元素", + "value": "contains_element" + }, + { + "display": "不包含元素", + "value": "not_contains_element" + }, + { + "display": "包含文本", + "value": "contains_text" + }, + { + "display": "不包含文本", + "value": "not_contains_text" + } + ] + } + }, + { + "name": "selector", + "label": "操作目标", + "required": false, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "text", + "label": "文本内容", + "required": false, + "tips": "文本内容", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "web.browser.element_display", + "statement": "workflow.if", + "title": "IF 元素可见(web)", + "description": "检测指定的元素在网页中是否可见", + "comment": "检测网页%browser%中元素%selector%在是否%content_type%", + "indent": "1", + "scope": "1", + "isCondition": true, + "icon": "BlockIcons/6-4.png", + "function": "xbot_visual.web.browser.element_display", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if元素可见(web).html", + "video": { + "time": "01:03" + }, + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "content_type", + "label": "检测网页是否", + "required": true, + "default": "10:display", + "defaultDisplay": "可见", + "tips": "指定你想要检测的内容类型,检测元素可见还是不可见", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "可见", + "value": "display" + }, + { + "display": "不可见", + "value": "undisplay" + } + ] + } + }, + { + "name": "selector", + "label": "操作目标", + "required": false, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + } + ] + }, + { + "name": "web.browser.get_scroll", + "title": "获取滚动条位置", + "description": "获取网页或元素中滚动条的当前位置或底部位置(即滚动条长度)", + "comment": "获取网页%browser%中滚动条的%location%,将滚动条位置保存到%scroll_value%", + "icon": "BlockIcons/2-10.png", + "function": "xbot_visual.web.browser.get_scroll", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetScrollControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取滚动条位置.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetScrollControlHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "scroll_on_element", + "label": "", + "required": true, + "default": "13:False", + "tips": "获取指定元素滚动条的位置,否则为整个网页的滚动条", + "type": "bool", + "editor": { + "label": "元素滚动条", + "kind": "checkbox" + } + }, + { + "name": "element", + "label": "操作目标", + "autoFill": false, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "elementType": "xbot._web.browser.WebBrowser" + } + }, + { + "name": "search_up", + "label": "", + "required": false, + "default": "13:False", + "tips": "若当前元素无滚动条,自动向上查找有滚动条元素", + "type": "bool", + "editor": { + "label": "元素无滚动条,自动向上查找", + "kind": "checkbox" + } + }, + { + "name": "direction", + "label": " 滚动条", + "required": true, + "tips": "根据实际需要选择纵向或横向滚动条", + "default": "10:vertical", + "defaultDisplay": "纵向滚动条", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "纵向滚动条", + "value": "vertical" + }, + { + "display": "横向滚动条", + "value": "horizontal" + } + ] + } + }, + { + "name": "location", + "label": "位置", + "required": true, + "tips": "当前位置为当前滚动条所在的位置与顶部的距离,底部位置为滚动条最大可滚动的长度", + "default": "10:current", + "defaultDisplay": "当前位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "当前位置", + "value": "current" + }, + { + "display": "底部位置", + "value": "bottom" + } + ] + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标滚动条存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "scroll_value", + "label": "保存滚动条位置至", + "variableLabel": "滚动条位置", + "tips": "指定一个变量名称,该变量用于保存获取到滚动条位置", + "name": "scroll_value", + "type": "int" + } + ] + }, + { + "name": "web.browser.wait_load_completed", + "title": "等待网页加载完成", + "description": "等待网页加载完成", + "comment": "等待网页%browser%加载完成,等待时间%load_timeout%秒", + "icon": "BlockIcons/2-9.png", + "function": "xbot_visual.web.browser.wait_load_completed", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/网页操作/等待网页加载完成.html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "load_timeout", + "label": "加载超时时间", + "required": true, + "default": "10:20", + "tips": "等待网页加载完成的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "action_after_load_timeout", + "label": "加载超时后执行", + "required": true, + "tips": "等待网页加载完成超时后希望执行的操作", + "type": "str", + "default": "10:handleExcept", + "defaultDisplay": "执行\"错误处理\"", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "执行\"错误处理\"", + "value": "handleExcept" + }, + { + "display": "停止网页加载", + "value": "stopLoad" + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/web.element.blocks.json b/src/assert/block_settings/web.element.blocks.json new file mode 100644 index 0000000..fa44336 --- /dev/null +++ b/src/assert/block_settings/web.element.blocks.json @@ -0,0 +1,3409 @@ +{ + "types": [ + { + "name": "xbot_visual._core.Rectangle", + "localName": "元素位置信息", + "props": [ + { + "name": "left", + "type": "int", + "label": "左边" + }, + { + "name": "top", + "type": "int", + "label": "顶部" + }, + { + "name": "right", + "type": "int", + "label": "右边" + }, + { + "name": "bottom", + "type": "int", + "label": "底部" + }, + { + "name": "center_x", + "type": "int", + "label": "中心点横坐标" + }, + { + "name": "center_y", + "type": "int", + "label": "中心点纵坐标" + }, + { + "name": "width", + "type": "int", + "label": "宽度" + }, + { + "name": "height", + "type": "int", + "label": "高度" + } + ] + } + ], + "blocks": [ + { + "name": "web.element.click", + "title": "点击元素(web)", + "description": "点击网页中的按钮、链接或者其他任何元素", + "comment": "在网页%browser%中,模拟人工%button%%clicks%网页元素%element%,点击%anchor_type%位置", + "icon": "BlockIcons/2-1.png", + "function": "xbot_visual.web.element.click", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.ClickElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/点击元素(web).html", + "video": { + "time": "04:00" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.ClickBrowserElementHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "simulate", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "注意:由于上方网页指令默认启用“运行时不抢占鼠标键盘”,需关闭后模拟人工点击才可生效。\r\n通过模拟人工点击执行操作,关闭将采用API方式执行操作。", + "type": "bool", + "editor": { + "label": "模拟人工点击", + "kind": "checkbox" + } + }, + { + "name": "move_mouse", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "是否显示鼠标移动轨迹", + "type": "bool", + "editor": { + "label": "显示鼠标移动轨迹", + "kind": "checkbox" + } + }, + { + "name": "clicks", + "label": "点击方式", + "required": true, + "default": "10:click", + "defaultDisplay": "单击", + "category": "advanced", + "tips": "选择点击的方式是单击还是双击", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单击", + "value": "click" + }, + { + "display": "双击", + "value": "dbclick" + } + ] + } + }, + { + "name": "button", + "label": "鼠标按钮", + "required": true, + "default": "10:left", + "defaultDisplay": "鼠标左键", + "category": "advanced", + "tips": "选择用于触发点击的鼠标按键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "鼠标左键", + "value": "left" + }, + { + "display": "鼠标右键", + "value": "right" + } + ] + } + }, + { + "name": "keys", + "label": "辅助按键", + "required": true, + "default": "10:null", + "defaultDisplay": "无", + "category": "advanced", + "tips": "在点击时需要按下的键盘功能键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "无", + "value": "null" + }, + { + "display": "Alt", + "value": "alt" + }, + { + "display": "Ctrl", + "value": "ctrl" + }, + { + "display": "Shift", + "value": "shift" + }, + { + "display": "Win", + "value": "win" + } + ] + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": true, + "tips": "支持点击元素中心位置(元素矩形区域的中心点)、随机位置(自动随机指定元素矩形范围内的点)、自定义位置(手动指定目标点)", + "type": "str", + "default": "10:center", + "category": "advanced", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "default": "10:MiddleCenter", + "category": "advanced", + "label": "目标元素的部位", + "tips": "默认点击目标元素的中心位置,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.hover", + "title": "鼠标悬停在元素上(web)", + "description": "将鼠标悬停在网页中的元素上", + "keywords": "悬浮;停留", + "comment": "在网页%browser%中,模拟人工将鼠标移动在网页元素%element%上,到达位置为元素%anchor_type%", + "icon": "BlockIcons/2-2.png", + "function": "xbot_visual.web.element.hover", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.HoverElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/鼠标悬停在元素上(web).html", + "video": { + "time": "02:33" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.HoverBrowserElementHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "simulate", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "如果使用模拟人工悬停则通过模拟人工的方式触发悬停事件,否则将根据目标元素的自动化接口触发悬停", + "type": "bool", + "editor": { + "label": "模拟人工悬停", + "kind": "checkbox" + } + }, + { + "name": "delay_after", + "label": "延迟时间(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": true, + "tips": "支持悬停在元素中心位置、随机位置(在元素矩形范围内)、自定义位置", + "type": "str", + "default": "10:center", + "category": "advanced", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "default": "10:middleCenter", + "category": "advanced", + "label": "目标元素的部位", + "tips": "默认悬停在目标元素的中心位置,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.input", + "title": "填写输入框(web)", + "description": "在网页的输入框中输入内容", + "comment": "在网页%browser%的%element%中,%input_type%%text%", + "icon": "BlockIcons/2-3.png", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.InputControl, ShadowBot.Shell.Development", + "function": "xbot_visual.web.element.input", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/填写输入框(web).html", + "video": { + "time": "06:49" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.InputBrowserHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "text", + "label": "输入内容", + "tips": "填写要输入的内容", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "append", + "label": "", + "required": true, + "default": "13:False", + "tips": "如果勾选追加输入则在现有内容后继续追加输入,否则清空现有内容后再进行输入", + "type": "bool", + "editor": { + "label": "追加输入", + "kind": "checkbox" + } + }, + { + "name": "simulate", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "如果使用模拟人工输入则通过模拟人工的方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "模拟人工输入", + "kind": "checkbox" + } + }, + { + "name": "driver_input", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "如果使用驱动输入则通过驱动方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "驱动输入", + "kind": "checkbox" + } + }, + { + "name": "save_to_clipboard", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "将输入内容添加到剪切板通过Ctrl+V指令将内容填写到输入框避免输入法问题", + "type": "bool", + "editor": { + "label": "剪切板输入", + "kind": "checkbox" + } + }, + { + "name": "input_type", + "label": "输入方式", + "required": true, + "tips": "注意:由于上方网页指令默认启用“运行时不抢占鼠标键盘”,需关闭后模拟人工输入才可生效。\r\n模拟人工输入: 通过模拟人工的方式触发输入事件(会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题)\r\n剪切板输入: 将输入内容添加到剪切板通过Ctrl+V指令将内容填写到输入框避免输入法问题\r\n自动化接口输入: 调用元素自身实现的自动化接口输入", + "type": "str", + "default": "10:simulate", + "category": "advanced", + "defaultDisplay": "模拟人工输入", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "模拟人工输入", + "value": "simulate" + }, + { + "display": "剪切板输入", + "value": "clipboard" + }, + { + "display": "自动化接口输入", + "value": "automatic" + }, + { + "display": "驱动输入", + "value": "driver" + } + ] + } + }, + { + "name": "contains_hotkey", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "可以在输入内容中加入快捷键,如{enter}代表输入回车键", + "type": "bool", + "editor": { + "label": "输入内容包含快捷键", + "kind": "checkbox" + } + }, + { + "name": "force_ime_ENG", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "存在不常见的输入法切换英文输入状态不成功的情况\r\n需要指定强制加载美式键盘(ENG), 确保模拟输入不受中文输入法影响", + "type": "bool", + "editor": { + "label": "强制加载美式键盘(ENG)", + "kind": "checkbox" + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(ms)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间(对影刀浏览器该参数无效), 单位是毫秒, 为避免输入错误, 请将该值调大,最大值为1000ms", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 5 + } + }, + { + "name": "focus_timeout", + "label": "焦点超时时间(ms)", + "category": "advanced", + "default": "10:1000", + "tips": "设置焦点超时时间(ms), 元素获取焦点后暂停指定时间后进行输入操作", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "click_before_input", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "在执行输入动作前,先点击元素,以便获取焦点", + "type": "bool", + "editor": { + "label": "输入前点击元素", + "kind": "checkbox" + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": false, + "tips": "支持点击元素中心位置(元素矩形区域的中心点)、随机位置(自动随机指定元素矩形范围内的点)、自定义位置(手动指定目标点)", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "default": "10:middleCenter", + "label": "鼠标点击位置", + "category": "advanced", + "tips": "该输入指令是通过(先点击输入框,后模拟键盘输入)实现的,默认点击输入框的中心位置,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "category": "advanced", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "category": "advanced", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标输入框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.check", + "title": "设置复选框(web)", + "keywords": "勾选", + "description": "将网页中的复选框的状态设置为勾选或不勾选", + "comment": "在网页%browser%中%mode%复选框%element%", + "icon": "BlockIcons/2-4.png", + "function": "xbot_visual.web.element.check", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/设置复选框(web).html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "mode", + "label": "操作", + "required": true, + "default": "10:check", + "defaultDisplay": "勾选", + "tips": "选择要对复选框进行的操作", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "勾选", + "value": "check" + }, + { + "display": "取消勾选", + "value": "uncheck" + }, + { + "display": "反选", + "value": "toggle" + } + ] + } + }, + { + "name": "delay_after", + "label": "延迟时间(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标复选框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.select", + "title": "设置下拉框(web)", + "description": "设置网页中下拉框的选中项", + "comment": "在网页%browser%中%mode%元素%element%", + "icon": "BlockIcons/2-5.png", + "function": "xbot_visual.web.element.select", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.SetSelectOptionControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/设置下拉框(web).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Element.SetSelectOptionHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "mode", + "label": "选择方式", + "required": true, + "default": "10:text", + "defaultDisplay": "按选项内容选择", + "tips": "选择设置选中项的依据", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "按选项内容选择", + "value": "text" + }, + { + "display": "按选项位置选择", + "value": "index" + } + ] + } + }, + { + "name": "value", + "label": "选择值", + "required": true, + "tips": "输入选项内容或者选项位置", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "match_mode", + "label": "匹配模式", + "required": false, + "default": "10:fuzzy", + "defaultDisplay": "匹配模式", + "tips": "选项内容的匹配模式, 默认是模糊匹配", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "模糊匹配", + "value": "fuzzy" + }, + { + "display": "精准匹配", + "value": "exact" + }, + { + "display": "正则匹配", + "value": "regex" + } + ] + } + }, + { + "name": "delay_after", + "label": "延迟时间(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标下拉框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.input_password", + "title": "填写密码框(web)", + "description": "在网页中的密码框中输入密码", + "keywords": "输入框", + "comment": "在网页%browser%的%element%中%input_type%密码", + "icon": "BlockIcons/2-6.png", + "function": "xbot_visual.web.element.input_password", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.InputPasswordControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/填写密码框(web).html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "text", + "label": "输入密码", + "required": true, + "tips": "填写要输入的密码", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "simulate", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "如果使用模拟人工输入则通过模拟人工的方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "模拟人工输入", + "kind": "checkbox" + } + }, + { + "name": "save_to_clipboard", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "将输入内容添加到剪切板通过Ctrl+V指令将内容填写到输入框避免输入法问题", + "type": "bool", + "editor": { + "label": "剪切板输入", + "kind": "checkbox" + } + }, + { + "name": "input_type", + "label": "输入方式", + "category": "advanced", + "required": true, + "tips": "模拟人工输入: 通过模拟人工的方式触发输入事件(会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题)\r\n剪切板输入: 将输入内容添加到剪切板通过Ctrl+V指令将内容填写到输入框避免输入法问题\r\n自动化接口输入: 调用元素自身实现的自动化接口输入", + "type": "str", + "default": "10:simulate", + "defaultDisplay": "模拟人工输入", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "模拟人工输入", + "value": "simulate" + }, + { + "display": "剪切板输入", + "value": "clipboard" + }, + { + "display": "自动化接口输入", + "value": "automatic" + } + ] + } + }, + { + "name": "force_ime_ENG", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "存在不常见的输入法切换英文输入状态不成功的情况\r\n需要指定强制加载美式键盘(ENG), 确保模拟输入不受中文输入法影响", + "type": "bool", + "editor": { + "label": "强制加载美式键盘(ENG)", + "kind": "checkbox" + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(ms)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间(对影刀浏览器该参数无效), 单位是毫秒, 为避免输入错误, 请将该值调大,最大值为1000ms", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 5 + } + }, + { + "name": "focus_timeout", + "label": "焦点超时时间(ms)", + "category": "advanced", + "default": "10:1000", + "tips": "设置焦点超时时间(ms), 元素获取焦点后暂停指定时间后进行输入操作", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "delay_after", + "label": "延迟时间(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标密码框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "click_before_input", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "在执行输入动作前,先点击元素,以便获取焦点", + "type": "bool", + "editor": { + "label": "输入前点击元素", + "kind": "checkbox" + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": false, + "tips": "支持点击元素中心位置(元素矩形区域的中心点)、随机位置(自动随机指定元素矩形范围内的点)、自定义位置(手动指定目标点)", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "label": "鼠标点击位置", + "default": "10:middleCenter", + "category": "advanced", + "tips": "该输入指令是通过(先点击输入框,后模拟键盘输入)实现的,默认点击输入框的中心位置,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "web.element.set_value", + "title": "设置元素值(web)", + "description": "设置网页中元素的值,一般是input、select元素的value", + "comment": "在网页%browser%中设置%element%的值为%value%", + "icon": "BlockIcons/2-7.png", + "function": "xbot_visual.web.element.set_value", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/设置元素值(web).html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素,若存在相似元素,则会默认选择第一个可见元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "value", + "label": "元素值", + "required": true, + "tips": "填写要设置的元素值", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.set_attribute", + "title": "设置元素属性(web)", + "description": "设置网页元素属性", + "comment": "在网页%browser%中设置%element%的属性%attribute_name%值为%value%", + "icon": "BlockIcons/2-8.png", + "function": "xbot_visual.web.element.set_attribute", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/设置元素属性(web).html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "attribute_name", + "label": "属性名称", + "required": true, + "tips": "填写要设置的属性名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "value", + "label": "属性值", + "required": true, + "tips": "填写要设置的属性值", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.wait", + "title": "等待元素(web)", + "description": "等待网页中元素出现或消失,再执行接下来的流程", + "comment": "等待网页%browser%中元素%element%出现,最多等待%timeout%秒", + "icon": "BlockIcons/2-9.png", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.WaitElementControl, ShadowBot.Shell.Development", + "function": "xbot_visual.web.element.wait", + "helpUrl": "yddoc/language/zh-cn/指令文档/等待/等待元素(web).html", + "video": { + "time": "08:03" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.WaitBrowserElementHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "state", + "label": "等待状态", + "required": true, + "default": "10:appear", + "defaultDisplay": "等待元素出现", + "tips": "选择等待状态", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "等待元素出现", + "value": "appear" + }, + { + "display": "等待元素消失", + "value": "disappear" + } + ] + } + }, + { + "name": "iswait", + "label": "", + "required": true, + "default": "13:True", + "tips": "设置等待超时时间,超时后流程将自动往下继续执行", + "type": "bool", + "editor": { + "label": "设置超时时间", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "超时时间(s)", + "default": "10:20", + "tips": "设置最大等待时间", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "wait_result", + "label": "等待结果", + "tips": "如果为True则等待成功,否则等待超时", + "name": "web_wait_result", + "type": "bool" + } + ] + }, + { + "name": "web.element.get_details", + "title": "获取元素信息(web)", + "keywords": "源代码;属性值;元素位置", + "description": "获取网页中的元素的文本内容、源代码、属性值、元素位置等信息", + "comment": "%operation%,目标元素为%element%,将结果保存到%element_attribute%", + "icon": "BlockIcons/3-2.png", + "function": "xbot_visual.web.element.get_details", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取元素信息(web).html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.GetElementDetailsControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetElementDetailsHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "elementType": "xbot._web.browser.WebBrowser" + } + }, + { + "name": "operation", + "label": "操作", + "required": true, + "default": "10:text", + "defaultDisplay": "获取元素文本内容", + "tips": "选择要获取的网页元素信息", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "获取元素文本内容", + "value": "text" + }, + { + "display": "获取元素源代码", + "value": "html" + }, + { + "display": "获取元素值", + "value": "value" + }, + { + "display": "获取网页链接地址", + "value": "href" + }, + { + "display": "获取元素属性", + "value": "other" + }, + { + "display": "获取元素位置", + "value": "bound" + } + ] + } + }, + { + "name": "absolute_url", + "label": "", + "required": true, + "default": "13:False", + "tips": "智能识别并补充地址前缀(http:// 或 https://)", + "type": "bool", + "editor": { + "label": "智能识别并补充地址前缀(http:// 或 https://)", + "kind": "checkbox" + } + }, + { + "name": "attribute_name", + "label": "属性名称", + "tips": "填写要获取的网页元素的属性名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "relative_to", + "label": "相对于", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕左上角", + "tips": "在整个屏幕中的位置还是在浏览器客户区域中的位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕左上角", + "value": "screen" + }, + { + "display": "浏览器页面左上角", + "value": "window" + } + ] + } + }, + { + "name": "to96dpi", + "label": "", + "required": true, + "category": "advanced", + "default": "13:True", + "tips": "是否需要将边框属性转换成与设备无关的单位 (每个单位1/96英寸)", + "type": "bool", + "editor": { + "label": "转为dpi为96对应值", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "element_attribute", + "label": "保存元素信息至", + "variableLabel": "元素信息", + "tips": "指定一个变量名称,该变量用于保存获取到的网页元素信息", + "name": "web_element_attribute", + "type": "str" + } + ] + }, + { + "name": "web.element.get_bounding", + "title": "获取元素位置(web)", + "description": "获取元素相对于屏幕或浏览器客户区域左上角的位置信息", + "comment": "获取网页%browser%中%element%相对于%relative_to%的位置信息,将结果保存到%bound%", + "icon": "BlockIcons/3-13.png", + "function": "xbot_visual.web.element.get_bounding", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取元素位置(web).html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "elementType": "xbot._web.browser.WebBrowser" + } + }, + { + "name": "to96dpi", + "label": "", + "required": true, + "category": "advanced", + "default": "13:True", + "tips": "是否需要将边框属性转换成与设备无关的单位 (每个单位1/96英寸)", + "type": "bool", + "editor": { + "label": "转为dpi为96对应值", + "kind": "checkbox" + } + }, + { + "name": "relative_to", + "label": "相对于", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕左上角", + "tips": "在整个屏幕中的位置还是在浏览器客户区域中的位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕左上角", + "value": "screen" + }, + { + "display": "浏览器页面左上角", + "value": "window" + } + ] + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "bound", + "label": "保存位置信息至", + "variableLabel": "元素位置信息", + "tips": "输入一个名称来保存元素位置信息", + "type": "xbot_visual._core.Rectangle", + "name": "bound" + } + ] + }, + { + "name": "web.element.get_element", + "title": "获取元素对象(web)", + "keywords": "CSS;XPath", + "description": "可通过捕获、CSS、XPath三种方式定位网页上的一个元素", + "comment": "获取网页%browser%中%selector%的对象,将对象保存到%element%", + "icon": "BlockIcons/3-3.png", + "function": "xbot_visual.web.element.get_element", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/获取元素对象(web).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetElementHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "select_type", + "label": "定位方式", + "required": true, + "default": "10:selector", + "defaultDisplay": "默认方式", + "tips": "指定一种定位元素的方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "默认方式", + "value": "selector" + }, + { + "display": "CSS选择器", + "value": "css_selector" + }, + { + "display": "XPath选择器", + "value": "xpath_selector" + } + ] + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "css_selector", + "label": "CSS选择器", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "xpath_selector", + "label": "XPath选择器", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_related_parent", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否关联父元素", + "type": "bool", + "editor": { + "label": "关联父元素", + "kind": "checkbox" + } + }, + { + "name": "parent", + "label": "父元素", + "required": false, + "tips": "在指定的父元素内查找目标元素", + "autoFill": false, + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "element", + "label": "保存元素对象至", + "variableLabel": "元素对象", + "tips": "指定一个变量名称,该变量用于保存获取到的元素对象", + "name": "web_element", + "type": "xbot._web.element.WebElement" + } + ] + }, + { + "name": "web.element.get_all_elements", + "title": "获取相似元素列表(web)", + "statement": "workflow.getall", + "keywords": "css;xpath", + "description": "可通过捕获元素、CSS、XPath三种方式定位到网页上的一组相似元素,获取他们的对象或文本等信息", + "comment": "在网页%browser%中获取一组与元素%selector%相似的元素,将结果保存到%element_list%", + "icon": "BlockIcons/3-4.png", + "function": "xbot_visual.web.element.get_all_elements", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.GetAllElementsControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/获取相似元素列表(web).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetAllElementsHandler", + "settings": { + "inputName": "output_with_element_count", + "outputName": "element_count" + } + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "select_type", + "label": "定位方式", + "required": true, + "default": "10:selector", + "defaultDisplay": "默认方式", + "category": "advanced", + "tips": "指定一种定位元素的方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "默认方式", + "value": "selector" + }, + { + "display": "CSS选择器", + "value": "css_selector" + }, + { + "display": "XPath选择器", + "value": "xpath_selector" + } + ] + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "css_selector", + "label": "CSS选择器", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "xpath_selector", + "label": "XPath选择器", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_related_parent", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否关联父元素", + "type": "bool", + "editor": { + "label": "关联父元素", + "kind": "checkbox" + } + }, + { + "name": "parent", + "label": "父元素", + "autoFill": false, + "tips": "在指定的父元素内查找目标元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "operation", + "label": "元素操作", + "required": true, + "default": "10:element", + "defaultDisplay": "元素操作", + "tips": "获取的元素信息", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "获取元素对象", + "value": "element" + }, + { + "display": "获取元素文本内容", + "value": "text" + }, + { + "display": "获取元素值", + "value": "value" + }, + { + "display": "获取元素链接地址", + "value": "href" + }, + { + "display": "获取元素源代码", + "value": "html" + }, + { + "display": "获取元素属性", + "value": "attr" + } + ] + } + }, + { + "name": "absolute_url", + "label": "", + "default": "13:False", + "tips": "智能识别并补充地址前缀(http:// 或 https://)", + "type": "bool", + "editor": { + "label": "智能识别并补充地址前缀(http:// 或 https://)", + "kind": "checkbox" + } + }, + { + "name": "attribute_name", + "label": "属性名称", + "tips": "填写要获取的网页元素的属性名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "output_with_element_count", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否输出相似元素个数", + "type": "bool", + "editor": { + "label": "输出相似元素个数", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "element_list", + "label": "保存相似元素列表至", + "variableLabel": "相似元素对象列表", + "tips": "指定一个变量名称,该变量用于保存获取到的相似元素列表", + "name": "web_element_list", + "type": "list" + }, + { + "id": "element_count", + "label": "保存相似元素个数至", + "variableLabel": "相似元素对象个数", + "tips": "指定一个变量名称,该变量用于保存获取到的相似元素个数", + "name": "web_element_count", + "type": "int" + } + ] + }, + { + "name": "web.element.screenshot", + "title": "网页截图", + "description": "对指定区域内元素进行截图,保存至文件或添加到剪切板中", + "comment": "在网页%browser%中对元素%element%进行截图,将结果保存到文件夹%folder_path%中,将存图路径保存到%screenshot_save_file_name%", + "icon": "BlockIcons/3-6.png", + "function": "xbot_visual.web.element.screenshot", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/网页截图.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.ScreenShotControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.ScreenShotHandler" + }, + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.ScreenShotOutputPathHandler", + "settings": { + "inputName": "save_to_clipboard", + "outputName": "screenshot_save_file_name" + } + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "capture_area", + "label": "截图区域", + "required": true, + "tips": "三种区域,若选择整个网页,会生成整个页面的长图", + "default": "10:Element", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "网页元素", + "value": "Element" + }, + { + "display": "网页可见区域", + "value": "ViewPort" + }, + { + "display": "整个网页", + "value": "Whole" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": false, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "folder_path", + "label": "保存文件夹", + "tips": "截图保存的文件夹", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "random_filename", + "label": "", + "required": true, + "default": "13:True", + "tips": "自动生成不重复的文件名", + "type": "bool", + "editor": { + "label": "使用自动随机文件名", + "kind": "checkbox" + } + }, + { + "name": "filename", + "label": "自定义文件名", + "tips": "自定义文件名 如: screenshot.png, 注意文件名不能包含下列任何字符: \\ / : * ? \" < > |", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "overwrite_file", + "label": "", + "default": "13:True", + "tips": "", + "type": "bool", + "editor": { + "label": "如果文件存在则覆盖", + "kind": "checkbox" + } + }, + { + "name": "save_to_clipboard", + "label": "", + "required": true, + "default": "13:False", + "tips": "保存图片至剪切板", + "type": "bool", + "editor": { + "label": "保存图片至剪切板", + "kind": "checkbox" + } + }, + { + "name": "height", + "label": "最大截图高度", + "required": false, + "tips": "设置最大截图的高度(相对于缩放100%)。用于因网页过长,导致截图失败的情况。默认值25000", + "default": "10:25000", + "type": "int", + "editor": { + "label": "最大截图高度", + "kind": "spin", + "minValue": 0, + "maxValue": 100000 + } + }, + { + "name": "piece_height", + "label": "单次截图高度", + "required": false, + "tips": "设置单次截图高度(相对于缩放100%)。对于长页面,采用分次截图再拼接来完成。可根据机器性能来调整每次截图高度,以提高截图的效率,建议每次不要超过5000", + "default": "10:3000", + "type": "int", + "editor": { + "label": "单次截图高度", + "kind": "spin", + "minValue": 0, + "maxValue": 10000 + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "设置网页截图的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "screenshot_save_file_name", + "label": "截图保存位置", + "variableLabel": "元素截图位置", + "tips": "截图文件所在的位置:文件路径+名称", + "name": "screenshot_save_file_name", + "type": "str" + } + ] + }, + { + "name": "web.element.data_scraping", + "title": "批量数据抓取", + "description": "在网页中抓取批量数据,常用于抓取列表页、详情页,同时可通过设置分页按钮抓取多页数据", + "comment": "在网页%browser%中抓取%table_element%,将结果保存到%data_table%,同时保存到数据表格", + "icon": "BlockIcons/3-5.png", + "function": "xbot_visual.web.element.data_scraping", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/批量数据抓取.html", + "video": { + "time": "12:30" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.DataScrapingControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.DataScrapingHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "table_element", + "label": "抓取目标", + "required": true, + "tips": "要抓取的表格元素", + "autoFill": false, + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "table" + } + }, + { + "name": "handle_pager", + "label": "抓取页数", + "required": true, + "default": "13:False", + "tips": "是否要处理分页,勾选后可抓取多页数据", + "type": "bool", + "editor": { + "label": "抓取多页", + "kind": "checkbox" + } + }, + { + "name": "page_element", + "label": "下一页按钮", + "required": false, + "tips": "分页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "scrape_multi_page", + "label": "", + "required": "false", + "default": "13:False", + "type": "bool", + "editor": { + "label": "", + "kind": "checkbox" + } + }, + { + "name": "max_page", + "label": "页数", + "required": false, + "default": "10:", + "tips": "要抓取的最大页数(必填)", + "type": "any", + "editor": { + "kind": "textbox", + "placeholder": "请填写要抓取的页数" + } + }, + { + "name": "page_interval", + "label": "翻页间隔(秒)", + "required": false, + "default": "10:1", + "category": "advanced", + "tips": "为了获取某些动态加载的数据,需要在抓取数据前等待其加载,\"翻页间隔\"即是在抓取数据前的等待时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "simulate_click_page", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "如果使用模拟人工点击则通过模拟人工的方式触发点击事件,否则将根据目标元素的自动化接口触发点击", + "type": "bool", + "editor": { + "label": "模拟人工点击翻页按钮", + "kind": "checkbox" + } + }, + { + "name": "scroll_to_bottom", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "抓取前会自动滚动以加载页面。可在不需要自动滚动时取消勾选", + "type": "bool", + "editor": { + "label": "自动滚到页面底部", + "kind": "checkbox" + } + }, + { + "name": "simulate_delay", + "label": "", + "required": false, + "default": "13:False", + "tips": "模拟真人在翻页操作之间随机停顿", + "category": "advanced", + "type": "bool", + "editor": { + "label": "模拟翻页停顿", + "kind": "checkbox" + } + }, + { + "name": "min_time", + "label": "最小停顿时长(秒)", + "required": false, + "tips": "指令执行完成后的最短等待时间", + "type": "int", + "default": "10:1", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "max_time", + "label": "最大停顿时长(秒)", + "required": false, + "tips": "指令执行完成后的最长等待时间", + "type": "int", + "default": "10:3", + "editor": { + "kind": "textbox", + "minValue": 1 + } + }, + { + "name": "save_to_datasheet", + "label": "", + "required": true, + "default": "13:True", + "tips": "是否将结果保存至数据表格", + "type": "bool", + "editor": { + "label": "保存至数据表格", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "data_table", + "label": "保存批量数据至", + "variableLabel": "批量数据", + "tips": "指定一个变量名称,该变量用于保存获取到的网页批量数据", + "name": "web_data_table", + "type": "list" + } + ] + }, + { + "name": "web.element.foreach_element", + "statement": "workflow.forin", + "function": "xbot_visual.web.element.iter_all_elements", + "title": "循环相似元素(web)", + "description": "依次循环网页中相似元素列表的每一项进行自动化操作", + "comment": "从网页%browser%中获取相似元素%selector%,将结果依次循环保存到%loop_item%", + "indent": "1", + "scope": "1", + "isLoop": true, + "icon": "BlockIcons/3-8.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/相似元素操作/循环相似元素(web).html", + "video": { + "time": "03:18" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.ForInControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Element.ForeachElementHandler", + "settings": { + "inputName": "output_with_index", + "outputName": "loop_index" + } + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "required": true, + "tips": "选择相似元素的控件", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "operation", + "label": "元素操作", + "required": true, + "default": "10:element", + "defaultDisplay": "元素操作", + "tips": "设置循环的相似元素内容:元素对象or元素的信息,比如文本内容等", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "获取元素对象", + "value": "element" + }, + { + "display": "获取元素文本内容", + "value": "text" + }, + { + "display": "获取元素值", + "value": "value" + }, + { + "display": "获取元素链接地址", + "value": "href" + }, + { + "display": "获取元素源代码", + "value": "html" + }, + { + "display": "获取元素属性", + "value": "attr" + } + ] + } + }, + { + "name": "absolute_url", + "label": "", + "default": "13:False", + "tips": "智能识别并补充地址前缀(http:// 或 https://)", + "type": "bool", + "editor": { + "label": "智能识别并补充地址前缀(http:// 或 https://)", + "kind": "checkbox" + } + }, + { + "name": "attribute_name", + "label": "属性名称", + "tips": "填写要获取的网页元素的属性名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "超时时间(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "loop_start_index", + "label": "循环开始位置", + "required": false, + "category": "advanced", + "default": "10:0", + "tips": "循环开始位置,0表示第一项", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "loop_end_index", + "label": "循环结束位置", + "required": false, + "category": "advanced", + "default": "10:-1", + "tips": "循环结束位置,-1表示倒数第一项,结果包含结束位置的项", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "output_with_index", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否输出循环项的位置", + "type": "bool", + "editor": { + "label": "输出循环项的位置", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "loop_item", + "label": "保存当前循环项至", + "variableLabel": "当前循环项的元素对象", + "tips": "指定一个变量名称,用于存储一组相似元素中的当前循环项", + "name": "web_loop_element", + "type": "xbot._web.element.WebElement" + }, + { + "id": "loop_index", + "label": "保存当前循环位置至", + "variableLabel": "当前循环项的位置", + "tips": "指定一个变量名称,用于存储一组相似元素中的当前循环项的位置", + "name": "web_loop_element_index", + "type": "int" + } + ] + }, + { + "name": "web.element.drag_to", + "title": "拖拽元素(web)", + "keywords": "拖动;滑动", + "description": "在指定的网页中将元素拖拽到指定位置", + "comment": "将元素拖拽到指定位置", + "icon": "BlockIcons/2-10.png", + "function": "xbot_visual.web.element.drag_to", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.DragElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/元素拖拽(web).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.DragElementToHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "elementType": "xbot._web.browser.WebBrowser" + } + }, + { + "name": "drag_way", + "label": "拖拽方式", + "required": true, + "default": "10:default", + "defaultDisplay": "拖拽至目标点", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "拖拽至目标点", + "value": "default" + }, + { + "display": "拖拽至目标元素上", + "value": "targetElement" + } + ] + } + }, + { + "name": "target_element", + "label": "操作目标", + "tips": "要操作的元素,可以从元素列表中选择一个录制好的网页元素,也可以使用动态元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "left", + "label": "X", + "default": "10:0", + "tips": "鼠标移动到的目标位置的横坐标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "top", + "label": "Y", + "default": "10:0", + "tips": "鼠标移动到的目标位置的纵坐标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "delay_after", + "label": "延迟时间(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "anchor_type", + "label": "鼠标按下位置锚点", + "required": true, + "tips": "支持鼠标在拖拽元素中心位置、随机位置(在元素矩形范围内)、自定义位置处按下", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "default": "10:middleCenter", + "label": "鼠标按下元素部位", + "tips": "默认鼠标在拖拽元素的中心位置按下,根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "move_speed", + "label": "移动速度", + "required": false, + "category": "advanced", + "default": "10:middle", + "defaultDisplay": "中速", + "tips": "选择移动鼠标的速度", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "瞬间", + "value": "instant" + }, + { + "display": "快速", + "value": "fast" + }, + { + "display": "中速", + "value": "middle" + }, + { + "display": "慢速", + "value": "slow" + } + ] + } + }, + { + "name": "release_anchor_type", + "label": "鼠标释放位置锚点", + "required": true, + "tips": "支持鼠标在拖拽至元素的中心位置、随机位置(在元素矩形范围内)、自定义位置释放", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "release_sudoku_part", + "default": "10:middleCenter", + "label": "鼠标释放元素部位", + "tips": "默认鼠标在拖拽至元素的中心位置释放,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "release_offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "release_offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.get_select_item", + "title": "获取下拉框选项(web)", + "description": "获取网页中下拉框的选项", + "comment": "获取网页%browser%中%element%的%get_way%,将结果保存到%select_items%", + "icon": "BlockIcons/2-10.png", + "function": "xbot_visual.web.element.get_select_item", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Element.GetSelectItemHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/数据提取/获取下拉框选项(web).html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "elementType": "xbot._web.browser.WebBrowser" + } + }, + { + "name": "get_way", + "label": "获取内容", + "required": true, + "default": "10:selected", + "defaultDisplay": "当前选中项", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "当前选中项", + "value": "selected" + }, + { + "display": "全部下拉项", + "value": "select_all" + } + ] + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标下拉框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "select_items", + "label": "保存获取到的内容至", + "tips": "指定一个变量名称,用于存储获取到的下拉选项内容", + "name": "select_items", + "type": "list" + } + ] + }, + { + "name": "web.element.get_associated_elements", + "title": "获取关联元素(web)", + "keywords": "父元素;子元素;相邻元素", + "description": "在指定的网页中获取元素的关联元素(父元素、子元素、相邻元素)", + "comment": "获取网页%browser%中%element%的%associated_kind%对象,将对象保存到%web_element_result%", + "icon": "BlockIcons/2-11.png", + "function": "xbot_visual.web.element.get_associated_elements", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.GetAssociatedElementsControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/元素操作/获取关联元素(web).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.GetAssociatedElementsHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "associated_kind", + "label": "关联方式", + "required": true, + "default": "10:parent", + "defaultDisplay": "父元素", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "父元素", + "value": "parent" + }, + { + "display": "子元素", + "value": "child" + }, + { + "display": "相邻元素", + "value": "sibling" + } + ] + } + }, + { + "name": "child_access_kind", + "label": "子元素获取方式", + "default": "10:all", + "defaultDisplay": "所有子元素", + "tips": "指定子元素的获取方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "所有子元素", + "value": "all" + }, + { + "display": "指定位置的子元素", + "value": "index" + } + ] + } + }, + { + "name": "child_index", + "label": "子元素位置", + "default": "10:0", + "tips": "在父元素中的索引位置,从0开始计数", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "sibling_direction", + "label": "相邻方向", + "default": "10:next", + "defaultDisplay": "下一个相邻元素", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "上一个相邻元素", + "value": "previous" + }, + { + "display": "下一个相邻元素", + "value": "next" + } + ] + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标关联元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "web_element_result", + "label": "保存网页元素至", + "variableLabel": "网页元素", + "tips": "指定一个变量名称,该变量用于保存获取到的网页元素", + "name": "web_element_result", + "type": "xbot._web.element.WebElement" + } + ] + }, + { + "name": "web.element.upload", + "title": "上传文件", + "description": "自动完成点击上传按钮、在文件选择对话框中输入待上传文件等系列操作", + "comment": "在网页%browser%中点击%element%,在弹出的文件选择对话框中输入文件%file_name%", + "icon": "BlockIcons/4-4.png", + "function": "xbot_visual.web.element.upload", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.UploadControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/对话框处理/上传文件.html", + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "element", + "label": "上传按钮", + "required": true, + "tips": "选择要点击的上传按钮对应的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "file_name", + "label": "上传文件路径", + "required": true, + "tips": "待上传文件完整路径。若要选择多个文件,切换到Python模式下,输入文件列表,比如: [\"文件1路径\",\"文件2路径\"]", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "All Files (*.*)|*.*" + } + } + }, + { + "name": "simulate", + "label": "", + "default": "13:False", + "category": "advanced", + "tips": "如果使用模拟人工输入则通过模拟人工的方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "模拟人工输入", + "kind": "checkbox" + } + }, + { + "name": "clipboard_input", + "label": "", + "default": "13:False", + "category": "advanced", + "tips": "将输入路径和文件名添加到剪切板, 通过Ctrl+V的方式将内容填写到上传对话框的文件名输入框中,避免输入法问题", + "type": "bool", + "editor": { + "label": "剪切板输入", + "kind": "checkbox" + } + }, + { + "name": "input_type", + "label": "输入方式", + "required": true, + "tips": "自动化接口输入: 调用文件名输入框自身实现的自动化接口输入\r\n剪切板输入: 将输入路径和文件名添加到剪切板, 通过Ctrl+V的方式将内容填写到上传对话框的文件名输入框中,避免输入法问题\r\n模拟人工输入: 如果使用模拟人工输入则通过模拟人工的方式触发输入事件(会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题),否则将根据目标元素的自动化接口触发输入", + "type": "str", + "default": "10:automatic", + "defaultDisplay": "自动化接口输入", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "自动化接口输入", + "value": "automatic" + }, + { + "display": "剪切板输入", + "value": "clipboard" + }, + { + "display": "模拟人工输入", + "value": "simulate" + } + ] + } + }, + { + "name": "wait_dialog_appear_timeout", + "label": "等待对话框出现(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "点击上传按钮后,等待上传对话框出现的超时时间,单位(秒)", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "force_ime_ENG", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "存在不常见的输入法切换英文输入状态不成功的情况\r\n需要指定强制加载美式键盘(ENG), 确保模拟输入不受中文输入法影响", + "type": "bool", + "editor": { + "label": "强制加载美式键盘(ENG)", + "kind": "checkbox" + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(ms)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间(仅模拟输入有效, 对影刀浏览器该参数无效), 单位是毫秒, 为避免输入错误, 请将该值调大,最大值为1000ms", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 5 + } + }, + { + "name": "focus_timeout", + "label": "焦点超时时间(ms)", + "category": "advanced", + "default": "10:1000", + "tips": "设置焦点超时时间,单位(毫秒)", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "web.element.download", + "title": "下载文件", + "description": "自动完成点击下载按钮、在文件保存对话框中输入保存文件信息等系列操作", + "comment": "在网页%browser%中点击%download_button%下载,保存到路径%filename%下,最多等待%wait_complete_timeout%秒直到下载完成,将文件路径保存到%download_file_name%", + "icon": "BlockIcons/4-5.png", + "function": "xbot_visual.web.element.download", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Web.DownloadControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/网页自动化/对话框处理/下载文件.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Web.DownloadHandler" + } + ], + "inputs": [ + { + "name": "browser", + "label": "网页对象", + "required": true, + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "scene", + "label": "下载场景", + "required": true, + "default": "10:Button", + "defaultDisplay": "点击下载按钮", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "点击下载按钮", + "value": "Button" + }, + { + "display": "指定下载地址", + "value": "Url" + } + ] + } + }, + { + "name": "download_button", + "label": "下载按钮", + "required": false, + "tips": "选择要点击的下载按钮对应的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "download_url", + "label": "下载地址", + "required": false, + "tips": "需要下载的请求地址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "file_folder", + "label": "保存文件夹", + "required": true, + "tips": "保存下载文件的文件夹", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder", + "filter": "All Files (*.*)|*.*" + } + } + }, + { + "name": "use_custom_filename", + "label": "是否自定文件名", + "required": true, + "default": "13:False", + "tips": "是否自定义保存文件名,不勾选则使用默文件名", + "type": "bool", + "editor": { + "label": "是否自定义保存文件名", + "kind": "checkbox" + } + }, + { + "name": "file_name", + "label": "保存文件名", + "required": false, + "tips": "自定义保存的文件名", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "wait_complete", + "label": "是否等待下载完成", + "required": true, + "default": "13:True", + "tips": "若是,会在最大超时时间内一直等待,直到文件下载完成", + "type": "bool", + "editor": { + "label": "是否等待下载完成", + "kind": "checkbox" + } + }, + { + "name": "wait_complete_timeout", + "label": "超时时间(s)", + "required": false, + "default": "10:300", + "tips": "等待下载超时时间,单位(秒)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "simulate", + "label": "", + "default": "13:False", + "category": "advanced", + "tips": "如果使用模拟人工输入则通过模拟人工的方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "模拟人工输入", + "kind": "checkbox" + } + }, + { + "name": "clipboard_input", + "label": "", + "default": "13:False", + "category": "advanced", + "tips": "将输入路径和文件名添加到剪切板, 通过Ctrl+V的方式将内容填写到上传对话框的文件名输入框中,避免输入法问题", + "type": "bool", + "editor": { + "label": "剪切板输入", + "kind": "checkbox" + } + }, + { + "name": "input_type", + "label": "输入方式", + "required": true, + "tips": "自动化接口输入: 调用文件名输入框自身实现的自动化接口输入\r\n剪切板输入: 将输入路径和文件名添加到剪切板, 通过Ctrl+V的方式将内容填写到上传对话框的文件名输入框中,避免输入法问题\r\n模拟人工输入: 如果使用模拟人工输入则通过模拟人工的方式触发输入事件(会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题),否则将根据目标元素的自动化接口触发输入", + "type": "str", + "default": "10:automatic", + "defaultDisplay": "自动化接口输入", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "自动化接口输入", + "value": "automatic" + }, + { + "display": "剪切板输入", + "value": "clipboard" + }, + { + "display": "模拟人工输入", + "value": "simulate" + } + ] + } + }, + { + "name": "wait_dialog_appear_timeout", + "label": "等待对话框出现(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "点击上传按钮后,等待上传对话框出现的超时时间,单位(秒)", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "force_ime_ENG", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "存在不常见的输入法切换英文输入状态不成功的情况\r\n需要指定强制加载美式键盘(ENG), 确保模拟输入不受中文输入法影响", + "type": "bool", + "editor": { + "label": "强制加载美式键盘(ENG)", + "kind": "checkbox" + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(ms)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间(仅模拟输入有效), 单位是毫秒, 为避免输入错误, 请将该值调大,最大值为1000ms", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 5 + } + }, + { + "name": "focus_timeout", + "label": "焦点超时时间(ms)", + "category": "advanced", + "default": "10:1000", + "tips": "设置焦点超时时间,单位(毫秒)", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "download_file_name", + "label": "文件保存位置", + "tips": "下载文件所在的位置:文件路径+名称", + "name": "download_file_name", + "type": "str" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/web.service.blocks.json b/src/assert/block_settings/web.service.blocks.json new file mode 100644 index 0000000..fc657c3 --- /dev/null +++ b/src/assert/block_settings/web.service.blocks.json @@ -0,0 +1,2135 @@ +{ + "types": [ + { + "name": "xbot_visual.web_service.HttpResponse", + "localName": "HTTP请求结果", + "props": [ + { + "name": "status_code", + "type": "int", + "label": "HTTP状态码" + }, + { + "name": "headers", + "type": "dict", + "label": "HTTP响应头" + }, + { + "name": "body", + "type": "str", + "label": "HTTP响应体" + } + ] + }, + { + "name": "xbot_visual_web_service_rest_response", + "localName": "HTTP请求结果", + "pythonName": "xbot_visual._core.xbot_visual_web_service_rest_response", + "props": [ + { + "name": "status_code", + "type": "int", + "label": "状态码" + }, + { + "name": "content_type", + "type": "str", + "label": "内容类型" + }, + { + "name": "content_encoding", + "type": "str", + "label": "内容编码" + }, + { + "name": "content", + "type": "str", + "label": "响应内容" + } + ] + } + ], + "blocks": [ + { + "name": "web_service.http_request", + "icon": "BlockIcons/34-1.png", + "description": "Http 请求", + "comment": "使用%method%方法请求%url%网页,将请求结果保存到%http_response%", + "title": "Http 请求", + "function": "xbot_visual.web_service.http_request", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/http/http请求.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.HttpRequest, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WebService.HttpRequestHandler" + } + ], + "inputs": [ + { + "name": "url", + "label": "网址", + "required": true, + "tips": "输入目标网址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "method", + "label": "方法", + "required": true, + "default": "10:GET", + "defaultDisplay": "GET", + "tips": "选择目标网页的操作方法", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "GET", + "value": "GET" + }, + { + "display": "POST", + "value": "POST" + }, + { + "display": "CONNECT", + "value": "CONNECT" + }, + { + "display": "HEAD", + "value": "HEAD" + }, + { + "display": "PUT", + "value": "PUT" + }, + { + "display": "DELETE", + "value": "DELETE" + }, + { + "display": "OPTIONS", + "value": "OPTIONS" + }, + { + "display": "TRACE", + "value": "TRACE" + }, + { + "display": "PATCH", + "value": "PATCH" + } + ] + } + }, + { + "name": "accept", + "label": "Accept", + "required": true, + "default": "10:text/html", + "defaultDisplay": "text/html", + "tips": "设置HTTP协议头的Accept字段值", + "type": "str", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "content_type", + "label": "Content Type", + "required": true, + "default": "10:text/html", + "defaultDisplay": "text/html", + "tips": "设置HTTP协议头的Content-Type字段值", + "type": "str", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "custom_headers", + "label": "自定义协议头", + "required": false, + "tips": "自定义协议头,多行,每行格式为“协议头名称:协议头内容”", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "request_body", + "label": "自定义协议体", + "required": false, + "tips": "自定义协议体,填写待发送到服务器的内容", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "return_data_save_way", + "label": "返回数据保存方式", + "required": true, + "default": "10:save_to_variable", + "defaultDisplay": "保存到变量(网页)", + "tips": "选择返回数据保存方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "保存到变量(网页)", + "value": "save_to_variable" + }, + { + "display": "保存到硬盘(文件)", + "value": "save_to_disk" + } + ] + } + }, + { + "name": "file_save_way", + "label": "文件保存方式", + "required": false, + "default": "10:specify_folder", + "defaultDisplay": "指定保存目录(保留原始文件名)", + "tips": "选择返回数据保存方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "指定保存目录(保留原始文件名)", + "value": "specify_folder" + }, + { + "display": "指定全路径(保存目录+文件名)", + "value": "specify_full_path" + } + ] + } + }, + { + "name": "folder_save_path", + "label": "保存到目录", + "required": false, + "tips": "输入保存路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "file_save_path", + "label": "保存到文件", + "required": false, + "tips": "输入保存路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile" + } + } + }, + { + "name": "connect_timeout_seconds", + "label": "连接超时秒数", + "required": true, + "default": "10:30", + "category": "advanced", + "tips": "输入连接超时秒数", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "follow_redirection", + "label": "", + "required": true, + "category": "advanced", + "tips": "是否支持网页重定向", + "type": "bool", + "default": "13:True", + "editor": { + "label": "重定向", + "kind": "checkbox" + } + }, + { + "name": "fail_on_error_status", + "label": "", + "required": true, + "category": "advanced", + "tips": "是否失败时抛出异常", + "type": "bool", + "default": "13:False", + "editor": { + "label": "失败时抛出异常", + "kind": "checkbox" + } + }, + { + "name": "encode_request_body", + "label": "", + "required": true, + "category": "advanced", + "tips": "是否编码协议体", + "type": "bool", + "default": "13:False", + "editor": { + "label": "编码协议体", + "kind": "checkbox" + } + }, + { + "name": "user_agent", + "label": "User Agent", + "required": true, + "category": "advanced", + "default": "10:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.355.0 Safari/533.3", + "defaultDisplay": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.355.0 Safari/533.3", + "tips": "设置HTTP协议头的User Agent字段值", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6", + "value": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6" + }, + { + "display": "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)", + "value": "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)" + }, + { + "display": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.355.0 Safari/533.3", + "value": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.355.0 Safari/533.3" + }, + { + "display": "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7", + "value": "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" + } + ] + } + }, + { + "name": "encoding", + "label": "返回数据编码格式", + "required": true, + "category": "advanced", + "default": "10:utf-8", + "defaultDisplay": "utf-8", + "tips": "设置HTTP协议头的User Agent字段值", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "自动检测", + "value": "Auto-detect" + }, + { + "display": "utf-8", + "value": "utf-8" + }, + { + "display": "gb2312", + "value": "gb2312" + }, + { + "display": "big5", + "value": "big5" + } + ] + } + }, + { + "name": "http_authentication", + "label": "", + "required": false, + "category": "advanced", + "tips": "HTTP 验证", + "type": "bool", + "default": "13:False", + "editor": { + "label": "HTTP 验证", + "kind": "checkbox" + } + }, + { + "name": "user_name", + "label": "用户名", + "required": false, + "category": "advanced", + "tips": "输入用户名", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "password", + "label": "密码", + "required": false, + "category": "advanced", + "tips": "输入密码", + "type": "str", + "editor": { + "kind": "password" + } + } + ], + "outputs": [ + { + "id": "http_response", + "label": "保存响应文件头到", + "tips": "指定一个变量名称,该变量用于存储响应协议头", + "name": "http_response", + "type": "xbot_visual.web_service.HttpResponse" + } + ] + }, + { + "name": "web_service.http_download", + "icon": "BlockIcons/34-2.png", + "description": "Http 下载", + "comment": "使用%method%方法向%url%网址发起下载请求,将结果保存到%file_instance%", + "title": "Http 下载", + "function": "xbot_visual.web_service.http_download", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/http/http下载.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.HttpDownload, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WebService.HttpDownloadHandler" + } + ], + "inputs": [ + { + "name": "url", + "label": "网址", + "required": true, + "tips": "输入目标网址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "method", + "label": "方法", + "required": true, + "default": "10:GET", + "defaultDisplay": "GET", + "tips": "选择目标网页的操作方法", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "GET", + "value": "GET" + }, + { + "display": "POST", + "value": "POST" + } + ] + } + }, + { + "name": "post_parameters", + "label": "Post 参数", + "required": false, + "tips": "Post 参数", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "return_data_save_way", + "label": "返回数据保存方式", + "required": true, + "default": "10:save_to_variable", + "defaultDisplay": "保存到变量(网页)", + "tips": "选择返回数据保存方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "保存到变量(网页)", + "value": "save_to_variable" + }, + { + "display": "保存到硬盘(文件)", + "value": "save_to_disk" + } + ] + } + }, + { + "name": "file_save_way", + "label": "文件保存方式", + "required": false, + "default": "10:specify_folder", + "defaultDisplay": "指定保存目录(保留原始文件名)", + "tips": "选择返回数据保存方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "指定保存目录(保留原始文件名)", + "value": "specify_folder" + }, + { + "display": "指定全路径(保存目录+文件名)", + "value": "specify_full_path" + } + ] + } + }, + { + "name": "folder_save_path", + "label": "保存到目录", + "required": false, + "tips": "输入保存路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "file_save_path", + "label": "文件保存路径", + "required": false, + "tips": "输入保存路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile" + } + } + }, + { + "name": "connect_timeout_seconds", + "label": "连接超时秒数", + "required": true, + "default": "10:30", + "category": "advanced", + "tips": "输入连接超时秒数", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "follow_redirection", + "label": "", + "required": true, + "category": "advanced", + "tips": "是否支持网页重定向", + "type": "bool", + "default": "13:True", + "editor": { + "label": "重定向", + "kind": "checkbox" + } + }, + { + "name": "user_agent", + "label": "User Agent", + "required": true, + "category": "advanced", + "default": "10:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.355.0 Safari/533.3", + "defaultDisplay": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.355.0 Safari/533.3", + "tips": "设置HTTP协议头的User Agent字段值", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6", + "value": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.21) Gecko/20100312 Firefox/3.6" + }, + { + "display": "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)", + "value": "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)" + }, + { + "display": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.355.0 Safari/533.3", + "value": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.3 (KHTML, like Gecko) Chrome/5.0.355.0 Safari/533.3" + }, + { + "display": "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7", + "value": "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7" + } + ] + } + }, + { + "name": "encoding", + "label": "返回数据编码格式", + "required": true, + "category": "advanced", + "default": "10:utf-8", + "defaultDisplay": "utf-8", + "tips": "设置HTTP协议头的User Agent字段值", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "自动检测", + "value": "Auto-detect" + }, + { + "display": "utf-8", + "value": "utf-8" + }, + { + "display": "gb2312", + "value": "gb2312" + }, + { + "display": "big5", + "value": "big5" + } + ] + } + }, + { + "name": "http_authentication", + "label": "", + "required": false, + "category": "advanced", + "tips": "HTTP 验证", + "type": "bool", + "default": "13:False", + "editor": { + "label": "HTTP 验证", + "kind": "checkbox" + } + }, + { + "name": "user_name", + "label": "用户名", + "required": false, + "category": "advanced", + "tips": "输入用户名", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "password", + "label": "密码", + "required": false, + "category": "advanced", + "tips": "输入密码", + "type": "str", + "editor": { + "kind": "password" + } + } + ], + "outputs": [ + { + "id": "file_instance", + "label": "保存下载的文件到", + "tips": "指定一个变量名称,该变量用于存储下载的文件内容", + "name": "file_instance", + "type": "str" + } + ] + }, + { + "name": "web_service.send_dingtalk_msg", + "icon": "BlockIcons/33-2.png", + "description": "发送内容至钉钉群", + "comment": "发送内容至钉钉群", + "title": "钉钉群通知", + "function": "xbot_visual.web_service.send_dingtalk_msg", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.SendDingTalkMsgControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/企业群通知/钉钉群通知.html", + "inputs": [ + { + "name": "webhook", + "label": "机器人地址", + "required": true, + "tips": "机器人的网络地址, 即webhook, 需要自行申请", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "secret", + "label": "密钥", + "required": true, + "tips": "机器人安全设置页面,加签一栏下面显示的SEC开头的字符串", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "msgtype", + "label": "消息格式类型", + "required": true, + "default": "10:text", + "defaultDisplay": "文本类型", + "tips": "消息类型及数据格式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文本类型", + "value": "text" + }, + { + "display": "markdown类型", + "value": "markdown" + } + ] + } + }, + { + "name": "text_content", + "label": "文本内容", + "tips": "文本内容", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "markdown_text", + "label": "markdown内容", + "tips": "markdown格式的消息", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "at_mobiles", + "label": "@某人", + "tips": "填写需@成员所绑定的手机号码。多个成员时需切换为 Python 模式后输入号码列表,如['手机号1','手机号2']", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "135xxxxxxxx" + } + }, + { + "name": "is_at_all", + "tips": "@所有人", + "type": "bool", + "default": "13:False", + "editor": { + "kind": "checkbox", + "label": "@所有人" + } + } + ] + }, + { + "name": "web_service.send_wxwork_msg", + "icon": "BlockIcons/33-1.png", + "description": "发送内容至企业微信群", + "keywords": "企微", + "comment": "发送内容至企业微信群", + "title": "企业微信群通知", + "function": "xbot_visual.web_service.send_wxwork_msg", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/企业群通知/企业微信群通知.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.SendWXWorkMsgControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "webhook", + "label": "机器人地址", + "required": true, + "tips": "机器人的网络地址, 即webhook, 需要自行申请", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "msgtype", + "label": "消息格式类型", + "required": true, + "default": "10:text", + "defaultDisplay": "文本类型", + "tips": "消息类型及数据格式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文本类型", + "value": "text" + }, + { + "display": "markdown类型", + "value": "markdown" + }, + { + "display": "文件类型", + "value": "file" + }, + { + "display": "图片类型", + "value": "image" + } + ] + } + }, + { + "name": "text_content", + "label": "文本内容", + "tips": "文本内容,最长不超过2048个字节", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "markdown_content", + "label": "markdown内容", + "tips": "markdown内容,最长不超过4096个字节", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "file_path", + "label": "文件路径", + "tips": "要求文件大小在5B~20M之间", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件(*.*)|*.*" + } + } + }, + { + "name": "image_file_path", + "label": "图片路径", + "tips": "最大不能超过2M,支持JPG,PNG格式", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.png)|*.jpg;*.png" + } + } + }, + { + "name": "at_mobiles", + "label": "@某人", + "tips": "填写需@成员所绑定的手机号码。多个成员时需切换为 Python 模式后输入号码列表,如['手机号1','手机号2']", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "135xxxxxxxx" + } + }, + { + "name": "is_at_all", + "tips": "@所有人", + "type": "bool", + "default": "13:False", + "editor": { + "kind": "checkbox", + "label": "@所有人" + } + } + ] + }, + { + "name": "web_service.send_feishu_msg", + "icon": "BlockIcons/33-3.png", + "description": "发送内容至飞书群", + "comment": "发送内容至飞书群", + "title": "飞书群通知", + "function": "xbot_visual.web_service.send_feishu_msg", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/企业群通知/飞书群通知.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.SendFeiShuMsgControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WebService.SendFeiShuMsgHandler" + } + ], + "inputs": [ + { + "name": "webhook", + "label": "机器人地址", + "required": true, + "tips": "机器人的网络地址, 即webhook, 需要自行申请", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "secret", + "label": "签名校验", + "tips": "机器人安全设置中的签名校验,如果没设置签名校验,则不需要输入", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "msgtype", + "label": "消息格式类型", + "required": true, + "default": "10:text", + "defaultDisplay": "文本类型", + "tips": "消息类型及数据格式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文本类型", + "value": "text" + }, + { + "display": "图片类型", + "value": "image" + }, + { + "display": "富文本类型", + "value": "post" + }, + { + "display": "消息卡片类型", + "value": "interactive" + } + ] + } + }, + { + "name": "text_content", + "label": "文本内容", + "tips": "文本内容", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "app_id", + "label": "app_id", + "tips": "用于获取tenant_access_token,请在使用文档中查看如何获取,在富文本消息和消息卡片中,如果不包含图片或者不需要通过电话或邮箱@用户,则不需要输入", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "app_secret", + "label": "app_secret", + "tips": "用于获取tenant_access_token,请在使用说明中查看如何获取,在发送富文本消息和消息卡片中,如果不包含图片或者不需要通过电话或邮箱@用户,则不需要输入", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_file_path", + "label": "图片路径", + "tips": "最大不能超过10M,支持JPG,PNG格式", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.png)|*.jpg;*.png" + } + } + }, + { + "name": "post_content", + "label": "富文本内容", + "tips": "富文本内容,格式内容请查看使用说明文档", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "interactive_content", + "label": "消息卡片内容", + "tips": "消息卡片内容,格式内容请查看使用说明文档", + "type": "str", + "editor": { + "kind": "memoedit" + } + } + ] + }, + { + "name": "web_service.rest_request", + "icon": "BlockIcons/34-1.png", + "description": "Http 请求", + "comment": "使用%method%方法请求%url%,将结果保存到%http_response%", + "title": "Http 请求", + "function": "xbot_visual.web_service.rest_request", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/http/http请求.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.RestRequest, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WebService.RestRequestHandler" + } + ], + "inputs": [ + { + "name": "url", + "label": "URL", + "required": true, + "tips": "请输入请求地址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "method", + "label": "方法", + "required": true, + "default": "10:GET", + "defaultDisplay": "GET", + "tips": "选择操作方法", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "GET", + "value": "GET" + }, + { + "display": "POST", + "value": "POST" + }, + { + "display": "CONNECT", + "value": "CONNECT" + }, + { + "display": "HEAD", + "value": "HEAD" + }, + { + "display": "PUT", + "value": "PUT" + }, + { + "display": "DELETE", + "value": "DELETE" + }, + { + "display": "OPTIONS", + "value": "OPTIONS" + }, + { + "display": "TRACE", + "value": "TRACE" + }, + { + "display": "PATCH", + "value": "PATCH" + } + ] + } + }, + { + "name": "headers", + "label": "协议头", + "required": false, + "tips": "协议头,多行,每行格式为“协议头名称:协议头内容”", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "body", + "label": "协议体", + "required": false, + "tips": "协议体,填写待发送到服务器的内容", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "save_to_file", + "label": "响应结果保存到文件", + "required": false, + "category": "advanced", + "default": "13:False", + "tips": "将响应结果保存到文本中", + "type": "bool", + "editor": { + "label": "响应结果保存到文件", + "kind": "checkbox" + } + }, + { + "name": "save_folder", + "label": "文件保存目录", + "required": false, + "category": "advanced", + "tips": "输入要保存到文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "save_filename", + "label": "文件名称", + "required": false, + "category": "advanced", + "tips": "输入要保存到的文件名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "connect_timeout_seconds", + "label": "连接超时秒数", + "required": true, + "default": "10:30", + "category": "advanced", + "tips": "输入连接超时秒数", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "send_by_web", + "label": "通过网页发送Http请求", + "required": false, + "category": "advanced", + "default": "13:False", + "tips": "适用场景:请求需要认证信息才可以发送成功。请选择已完成认证的相应网页", + "type": "bool", + "editor": { + "label": "通过网页发送Http请求", + "kind": "checkbox" + } + }, + { + "name": "browser", + "label": "网页对象", + "required": false, + "category": "advanced", + "tips": "输入一个通过\"获取已打开网页对象\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ], + "outputs": [ + { + "id": "http_response", + "label": "保存响应结果到", + "tips": "指定一个变量名称,该变量用于存储响应信息", + "name": "http_response", + "type": "xbot_visual_web_service_rest_response" + } + ] + }, + { + "name": "web_service.download", + "icon": "BlockIcons/34-2.png", + "description": "Http 下载", + "comment": "向%url%发起下载请求,将下载文件保存到文件夹%save_folder%中,使用默认文件名,将下载文件名保存到%http_dowload_filename%", + "title": "Http 下载", + "function": "xbot_visual.web_service.download", + "helpUrl": "yddoc/language/zh-cn/指令文档/其他/http/http下载.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.Download, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WebService.DownloadHandler" + } + ], + "inputs": [ + { + "name": "url", + "label": "下载地址", + "required": true, + "tips": "请输入下载地址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "save_folder", + "label": "文件保存目录", + "required": false, + "tips": "输入要保存到文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "custom_filename", + "label": "指定文件名", + "required": false, + "default": "13:False", + "tips": "若不指定,用默认文件名。若没有默认文件名会抛异常", + "type": "bool", + "editor": { + "label": "指定文件名", + "kind": "checkbox" + } + }, + { + "name": "save_filename", + "label": "文件名称", + "required": false, + "tips": "输入要保存到的文件名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "wait_complete_timeout", + "label": "超时时间(秒)", + "required": true, + "default": "10:300", + "tips": "等待下载超时时间,单位(秒)", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "connect_timeout_seconds", + "label": "连接超时秒数", + "required": true, + "default": "10:30", + "category": "advanced", + "tips": "输入连接超时秒数", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "send_by_web", + "label": "通过网页发送Http请求", + "required": false, + "default": "13:False", + "category": "advanced", + "tips": "适用场景:请求需要认证信息才可以发送成功。请选择已完成认证的相应网页", + "type": "bool", + "editor": { + "label": "通过网页发送Http请求", + "kind": "checkbox" + } + }, + { + "name": "browser", + "label": "网页对象", + "required": false, + "category": "advanced", + "tips": "输入一个通过\"获取已打开网页对象\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ], + "outputs": [ + { + "id": "http_dowload_filename", + "label": "保存下载文件名称到", + "tips": "指定一个变量名称,该变量用于存储保存下载文件名称(包括路径)", + "name": "http_download_filename", + "type": "str" + } + ] + }, + { + "name": "web_service.captcha", + "icon": "BlockIcons/23-1.png", + "description": "基于图鉴网络科技提供的验证码识别服务", + "comment": "提取%image_source%中类型为%captcha_type%的验证码信息", + "title": "验证码识别", + "function": "xbot_visual.web_service.captcha", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.CaptchaControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/ocr/验证码识别.html", + "inputs": [ + { + "name": "username", + "label": "用户名", + "required": true, + "tips": "需要在图鉴网络科技官网注册申请, 具体操作详见使用说明", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "password", + "label": "密码", + "required": true, + "tips": "需要在图鉴网络科技官网注册申请, 具体操作详见使用说明", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "captcha_type", + "label": "验证码类型", + "required": true, + "default": "10:3", + "defaultDisplay": "数英混合", + "tips": "请选择要识别的验证码类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "数英混合", + "value": "3" + }, + { + "display": "问答题", + "value": "66" + }, + { + "display": "计算题", + "value": "11" + }, + { + "display": "快速计算题", + "value": "1005" + }, + { + "display": "单缺口滑块(返回X轴坐标)", + "value": "33" + }, + { + "display": "缺口识别", + "value": "18" + }, + { + "display": "点选1个坐标", + "value": "19" + }, + { + "display": "点选3个坐标", + "value": "20" + }, + { + "display": "点选3~5个坐标", + "value": "21" + }, + { + "display": "点选5~8个坐标", + "value": "22" + }, + { + "display": "点选1~4个坐标", + "value": "27" + }, + { + "display": "图片旋转", + "value": "29" + }, + { + "display": "图片拼图", + "value": "53" + }, + { + "display": "纯数字", + "value": "1" + }, + { + "display": "纯英文", + "value": "2" + }, + { + "display": "纯数字2", + "value": "1001" + }, + { + "display": "纯英文2", + "value": "1002" + }, + { + "display": "数英混合2", + "value": "1003" + }, + { + "display": "汉字", + "value": "16" + }, + { + "display": "无感学习", + "value": "7" + }, + { + "display": "通用文字识别(证件、单据)", + "value": "32" + }, + { + "display": "描绘轨迹", + "value": "48" + } + ] + } + }, + { + "name": "image_source", + "label": "图片来源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕指定位置", + "tips": "选择一个验证码来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕指定位置", + "value": "screen" + }, + { + "display": "网页元素", + "value": "web_element" + }, + { + "display": "win元素", + "value": "win_element" + }, + { + "display": "剪贴板", + "value": "clipboard" + } + ] + } + }, + { + "name": "image_browser", + "label": "网页对象", + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_web_selector", + "label": "操作目标", + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "image_window", + "label": "窗口对象", + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_win_selector", + "label": "操作目标", + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "image_region_x1", + "label": "X1", + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_region_y1", + "label": "Y1", + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_region_x2", + "label": "X2", + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_region_y2", + "label": "Y2", + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "imageback_source", + "label": "背景图来源", + "default": "10:screen", + "defaultDisplay": "屏幕指定位置", + "tips": "选择一个背景图来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕指定位置", + "value": "screen" + }, + { + "display": "网页元素", + "value": "web_element" + }, + { + "display": "win元素", + "value": "win_element" + }, + { + "display": "剪贴板", + "value": "clipboard" + } + ] + } + }, + { + "name": "imageback_browser", + "label": "网页对象", + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "imageback_web_selector", + "label": "操作目标", + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "imageback_window", + "label": "窗口对象", + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "imageback_win_selector", + "label": "操作目标", + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "imageback_region_x1", + "label": "X1", + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "imageback_region_y1", + "label": "Y1", + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "imageback_region_x2", + "label": "X2", + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "imageback_region_y2", + "label": "Y2", + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "typename", + "label": "子类型名称", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "remark", + "label": "备注字段", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "captcha_result", + "label": "保存验证码识别结果至", + "variableLabel": "验证码识别结果", + "tips": "指定一个变量名称,该变量用于保存验证码识别结果", + "name": "captcha_result", + "type": "str" + } + ] + }, + { + "name": "web_service.captcha_paid", + "icon": "BlockIcons/23-1.png", + "description": "基于AI引擎提供的验证码识别服务", + "comment": "使用%engine_type%AI引擎,识别%image_source%中类型为%captcha_type%的验证码信息,将结果保存到%captcha_result%", + "title": "验证码识别", + "function": "xbot_visual.web_service.captcha", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.WebService.CaptchaPaidControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/ocr/验证码识别.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WebService.CaptchaHandler" + } + ], + "inputs": [ + { + "name": "engine_type", + "label": "识别引擎", + "tips": "选择一个识别引擎", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "value": "shadowbot", + "display": "影刀" + }, + { + "value": "ttshitu", + "display": "图鉴" + } + ] + } + }, + { + "name": "username", + "label": "用户名", + "tips": "需要在图鉴网络科技官网注册申请, 具体操作详见使用说明", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "password", + "label": "密码", + "tips": "需要在图鉴网络科技官网注册申请, 具体操作详见使用说明", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "captcha_type", + "label": "验证码类型", + "required": true, + "default": "10:3", + "defaultDisplay": "数英混合", + "tips": "请选择要识别的验证码类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "纯数字", + "value": "1" + }, + { + "display": "纯数字2", + "value": "1001" + }, + { + "display": "纯英文", + "value": "2" + }, + { + "display": "纯英文2", + "value": "1002" + }, + { + "display": "数英混合", + "value": "3" + }, + { + "display": "数英混合2", + "value": "1003" + }, + { + "display": "闪动GIF", + "value": "4" + }, + { + "display": "计算题", + "value": "11" + }, + { + "display": "快速计算题", + "value": "1005" + }, + { + "display": "通用文字识别(证件、单据)", + "value": "32" + }, + { + "display": "问答题", + "value": "66" + }, + { + "display": "图片旋转", + "value": "29" + }, + { + "display": "点选1个坐标", + "value": "19" + }, + { + "display": "点选3个坐标", + "value": "20" + }, + { + "display": "点选1~4个坐标", + "value": "27" + }, + { + "display": "点选3~5个坐标", + "value": "21" + }, + { + "display": "点选5~8个坐标", + "value": "22" + }, + { + "display": "缺口识别", + "value": "18" + }, + { + "display": "单缺口滑块(返回X轴坐标)", + "value": "33" + }, + { + "display": "图片拼图", + "value": "53" + } + ] + } + }, + { + "name": "third_party_code", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_source", + "label": "图片来源", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕指定位置", + "tips": "选择一个验证码来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕指定位置", + "value": "screen" + }, + { + "display": "网页元素", + "value": "web_element" + }, + { + "display": "win元素", + "value": "win_element" + }, + { + "display": "剪贴板", + "value": "clipboard" + }, + { + "display": "本地文件", + "value": "image_file" + } + ] + } + }, + { + "name": "image_file", + "label": "文件路径", + "tips": "选择本地需要识别的图片文件", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.PNG)|*.png|(.JPEG)|*.jpeg|(.JPG)|*.jpg|(*.*)|*.*" + } + } + }, + { + "name": "image_browser", + "label": "网页对象", + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_web_selector", + "label": "操作目标", + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "image_window", + "label": "窗口对象", + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_win_selector", + "label": "操作目标", + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "image_region_x1", + "label": "X1", + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_region_y1", + "label": "Y1", + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_region_x2", + "label": "X2", + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "image_region_y2", + "label": "Y2", + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "imageback_source", + "label": "背景图来源", + "default": "10:screen", + "defaultDisplay": "屏幕指定位置", + "tips": "选择一个背景图来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕指定位置", + "value": "screen" + }, + { + "display": "网页元素", + "value": "web_element" + }, + { + "display": "win元素", + "value": "win_element" + }, + { + "display": "剪贴板", + "value": "clipboard" + }, + { + "display": "本地文件", + "value": "image_file" + } + ] + } + }, + { + "name": "back_image_file", + "label": "文件路径", + "tips": "选择本地需要识别的图片文件", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "所有文件 (.PNG)|*.png|(.JPEG)|*.jpeg|(.JPG)|*.jpg|(*.*)|*.*" + } + } + }, + { + "name": "imageback_browser", + "label": "网页对象", + "tips": "输入一个获取到的或者通过\"打开网页\"创建的网页对象", + "type": "xbot._web.browser.WebBrowser", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "imageback_web_selector", + "label": "操作目标", + "tips": "选择要操作的网页元素", + "type": "xbot._web.element.WebElement", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "imageback_window", + "label": "窗口对象", + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "imageback_win_selector", + "label": "操作目标", + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "imageback_region_x1", + "label": "X1", + "tips": "图片左上角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "imageback_region_y1", + "label": "Y1", + "tips": "图片左上角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "imageback_region_x2", + "label": "X2", + "tips": "图片右下角X值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "imageback_region_y2", + "label": "Y2", + "tips": "图片右下角Y值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "typename", + "label": "子类型名称", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "is_to96dpi", + "label": "", + "required": false, + "category": "advanced", + "default": "13:False", + "tips": "是否需要将位置信息值转换成与设备无关的单位 (每个单位1/96英寸)", + "type": "bool", + "editor": { + "label": "转为dpi为96对应值", + "kind": "checkbox" + } + }, + { + "name": "remark", + "label": "备注字段", + "tips": "", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "captcha_result", + "label": "保存验证码识别结果至", + "variableLabel": "验证码识别结果", + "tips": "指定一个变量名称,该变量用于保存验证码识别结果", + "name": "captcha_result", + "type": "str" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/win32.blocks.json b/src/assert/block_settings/win32.blocks.json new file mode 100644 index 0000000..8ee84cf --- /dev/null +++ b/src/assert/block_settings/win32.blocks.json @@ -0,0 +1,808 @@ +{ + "types": [ + { + "name": "xbot.win32.window.Win32Window", + "localName": "窗口对象", + "methods": [ + { + "display": "该窗口的标题", + "function": "$0.get_detail('title')", + "type": "str" + }, + { + "display": "该窗口的进程名称", + "function": "$0.get_detail('process_name')", + "type": "str" + } + ] + } + ], + "blocks": [ + { + "name": "win32.manual_motion_on", + "title": "开启模拟真人操作", + "description": "一次对多个鼠标操作指令用模拟真人的操作习惯运行(从开启到结束区间内的指令)", + "comment": "开启仿真操作,区间内的所有鼠标操作指令将依据设置,模拟真人操作习惯运行", + "icon": "BlockIcons/manual_motion_on.png", + "indent": "1", + "scope": "1", + "canDebug": false, + "function": "xbot_visual.win32.manual_motion_on", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/开启模拟真人操作.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.ManualMotionOnControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "motion_move", + "label": "", + "required": true, + "default": "13:True", + "tips": "模拟真人按随机路线和速度移动鼠标", + "type": "bool", + "editor": { + "label": "仿真移动鼠标", + "kind": "checkbox" + } + }, + { + "name": "motion_click", + "label": "", + "default": "13:True", + "tips": "模拟真人在随机位置点击元素", + "type": "bool", + "editor": { + "label": "仿真点击元素", + "kind": "checkbox" + } + }, + { + "name": "motion_delay", + "label": "", + "default": "13:False", + "tips": "模拟真人在操作之间随机停顿", + "type": "bool", + "editor": { + "label": "仿真操作停顿", + "kind": "checkbox" + } + }, + { + "name": "min_time", + "label": "最小停顿时长(秒)", + "required": false, + "tips": "指令执行完成后的最短等待时间", + "type": "int", + "default": "10:1", + "editor": { + "kind": "textbox" + } + }, + { + "name": "max_time", + "label": "最大停顿时长(秒)", + "required": false, + "tips": "指令执行完成后的最长等待时间", + "type": "int", + "default": "10:3", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "win32.manual_motion_off", + "title": "结束模拟真人操作", + "description": "结束模拟真人操作", + "comment": "结束模拟真人操作", + "icon": "BlockIcons/manual_motion_off.png", + "indent": "2", + "scope": "2", + "canDebug": false, + "function": "xbot_visual.win32.manual_motion_off", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/结束模拟真人操作.html" + }, + { + "name": "win32.minimize_all", + "title": "最小化所有窗口", + "icon": "BlockIcons/1-3.png", + "comment": "最小化所有窗口", + "description": "最小化所有窗口", + "function": "xbot_visual.win32.minimize_all", + "helpUrl": "" + }, + { + "name": "win32.move_mouse", + "title": "移动鼠标", + "icon": "BlockIcons/20-5.png", + "comment": "将鼠标相对于%relative_to%%move_speed%移动到指定坐标位置(%point_x%,%point_y%)", + "description": "将鼠标移动到指定位置", + "function": "xbot_visual.win32.move_mouse", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.MoveMouseControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/移动鼠标.html", + "inputs": [ + { + "name": "point_x", + "label": "移动鼠标至 X", + "required": true, + "default": "10:0", + "tips": "鼠标移动到指定位置的坐标 ,通过快捷键Ctrl+Alt可捕获当前鼠标位置,支持在ShadowBot窗口最小化的状况下通过快捷键来输入坐标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "point_y", + "label": "移动鼠标至 Y", + "required": true, + "default": "10:0", + "tips": "鼠标移动到指定位置的坐标 ,通过快捷键Ctrl+Alt可捕获当前鼠标位置,支持在ShadowBot窗口最小化的状况下通过快捷键来输入坐标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "relative_to", + "label": "相对于", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕左上角", + "tips": "选择新鼠标位置是相对于屏幕左上角、激活窗口左上角或 运行过程中鼠标当前位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕左上角", + "value": "screen" + }, + { + "display": "激活窗口左上角", + "value": "currentactivatedwindow" + }, + { + "display": "运行中当前鼠标位置", + "value": "currentmouseposition" + } + ] + } + }, + { + "name": "move_speed", + "label": "移动速度", + "required": true, + "default": "10:middle", + "defaultDisplay": "中速", + "tips": "选择移动鼠标的速度", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "瞬间", + "value": "instant" + }, + { + "display": "快速", + "value": "fast" + }, + { + "display": "中速", + "value": "middle" + }, + { + "display": "慢速", + "value": "slow" + } + ] + } + }, + { + "name": "delay_after", + "label": "执行后延迟(秒)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.send_keys", + "title": "键盘输入", + "icon": "BlockIcons/20-4.png", + "keywords": "填写;填入", + "comment": "将文本内容%keys%发送给当前激活的窗口", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.SendKeysControl, ShadowBot.Shell.Development", + "description": "给当前激活窗口发送文本", + "function": "xbot_visual.win32.send_keys", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/键盘输入.html", + "inputs": [ + { + "name": "keys", + "label": "文本内容", + "required": true, + "tips": "键盘的输入可以分为两种模式,普通模式和特殊按键模式。通过勾选高级->输入内容包含特殊按键来使用特殊按键模式,不勾选则使用普通模式,默认为特殊按键模式。", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "hardware_driver_input", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "通过硬件驱动的方式输入", + "type": "bool", + "editor": { + "label": "驱动输入", + "kind": "checkbox" + } + }, + { + "name": "force_ime_eng", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "使用模拟输入时会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题。存在不常见的输入法切换英文输入状态不成功的情况, 需要指定强制加载美式键盘(ENG), 确保模拟输入不受中文输入法影响, 默认值为`False`", + "type": "bool", + "editor": { + "label": "强制加载美式键盘", + "kind": "checkbox" + } + }, + { + "name": "contains_hotkey", + "label": "", + "default": "13:True", + "category": "advanced", + "tips": "特殊按键模式,即可输入特殊的按键,包括快捷键(ctrl+a等)和按键特殊操作(持续按下shift键不弹起等)。", + "type": "bool", + "editor": { + "label": "输入内容包含特殊按键(快捷键和按键特殊操作)", + "kind": "checkbox" + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(毫秒)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间, 单位是毫秒, 为避免输入错误, 请将该值调大,最大值为1000ms", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 5 + } + }, + { + "name": "delay_after", + "label": "执行后延迟(秒)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.click_mouse", + "title": "鼠标点击", + "keywords": "单击;双击;右键", + "icon": "BlockIcons/20-3.png", + "comment": "鼠标%button%%click_type%", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.ClickMouseControl, ShadowBot.Shell.Development", + "description": "可进行鼠标按下、弹起、单击、双击、右键点击等动作", + "function": "xbot_visual.win32.click_mouse", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/鼠标点击.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.ClickMouseHandler" + } + ], + "inputs": [ + { + "name": "is_move_mouse_before_click", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "type": "bool", + "editor": { + "label": "点击前将鼠标移动到指定位置", + "kind": "checkbox" + } + }, + { + "name": "point_x", + "label": "移动鼠标至 X", + "required": true, + "default": "10:0", + "tips": "", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "point_y", + "label": "移动鼠标至 Y", + "required": true, + "default": "10:0", + "tips": "", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "relative_to", + "label": "相对于", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕左上角", + "tips": "选择新鼠标位置是相对于屏幕左上角、激活窗口左上角或 运行过程中鼠标当前位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕左上角", + "value": "screen" + }, + { + "display": "激活窗口左上角", + "value": "currentactivatedwindow" + }, + { + "display": "运行中当前鼠标位置", + "value": "currentmouseposition" + } + ] + } + }, + { + "name": "move_speed", + "label": "移动速度", + "required": true, + "default": "10:middle", + "defaultDisplay": "中速", + "tips": "鼠标移动的速度", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "瞬间", + "value": "instant" + }, + { + "display": "快速", + "value": "fast" + }, + { + "display": "中速", + "value": "middle" + }, + { + "display": "慢速", + "value": "slow" + } + ] + } + }, + { + "name": "button", + "label": "鼠标按钮", + "required": true, + "default": "10:left", + "defaultDisplay": "左键", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "左键", + "value": "left" + }, + { + "display": "右键", + "value": "right" + }, + { + "display": "中键", + "value": "middle" + } + ] + } + }, + { + "name": "click_type", + "label": "点击方式", + "required": true, + "default": "10:click", + "defaultDisplay": "单击", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单击", + "value": "click" + }, + { + "display": "双击", + "value": "dbclick" + }, + { + "display": "按下", + "value": "down" + }, + { + "display": "弹起", + "value": "up" + } + ] + } + }, + { + "name": "hardware_driver_click", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "通过硬件驱动的方式点击", + "type": "bool", + "editor": { + "label": "驱动点击", + "kind": "checkbox" + } + }, + { + "name": "keys", + "label": "键盘辅助按钮", + "required": true, + "default": "10:null", + "defaultDisplay": "无", + "category": "advanced", + "tips": "在点击时需要按下的键盘功能键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "无", + "value": "null" + }, + { + "display": "Alt", + "value": "alt" + }, + { + "display": "Ctrl", + "value": "ctrl" + }, + { + "display": "Shift", + "value": "shift" + }, + { + "display": "Win", + "value": "win" + } + ] + } + }, + { + "name": "delay_after", + "label": "执行后延迟(秒)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.wheel_mouse", + "title": "滚动鼠标滚轮", + "icon": "BlockIcons/20-2.png", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.WheelMouseControl, ShadowBot.Shell.Development", + "comment": "%wheel_direction%鼠标滚轮%wheel_times%次", + "description": "滚动鼠标滚轮", + "function": "xbot_visual.win32.wheel_mouse", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/滚动鼠标滚轮.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.WheelMouseHandler" + } + ], + "inputs": [ + { + "name": "wheel_direction", + "label": "滚动方向", + "required": true, + "default": "10:down", + "defaultDisplay": "向下滚动", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "向下滚动", + "value": "down" + }, + { + "display": "向上滚动", + "value": "up" + } + ] + } + }, + { + "name": "wheel_times", + "label": "滚动次数", + "required": true, + "default": "10:1", + "tips": "指定滚轮需要滚动的次数", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": "0" + } + }, + { + "name": "keys", + "label": "键盘辅助按钮", + "required": true, + "default": "10:null", + "defaultDisplay": "无", + "category": "advanced", + "tips": "在点击时需要按下的键盘功能键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "无", + "value": "null" + }, + { + "display": "Alt", + "value": "alt" + }, + { + "display": "Ctrl", + "value": "ctrl" + }, + { + "display": "Shift", + "value": "shift" + }, + { + "display": "Win", + "value": "win" + } + ] + } + }, + { + "name": "delay_after", + "label": "执行后延迟(秒)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "is_wheel_point", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "type": "bool", + "editor": { + "label": "滚动前将鼠标移动至指定位置", + "kind": "checkbox" + } + }, + { + "name": "point_x", + "label": "移动鼠标至 X", + "required": true, + "category": "advanced", + "default": "10:0", + "tips": "", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "point_y", + "label": "移动鼠标至 Y", + "required": true, + "category": "advanced", + "default": "10:0", + "tips": "", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "relative_to", + "label": "相对于", + "required": true, + "category": "advanced", + "default": "10:screen", + "defaultDisplay": "屏幕左上角", + "tips": "选择新鼠标位置是相对于屏幕左上角、激活窗口左上角或 运行过程中鼠标当前位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕左上角", + "value": "screen" + }, + { + "display": "激活窗口左上角", + "value": "currentactivatedwindow" + }, + { + "display": "运行中当前鼠标位置", + "value": "currentmouseposition" + } + ] + } + }, + { + "name": "move_speed", + "label": "移动速度", + "required": true, + "category": "advanced", + "default": "10:middle", + "defaultDisplay": "中速", + "tips": "鼠标移动的速度", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "瞬间", + "value": "instant" + }, + { + "display": "快速", + "value": "fast" + }, + { + "display": "中速", + "value": "middle" + }, + { + "display": "慢速", + "value": "slow" + } + ] + } + } + ] + }, + { + "name": "win32.get_mouse_position", + "title": "获取鼠标当前位置", + "icon": "BlockIcons/20-1.png", + "comment": "获取应用运行中的鼠标相对于%relative_to%的位置,将坐标保存到(%point_x%,%point_y%)", + "description": "获取机器人在运行过程中,执行该条指令时的鼠标位置", + "function": "xbot_visual.win32.get_mouse_position", + "helpUrl": "yddoc/language/zh-cn/指令文档/鼠标键盘/获取鼠标当前位置.html", + "video": { + "time": "06:30" + }, + "inputs": [ + { + "name": "relative_to", + "label": "相对于", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕左上角", + "tips": "在整个屏幕中的坐标还是在激活窗口中的坐标", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕左上角", + "value": "screen" + }, + { + "display": "激活窗口左上角", + "value": "currentactivatedwindow" + } + ] + } + } + ], + "outputs": [ + { + "id": "point_x", + "label": "保存横坐标至", + "variableLabel": "鼠标的横坐标", + "tips": "输入一个名称来保存鼠标横坐标,其类型是整数", + "type": "int", + "name": "point_x" + }, + { + "id": "point_y", + "label": "保存纵坐标至", + "variableLabel": "鼠标的纵坐标", + "tips": "输入一个名称来保存鼠标纵坐标,其类型是整数", + "type": "int", + "name": "point_y" + } + ] + }, + { + "name": "win32.get_selected_text", + "title": "获取选中文本", + "icon": "BlockIcons/20-1.png", + "comment": "获取选中的文本,将文本保存到%selected_text%", + "description": "获取选中的文本", + "function": "xbot_visual.win32.get_selected_text", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/数据提取/获取选中文本.html", + "inputs": [ + { + "name": "wait_time", + "label": "等待时间(毫秒)", + "required": true, + "default": "10:0", + "tips": "当选中内容过多或系统反应慢时,需要调大此参数,避免获取不到选中内容", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "selected_text", + "label": "保存选中文本至", + "variableLabel": "选中文本", + "tips": "指定一个变量名称,该变量用于保存获取到的选中文本", + "name": "selected_text", + "type": "str" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/win32.element.blocks.json b/src/assert/block_settings/win32.element.blocks.json new file mode 100644 index 0000000..0219bc4 --- /dev/null +++ b/src/assert/block_settings/win32.element.blocks.json @@ -0,0 +1,2571 @@ +{ + "types": [], + "blocks": [ + { + "name": "win32.element.get_element", + "title": "获取元素对象(win)", + "description": "获取窗口中元素的具体数据项,可对该项进行内容提取、值设置等自动化操作", + "comment": "获取窗口%window%中%selector%的对象,将对象保存到%element%", + "icon": "BlockIcons/3-3.png", + "function": "xbot_visual.win32.element.get_element", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.GetElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/元素操作/获取元素对象(win).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.GetElementHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "selector", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "is_related_parent", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否关联父元素", + "type": "bool", + "editor": { + "label": "关联父元素", + "kind": "checkbox" + } + }, + { + "name": "parent", + "label": "父元素", + "required": false, + "tips": "在指定的父元素内查找目标元素", + "autoFill": false, + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "element", + "label": "保存元素对象至", + "variableLabel": "元素对象", + "tips": "指定一个变量名称,该变量用于保存获取到的元素对象", + "name": "win_element", + "type": "xbot.win32.element.Win32Element" + } + ] + }, + { + "name": "win32.element.get_all_elements", + "title": "获取相似元素列表(win)", + "statement": "workflow.getall", + "description": "获取窗口中的相似元素列表,对该列表中的项进行自动化操作", + "comment": "在窗口%window%中获取一组与元素%selector%相似的元素,将结果保存到%element_list%", + "icon": "BlockIcons/3-3.png", + "function": "xbot_visual.win32.element.get_all_elements", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/元素操作/获取相似元素列表(win).html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.GetAllElementsControl,ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.GetAllElementsHandler", + "settings": { + "inputName": "output_with_element_count", + "outputName": "element_count" + } + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "selector", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "operation", + "label": "元素操作", + "required": true, + "default": "10:element", + "defaultDisplay": "元素操作", + "tips": "获取的元素信息", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "获取元素对象", + "value": "element" + }, + { + "display": "获取元素文本内容", + "value": "text" + }, + { + "display": "获取元素值", + "value": "value" + }, + { + "display": "获取元素属性", + "value": "attr" + } + ] + } + }, + { + "name": "attribute_name", + "label": "属性名称", + "tips": "填写要获取的元素的属性名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "output_with_element_count", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否输出相似元素个数", + "type": "bool", + "editor": { + "label": "输出相似元素个数", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "element_list", + "label": "保存相似元素列表至", + "variableLabel": "相似元素对象列表", + "tips": "指定一个变量名称,该变量用于保存获取到的相似元素列表", + "name": "win_element_list", + "type": "list" + }, + { + "id": "element_count", + "label": "保存相似元素个数至", + "variableLabel": "相似元素对象个数", + "tips": "指定一个变量名称,该变量用于保存获取到的相似元素个数", + "name": "win_element_count", + "type": "int" + } + ] + }, + { + "name": "win32.element.click", + "title": "点击元素(win)", + "description": "点击窗口中的元素,如按钮、链接或其他任何元素", + "comment": "在窗口%window%中,模拟人工%button%%clicks%元素%element%,点击%anchor_type%位置", + "icon": "BlockIcons/2-1.png", + "function": "xbot_visual.win32.element.click", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.ClickElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/点击元素(win).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.ClickElementHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "clicks", + "label": "点击方式", + "required": true, + "default": "10:click", + "category": "advanced", + "defaultDisplay": "单击", + "tips": "选择点击的方式是单击还是双击", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "单击", + "value": "click" + }, + { + "display": "双击", + "value": "dbclick" + } + ] + } + }, + { + "name": "button", + "label": "鼠标按钮", + "required": true, + "default": "10:left", + "category": "advanced", + "defaultDisplay": "鼠标左键", + "tips": "选择用于触发点击的鼠标按键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "鼠标左键", + "value": "left" + }, + { + "display": "鼠标右键", + "value": "right" + } + ] + } + }, + { + "name": "keys", + "label": "辅助按键", + "required": true, + "default": "10:null", + "defaultDisplay": "无", + "category": "advanced", + "tips": "在点击时需要按下的键盘功能键", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "无", + "value": "null" + }, + { + "display": "Alt", + "value": "alt" + }, + { + "display": "Ctrl", + "value": "ctrl" + }, + { + "display": "Shift", + "value": "shift" + }, + { + "display": "Win", + "value": "win" + } + ] + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": true, + "tips": "支持点击元素中心位置(元素矩形区域的中心点)、随机位置(自动随机指定元素矩形范围内的点)、自定义位置(手动指定目标点)", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "label": "目标元素的部位", + "default": "10:middleCenter", + "category": "advanced", + "tips": "默认点击目标元素的中心位置,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "move_mouse", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "是否显示鼠标移动轨迹", + "type": "bool", + "editor": { + "label": "显示鼠标移动轨迹", + "kind": "checkbox" + } + }, + { + "name": "simulate", + "label": "", + "required": true, + "category": "advanced", + "default": "13:True", + "tips": "如果使用模拟人工点击则通过模拟人工的方式触发点击事件,否则将根据目标元素的自动化接口触发点击", + "type": "bool", + "editor": { + "label": "模拟人工点击", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.element.input", + "title": "填写输入框(win)", + "description": "在窗口的输入框中输入内容", + "comment": "在窗口%window%的%element%中,%input_type%%text%", + "icon": "BlockIcons/2-3.png", + "function": "xbot_visual.win32.element.input", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.InputControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/填写输入框(win).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.InputHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "text", + "label": "输入内容", + "tips": "填写要输入的内容", + "type": "str", + "editor": { + "kind": "memoedit" + } + }, + { + "name": "append", + "label": "", + "required": true, + "default": "13:False", + "tips": "如果勾选追加输入则在现有内容后继续追加输入,否则清空现有内容后再进行输入", + "type": "bool", + "editor": { + "label": "追加输入", + "kind": "checkbox" + } + }, + { + "name": "simulate", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "如果使用模拟人工输入则通过模拟人工的方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "模拟人工输入", + "kind": "checkbox" + } + }, + { + "name": "save_to_clipboard", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "将输入内容添加到剪切板通过Ctrl+V指令将内容填写到输入框避免输入法问题", + "type": "bool", + "editor": { + "label": "剪切板输入", + "kind": "checkbox" + } + }, + { + "name": "input_type", + "label": "输入方式", + "required": true, + "tips": "模拟人工输入: 通过模拟人工的方式触发输入事件(会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题)\r\n剪切板输入: 将输入内容添加到剪切板通过Ctrl+V指令将内容填写到输入框避免输入法问题\r\n自动化接口输入: 调用元素自身实现的自动化接口输入", + "type": "str", + "default": "10:simulate", + "defaultDisplay": "模拟人工输入", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "模拟人工输入", + "value": "simulate" + }, + { + "display": "剪切板输入", + "value": "clipboard" + }, + { + "display": "自动化接口输入", + "value": "automatic" + } + ] + } + }, + { + "name": "contains_hotkey", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "可以在输入内容中加入快捷键,如{enter}代表输入回车键", + "type": "bool", + "editor": { + "label": "输入内容包含快捷键", + "kind": "checkbox" + } + }, + { + "name": "force_ime_ENG", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "存在不常见的输入法切换英文输入状态不成功的情况\r\n需要指定强制加载美式键盘(ENG), 确保模拟输入不受中文输入法影响", + "type": "bool", + "editor": { + "label": "强制加载美式键盘(ENG)", + "kind": "checkbox" + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(ms)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间, 单位是毫秒, 为避免输入错误, 请将该值调大", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 5 + } + }, + { + "name": "focus_timeout", + "label": "焦点超时时间(ms)", + "category": "advanced", + "default": "10:1000", + "tips": "设置焦点超时时间(ms), 元素获取焦点后暂停指定时间后进行输入操作", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "click_before_input", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "在执行输入动作前,先点击元素,以便获取焦点", + "type": "bool", + "editor": { + "label": "输入前点击元素", + "kind": "checkbox" + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": false, + "tips": "支持点击元素中心位置(元素矩形区域的中心点)、随机位置(自动随机指定元素矩形范围内的点)、自定义位置(手动指定目标点)", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "label": "鼠标点击位置", + "default": "10:middleCenter", + "category": "advanced", + "tips": "该输入指令是通过(先点击输入框,后模拟键盘输入)实现的,默认点击输入框的中心位置,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标输入框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.element.hover", + "title": "鼠标悬停在元素上(win)", + "keywords": "悬浮;停留", + "description": "将鼠标悬停在窗口中的元素上", + "comment": "在窗口%window%中,将鼠标移动到元素%element%上,到达位置为元素%anchor_type%", + "icon": "BlockIcons/2-2.png", + "function": "xbot_visual.win32.element.hover", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.HoverElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/鼠标悬停在元素上(win).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.HoverElementHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": true, + "tips": "支持悬停在元素中心位置、随机位置(在元素矩形范围内)、自定义位置", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "default": "10:middleCenter", + "category": "advanced", + "label": "目标元素的部位", + "tips": "默认悬停在目标元素的中心位置,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.element.check", + "title": "设置复选框(win)", + "keywords": "勾选", + "description": "将窗口中的复选框设置成勾选或不勾选", + "comment": "在窗口%window%中%mode%复选框%element%", + "icon": "BlockIcons/2-4.png", + "function": "xbot_visual.win32.element.check", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/元素操作/设置复选框(win).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "mode", + "label": "操作", + "required": true, + "default": "10:check", + "defaultDisplay": "勾选", + "tips": "选择要对复选框进行的操作", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "勾选", + "value": "check" + }, + { + "display": "取消勾选", + "value": "uncheck" + }, + { + "display": "反选", + "value": "toggle" + } + ] + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标复选框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.element.select", + "title": "设置下拉框(win)", + "description": "设置窗口中下拉框的选中项", + "comment": "在窗口%window%中%mode%下拉框%element%中等于%value%的项", + "icon": "BlockIcons/2-5.png", + "function": "xbot_visual.win32.element.select", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/元素操作/设置下拉框(win).html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.SetSelectOptionControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Element.SetSelectOptionHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "mode", + "label": "选择方式", + "required": true, + "default": "10:text", + "defaultDisplay": "按选项内容选择", + "tips": "选择设置选中项的依据", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "按选项内容选择", + "value": "text" + }, + { + "display": "按选项位置选择", + "value": "index" + } + ] + } + }, + { + "name": "value", + "label": "选择值", + "required": true, + "tips": "输入选项内容或者选项位置", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "match_mode", + "label": "匹配模式", + "required": false, + "default": "10:fuzzy", + "defaultDisplay": "匹配模式", + "tips": "选项内容的匹配模式, 默认是模糊匹配", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "模糊匹配", + "value": "fuzzy" + }, + { + "display": "精准匹配", + "value": "exact" + }, + { + "display": "正则匹配", + "value": "regex" + } + ] + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标下拉框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.element.input_password", + "title": "填写密码框(win)", + "description": "在窗口中的密码框中输入密码", + "comment": "在窗口%window%的%element%中%input_type%密码", + "icon": "BlockIcons/2-6.png", + "function": "xbot_visual.win32.element.input_password", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.InputPasswordControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/元素操作/填写密码框(win).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "text", + "label": "输入密码", + "required": true, + "tips": "填写要输入的密码", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "simulate", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "如果使用模拟人工输入则通过模拟人工的方式触发输入事件,否则将根据目标元素的自动化接口触发输入", + "type": "bool", + "editor": { + "label": "模拟人工输入", + "kind": "checkbox" + } + }, + { + "name": "save_to_clipboard", + "label": "", + "required": true, + "default": "13:False", + "category": "advanced", + "tips": "将输入内容添加到剪切板通过Ctrl+V指令将内容填写到输入框避免输入法问题", + "type": "bool", + "editor": { + "label": "剪切板输入", + "kind": "checkbox" + } + }, + { + "name": "input_type", + "label": "输入方式", + "required": true, + "tips": "模拟人工输入: 通过模拟人工的方式触发输入事件(会自动切换当前输入法为英文输入状态, 以避免输入法造成的输入错误问题)\r\n剪切板输入: 将输入内容添加到剪切板通过Ctrl+V指令将内容填写到输入框避免输入法问题\r\n自动化接口输入: 调用元素自身实现的自动化接口输入", + "type": "str", + "default": "10:simulate", + "defaultDisplay": "模拟人工输入", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "模拟人工输入", + "value": "simulate" + }, + { + "display": "剪切板输入", + "value": "clipboard" + }, + { + "display": "自动化接口输入", + "value": "automatic" + } + ] + } + }, + { + "name": "send_key_delay", + "label": "按键输入间隔(ms)", + "required": true, + "category": "advanced", + "default": "10:50", + "tips": "两次按键输入的间隔时间, 单位是毫秒, 为避免输入错误, 请将该值调大,最大值为1000ms", + "type": "int", + "editor": { + "kind": "spin", + "minValue": 5 + } + }, + { + "name": "focus_timeout", + "label": "焦点超时时间(ms)", + "category": "advanced", + "default": "10:1000", + "tips": "设置焦点超时时间(ms), 元素获取焦点后暂停指定时间后进行输入操作", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "click_before_input", + "label": "", + "required": true, + "default": "13:True", + "category": "advanced", + "tips": "在执行输入动作前,先点击元素,以便获取焦点", + "type": "bool", + "editor": { + "label": "输入前点击元素", + "kind": "checkbox" + } + }, + { + "name": "anchor_type", + "label": "锚点", + "required": false, + "tips": "支持点击元素中心位置(元素矩形区域的中心点)、随机位置(自动随机指定元素矩形范围内的点)、自定义位置(手动指定目标点)", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "category": "advanced", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "label": "鼠标点击位置", + "default": "10:middleCenter", + "category": "advanced", + "tips": "该输入指令是通过(先点击输入框,后模拟键盘输入)实现的,默认点击输入框的中心位置,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "category": "advanced", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标密码框存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.element.set_value", + "title": "设置元素值(win)", + "description": "设置窗口元素的值,一般用于输入框和下拉框的操作", + "comment": "在窗口%window%中设置%element%的值为%value%", + "icon": "BlockIcons/2-7.png", + "function": "xbot_visual.win32.element.set_value", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/元素操作/设置元素值(win).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "value", + "label": "元素值", + "required": true, + "tips": "填写要设置的元素值", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.element.get_details", + "title": "获取元素信息(win)", + "keywords": "元素值;元素属性;元素位置", + "description": "获取窗口中的指定元素的文本内容、值、属性、元素位置等信息", + "comment": "%operation%,目标元素为%element%,将结果保存到%element_attribute%", + "icon": "BlockIcons/3-2.png", + "function": "xbot_visual.win32.element.get_details", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/数据提取/获取元素信息(win).html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.GetElementDetailsControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.GetElementDetailsHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "operation", + "label": "操作", + "required": true, + "default": "10:text", + "defaultDisplay": "获取元素文本内容", + "tips": "选择要获取的窗口元素信息", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "获取元素文本内容", + "value": "text" + }, + { + "display": "获取元素值", + "value": "value" + }, + { + "display": "获取元素属性", + "value": "other" + }, + { + "display": "获取元素位置", + "value": "bound" + } + ] + } + }, + { + "name": "attribute_name", + "label": "属性名称", + "tips": "填写要获取的窗口元素的属性名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "relative_to", + "label": "相对于", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕左上角", + "tips": "在整个屏幕中的位置还是在元素所在窗口中的位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕左上角", + "value": "screen" + }, + { + "display": "元素所在窗口左上角", + "value": "window" + } + ] + } + }, + { + "name": "to96dpi", + "label": "", + "required": true, + "category": "advanced", + "default": "13:True", + "tips": "是否需要将边框属性转换成与设备无关的单位 (每个单位1/96英寸)", + "type": "bool", + "editor": { + "label": "转为dpi为96对应值", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "element_attribute", + "label": "保存元素信息至", + "variableLabel": "元素信息", + "tips": "指定一个变量名称,该变量用于保存获取到的窗口元素信息", + "name": "win_element_attribute", + "type": "str" + } + ] + }, + { + "name": "win32.element.get_bounding", + "title": "获取元素位置(win)", + "description": "获取元素相对于屏幕或所在窗口的位置信息", + "comment": "获取窗口%window%中%element%相对于%relative_to%的位置信息,将结果保存到%bound%", + "icon": "BlockIcons/3-13.png", + "function": "xbot_visual.win32.element.get_bounding", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/数据提取/获取元素位置(win).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "to96dpi", + "label": "", + "required": true, + "category": "advanced", + "default": "13:True", + "tips": "是否需要将位置信息值转换成与设备无关的单位 (每个单位1/96英寸)", + "type": "bool", + "editor": { + "label": "转为dpi为96对应值", + "kind": "checkbox" + } + }, + { + "name": "relative_to", + "label": "相对于", + "required": true, + "default": "10:screen", + "defaultDisplay": "屏幕左上角", + "tips": "在整个屏幕中的位置还是在元素所在窗口中的位置", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "屏幕左上角", + "value": "screen" + }, + { + "display": "元素所在窗口左上角", + "value": "window" + } + ] + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "bound", + "label": "保存位置信息至", + "variableLabel": "元素位置信息", + "tips": "输入一个名称来保存元素位置信息", + "type": "xbot_visual._core.Rectangle", + "name": "bound" + } + ] + }, + { + "name": "win32.element.wait", + "title": "等待元素(win)", + "keywords": "出现;消失", + "description": "等待窗口中元素出现或消失,再执行接下来的流程", + "comment": "等待窗口%window%中元素%element%出现,最多等待%timeout%秒", + "icon": "BlockIcons/2-9.png", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.WaitElementControl, ShadowBot.Shell.Development", + "function": "xbot_visual.win32.element.wait", + "helpUrl": "yddoc/language/zh-cn/指令文档/等待/等待元素(win).html", + "video": { + "time": "06:39" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.WaitWindowElementHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "state", + "label": "等待状态", + "required": true, + "default": "10:appear", + "defaultDisplay": "等待元素出现", + "tips": "选择等待状态", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "等待元素出现", + "value": "appear" + }, + { + "display": "等待元素消失", + "value": "disappear" + } + ] + } + }, + { + "name": "iswait", + "label": "", + "required": true, + "default": "13:True", + "tips": "设置等待超时时间,超时后流程将自动往下继续执行", + "type": "bool", + "editor": { + "label": "设置超时时间", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "超时时间(s)", + "required": true, + "default": "10:20", + "tips": "设置最大等待时间", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "wait_result", + "label": "等待结果", + "tips": "如果为True则等待成功,否则等待超时", + "name": "win_wait_result", + "type": "bool" + } + ] + }, + { + "name": "win32.element.foreach_element", + "statement": "workflow.forin", + "function": "xbot_visual.win32.element.iter_all_elements", + "title": "循环相似元素(win)", + "description": "依次循环窗口中相似元素列表的每一项进行自动化操作", + "comment": "从窗口%window%中获取相似元素%selector%,将结果依次循环保存到%loop_item%", + "indent": "1", + "scope": "1", + "isLoop": true, + "icon": "BlockIcons/3-8.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/循环相似元素(win).html", + "video": { + "time": "04:47" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.ForInControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Element.ForeachElementHandler", + "settings": { + "inputName": "output_with_index", + "outputName": "loop_index" + } + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "autoFill": false, + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "selector", + "label": "操作目标", + "required": true, + "tips": "选择一组相似元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "onlySelector": true, + "selectorType": "simple" + } + }, + { + "name": "operation", + "label": "元素操作", + "required": true, + "default": "10:element", + "defaultDisplay": "元素操作", + "tips": "设置循环的相似元素内容:元素对象or元素的信息,比如文本内容等", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "获取元素对象", + "value": "element" + }, + { + "display": "获取元素文本内容", + "value": "text" + }, + { + "display": "获取元素值", + "value": "value" + }, + { + "display": "获取元素属性", + "value": "attr" + } + ] + } + }, + { + "name": "attribute_name", + "label": "属性名称", + "tips": "填写要获取的元素的属性名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "loop_start_index", + "label": "循环开始位置", + "category": "advanced", + "required": false, + "default": "10:0", + "tips": "循环开始位置,0表示第一项", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "loop_end_index", + "label": "循环结束位置", + "category": "advanced", + "required": false, + "default": "10:-1", + "tips": "循环结束位置,-1表示倒数第一项,结果包含结束位置的项", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "超时时间(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素出现的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "output_with_index", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否输出循环项的位置", + "type": "bool", + "editor": { + "label": "输出循环项的位置", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "loop_item", + "label": "保存当前循环项至", + "variableLabel": "当前循环项", + "tips": "指定一个变量名称,用于存储一组相似元素中的当前循环项", + "name": "win_loop_element", + "type": "xbot.win32.element.Win32Element" + }, + { + "id": "loop_index", + "label": "保存当前循环位置至", + "variableLabel": "当前循环项的位置", + "tips": "指定一个变量名称,用于存储一组相似元素中的当前循环项位置", + "name": "win_loop_element_index", + "type": "int" + } + ] + }, + { + "name": "win32.element.drag_to", + "title": "拖拽元素(win)", + "keywords": "拖动", + "description": "在指定的窗口中将元素拖拽至指定的位置", + "comment": "将元素拖拽到指定位置", + "icon": "BlockIcons/2-10.png", + "function": "xbot_visual.win32.element.drag_to", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.DragElementControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/元素操作/元素拖拽(win).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.DragElementToHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "drag_way", + "label": "拖拽方式", + "required": true, + "default": "10:default", + "defaultDisplay": "拖拽至目标点", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "拖拽至目标点", + "value": "default" + }, + { + "display": "拖拽至目标元素上", + "value": "targetElement" + } + ] + } + }, + { + "name": "target_element", + "label": "操作目标", + "tips": "要操作的元素,可以从元素列表中选择一个录制好的桌面软件元素,也可以使用动态元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "left", + "label": "X", + "default": "10:0", + "tips": "鼠标移动到的目标位置的横坐标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "top", + "label": "Y", + "default": "10:0", + "tips": "鼠标移动到的目标位置的纵坐标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "delay_after", + "label": "执行后延迟(s)", + "required": true, + "category": "advanced", + "default": "10:1", + "tips": "指令执行完成后的等待时间", + "type": "float", + "editor": { + "kind": "spin", + "minValue": 0 + } + }, + { + "name": "anchor_type", + "label": "鼠标按下位置锚点", + "required": true, + "tips": "支持鼠标在拖拽元素中心位置、随机位置(在元素矩形范围内)、自定义位置处按下", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "sudoku_part", + "default": "10:middleCenter", + "label": "鼠标按下元素部位", + "tips": "默认鼠标在拖拽元素的中心位置按下,根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "move_speed", + "label": "移动速度", + "required": false, + "category": "advanced", + "default": "10:middle", + "defaultDisplay": "中速", + "tips": "选择移动鼠标的速度", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "瞬间", + "value": "instant" + }, + { + "display": "快速", + "value": "fast" + }, + { + "display": "中速", + "value": "middle" + }, + { + "display": "慢速", + "value": "slow" + } + ] + } + }, + { + "name": "release_anchor_type", + "label": "鼠标释放位置锚点", + "required": true, + "tips": "支持鼠标在拖拽至元素的中心位置、随机位置(在元素矩形范围内)、自定义位置释放", + "type": "str", + "default": "10:center", + "defaultDisplay": "中心点", + "autoFill": true, + "editor": { + "kind": "select", + "options": [ + { + "display": "中心点", + "value": "center" + }, + { + "display": "随机位置", + "value": "random" + }, + { + "display": "自定义", + "value": "custom" + } + ] + } + }, + { + "name": "release_sudoku_part", + "default": "10:middleCenter", + "label": "鼠标释放元素部位", + "tips": "默认鼠标在拖拽至元素的中心位置释放,请根据实际情况调整", + "type": "str", + "editor": { + "kind": "sudoku" + } + }, + { + "name": "release_offset_x", + "label": "横向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向右移动 5px,输入负数代表向左移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "release_offset_y", + "label": "纵向偏移", + "required": true, + "default": "10:0", + "tips": "输入 5 表示将鼠标向下移动 5px,输入负数代表向上移动鼠标", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ] + }, + { + "name": "win32.element.screenshot", + "title": "元素截图(win)", + "description": "对桌面软件中的元素进行截图,将结果保存至指定文件", + "comment": "在窗口%window%中对元素%element%进行截图,将截图保存到文件夹%folder_path%中,将存图路径保存到%screenshot_save_file_name%", + "icon": "BlockIcons/3-6.png", + "function": "xbot_visual.win32.element.screenshot", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/数据提取/元素截图(win).html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.ScreenShotControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.ScreenShotHandler" + }, + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.ScreenShotOutputPathHandler", + "settings": { + "inputName": "save_to_clipboard", + "outputName": "screenshot_save_file_name" + } + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "folder_path", + "label": "保存文件夹", + "tips": "截图保存的文件夹", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "random_filename", + "label": "", + "required": true, + "default": "13:True", + "tips": "自动生成不重复的文件名", + "type": "bool", + "editor": { + "label": "使用自动随机文件名", + "kind": "checkbox" + } + }, + { + "name": "filename", + "label": "自定义文件名", + "tips": "自定义文件名 如: screenshot.png", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "overwrite_file", + "label": "", + "default": "13:True", + "tips": "", + "type": "bool", + "editor": { + "label": "如果文件存在则覆盖", + "kind": "checkbox" + } + }, + { + "name": "save_to_clipboard", + "label": "", + "required": true, + "default": "13:False", + "tips": "保存图片至剪切板", + "type": "bool", + "editor": { + "label": "保存图片至剪切板", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "设置元素截图的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "screenshot_save_file_name", + "label": "截图保存位置", + "variableLabel": "元素截图位置", + "tips": "截图文件所在的位置:文件路径+名称", + "name": "screenshot_save_file_name", + "type": "str" + } + ] + }, + { + "name": "win32.element.get_select_item", + "title": "获取下拉框选项(win)", + "description": "获取窗口中下拉框的选项", + "comment": "获取窗口%window%中%element%的%get_way%,将结果保存到%select_items%", + "icon": "BlockIcons/2-10.png", + "function": "xbot_visual.win32.element.get_select_item", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Element.GetSelectItemHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/数据提取/获取下拉框选项(win).html", + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "get_way", + "label": "获取内容", + "required": true, + "default": "10:selected", + "defaultDisplay": "当前选中项", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "当前选中项", + "value": "selected" + }, + { + "display": "全部下拉项", + "value": "select_all" + } + ] + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待目标元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "select_items", + "label": "保存获取到的内容至", + "tips": "指定一个变量名称,用于存储获取到的下拉选项内容", + "name": "select_items", + "type": "list" + } + ] + }, + { + "name": "win32.element.get_associated_elements", + "title": "获取关联元素(win)", + "keywords": "父元素;子元素;相邻元素", + "description": "在窗口%window%中获取元素的关联元素(父元素、子元素、相邻元素)", + "comment": "获取窗口元素%element%的%associated_kind%,将对象保存到%win_element_result%", + "icon": "BlockIcons/2-11.png", + "function": "xbot_visual.win32.element.get_associated_elements", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Element.GetAssociatedElementsControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/元素操作/获取关联元素(win).html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.GetAssociatedElementsHandler" + } + ], + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "default": "10:0", + "tips": "输入一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "associated_kind", + "label": "关联方式", + "required": true, + "default": "10:parent", + "defaultDisplay": "父元素", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "父元素", + "value": "parent" + }, + { + "display": "子元素", + "value": "child" + }, + { + "display": "相邻元素", + "value": "sibling" + } + ] + } + }, + { + "name": "child_access_kind", + "label": "子元素获取方式", + "default": "10:all", + "defaultDisplay": "所有子元素", + "tips": "指定子元素的获取方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "所有子元素", + "value": "all" + }, + { + "display": "指定位置的子元素", + "value": "index" + } + ] + } + }, + { + "name": "child_index", + "label": "子元素位置", + "default": "10:0", + "type": "int", + "tips": "在父元素中的索引位置,从0开始计数", + "editor": { + "kind": "textbox", + "minValue": 0 + } + }, + { + "name": "sibling_direction", + "label": "相邻方向", + "default": "10:next", + "defaultDisplay": "下一个相邻元素", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "上一个相邻元素", + "value": "previous" + }, + { + "display": "下一个相邻元素", + "value": "next" + } + ] + } + }, + { + "name": "timeout", + "label": "等待元素存在(s)", + "required": true, + "category": "advanced", + "default": "10:20", + "tips": "等待关联元素存在的超时时间", + "type": "int", + "editor": { + "kind": "textbox", + "minValue": 0 + } + } + ], + "outputs": [ + { + "id": "win_element_result", + "label": "保存软件元素至", + "variableLabel": "软件元素", + "tips": "指定一个变量名称,该变量用于保存获取到的软件元素", + "name": "win_element_result", + "type": "xbot.win32.element.Win32Element" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/win32.window.blocks.json b/src/assert/block_settings/win32.window.blocks.json new file mode 100644 index 0000000..5c8dd0d --- /dev/null +++ b/src/assert/block_settings/win32.window.blocks.json @@ -0,0 +1,1564 @@ +{ + "types": [ + { + "name": "xbot.win32.element.Win32Element", + "localName": "win元素", + "methods": [ + { + "display": "该元素的文本内容", + "function": "$0.get_text()", + "type": "str" + } + ] + } + ], + "blocks": [ + { + "name": "win32.window.get_window", + "title": "获取窗口对象", + "icon": "BlockIcons/1-14.png", + "comment": " ", + "description": "在对指定窗口进行自动化操作,先需要获取软件运行窗口对象", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.GetWindowControl,ShadowBot.Shell.Development", + "function": "xbot_visual.win32.window.get", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/获取窗口对象.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.GetWindowHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:win_title_or_class", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "当前激活窗口", + "value": "active" + }, + { + "display": "窗口句柄", + "value": "win_handle" + }, + { + "display": "桌面", + "value": "desktop" + } + ] + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + } + + ], + "outputs": [ + { + "id": "result_window_instance", + "label": "保存窗口对象至", + "variableLabel": "窗口实例", + "tips": "该变量保存的是窗口对象,使用此窗口对象可以对窗口进行自动化操作", + "name": "software_window", + "type": "xbot.win32.window.Win32Window" + } + ] + }, + { + "name": "win32.window.get_window_list", + "title": "获取窗口对象列表", + "icon": "BlockIcons/1-14.png", + "comment": "", + "description": "获取所有满足条件的窗口对象", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.GetWindowListControl,ShadowBot.Shell.Development", + "function": "xbot_visual.win32.window.get_list", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/获取窗口对象列表.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.GetWindowListHandler" + } + ], + "inputs": [ + { + "name": "title", + "label": "窗口标题包含", + "tips": "窗口包含的标题,标题为空时表示获取全部窗口对象", + "required": false, + "type": "str", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "result_window_list", + "label": "保存窗口列表对象至", + "variableLabel": "窗口列表实列", + "tips": "该变量保存的是窗口对象列表,遍历窗口列表可通过窗口对象对窗口进行自动化操作", + "name": "software_window_list", + "type": "list" + } + ] + }, + { + "name": "win32.window.get_details", + "title": "获取窗口信息", + "icon": "BlockIcons/1-13.png", + "comment": "%operation%,目标窗口为%window%,将结果保存到%window_property%", + "description": "获取指定窗口的标题、内容、进程名等信息", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.GetWindowDetail,ShadowBot.Shell.Development", + "function": "xbot_visual.win32.window.get_details", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/窗口操作/获取窗口信息.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.GetWindowDetailHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:window_instance", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口对象", + "value": "window_instance" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "窗口句柄", + "value": "win_handle" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "operation", + "label": "操作", + "required": true, + "default": "10:title", + "defaultDisplay": "获取窗口标题", + "tips": "选择一种对窗口的操作方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "获取窗口标题", + "value": "title" + }, + { + "display": "获取窗口内容", + "value": "text" + }, + { + "display": "获取窗口进程名", + "value": "process_name" + } + ] + } + } + ], + "outputs": [ + { + "id": "window_property", + "label": "保存窗口属性至", + "variableLabel": "属性对象", + "tips": "该对象保存的是窗口的属性对象", + "name": "win_property", + "type": "str" + } + ] + }, + { + "name": "win32.window.set_state", + "title": "设置窗口状态", + "keywords": "最大化;最小化", + "icon": "BlockIcons/1-11.png", + "comment": "设置窗口%window%状态为%flag%", + "description": "对窗口还原、最大化或最小化的操作", + "function": "xbot_visual.win32.window.set_state", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.SetWindowStateControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/窗口操作/设置窗口状态.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.SetWindowStateHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:window_instance", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口对象", + "value": "window_instance" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "窗口句柄", + "value": "win_handle" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "flag", + "label": "要设置窗口的状态", + "required": true, + "tips": "选择想要设置的窗口状态", + "type": "str", + "defaultDisplay": "还原", + "default": "10:restore", + "editor": { + "kind": "select", + "options": [ + { + "display": "还原", + "value": "restore" + }, + { + "display": "最大化窗口", + "value": "maximize" + }, + { + "display": "最小化窗口", + "value": "minimize" + } + ] + } + } + ] + }, + { + "name": "win32.window.set_visibility", + "title": "设置窗口是否显示", + "keywords": "隐藏", + "icon": "BlockIcons/1-10.png", + "comment": "%flag%%window%", + "description": "设置窗口显示、隐藏状态", + "function": "xbot_visual.win32.window.set_visibility", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.SetWindowVisibilityControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/窗口操作/设置窗口是否显示.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.SetWindowVisibilityHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:window_instance", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口对象", + "value": "window_instance" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "窗口句柄", + "value": "win_handle" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "flag", + "label": "窗体可见性", + "required": true, + "tips": "选择想要设置的窗口可见性", + "default": "10:hide", + "defaultDisplay": "隐藏窗口", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "显示窗口", + "value": "show" + }, + { + "display": "隐藏窗口", + "value": "hide" + } + ] + } + } + ] + }, + { + "name": "win32.window.activate", + "title": "激活软件窗口", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.FocusWindowControl,ShadowBot.Shell.Development", + "icon": "BlockIcons/1-12.png", + "comment": " ", + "description": "激活指定窗口使其在前台运行", + "function": "xbot_visual.win32.window.activate", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/窗口操作/激活软件窗口.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.FocusWindowHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:window_instance", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口对象", + "value": "window_instance" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "窗口句柄", + "value": "win_handle" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + } + ] + }, + { + "name": "win32.window.close", + "title": "关闭软件窗口", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.CloseWindowControl,ShadowBot.Shell.Development", + "icon": "BlockIcons/1-7.png", + "comment": " ", + "description": "此操作将关闭指定窗口", + "function": "xbot_visual.win32.window.close", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/窗口操作/关闭软件窗口.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.CloseWindowHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:window_instance", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口对象", + "value": "window_instance" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "窗口句柄", + "value": "win_handle" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + } + ] + }, + { + "name": "win32.window.move", + "title": "移动窗口位置", + "icon": "BlockIcons/1-9.png", + "comment": " ", + "description": "移动窗口至指定位置", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.MoveWindowControl,ShadowBot.Shell.Development", + "function": "xbot_visual.win32.window.move", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/窗口操作/移动窗口位置.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.MoveWindowHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:window_instance", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口对象", + "value": "window_instance" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "窗口句柄", + "value": "win_handle" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "x", + "label": "X", + "required": true, + "tips": "输入窗口移动的目标横坐标x", + "default": "10:400", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "y", + "label": "Y", + "required": true, + "tips": "输入窗口移动的目标纵坐标y", + "default": "10:400", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "win32.window.resize", + "title": "调整窗口大小", + "keywords": "缩放", + "icon": "BlockIcons/1-8.png", + "comment": " ", + "description": "对窗口大小进行调整", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.ResizeWindowControl,ShadowBot.Shell.Development", + "function": "xbot_visual.win32.window.resize", + "helpUrl": "yddoc/language/zh-cn/指令文档/桌面软件自动化/窗口操作/调整窗口大小.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.ResizeWindowHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:window_instance", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口对象", + "value": "window_instance" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "窗口句柄", + "value": "win_handle" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "width", + "label": "宽度", + "required": true, + "tips": "设置窗口宽度", + "default": "10:400", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "height", + "label": "高度", + "required": true, + "tips": "设置窗口高度", + "default": "10:400", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "win32.window.contains_element", + "statement": "workflow.if", + "title": "IF 窗口包含", + "description": "检测指定的元素是否包含在指定窗口中", + "comment": "检查窗口%window%中是否%content_type%%element%", + "indent": "1", + "scope": "1", + "isCondition": true, + "icon": "BlockIcons/6-4.png", + "function": "xbot_visual.win32.window.contains_element", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if窗口包含.html", + "video": { + "time": "01:03" + }, + "inputs": [ + { + "name": "window", + "label": "窗口对象", + "required": true, + "tips": "选择一个窗口对象", + "type": "xbot.win32.window.Win32Window", + "autoFill": false, + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [ + { + "display": "根据操作目标自动匹配", + "value": "0" + } + ] + } + }, + { + "name": "content_type", + "label": "检测指定窗口是否", + "required": true, + "default": "10:contains_element", + "defaultDisplay": "包含元素", + "tips": "检测窗口是否存在某个元素", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "包含元素", + "value": "contains_element" + }, + { + "display": "不包含元素", + "value": "not_contains_element" + } + ] + } + }, + { + "name": "element", + "label": "操作目标", + "required": true, + "tips": "选择要操作的桌面软件元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + } + ] + }, + { + "name": "win32.window.exists", + "statement": "workflow.if", + "title": "IF 窗口存在", + "description": "检测指定窗口是否存在", + "comment": "检查窗口%window%是否是%window_status%", + "indent": "1", + "scope": "1", + "isCondition": true, + "icon": "BlockIcons/6-4.png", + "function": "xbot_visual.win32.window.exists", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.WindowExistedControl,ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.WindowExistedHandler" + } + ], + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if窗口存在.html", + "video": { + "time": "01:50" + }, + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "default": "10:window_instance", + "defaultDisplay": "窗口对象", + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "窗口对象", + "value": "window_instance" + }, + { + "display": "捕获窗口元素", + "value": "window_selector" + }, + { + "display": "窗口标题或类型名", + "value": "win_title_or_class" + }, + { + "display": "窗口句柄", + "value": "win_handle" + } + ] + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "选择或输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "选择或输入窗口类型。一般用于标题相同的窗口有多个,无法只根据标题来区分窗口的情况", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "use_wildcard", + "label": "", + "required": true, + "default": "13:False", + "tips": "根据通配符匹配,比如‘*记事本’表示以’记事本‘结尾的任意文本", + "type": "bool", + "editor": { + "label": "根据通配符匹配", + "kind": "checkbox" + } + }, + { + "name": "window_status", + "label": "窗口是否", + "required": true, + "default": "10:existed", + "defaultDisplay": "存在", + "tips": "选择需要判断的窗口存在或不存在", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "存在", + "value": "existed" + }, + { + "display": "不存在", + "value": "not_existed" + } + ] + } + } + ] + }, + { + "name": "win32.window.wait_window", + "title": "等待窗口", + "description": "等待窗口发生状态变化", + "comment": "等待窗口%window%%wait_way%,最多等待%timeout%秒", + "icon": "BlockIcons/6-4.png", + "function": "xbot_visual.win32.window.wait_window", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Win32.WindowWaitControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/等待/等待窗口.html", + "video": { + "time": "02:35" + }, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Win32.WindowWaitHandler" + } + ], + "inputs": [ + { + "name": "window_type", + "label": "获取窗口方式", + "required": true, + "tips": "选择获取窗口方式", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "window", + "label": "窗口对象", + "tips": "输入一个通过\"获取窗口对象\"获取的窗口对象", + "type": "xbot.win32.window.Win32Window", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "selector", + "label": "操作目标", + "tips": "从元素列表中选择一个录制好的窗口元素", + "type": "xbot.win32.element.Win32Element", + "editor": { + "kind": "uitarget", + "selectorType": "simple" + } + }, + { + "name": "handle", + "label": "窗口句柄", + "tips": "输入一个窗口句柄", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox" + } + }, + { + "name": "title", + "label": "窗口标题", + "tips": "输入窗口标题", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "handle_checked", + "label": "", + "required": true, + "default": "13:False", + "tips": "添加窗口类型", + "type": "bool", + "editor": { + "label": "添加窗口类型", + "kind": "checkbox" + } + }, + { + "name": "class_name", + "label": "窗口类型", + "tips": "输入窗口类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "wait_way", + "label": "等待状态", + "required": true, + "default": "10:appear", + "defaultDisplay": "存在", + "tips": "选择需要等待的窗口状态", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "存在", + "value": "appear" + }, + { + "display": "不存在", + "value": "disappear" + }, + { + "display": "激活", + "value": "be_focus" + }, + { + "display": "未激活", + "value": "lost_focus" + } + ] + } + }, + { + "name": "use_timeout", + "label": "", + "required": true, + "default": "13:True", + "tips": "设置超时时间, 如果不设置则一直等待", + "type": "bool", + "editor": { + "label": "设置超时时间", + "kind": "checkbox" + } + }, + { + "name": "timeout", + "label": "超时时间(s)", + "required": false, + "default": "10:20", + "tips": "请输入超时时间(单位:秒)", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "window_wait_result", + "label": "等待结果", + "tips": "窗口是否出现或消失的结果", + "name": "win_wait_result", + "type": "bool" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/word.blocks.json b/src/assert/block_settings/word.blocks.json new file mode 100644 index 0000000..9216156 --- /dev/null +++ b/src/assert/block_settings/word.blocks.json @@ -0,0 +1,1211 @@ +{ + "types": [ + { + "name": "Word.Document", + "localName": "Word对象", + "props": [] + } + ], + "blocks": [ + { + "name": "word.launch", + "title": "打开/新建Word", + "keywords": "新建word;打开word;启动word", + "icon": "BlockIcons/35-1.png", + "comment": "%launch_way%:%open_filename%,将Word对象保存到%word_instance%", + "description": "打开已有Word文件,或新建Word,以实现Word程序的自动化", + "function": "xbot_visual.word.launch", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.LaunchWordControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/启动word.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Word.LaunchWordHandler" + } + ], + "inputs": [ + { + "name": "launch_way", + "label": "启动方式", + "required": true, + "default": "10:open", + "defaultDisplay": "打开已有的Word", + "tips": "选择要新建一个Word文件还是打开一个Word文件", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "新建Word", + "value": "create" + }, + { + "display": "打开已有的Word", + "value": "open" + } + ] + } + }, + { + "name": "driver_way", + "label": "驱动方式", + "required": true, + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "自动检测", + "value": "auto_check" + }, + { + "display": "office", + "value": "office" + }, + { + "display": "wps", + "value": "wps" + } + ] + } + }, + { + "name": "open_filename", + "label": "Word文件路径", + "required": false, + "tips": "填写或选择要打开的Word文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "Word 工作簿|*.docx;*.doc" + } + } + }, + { + "name": "save_filename", + "label": "Word文件路径", + "required": false, + "tips": "填写打开的Word路径或保存Word的路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "defaultFileName": "Document", + "filter": "Word 工作簿|*.docx;*.doc" + } + } + }, + { + "name": "isvisible", + "label": "", + "default": "13:True", + "tips": "此选项并不会限制Word自动化的能力,只是用于控制可视化操作是否用户可见,如果是非可视化下操作Word,保存之后必须要关闭Word", + "type": "bool", + "editor": { + "label": "是否可视化", + "kind": "checkbox" + } + }, + { + "name": "open_password", + "label": "打开密码", + "category": "advanced", + "tips": "用于打开加密Word文件的打开密码", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "edit_password", + "label": "编辑密码", + "category": "advanced", + "tips": "用于打开加密Word文件编辑权限的编辑密码", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "word_instance", + "label": "保存Word对象至", + "variableLabel": "打开的Word对象", + "tips": "该变量保存的是Word对象,使用此Word对象可以对Word进行自动化操作", + "name": "word_instance", + "type": "Word.Document" + } + ] + }, + { + "name": "word.save", + "title": "保存Word", + "keywords": "另存为Word;导出Word", + "comment": "将Word对象%word_instance%%save_way%Word文件%filename%", + "description": "保存Word", + "icon": "BlockIcons/35-2.png", + "function": "xbot_visual.word.save", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.SaveWordControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/保存word.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Word.SaveWordHandler" + } + ], + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "save_way", + "label": "保存方式", + "required": true, + "default": "10:save", + "defaultDisplay": "保存", + "tips": "保存对Word的更改或另存为到新的路径", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "保存", + "value": "save" + }, + { + "display": "另存为", + "value": "saveas" + } + ] + } + }, + { + "name": "filename", + "label": "Word文件路径", + "tips": "填写或选择要打开的Word文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "defaultFileName": "Document", + "filter": "Word 工作簿 (.docx)|*.docx" + } + } + }, + { + "name": "overwrite_file", + "label": "", + "default": "13:True", + "tips": "若文件已存在,又选择不覆盖,会报错提示文件已存在", + "type": "bool", + "editor": { + "label": "如果文件存在则覆盖", + "kind": "checkbox" + } + }, + { + "name": "is_close_after_save", + "label": "", + "default": "13:False", + "tips": "", + "type": "bool", + "editor": { + "label": "保存后关闭", + "kind": "checkbox" + } + } + ] + }, + { + "name": "word.close", + "title": "关闭Word", + "comment": "关闭Word", + "description": "关闭Word", + "icon": "BlockIcons/35-3.png", + "function": "xbot_visual.word.close", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.CloseWordControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/关闭word.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Word.CloseWordHandler" + } + ], + "inputs": [ + { + "name": "operation", + "label": "操作", + "required": true, + "default": "10:close_specified", + "defaultDisplay": "关闭指定Word文件", + "tips": "选择要关闭一个指定的Word文件还是关闭所有Word文件", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "关闭指定Word文件", + "value": "close_specified" + }, + { + "display": "关闭所有Word文件", + "value": "close_all" + } + ] + } + }, + { + "name": "word_instance", + "label": "Word对象", + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "close_way", + "label": "关闭方式", + "required": true, + "default": "10:save", + "defaultDisplay": "保存", + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "不保存", + "value": "notsave" + }, + { + "display": "保存", + "value": "save" + }, + { + "display": "另存为", + "value": "saveas" + } + ] + } + }, + { + "name": "filename", + "label": "文件路径", + "tips": "填写或选择要打开的Word文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "defaultFileName": "Document", + "filter": "Word 工作簿 (.docx)|*.docx" + } + } + }, + { + "name": "overwrite_file", + "label": "", + "default": "13:True", + "tips": "若文件已存在,又选择不覆盖,会报错提示文件已存在", + "type": "bool", + "editor": { + "label": "如果文件存在则覆盖", + "kind": "checkbox" + } + }, + { + "name": "close_process", + "label": "关闭进程", + "required": true, + "default": "10:office", + "defaultDisplay": "office", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "office", + "value": "office" + }, + { + "display": "wps", + "value": "wps" + } + ] + } + }, + { + "name": "task_kill", + "label": "", + "required": true, + "default": "13:False", + "tips": "如果勾选,将强制结束属于当前用户的指定Word进程和由它启动的所有子进程", + "type": "bool", + "editor": { + "label": "终止Word进程", + "kind": "checkbox" + } + } + ] + }, + { + "name": "word.read_text_from_document", + "title": "读取Word文本", + "icon": "BlockIcons/35-5.png", + "comment": "从Word对象%document%中读取%read_range%中的文本,将结果保存到%word_text%", + "description": "从Word文件中读取文本", + "function": "xbot_visual.word.read_text_from_document", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/读取word文本.html", + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "read_range", + "label": "读取范围", + "required": true, + "default": "10:entire_document", + "defaultDisplay": "整个文档", + "tips": "提供Word内容读取范围", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "整个文档", + "value": "entire_document" + }, + { + "display": "选中区域", + "value": "select_area" + } + ] + } + } + ], + "outputs": [ + { + "id": "word_text", + "label": "保存Word内容为", + "variableLabel": "Word数据对象", + "tips": "指定一个变量名称,该变量用于保存域数据内容", + "name": "word_text", + "type": "any" + } + ] + }, + { + "name": "word.write_text_to_document", + "title": "写入文本至Word中", + "keywords": "写入word", + "icon": "BlockIcons/35-6.png", + "comment": "在Word对象%word_instance%文档当前选择区域中写入文本%content%", + "description": "在Word文档当前选择区域中写入或覆盖文本", + "function": "xbot_visual.word.write_text_to_document", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.WriteTextToDocumentControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/写入文本至word中.html", + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "content", + "label": "文本内容", + "required": true, + "tips": "写入到当前选择区域的文本", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "text_format", + "label": "文本格式", + "required": true, + "tips": "可直接在此设置简单的格式,复杂的格式可事先在Word中设置好,再点击编辑格式内的‘在Word中指出’提取", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "newline", + "label": "", + "default": "13:False", + "tips": "若勾选,则在写入前换行", + "type": "bool", + "editor": { + "label": "写入文本前换行", + "kind": "checkbox" + } + } + ] + }, + { + "name": "word.export_to_pdf", + "title": "Word导出PDF", + "icon": "BlockIcons/35-4.png", + "description": "将Word文档导出为PDF", + "comment": "将Word对象%word_instance%导出为PDF文件,将文件保存到%pdf_name%", + "function": "xbot_visual.word.export_to_pdf", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.WordExportToPDFControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/word导出pdf.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Word.WordExportToPDFHandler" + } + ], + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "export_range", + "label": "导出范围", + "required": true, + "default": "10:0", + "defaultDisplay": "所有页面", + "tips": "提供多种Word导出范围", + "type": "int", + "editor": { + "kind": "select", + "options": [ + { + "display": "所有页面", + "value": 0 + }, + { + "display": "当前页面", + "value": 2 + }, + { + "display": "指定页面", + "value": 3 + }, + { + "display": "当前选区", + "value": 1 + } + ] + } + }, + { + "name": "page_from", + "label": "起始页数", + "tips": "要导出为PDF内容的起始页数", + "type": "int", + "default": "10:1", + "editor": { + "placeholder": "输入页数,从1开始", + "kind": "textbox" + } + }, + { + "name": "page_to", + "label": "结束页数", + "tips": "要导出为PDF内容的结束页数", + "type": "int", + "default": "10:1", + "editor": { + "placeholder": "输入页数,从1开始", + "kind": "textbox" + } + }, + { + "name": "pdf_name", + "label": "PDF保存到", + "tips": "填写要导出的PDF保存的文件名", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SaveFile", + "filter": "PDF|*.pdf" + } + } + }, + { + "name": "overwrite", + "label": "", + "default": "13:True", + "tips": "如果PDF文件存在则覆盖,PDF保存路径若不存在会自动创建", + "type": "bool", + "editor": { + "label": "如果文件存在则覆盖", + "kind": "checkbox" + } + } + ] + }, + { + "name": "word.locate_cursor", + "title": "定位Word光标", + "icon": "BlockIcons/35-7.png", + "description": "将Word文档中定位到指定位置的光标", + "comment": "在Word对象%word_instance%中定位光标,定位到文本%text_content%后", + "function": "xbot_visual.word.locate_cursor", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.LocateCursorControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/定位word光标.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Word.LocateCursorHandler" + } + ], + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "locate_type", + "label": "相对于", + "required": true, + "default": "10:text", + "defaultDisplay": "文本", + "tips": "选择定位类型", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文本", + "value": "text" + }, + { + "display": "文档", + "value": "document" + }, + { + "display": "书签", + "value": "bookmark" + } + ] + } + }, + { + "name": "text_content", + "label": "文本内容", + "tips": "要定位的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "text_index", + "label": "文本出现的位置", + "tips": "文本出现的位置", + "type": "int", + "default": "10:1", + "editor": { + "placeholder": "1表示第一个,2表示第二个,以此类推,-2表示倒数第二个,-1表示最后一个", + "kind": "textbox" + } + }, + { + "name": "text_cursor_position", + "label": "光标定位到", + "required": true, + "default": "10:after_text", + "defaultDisplay": "文本后", + "tips": "选择光标定位在文本前面还是后面", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文本前", + "value": "before_text" + }, + { + "display": "文本后", + "value": "after_text" + } + ] + } + }, + { + "name": "text_from_start", + "label": "", + "default": "13:True", + "tips": "若勾选,则从头开始查找,否则从当前位置开始", + "type": "bool", + "editor": { + "label": "从头开始查找文本", + "kind": "checkbox" + } + }, + { + "name": "document_cursor_position", + "label": "光标定位到", + "required": true, + "default": "10:end_document", + "defaultDisplay": "文档结尾", + "tips": "选择光标定位在文档开头还是结尾", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "文档开头", + "value": "begin_document" + }, + { + "display": "文档结尾", + "value": "end_document" + } + ] + } + }, + { + "name": "bookmark_name", + "label": "书签名称", + "tips": "要定位书签的名称", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "bookmark_cursor_position", + "label": "光标定位到", + "required": true, + "default": "10:after_bookmark", + "defaultDisplay": "书签后", + "tips": "选择光标定位在书签前面还是后面", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "书签前", + "value": "before_bookmark" + }, + { + "display": "书签后", + "value": "after_bookmark" + } + ] + } + } + ] + }, + { + "name": "word.move_cursor", + "title": "移动Word光标", + "icon": "BlockIcons/35-8.png", + "description": "移动Word文档中光标", + "comment": "在Word对象%word_instance%中%move_direction%%move_count%个字符单位长度光标", + "function": "xbot_visual.word.move_cursor", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/移动word光标.html", + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "move_direction", + "label": "移动方向", + "required": true, + "default": "10:move_right", + "defaultDisplay": "向右移动", + "tips": "选择光标移动方向", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "向左移动", + "value": "move_left" + }, + { + "display": "向上移动", + "value": "move_up" + }, + { + "display": "向右移动", + "value": "move_right" + }, + { + "display": "向下移动", + "value": "move_down" + } + ] + } + }, + { + "name": "move_count", + "label": "移动长度", + "tips": "输入需要移动的单位长度", + "type": "int", + "default": "10:1", + "editor": { + "placeholder": "需要移动的单位长度", + "kind": "textbox" + } + }, + { + "name": "press_shift", + "label": "", + "default": "13:False", + "tips": "若勾选,则在移动时按下shift键,移动区域的文本被选中", + "type": "bool", + "editor": { + "label": "是否按下Shift键", + "kind": "checkbox" + } + } + ] + }, + { + "name": "word.replace_text", + "title": "替换Word文本", + "icon": "BlockIcons/35-9.png", + "description": "替换Word文档中文本内容", + "comment": "将Word对象%word_instance%中文本%search_text%替换为%replace_text%,将替换个数保存到%replace_count%", + "function": "xbot_visual.word.replace_text", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/替换word文本.html", + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "search_text", + "label": "查找文本", + "required": true, + "tips": "要查找的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "replace_text", + "label": "替换为", + "tips": "要替换的文本", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "replace_all", + "label": "", + "default": "13:True", + "tips": "若勾选,则替换全部查找到的文本", + "type": "bool", + "editor": { + "label": "全部替换", + "kind": "checkbox" + } + }, + { + "name": "case_sensitive", + "label": "", + "default": "13:False", + "tips": "若勾选,则区分大小写", + "type": "bool", + "editor": { + "label": "区分大小写", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "replace_count", + "label": "保存文本替换个数至", + "variableLabel": "文本替换个数", + "tips": "指定一个变量名称,该变量用于保存文本替换个数", + "type": "int", + "name": "word_replace_count" + } + ] + }, + { + "name": "word.read_table_from_document", + "title": "读取Word表格", + "icon": "BlockIcons/35-10.png", + "description": "读取Word文档中表格内容", + "comment": "在%word_instance%中读取第%table_index%个表格内容,将数据存储到%table_data%", + "function": "xbot_visual.word.read_table_from_document", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.ReadTableFromDocumentControl, ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/读取word表格.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Word.ReadTableFromDocumentHandler" + } + ], + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "find_way", + "label": "表格查找方式", + "required": true, + "default": "10:index", + "defaultDisplay": "根据表格位置", + "tips": "选择一个表格查找方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "根据表格位置", + "value": "index" + }, + { + "display": "根据表格内容", + "value": "content" + } + ] + } + }, + { + "name": "table_index", + "label": "表格出现位置", + "tips": "输入表格出现位置", + "type": "int", + "default": "10:1", + "editor": { + "kind": "textbox" + } + }, + { + "name": "table_content", + "label": "表格查找内容", + "tips": "输入查找表格所需的内容", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "table_data", + "label": "表格内容保存至", + "variableLabel": "Word表格数据对象", + "tips": "指定一个变量名称,该变量用于保存区域数据内容", + "type": "any", + "name": "word_table_data" + } + ] + }, + { + "name": "word.insert_table", + "title": "插入Word表格", + "icon": "BlockIcons/35-11.png", + "description": "在Word文档中插入表格", + "comment": "在Word对象%word_instance%插入表格,表格数据为%table_data%", + "function": "xbot_visual.word.insert_table", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.InsertTableControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/插入word表格.html", + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "table_data", + "label": "表格数据", + "required": true, + "tips": "内容的数据格式需要跟写入范围对应,写入行、列、区域的内容需要是列表类型", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "table_data_format", + "label": "表格数据格式", + "required": true, + "tips": "可直接在此设置简单的格式,复杂的格式可事先在Word中设置好,再点击编辑格式内的‘在Word中指出’提取", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "grid", + "label": "", + "default": "13:True", + "tips": "若勾选,则表格含有边框", + "type": "bool", + "editor": { + "label": "表格是否有边框", + "kind": "checkbox" + } + }, + { + "name": "newline", + "label": "", + "default": "13:False", + "tips": "若勾选,则在插入表格前换行", + "type": "bool", + "editor": { + "label": "插入表格前换行", + "kind": "checkbox" + } + } + ] + }, + { + "name": "word.insert_picture", + "title": "Word插入图片", + "icon": "BlockIcons/35-12.png", + "description": "在Word文档中插入图片", + "comment": "在Word对象%word_instance%中插入图片%image_path%,缩放比例为%image_scale%%", + "function": "xbot_visual.word.insert_picture", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Word.InsertPictureControl,ShadowBot.Shell.Development", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/插入图片.html", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.Word.InsertPictureHandler" + } + ], + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "image_source", + "label": "图片来源", + "required": true, + "default": "10:file", + "defaultDisplay": "本地图片", + "tips": "选择一个图片来源", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "本地图片", + "value": "file" + }, + { + "display": "剪贴板", + "value": "clipboard" + } + ] + } + }, + { + "name": "image_path", + "label": "图片路径", + "tips": "请选择硬盘上的图片路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "图片(*.jpg;*.bmp;*.png;*.pdf)|*.jpg;*.bmp;*.png;*.pdf" + } + } + }, + { + "name": "image_scale", + "label": "图像缩放百分比", + "tips": "插入图像的缩放比例", + "default": "10:100", + "type": "int", + "editor": { + "placeholder": "输入缩放比例", + "kind": "textbox" + } + }, + { + "name": "newline", + "label": "", + "default": "13:False", + "tips": "若勾选,则在插入图片前换行", + "type": "bool", + "editor": { + "label": "插入图片前换行", + "kind": "checkbox" + } + } + ] + }, + { + "name": "word.insert_hyperlink", + "title": "Word插入超链接", + "icon": "BlockIcons/35-13.png", + "description": "在Word文档中插入超链接", + "comment": "在Word对象%word_instance%中插入超链接%hyperlink_url%,显示文字为%text%", + "function": "xbot_visual.word.insert_hyperlink", + "helpUrl": "yddoc/language/zh-cn/指令文档/word/插入超链接.html", + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + }, + { + "name": "text", + "label": "要显示的文字", + "tips": "写在超链前的文字", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "若不输入,则显示超链接地址" + } + }, + { + "name": "hyperlink_url", + "label": "超链接地址", + "required": true, + "tips": "用于访问的超链接地址", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "newline", + "label": "", + "default": "13:False", + "tips": "若勾选,则在插入超链前换行", + "type": "bool", + "editor": { + "label": "插入超链前换行", + "kind": "checkbox" + } + } + ] + }, + { + "name": "word.copy", + "title": "拷贝Word内容", + "keywords": "复制word", + "icon": "BlockIcons/35-14.png", + "comment": "从Word对象%word_instance%中拷贝选择区域的内容", + "description": "从Word文件中拷贝内容", + "function": "xbot_visual.word.copy", + "helpUrl": "doc/指令文档/17Word/拷贝Word内容.html", + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ] + }, + { + "name": "word.paste", + "title": "粘贴Word内容", + "icon": "BlockIcons/35-15.png", + "comment": "在Word对象%word_instance%当前选择区域中粘贴内容", + "description": "从Word文件中拷贝内容", + "function": "xbot_visual.word.paste", + "helpUrl": "doc/指令文档/17Word/粘贴Word内容.html", + "inputs": [ + { + "name": "word_instance", + "label": "Word对象", + "required": true, + "tips": "输入一个通过\"新建Word\"或\"打开Word\"创建的Word对象", + "type": "Word.Document", + "editor": { + "kind": "select", + "useVariableOptions": true + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/workflow.blocks.json b/src/assert/block_settings/workflow.blocks.json new file mode 100644 index 0000000..a2793b0 --- /dev/null +++ b/src/assert/block_settings/workflow.blocks.json @@ -0,0 +1,795 @@ +{ + "types": [], + "blocks": [ + { + "name": "workflow.if", + "statement": "workflow.if", + "function": "xbot_visual.workflow.test", + "title": "IF 条件", + "description": "条件判断开始标记", + "comment": "如果%operand1%%operator%%operand2%,则执行以下操作", + "indent": "1", + "scope": "1", + "isCondition": true, + "icon": "BlockIcons/6-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if条件.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Workflow.ConditonalControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WorkFlow.ConditonalHandler" + } + ], + "inputs": [ + { + "name": "operand1", + "label": "对象1", + "required": true, + "tips": "输入前面指令创建的变量、Python表达式、文本或数字,与对象2进行比较", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "operator", + "label": "关系", + "required": true, + "default": "10:==", + "defaultDisplay": "等于", + "tips": "选择对象1和对象2的比较方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "等于", + "value": "==" + }, + { + "display": "不等于", + "value": "!=" + }, + { + "display": "大于", + "value": ">" + }, + { + "display": "大于等于", + "value": ">=" + }, + { + "display": "小于", + "value": "<" + }, + { + "display": "小于等于", + "value": "<=" + }, + { + "display": "包含", + "value": "in" + }, + { + "display": "不包含", + "value": "not in" + }, + { + "display": "等于True", + "value": "is true" + }, + { + "display": "等于False", + "value": "is false" + }, + { + "display": "是空值", + "value": "empty value" + }, + { + "display": "不是空值", + "value": "not empty value" + }, + { + "display": "以对象2开头", + "value": "starts with" + }, + { + "display": "不以对象2开头", + "value": "not starts with" + }, + { + "display": "以对象2结束", + "value": "ends with" + }, + { + "display": "不以对象2结束", + "value": "not ends with" + } + ] + } + }, + { + "name": "operand2", + "label": "对象2", + "tips": "输入前面指令创建的变量、Python表达式、文本或数字,与对象1进行比较", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "operator_options", + "label": "操作符参数", + "tips": "操作符参数不展示", + "default": "10:{}", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "workflow.elseif", + "statement": "workflow.elseif", + "function": "xbot_visual.workflow.test", + "title": "Else IF", + "description": "条件分支判断", + "comment": "如果%operand1%%operator%%operand2%,则执行以下操作", + "indent": "3", + "scope": "3", + "isCondition": true, + "icon": "BlockIcons/6-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/elseif.html", + "video": { + "time": "03:23" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Workflow.ConditonalControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WorkFlow.ConditonalHandler" + } + ], + "inputs": [ + { + "name": "operand1", + "label": "对象1", + "required": true, + "tips": "输入前面指令创建的变量、Python表达式、文本或数字,与对象2进行比较", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "operator", + "label": "关系", + "required": true, + "default": "10:==", + "defaultDisplay": "等于", + "tips": "选择对象1和对象2的比较方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "等于", + "value": "==" + }, + { + "display": "不等于", + "value": "!=" + }, + { + "display": "大于", + "value": ">" + }, + { + "display": "大于等于", + "value": ">=" + }, + { + "display": "小于", + "value": "<" + }, + { + "display": "小于等于", + "value": "<=" + }, + { + "display": "包含", + "value": "in" + }, + { + "display": "不包含", + "value": "not in" + }, + { + "display": "等于True", + "value": "is true" + }, + { + "display": "等于False", + "value": "is false" + }, + { + "display": "是空值", + "value": "empty value" + }, + { + "display": "不是空值", + "value": "not empty value" + }, + { + "display": "以对象2开头", + "value": "starts with" + }, + { + "display": "不以对象2开头", + "value": "not starts with" + }, + { + "display": "以对象2结束", + "value": "ends with" + }, + { + "display": "不以对象2结束", + "value": "not ends with" + } + ] + } + }, + { + "name": "operand2", + "label": "对象2", + "tips": "输入前面指令创建的变量、Python表达式、文本或数字,与对象1进行比较", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "operator_options", + "label": "操作符参数", + "tips": "操作符参数不展示", + "default": "10:{}", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "workflow.multiple_conditions_if", + "statement": "workflow.multiple_conditions_if", + "function": "xbot_visual.workflow.multiconditional_judgment", + "title": "IF 多条件", + "description": "条件判断开始标记", + "comment": "判断条件列表中的条件是否全部满足", + "indent": "1", + "scope": "1", + "isCondition": true, + "icon": "BlockIcons/6-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/if多条件.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Workflow.MultipleConditionalControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WorkFlow.MultipleConditonalHandler" + } + ], + "inputs": [ + { + "name": "relation", + "label": "条件关系", + "tips": "下面使用的条件将会以此关系进行合并得到最终的结果", + "default": "10:and", + "defaultDisplay": "符合以下全部条件", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "符合以下全部条件", + "value": "and" + }, + { + "display": "符合以下任意条件", + "value": "or" + } + ] + } + }, + { + "name": "conditionals", + "type": "str", + "lable": "条件列表", + "tips": "要使用的条件列表,可通过'添加条件'和条件后方的'x'按钮经行添加的添加或删除,至少保证使用一个条件", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "workflow.else", + "statement": "workflow.else", + "icon": "BlockIcons/6-2.png", + "indent": "3", + "scope": "3", + "canDebug": false, + "comment": "否则执行以下操作", + "description": "如果不满足前面IF指令中指定的条件,则执行以下操作", + "title": "Else", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/else.html", + "video": { + "time": "02:53" + } + }, + { + "name": "workflow.multiple_conditions_elseif", + "statement": "workflow.multiple_conditions_elseif", + "function": "xbot_visual.workflow.multiconditional_judgment", + "title": "Else IF 多条件", + "description": "条件分支判断", + "comment": "判断条件列表中的条件是否全部满足", + "indent": "3", + "scope": "3", + "isCondition": true, + "icon": "BlockIcons/6-5.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/elseif多条件.html", + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Workflow.MultipleConditionalControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WorkFlow.MultipleConditonalHandler" + } + ], + "inputs": [ + { + "name": "relation", + "label": "条件关系", + "tips": "下面使用得的条件将会以次关系进行合并等到最终的结果", + "default": "10:and", + "defaultDisplay": "符合以下全部条件", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "符合以下全部条件", + "value": "and" + }, + { + "display": "符合以下任意条件", + "value": "or" + } + ] + } + }, + { + "name": "conditionals", + "type": "str", + "lable": "条件列表", + "tips": "要使用的条件列表,可通过'添加条件'和条件后方的'x'按钮经行添加的添加或删除,至少保证使用一个条件", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "workflow.endif", + "statement": "workflow.endif", + "icon": "BlockIcons/6-3.png", + "indent": "2", + "scope": "2", + "isCondition": true, + "isPseudo": true, + "canDebug": false, + "description": "条件判断结束标记", + "comment": "结束判断", + "title": "End IF", + "helpUrl": "yddoc/language/zh-cn/指令文档/条件判断/endif.html", + "video": { + "time": "00:31" + } + }, + { + "name": "workflow.for", + "statement": "workflow.for", + "function": "xbot_visual.workflow.range_iterator", + "title": "For次数循环", + "description": "对一组指令进行指定次数的循环操作", + "comment": "从%start%开始到%stop%结束,递增值为%step%,将当前循环值保存到%loop_index%", + "indent": "1", + "scope": "1", + "isLoop": true, + "icon": "BlockIcons/7-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/for次数循环.html", + "video": { + "time": "02:40" + }, + "inputs": [ + { + "name": "start", + "label": "起始数", + "required": true, + "tips": "设置循环计数器的起点数值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "stop", + "label": "结束数", + "required": true, + "tips": "设置循环计数器的终点数值", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "step", + "label": "递增值", + "required": true, + "tips": "设置每次循环后递增的数值", + "type": "int", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "loop_index", + "label": "保存当前循环项至", + "variableLabel": "当前循环项", + "type": "int", + "tips": "输入一个名称作为保存当前循环数值的变量,从起始值开始,此变量的值将随每次循环的增量而变化", + "name": "loop_index" + } + ] + }, + { + "name": "workflow.while", + "statement": "workflow.while", + "function": "xbot_visual.workflow.test", + "title": "While条件循环", + "description": "当条件为真时,对一组指令进行循环操作", + "comment": "如果%operand1%%operator%%operand2%,则执行以下操作", + "indent": "1", + "scope": "1", + "isLoop": true, + "icon": "BlockIcons/7-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/while条件循环.html", + "video": { + "time": "02:55" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Workflow.ConditonalControl, ShadowBot.Shell.Development", + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WorkFlow.ConditonalHandler" + } + ], + "inputs": [ + { + "name": "operand1", + "label": "对象1", + "required": true, + "tips": "输入前面指令创建的变量、Python表达式、文本或数字,与对象2进行比较", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "operator", + "label": "关系", + "required": true, + "default": "10:==", + "defaultDisplay": "等于", + "tips": "选择对象1和对象2的比较方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "等于", + "value": "==" + }, + { + "display": "不等于", + "value": "!=" + }, + { + "display": "大于", + "value": ">" + }, + { + "display": "大于等于", + "value": ">=" + }, + { + "display": "小于", + "value": "<" + }, + { + "display": "小于等于", + "value": "<=" + }, + { + "display": "包含", + "value": "in" + }, + { + "display": "不包含", + "value": "not in" + }, + { + "display": "等于True", + "value": "is true" + }, + { + "display": "等于False", + "value": "is false" + }, + { + "display": "是空值", + "value": "empty value" + }, + { + "display": "不是空值", + "value": "not empty value" + }, + { + "display": "以对象2开头", + "value": "starts with" + }, + { + "display": "不以对象2开头", + "value": "not starts with" + }, + { + "display": "以对象2结束", + "value": "ends with" + }, + { + "display": "不以对象2结束", + "value": "not ends with" + } + ] + } + }, + { + "name": "operand2", + "label": "对象2", + "tips": "输入前面指令创建的变量、Python表达式、文本或数字,与对象1进行比较", + "type": "any", + "editor": { + "kind": "textbox" + } + }, + { + "name": "operator_options", + "label": "操作符参数", + "tips": "操作符参数不展示", + "default": "10:{}", + "type": "any", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "workflow.forin", + "statement": "workflow.forin", + "function": "xbot_visual.workflow.list_iterator", + "title": "ForEach列表循环", + "description": "依次循环列表中的每一项进行自动化操作", + "comment": "对列表%list%中的每一项进行循环操作,将当前循环项保存到%loop_item%", + "indent": "1", + "scope": "1", + "isLoop": true, + "handlers": [ + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.List.UseOutputTypeByInputListItemTypeHandler", + "settings": { + "inputName": "list", + "outputName": "loop_item" + } + }, + { + "name": "ShadowBot.Runtime.Development.Blockly.Handlers.WorkFlow.OutputForeachItemIndexHandler", + "settings": { + "inputName": "output_with_index", + "outputName": "loop_index" + } + } + ], + "icon": "BlockIcons/7-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/foreach列表循环.html", + "video": { + "time": "02:34" + }, + "settingsControl": "ShadowBot.Shell.Development.BlockSettings.Controls.Workflow.ForInControl, ShadowBot.Shell.Development", + "inputs": [ + { + "name": "list", + "label": "列表", + "required": true, + "tips": "输入列表项或者选择前面指令创建的列表。(列表:表示多个数据项的一组,如列表:[\"中国\",\"美国\",\"法国\"])", + "type": "list", + "editor": { + "kind": "textbox" + } + }, + { + "name": "loop_start_index", + "label": "循环开始位置", + "category": "advanced", + "required": false, + "default": "10:0", + "tips": "循环开始位置,0表示第一项", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "loop_end_index", + "label": "循环结束位置", + "category": "advanced", + "required": false, + "default": "10:-1", + "tips": "循环结束位置,-1表示倒数第一项,结果包含结束位置的项", + "type": "int", + "editor": { + "kind": "textbox" + } + }, + { + "name": "output_with_index", + "label": "", + "required": true, + "default": "13:False", + "tips": "是否输出循环项的位置", + "type": "bool", + "editor": { + "label": "输出循环项的位置", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "loop_item", + "label": "存储循环项至", + "variableLabel": "当前循环项", + "tips": "指定一个变量名称,保存当前的循环项(循环项可以为具体列表的一项、行或单元格)", + "type": "any", + "name": "loop_item" + }, + { + "id": "loop_index", + "label": "存储当前循环位置至", + "variableLabel": "当前循环项的位置", + "tips": "指定一个变量名称,用于存储一组相似元素中的当前循环项的位置", + "type": "int", + "name": "loop_item_index" + } + ] + }, + { + "name": "workflow.continue", + "statement": "workflow.continue", + "canDebug": false, + "icon": "BlockIcons/7-4.png", + "description": "忽略本次循环,继续下一次循环", + "comment": "忽略本次循环,继续下一次循环", + "title": "继续下一次循环", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/继续下一次循环.html", + "video": { + "time": "03:37" + } + }, + { + "name": "workflow.break", + "statement": "workflow.break", + "canDebug": false, + "icon": "BlockIcons/7-5.png", + "description": "退出当前循环", + "comment": "退出当前循环", + "title": "退出循环", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/循环退出.html", + "video": { + "time": "02:40" + } + }, + { + "name": "workflow.endloop", + "statement": "workflow.endloop", + "icon": "BlockIcons/7-6.png", + "indent": "2", + "scope": "2", + "isPseudo": true, + "description": "表示一个循环区域的结尾", + "comment": "表示一个循环区域的结尾", + "title": "循环结束标记", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/循环结束.html", + "video": { + "time": "00:35" + } + }, + { + "name": "workflow.infinite_loop", + "statement": "workflow.infinite_loop", + "icon": "BlockIcons/7-2.png", + "title": "无限循环", + "comment": "无限循环", + "description": "无限循环", + "indent": "1", + "scope": "1", + "isLoop": true, + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/无限循环.html", + "video": { + "time": "04:01" + }, + "outputs": [ + { + "id": "loop_index", + "label": "存储当前循环位置至", + "variableLabel": "当前循环的位置", + "tips": "", + "type": "int", + "name": "loop_index" + } + ] + }, + { + "name": "workflow.loop_dict", + "statement": "excel.forin", + "function": "xbot_visual.workflow.dict_iterator", + "title": "ForEach字典循环", + "description": "依次循环字典中的每一项进行自动化操作", + "comment": "对字典%dict%中的每一项进行循环操作,当前循环项键名保存至变量%loop_key%中,键值保存至变量%loop_value%中", + "indent": "1", + "scope": "1", + "isLoop": true, + "icon": "BlockIcons/7-3.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/循环/foreach字典循环.html", + "inputs": [ + { + "name": "dict", + "label": "字典", + "required": true, + "tips": "输入字典或者选择前面指令创建的字典对象", + "type": "dict", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [ + { + "id": "loop_key", + "label": "存储循环项键名至", + "variableLabel": "当前循环项的键名", + "tips": "指定一个变量名称,保存当前的循环项的键名", + "type": "any", + "name": "loop_key" + }, + { + "id": "loop_value", + "label": "存储循环项键值至", + "variableLabel": "当前循环项的键值", + "tips": "指定一个变量名称,保存当前的循环项的键值", + "type": "any", + "name": "loop_value" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/workqueue.blocks.json b/src/assert/block_settings/workqueue.blocks.json new file mode 100644 index 0000000..49dd445 --- /dev/null +++ b/src/assert/block_settings/workqueue.blocks.json @@ -0,0 +1,279 @@ +{ + "types": [ + { + "name": "xbot_visual.workqueue.WorkQueueItem", + "localName": "工作队列项", + "props": [ + { + "name": "uuid", + "type": "str", + "label": "ID" + }, + { + "name": "name", + "type": "str", + "label": "名称" + }, + { + "name": "bizInfo", + "type": "str", + "label": "业务信息" + }, + { + "name": "description", + "type": "str", + "label": "结果注释" + }, + { + "name": "expireTime", + "type": "str", + "label": "过期时间" + }, + { + "name": "status", + "type": "str", + "label": "状态" + } + ] + } + ], + "blocks": [ + { + "name": "workqueue.enqueue", + "title": "新增队列项", + "icon": "BlockIcons/37-1.png", + "comment": "向%workqueue_id%中新增一个队列项%item_name%", + "description": "向选定的工作队列新增一个队列项", + "function": "xbot_visual.workqueue.enqueue", + "settingsControl": "ShadowBot.Shell.Console.BlockSettings.Controls.WorkQueue.AddQueueItemControl, ShadowBot.Shell.Console", + "helpUrl": "yddoc/command-doc/2fbe8545284581520bd51976a48a05b2.html", + "handlers": [ + + ], + "inputs": [ + { + "name": "workqueue_id", + "label": "队列名称", + "required": true, + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [] + } + }, + { + "name": "item_name", + "label": "队列项名称", + "required": true, + "tips": "名称将显示在队列管理列表中,作为不同队列项的区分", + "type": "str", + "editor": { + "kind": "textbox" + } + }, + { + "name": "item_priority", + "label": "队列项优先级", + "required": true, + "tips": "系统将优先执行优先级为“高”的队列项", + "default": "10:100", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "低", + "value": "200" + }, + { + "display": "中", + "value": "100" + }, + { + "display": "高", + "value": "0" + } + ] + } + }, + { + "name": "item_expiration", + "label": "过期时间", + "required": false, + "tips": "队列项在过期时间前都可以被执行,如果过期则不能被执行。若日期是文本,只支持常用格式,如:2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等。", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本" + } + }, + { + "name": "item_userdata", + "label": "业务信息", + "required": true, + "tips": "可以将队列处理过程中的业务信息放到这里", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [] + }, + { + "name": "workqueue.loop_queue", + "statement":"workqueue.loop_queue", + "title": "循环获取队列项", + "indent": "1", + "scope": "1", + "isLoop": true, + "icon": "BlockIcons/37-3.png", + "comment": "循环%workqueue_id%获取队列项,将当前循环项保存到%workqueue_item%中", + "description": "循环获取指定队列的队列项", + "function": "xbot_visual.workqueue.loop_queue", + "settingsControl": "ShadowBot.Shell.Console.BlockSettings.Controls.WorkQueue.LoopQueueControl, ShadowBot.Shell.Console", + "helpUrl": "yddoc/command-doc/59d825460617877868946ad09e34b35a.html", + "handlers": [ + + ], + "inputs": [ + { + "name": "workqueue_id", + "label": "队列名称", + "required": true, + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [] + } + } + ], + "outputs": [ + { + "id": "workqueue_item", + "label": "保存结果至", + "variableLabel": "当前执行的工作队列项", + "tips": "", + "type": "xbot_visual.workqueue.WorkQueueItem", + "name": "workqueue_item" + } + ] + }, + { + "name": "workqueue.update_item", + "title": "更新队列项", + "icon": "BlockIcons/37-2.png", + "comment": "更新队列项%workqueue_item%的处理结果", + "description": "更新当前队列项的处理结果", + "function": "xbot_visual.workqueue.update_item", + "settingsControl": "ShadowBot.Shell.Console.BlockSettings.Controls.WorkQueue.UpdateQueueItemControl, ShadowBot.Shell.Console", + "helpUrl": "yddoc/command-doc/c556682638137bb7a229ecf902a97de7.html", + "handlers": [ + + ], + "inputs": [ + { + "name": "workqueue_item", + "label": "队列项", + "required": true, + "tips": "", + "type": "xbot_visual.workqueue.WorkQueueItem", + "editor": { + "kind": "textbox" + } + }, + { + "name": "item_status", + "label": "处理结果", + "required": true, + "tips": "", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "已处理", + "value": "processed" + }, + { + "display": "异常", + "value": "exception" + } + ] + } + }, + { + "name": "item_description", + "required": false, + "label": "结果注释", + "tips": "执行过程中的额外的信息可以存储到这里,支持在队列管理后台查看和下载", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [] + }, + { + "name": "workqueue.reenqueue", + "title": "队列项重新排队", + "icon": "BlockIcons/37-4.png", + "comment": "将队列项%workqueue_item%重新入队", + "description": "将选定得队列项重新入列并设置新的过期时间", + "function": "xbot_visual.workqueue.reenqueue", + "settingsControl": "ShadowBot.Shell.Console.BlockSettings.Controls.WorkQueue.ReenqueueItemControl, ShadowBot.Shell.Console", + "helpUrl": "yddoc/command-doc/895a01cbbff19aa12773d5531f742436.html", + "handlers": [ + + ], + "inputs": [ + { + "name": "workqueue_item", + "label": "队列项", + "required": true, + "tips": "", + "type": "xbot_visual.workqueue.WorkQueueItem", + "editor": { + "kind": "textbox" + } + }, + { + "name": "item_effective_time", + "label": "生效时间", + "required": true, + "tips": "在设定的时间前,队列项将不会生效和分发。若日期是文本,只支持常用格式,如:2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等。", + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本" + } + }, + { + "name": "item_expire_time", + "label": "过期时间", + "tips": "可以设置一个新的过期时间,这个过期时间必须大于生效时间。若日期是文本,只支持常用格式,如:2020-02-02、2020/02/02 02:02:02、2020年2月2日 2时2分2秒等。", + "required": false, + "type": "str", + "editor": { + "kind": "textbox", + "placeholder": "日期时间对象或文本" + } + }, + { + "name": "item_description", + "label": "结果注释", + "required": false, + "tips": "执行过程中的额外的信息可以存储到这里,支持在队列管理后台查看和下载", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ], + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/xbot_extensions.activity_temu_shop.blocks.json b/src/assert/block_settings/xbot_extensions.activity_temu_shop.blocks.json new file mode 100644 index 0000000..756e696 --- /dev/null +++ b/src/assert/block_settings/xbot_extensions.activity_temu_shop.blocks.json @@ -0,0 +1,2560 @@ +{ + "types": [], + "blocks": [ + { + "name": "xbot_extensions.activity_temu_shop.main", + "statement": "process.invoke_activity", + "title": "temu 商家后台扩展", + "keywords": "", + "description": "该指令集实现了商家后台登录, 数据采集等操作", + "comment": "", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/3e/bd/3ebd9158b49959177dbc223895f83830.png", + "function": "xbot_extensions.activity_temu_shop.main", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.utils", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.activity_temu_shop.utils", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.login", + "statement": "process.invoke_activity", + "title": "Temu-账号登录", + "keywords": "", + "description": "该指令实现了打开Temu账号,并进行自动登录的功能", + "comment": "在网页对象%web_page%中, 登录%username%账号进入Temu 商家后台", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/ad/c5/adc5107f9e1e9ad8db907ca86ec3eda2.png", + "function": "xbot_extensions.activity_temu_shop.login", + "helpUrl": "yddoc/rpa/771262214638489600", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "username", + "label": "账号", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入Temu商家后台账号" + }, + "category": "general" + }, + { + "name": "password", + "label": "密码", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "password" + }, + "category": "general" + }, + { + "name": "target_store", + "label": "选择店铺", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "选择登录一个指定的店铺,可为空,空则默认" + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.switch_store", + "statement": "process.invoke_activity", + "title": "Temu-切换店铺", + "keywords": "", + "description": "该指令实现了在Temu商家后台中,对店铺进行切换的功能", + "comment": "在网页对象 %web_page% 中,切换当前店铺为%store_name%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/31/47/31477b644e08ec7f8d1f218ee20eea7f.png", + "function": "xbot_extensions.activity_temu_shop.switch_store", + "helpUrl": "yddoc/rpa/771276199978946560", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "store_name", + "label": "店铺名称", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入完整的店铺名称" + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.reconciliation", + "statement": "process.invoke_activity", + "title": "Temu-卖家中心-对账中心-财务明细下载", + "keywords": "", + "description": "该指令实现了在Temu卖家中心中,对Temu卖家中心-对账中心-财务明细下载的功能", + "comment": "在网页对象 %web_page% 中,下载日期为%start_time%到%end_time%的报表,并保存于%file_path%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/c4/17/c4174b6a988d8f4e66ccb6bb8b10bb28.png", + "function": "xbot_extensions.activity_temu_shop.reconciliation", + "helpUrl": "yddoc/rpa/771278088904974336", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始日期", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "选择报表开始日期,格式为YYYY-MM-DD" + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束日期", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "选择报表结束日期,格式为YYYY-MM-DD" + }, + "category": "general" + }, + { + "name": "file_folder", + "label": "保存文件夹", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写文件保存地址" + }, + "category": "general" + }, + { + "name": "file_name", + "label": "保存文件名", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写文件保存名称" + }, + "category": "general" + }, + { + "name": "confirm_download", + "label": "", + "required": false, + "tips": "", + "type": "bool", + "default": "13:True", + "editor": { + "kind": "checkbox", + "label": "是否完成下载报表" + }, + "category": "general" + }, + { + "name": "capital_flow", + "label": "资金流向", + "required": false, + "tips": "", + "type": "any", + "default": "13:", + "editor": { + "kind": "textbox", + "placeholder": "填写一个资金流向,若有多个则以列表的方式。如['xx', 'xx']" + }, + "category": "advanced" + }, + { + "name": "financial_type", + "label": "财务类型", + "required": false, + "tips": "", + "type": "any", + "default": "13:", + "editor": { + "kind": "textbox", + "placeholder": "填写一个财务,若有多个则以列表的方式。如['xx', 'xx']" + }, + "category": "advanced" + }, + { + "name": "fund_mix", + "label": "收支金额最小值", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "fund_max", + "label": "收支金额最大值", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "export_type", + "label": "导出内容", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "文件路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.download_finance_report", + "statement": "process.invoke_activity", + "title": "Temu-下载财务明细报表", + "keywords": "", + "description": "该指令实现了对Temu的财务报表进行批量下载的功能", + "comment": "在网页对象 %web_page% 中,下载日期大于%date%的财务明细报表,并存于%file_folder%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/43/df/43df879fde866d53a07d0e08874d3faf.png", + "function": "xbot_extensions.activity_temu_shop.download_finance_report", + "helpUrl": "yddoc/rpa/772992697877483520", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "date", + "label": "日期", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写日期,格式为YYYY-MM-DD/YYYY-MM-DD HH:mm:ss" + }, + "category": "general" + }, + { + "name": "file_folder", + "label": "保存文件夹", + "required": false, + "tips": "", + "type": "directory", + "default": "13:", + "editor": { + "kind": "textbox", + "placeholder": "填写一个报表文件的保存地址", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.create_coupon", + "statement": "process.invoke_activity", + "title": "Temu-创建优惠券", + "keywords": "", + "description": "该指令实现了自动批量创建优惠券的功能", + "comment": "在网页对象%web_page%,创一个优惠券名称为%coupon_name%,时间为%start_time%到%end_time%的优惠券", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/59/dc/59dcff3891ed3be7c07da01e0492f777.png", + "function": "xbot_extensions.activity_temu_shop.create_coupon", + "helpUrl": "yddoc/rpa/793668557410856960", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "coupon_name", + "label": "优惠券名称", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "请输入自定义优惠券名称" + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "请输入优惠券开始时间,格式为YYYY-MM-DD" + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "请输入优惠券结束时间,格式为YYYY-MM-DD" + }, + "category": "general" + }, + { + "name": "coupon_file_path", + "label": "优惠券路径", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "请输入优惠券模板文件路径", + "dialog": { + "type": "OpenFile", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.balance_screenshot", + "statement": "process.invoke_activity", + "title": "Temu-资金中心-余额截图", + "keywords": "", + "description": "该指令实现了自动截取店铺内资金中心的余额", + "comment": "在网页对象 %web_page% 中,截图店铺余额的图片并报错于%folder_path%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/12/63/1263a25df405d5cb85098f7c32e3b43b.png", + "function": "xbot_extensions.activity_temu_shop.balance_screenshot", + "helpUrl": "yddoc/rpa/775200191869087744", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "folder_path", + "label": "保存文件夹", + "required": false, + "tips": "截图保存文件夹路径", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "请选择存放截图的文件夹", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "station", + "label": "站点名称", + "required": false, + "tips": "站点名称", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "截图命名时拼接站点名称" + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "img_path", + "label": "图片路径", + "name": "img_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.finish_data_export", + "statement": "process.invoke_activity", + "title": "Temu-结算数据-已到账数据导出", + "keywords": "", + "description": "该指令实现了对Temu的结算数据进行导出", + "comment": "在网页对象 %web_page% 中,选择%start_time%到%end_time%的报表进行导出,并保存于%file_path%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/93/8d/938d2d4c11018f8e48a5e32dc71c6946.png", + "function": "xbot_extensions.activity_temu_shop.finish_data_export", + "helpUrl": "yddoc/rpa/775258660518854656", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始日期", + "required": false, + "tips": "输入报表开始日期", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写一个开始日期,格式为YYYY-MM-dd" + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束日期", + "required": false, + "tips": "输入报表结束日期", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写一个结束日期,格式为YYYY-MM-dd" + }, + "category": "general" + }, + { + "name": "area", + "label": "区域", + "required": false, + "tips": "区域", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "选择区域,如:全球,欧区" + }, + "category": "general" + }, + { + "name": "folder_path", + "label": "保存文件夹", + "required": false, + "tips": "保存文件夹的地址", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入一个存储保存文件的地址", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "file_name", + "label": "保存文件名", + "required": false, + "tips": "自定义文件名称", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "自定义一个文件名称" + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "文件路径", + "tips": "报表文件路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.adjust_prices", + "statement": "process.invoke_activity", + "title": "Temu-调价管理-拒绝调价(全托)", + "keywords": "", + "description": "该指令实现了对全托平台进行拒绝调价的功能", + "comment": "在网页对象 %web_page% 中,对商品管理-调价管理-待买家确认里进行拒绝调价的行为,拒绝理由为%reason%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/2c/b8/2cb87e522d30aea6f31d266463a6e977.png", + "function": "xbot_extensions.activity_temu_shop.adjust_prices", + "helpUrl": "yddoc/rpa/777450086620012544", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "reason", + "label": "拒绝理由", + "required": false, + "tips": "拒绝理由,拒绝理由统一", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "请输入拒绝的理由,例:商品没有利润空间,已申报营销活动" + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.deliver_goods_opration", + "statement": "process.invoke_activity", + "title": "Temu-抢备货台", + "keywords": "", + "description": "该指令实现了将今日可发货的单批量加入发货台的功能", + "comment": "在网页对象 %web_page% 中,对今日可发货的单批量加入发货台", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/2f/09/2f09157e1acc6be08a35b6f445492223.png", + "function": "xbot_extensions.activity_temu_shop.deliver_goods_opration", + "helpUrl": "yddoc/rpa/777451922611036160", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "orders_num", + "label": "备货单号", + "required": false, + "tips": "", + "type": "any", + "default": "13:None", + "editor": { + "kind": "textbox", + "placeholder": "格式为:\"全部\",\"单号\",单号列表,例[”aaa“,\"bbb\"]" + }, + "category": "general" + }, + { + "name": "ready_type", + "label": "备货建议", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "可填紧急备货建议,普通备货建议等,默认为普通备货建议" + }, + "category": "general" + }, + { + "name": "retry_time", + "label": "重试次数", + "required": false, + "tips": "", + "type": "int", + "default": "13:3", + "editor": { + "kind": "spin" + }, + "category": "advanced" + } + ], + "outputs": [ + { + "id": "result", + "label": "添加结果", + "name": "result", + "type": "any" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.finishing_data_export", + "statement": "process.invoke_activity", + "title": "Temu-结算数据-结算中数据导出", + "keywords": "", + "description": "该指令实现了对Temu的结算中数据进行导出", + "comment": "在网页对象 %web_page% 中, 将结算数据-结算中款项的数据下载到%folder_path%\\%file_name%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/2e/76/2e76e24a489bc896bfd5e2fc336466f4.png", + "function": "xbot_extensions.activity_temu_shop.finishing_data_export", + "helpUrl": "yddoc/rpa/779169399710244864", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "folder_path", + "label": "保存文件夹", + "required": false, + "tips": "保存文件夹的地址", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null, + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "file_name", + "label": "保存文件名", + "required": false, + "tips": "自定义文件名称", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "保存路径", + "tips": "报表文件路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.pending_data_export", + "statement": "process.invoke_activity", + "title": "Temu-结算数据-待处理数据导出", + "keywords": "", + "description": "该指令实现了对Temu的待处理数据进行导出", + "comment": "在网页对象 %web_page% 中, 将结算数据-结算中款项的数据下载到%folder_path% \\ %file_name%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/2e/e5/2ee51e3991f95e96685260352768f3e9.png", + "function": "xbot_extensions.activity_temu_shop.pending_data_export", + "helpUrl": "yddoc/rpa/779170544240910336", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "folder_path", + "label": "保存文件夹", + "required": false, + "tips": "保存文件夹的地址", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null, + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "file_name", + "label": "保存文件名", + "required": false, + "tips": "自定义文件名称", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "保存路径", + "tips": "报表文件路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.active_record", + "statement": "process.invoke_activity", + "title": "Temu-营销活动-获取报名记录信息", + "keywords": "", + "description": "该指令实现了对全托平台进行获取报名记录信息的功能", + "comment": "在网页对象 %web_page% 中,选择%active_category%,%start_time%到%end_time%范围的报名记录存入到数据表格中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/5b/00/5b00ae2db01335b221009130c316cd2a.png", + "function": "xbot_extensions.activity_temu_shop.active_record", + "helpUrl": "yddoc/rpa/786141403486613504", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "active_category", + "label": "活动分类", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "active_type", + "label": "活动类型", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "SPU", + "label": "SPU", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "goods_num", + "label": "货号", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "active_status", + "label": "活动状态", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "end_status", + "label": "到期状态", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.sale_manage_info", + "statement": "process.invoke_activity", + "title": "Temu-销售管理-销售管理数据获取", + "keywords": "", + "description": "该指令实现了在Temu平台对销售管理数据进行获取的功能", + "comment": "在Temu销售管理网页%web_page%上,进行数据爬取", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/f8/cb/f8cb7d50c743efc4f2c63d9000c5862e.png", + "function": "xbot_extensions.activity_temu_shop.sale_manage_info", + "helpUrl": "yddoc/rpa/788326694266372096", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "data", + "label": "data", + "name": "data", + "type": "list" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.return_goods_info", + "statement": "process.invoke_activity", + "title": "Temu-库存管理-退货单数据获取", + "keywords": "", + "description": "该指令实现了对Temu进行退货单数据抓取的功能", + "comment": "在网页对象%web_page%上,抓取%start_time%到%end_time%的退货单并存入数据表格中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/51/a2/51a29bfb113dcd080083ee477f9b0122.png", + "function": "xbot_extensions.activity_temu_shop.return_goods_info", + "helpUrl": "yddoc/rpa/788382259556765696", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始日期", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束日期", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "odds_number", + "label": "退货单号", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "status", + "label": "弃货状态", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "discard_type", + "label": "退货类型", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "reason", + "label": "退货原因", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.sold_out_info", + "statement": "process.invoke_activity", + "title": "Temu-销售管理-售罄看板信息获取", + "keywords": "", + "description": "该指令实现了在Temu平台对售罄看板数据进行获取的功能", + "comment": "在网页对象%web_page%中,抓取可售天数为%available_start_day%到%available_end_day%的售罄看板信息,并存入到数据表格中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/62/90/629076d7dd480d2b61657b78cf0bc821.png", + "function": "xbot_extensions.activity_temu_shop.sold_out_info", + "helpUrl": "yddoc/rpa/788737790537986048", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "available_start_day", + "label": "起始库存可售天数", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "available_end_day", + "label": "结束库存可售天数", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.return_apply_data", + "statement": "process.invoke_activity", + "title": "Temu-库存管理-退货申请数据获取", + "keywords": "", + "description": "该指令实现了在Temu平台对退货申请数据进行获取的功能", + "comment": "在网页对象%web_page%中,将%start_time%到%end_time%的退货申请数据保存于数据表格中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/7d/1c/7d1c8f40404adc9df407c8f5c9d0ccdd.png", + "function": "xbot_extensions.activity_temu_shop.return_apply_data", + "helpUrl": "yddoc/rpa/790844049976418304", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入开始时间,格式为YYYY-MM-dd,例:2025-01-01" + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入结束时间,格式为YYYY-MM-dd,例:2025-01-01" + }, + "category": "general" + }, + { + "name": "odds_number", + "label": "申请单号", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入指定的申请单号" + }, + "category": "advanced" + }, + { + "name": "SKC", + "label": "SKC", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入指定的SKC" + }, + "category": "advanced" + }, + { + "name": "stock", + "label": "备货单号", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入指定的备货单号" + }, + "category": "advanced" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.return_detail_data", + "statement": "process.invoke_activity", + "title": "Temu-库存管理-退货明细数据获取", + "keywords": "", + "description": "该指令实现了在Temu平台对退货明细数据进行获取的功能", + "comment": "在网页对%web_page%中,将%start_time%到%end_time%的退货明细数据存于数据表格中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/d5/c0/d5c01eb41550cfae5c94ace8de894108.png", + "function": "xbot_extensions.activity_temu_shop.return_detail_data", + "helpUrl": "/yddoc/rpa/790845108907802624", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入开始时间,格式为YYYY-MM-dd,例:2025-01-01" + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入结束时间,格式为YYYY-MM-dd,例:2025-01-01" + }, + "category": "general" + }, + { + "name": "package_num", + "label": "退货包裹号", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入指定的快递包裹号" + }, + "category": "advanced" + }, + { + "name": "SKU", + "label": "SKU", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入指定的SKU" + }, + "category": "advanced" + }, + { + "name": "stock", + "label": "备货单号", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "输入指定的备货单号" + }, + "category": "advanced" + } + ], + "outputs": [ + { + "id": "data", + "label": "data", + "name": "data", + "type": "list" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.order_management", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.activity_temu_shop.order_management", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.switch_area", + "statement": "process.invoke_activity", + "title": "Temu-卖家中心-切换区域", + "keywords": "", + "description": "该指令实现了在Temu-卖家中心切换区域的功能", + "comment": "在网页对象%web_page%中,将当前的区域切换成%area%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/55/e5/55e5a45b9fe4da8e6a56eeef3be2e262.png", + "function": "xbot_extensions.activity_temu_shop.switch_area", + "helpUrl": "yddoc/rpa/795933888705499136", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "area", + "label": "区域", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.comment_data", + "statement": "process.invoke_activity", + "title": "Temu-商品管理-评价管理数据获取", + "keywords": "", + "description": "该指令实现了对半托平台进行获取商品评价的功能", + "comment": "在网页对象%web_page%中,将%start_time%到%end_time%星级为%level%的评论数据保存到数据表格中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/87/c5/87c5005f3c6602274824602637337a0a.png", + "function": "xbot_extensions.activity_temu_shop.comment_data", + "helpUrl": "yddoc/rpa/798517129808707584", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写日期,格式为YYYY-MM-DD/YYYY-MM-DD" + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写日期,格式为YYYY-MM-DD/YYYY-MM-DD" + }, + "category": "general" + }, + { + "name": "level", + "label": "星级", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写评论星级,例:'1星', 多个星级则[\"1星\",'2星']" + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.product_quality_dashboard", + "statement": "process.invoke_activity", + "title": "Temu-店铺品质指标获取", + "keywords": "", + "description": "该指令实现了对Temu的店铺品质指标获取", + "comment": "在网页对象%web_page%中,获取店铺品质指标并返回给%data_dict%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/47/8b/478b5f20924db75fdf043d84802ba79b.png", + "function": "xbot_extensions.activity_temu_shop.product_quality_dashboard", + "helpUrl": "yddoc/rpa/798530482961530880", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "data_dict", + "label": "店铺品质指标", + "name": "data_dict", + "type": "any" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.batch_participate_active", + "statement": "process.invoke_activity", + "title": "Temu-营销活动-批量报名活动", + "keywords": "", + "description": "该指令实现了对半托平台进行获取报名记录信息的功能", + "comment": "在网页对象%web_page%中,根据模板%file_path%批量报名活动", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/52/a0/52a0cd100d6694278faceb269044a9b8.png", + "function": "xbot_extensions.activity_temu_shop.batch_participate_active", + "helpUrl": "yddoc/rpa/798896040988516352", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "file_path", + "label": "文件地址", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.get_batch_active_module", + "statement": "process.invoke_activity", + "title": "Temu-营销活动-生成批量报名活动模板", + "keywords": "", + "description": "该指令实现了对半托平台进行生成批量报名活动的模板", + "comment": "在网页对象%web_page%中,生成活动类型为%active_type%,选择报名活动的站点为%active_site%,商品SPU为%SPU%的批量活动模板,并保存于%file_folder%\\%file_name%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/85/7b/857b9375e63711a64969fe6ad8b3f528.png", + "function": "xbot_extensions.activity_temu_shop.get_batch_active_module", + "helpUrl": "yddoc/rpa/798896080112013312", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "active_type", + "label": "报名活动类型", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "例:清仓甩卖,多个例:['清仓甩卖', '限时秒杀']" + }, + "category": "general" + }, + { + "name": "active_site", + "label": "选择活动站点", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "例:美国站,多个例:['美国站', '加拿大站']" + }, + "category": "general" + }, + { + "name": "SPU", + "label": "SPU", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "例:19999,多个例:['10099', '12333']" + }, + "category": "general" + }, + { + "name": "file_folder", + "label": "保存文件夹", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写保存文件夹地址", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "file_name", + "label": "保存文件名", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写保存文件名" + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "模板文件路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.labor_bill", + "statement": "process.invoke_activity", + "title": "账户资金-财务明细-导出列表+账务详情", + "keywords": "", + "description": "该指令实现在temu下载财务明细导出列表 + 账务详情的账单数据", + "comment": "在网页对象 %web_page% 中, 下载日期为%start_time%到%end_time%的导出列表 + 账务详情报表并保存至%save_path_list%", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.activity_temu_shop.labor_bill", + "helpUrl": "/yddoc/rpa/zh-CN/861217250444316672", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "start_time", + "label": "开始日期", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "选择报表开始日期,格式为YYYY-MM-DD" + }, + "category": "general" + }, + { + "name": "end_time", + "label": "结束日期", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "选择报表结束日期,格式为YYYY-MM-DD" + }, + "category": "general" + }, + { + "name": "file_folder", + "label": "保存文件夹", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "填写文件保存地址", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "capital_flow", + "label": "资金流向", + "required": false, + "tips": "", + "type": "any", + "default": "13:", + "editor": { + "kind": "textbox", + "placeholder": "填写一个资金流向,若有多个则以列表的方式。如['xx', 'xx']" + }, + "category": "advanced" + }, + { + "name": "financial_type", + "label": "财务类型", + "required": false, + "tips": "", + "type": "any", + "default": "13:", + "editor": { + "kind": "textbox", + "placeholder": "填写一个财务,若有多个则以列表的方式。如['xx', 'xx']" + }, + "category": "advanced" + }, + { + "name": "fund_mix", + "label": "收支金额最小值", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "fund_max", + "label": "收支金额最大值", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "advanced" + }, + { + "name": "report_type", + "label": "下载清单", + "required": false, + "tips": "为空, 表示下载全部, \"全球,美国\"表示下载全球,美国", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "为空, 表示下载全部, \"全球,美国\"" + }, + "category": "advanced" + } + ], + "outputs": [ + { + "id": "save_path_list", + "label": "文件保存列表", + "name": "save_path_list", + "type": "list" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.test", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.activity_temu_shop.test", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.account_balance_collection", + "statement": "process.invoke_activity", + "title": "Temu-资金中心-账户余额数据采集", + "keywords": "", + "description": "该指令实现了Temu店铺资金中心中的账户余额数据采集功能", + "comment": "在网页%web_page%中进行账户余额数据采集,结果保存至%输出结果%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/54/37/54375af85fe3834d8a7f083059ed6d5f.png", + "function": "xbot_extensions.activity_temu_shop.account_balance_collection", + "helpUrl": "/yddoc/rpa/zh-CN/859620240341803008", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "web_page", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [] + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "输出结果", + "label": "输出结果", + "name": "输出结果", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.pending_data_screenshot", + "statement": "process.invoke_activity", + "title": "Temu-结算数据-待结算数据截图", + "keywords": "", + "description": "该指令实现了Temu结算数据模块的待结算数据自动截图的功能", + "comment": "在网页%web_page%中,进行待结算账户的截图,截图存放在%file_folder%文件夹下,截图完整路径保存至%file_path%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/99/58/9958eb2f023321f23053ff0d4b609172.png", + "function": "xbot_extensions.activity_temu_shop.pending_data_screenshot", + "helpUrl": "/yddoc/rpa/zh-CN/859707965554581504", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "file_folder", + "label": "文件夹", + "required": false, + "tips": "文件夹路径", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "截图保存的文件夹位置", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "station", + "label": "站点", + "required": false, + "tips": "站点", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "站点名称,只用于截图文件的命名拼接,不进行站点转换" + }, + "category": "general" + }, + { + "name": "web_page", + "label": "web_page", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "文件路径", + "tips": "截图完整路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.return_refund_collection", + "statement": "process.invoke_activity", + "title": "Temu-退货退款-数据采集", + "keywords": "", + "description": "该指令实现了Temu店铺的退货退款的数据自动采集功能", + "comment": "", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/c8/29/c8297dd00fcfff1877b273493029f2f8.png", + "function": "xbot_extensions.activity_temu_shop.return_refund_collection", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.注入js代码", + "statement": "process.invoke_activity", + "title": "子流程1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.activity_temu_shop.process1", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.test1", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.activity_temu_shop.test1", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.goods_list_download", + "statement": "process.invoke_activity", + "title": "Temu-商品管理-商品列表下载", + "keywords": "", + "description": "该指令实现了Temu店铺商品管理模块的商品列表的自动下载", + "comment": "在网页%web_page%中,选择商品列表类型%goods_type%进行下载,下载保存在%file_folder%文件夹下,报表名称为%file_name%,报表完整路径保存至%file_path%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/81/50/81509cf28d8fe8b1ed914c5535045ccf.png", + "function": "xbot_extensions.activity_temu_shop.goods_list_download", + "helpUrl": "/yddoc/rpa/zh-CN/862222205631148032", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [] + }, + "category": "general" + }, + { + "name": "goods_type", + "label": "goods_type", + "required": false, + "tips": "商品列表类型", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "商品列表类型 参数有 全部/在售中/未发布到站点/已下架" + }, + "category": "general" + }, + { + "name": "file_folder", + "label": "文件夹路径", + "required": false, + "tips": "报表保存的文件夹", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "报表下载保存的文件夹", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "file_name", + "label": "文件名称", + "required": false, + "tips": "报表名称", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "报表名称", + "dialog": { + "type": "SaveFile", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "输出结果", + "tips": "报表完整路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.fix_web_download", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.activity_temu_shop.fix_web_download", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.activity_temu_shop.traffic_analysis_collection", + "statement": "process.invoke_activity", + "title": "Temu-数据中心-流量分析数据采集", + "keywords": "", + "description": "该指令实现了Temu店铺数据中心模块的流量分析数据采集的功能", + "comment": "在网页%web_page%中选择%date_time%日期,进行数据采集,采集结果保存至%data%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/11/1c/111c8c7e7b25a50c3395a39a58b72010.png", + "function": "xbot_extensions.activity_temu_shop.traffic_analysis_collection", + "helpUrl": "/yddoc/rpa/zh-CN/862230926765510656", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "date_time", + "label": "日期选择", + "required": false, + "tips": "日期选择", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "日期选择 参数有 昨日/今日/本周/本月/近7日/近30日" + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "data", + "label": "输出结果", + "tips": "输出结果", + "name": "data", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.active_data_export", + "statement": "process.invoke_activity", + "title": "Temu-数据中心-活动数据导出(全托)", + "keywords": "", + "description": "该指令实现了Temu全托店铺的活动数据导出", + "comment": "在网页%web_page%中,选择时间范围%time_range%,文件保存至%file_path%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/25/17/2517754322b7338d6a09ff7a2a65c86a.png", + "function": "xbot_extensions.activity_temu_shop.active_data_export", + "helpUrl": "/yddoc/rpa/zh-CN/864316233210437632", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "网页对象", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "time_range", + "label": "时间范围", + "required": false, + "tips": "时间范围", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "时间范围,格式为 yyyy-mm-dd~yyyy-mm-dd" + }, + "category": "general" + }, + { + "name": "file_folder", + "label": "文件夹路径", + "required": false, + "tips": "文件夹路径", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "报表导出的文件夹位置", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "file_name", + "label": "文件名称", + "required": false, + "tips": "文件名称", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "报表导出的名称", + "dialog": { + "type": "SaveFile", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "输出路径", + "tips": "文件完整路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.active_data_export_half", + "statement": "process.invoke_activity", + "title": "Temu-数据中心-活动数据导出(半托)", + "keywords": "", + "description": "该指令实现了temu半托店铺的数据导出", + "comment": "在网页%web_page%中,选择时间%time_range%,结果文件保存至%file_path%中", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/81/5e/815ee50a0c19345a5bb043400faf81ac.png", + "function": "xbot_extensions.activity_temu_shop.active_data_export_half", + "helpUrl": "/yddoc/rpa/zh-CN/864314324638539776", + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "web_page", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "time_range", + "label": "时间范围", + "required": false, + "tips": "时间范围", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "时间范围, 格式为yyyy-dd-mm~yyyy-dd-mm" + }, + "category": "general" + }, + { + "name": "file_folder", + "label": "文件夹路径", + "required": false, + "tips": "文件夹路径", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "导出的数据存储的文件夹位置", + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "file_name", + "label": "报表名称", + "required": false, + "tips": "文件名称", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "导出文件的名称", + "dialog": { + "type": "SaveFile", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "file_path", + "label": "输出路径", + "tips": "文件夹完整路径", + "name": "file_path", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.activity_temu_shop.declared_value", + "statement": "process.invoke_activity", + "title": "Temu-商品管理-申报价格", + "keywords": "", + "description": "该指令实现了temu店铺的价格自动申报", + "comment": "", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/39/41/39414c86f5f33f8e198ef56d4f605322.png", + "function": "xbot_extensions.activity_temu_shop.declared_value", + "helpUrl": null, + "extension": "temu 商家后台扩展", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "web_page", + "label": "web_page", + "required": false, + "tips": "网页对象", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true + }, + "category": "general" + }, + { + "name": "two_list", + "label": "two_list", + "required": false, + "tips": "用户传输的数据", + "type": "list", + "default": "13:[]", + "editor": { + "kind": "textbox", + "placeholder": "请传入一个二维列表,内容包含对应的原申报价格以及参考申报价格" + }, + "category": "general" + } + ], + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/xbot_extensions.popup_detector.blocks.json b/src/assert/block_settings/xbot_extensions.popup_detector.blocks.json new file mode 100644 index 0000000..68c1423 --- /dev/null +++ b/src/assert/block_settings/xbot_extensions.popup_detector.blocks.json @@ -0,0 +1,348 @@ +{ + "types": [], + "blocks": [ + { + "name": "xbot_extensions.popup_detector.main", + "statement": "process.invoke_activity", + "title": "弹窗智能侦测器", + "keywords": "", + "description": "该指令集实现了自动侦测弹窗,并执行屏蔽弹窗,或者自定义操作", + "comment": "", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/92/80/92800ec38d8d165be91732ddee75bb2d.png", + "function": "xbot_extensions.popup_detector.main", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.js_script", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.js_script", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.popup_detector_core_old", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.popup_detector_core_old", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.A1 智能屏蔽弹窗(web)", + "statement": "process.invoke_activity", + "title": "智能屏蔽弹窗(web)", + "keywords": "", + "description": "该指令实现了全程智能侦测并屏蔽弹窗的操作", + "comment": "开始全程智能侦测并屏蔽弹窗~~~", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/92/80/92800ec38d8d165be91732ddee75bb2d.png", + "function": "xbot_extensions.popup_detector.process1", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/popup_detector", + "extension": "弹窗智能侦测器", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.utils", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.utils", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.A2 智能侦测弹窗(web)", + "statement": "process.invoke_activity", + "title": "智能侦测弹窗(web) 测试", + "keywords": "", + "description": "该指令实现了全程智能侦测并执行指定流程的操作", + "comment": "开始全程智能侦测弹窗,侦测到弹窗后执行流程%执行流程%,执行完后%执行流程后的操作%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/92/80/92800ec38d8d165be91732ddee75bb2d.png", + "function": "xbot_extensions.popup_detector.process2", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/popup_detector2", + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "执行流程", + "label": "执行流程", + "required": true, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "侦测到弹窗后,要执行的流程名" + }, + "category": "general" + }, + { + "name": "执行流程后的操作", + "label": "执行流程后的操作", + "required": true, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "select", + "useVariableOptions": false, + "options": [ + { + "display": "执行上个步骤", + "value": "执行上个步骤", + "Unicode": null + }, + { + "display": "执行下个步骤", + "value": "执行下个步骤", + "Unicode": null + } + ] + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.A3 移除智能侦测弹窗(web)", + "statement": "process.invoke_activity", + "title": "移除智能侦测弹窗(web)", + "keywords": "", + "description": "该指令实现了移除智能侦测弹窗的操作", + "comment": "移除智能侦测弹窗~~~", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.process3", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/oy8nesf3b0eknzkr", + "extension": "弹窗智能侦测器", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.运行", + "statement": "process.invoke_activity", + "title": "子流程1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.process4", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.验证码", + "statement": "process.invoke_activity", + "title": "子流程1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.process5", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.popup_detector_core", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.popup_detector_core", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.聚水潭", + "statement": "process.invoke_activity", + "title": "子流程1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.process6", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.popup_xpath", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.popup_xpath", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.test", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.test", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.京东", + "statement": "process.invoke_activity", + "title": "子流程1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.process7", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.拼多多", + "statement": "process.invoke_activity", + "title": "子流程1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.process8", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.popup_detector.测试网页激活", + "statement": "process.invoke_activity", + "title": "子流程1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.popup_detector.process9", + "helpUrl": null, + "extension": "弹窗智能侦测器", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/xbot_extensions.super_browser.blocks.json b/src/assert/block_settings/xbot_extensions.super_browser.blocks.json new file mode 100644 index 0000000..4ced2d4 --- /dev/null +++ b/src/assert/block_settings/xbot_extensions.super_browser.blocks.json @@ -0,0 +1,1104 @@ +{ + "types": [], + "blocks": [ + { + "name": "xbot_extensions.super_browser.main", + "statement": "process.invoke_activity", + "title": "紫鸟控制台操作", + "keywords": "", + "description": "该指令集实现了紫鸟控制台的一些高频操作,如进入账号管理页面、打开店铺等待", + "comment": "", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/b1/37/b137094f228d10368c7f0a9d3c2e13b6.png", + "function": "xbot_extensions.super_browser.main", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.A1 进入账号管理页面", + "statement": "process.invoke_activity", + "title": "进入账号管理页面", + "keywords": "", + "description": "从紫鸟浏览器控制台进入账号管理页面", + "comment": "从紫鸟浏览器控制台进入账号管理页面", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/icons/activity-icons/01%E9%80%9A%E7%94%A8/contacts.png", + "function": "xbot_extensions.super_browser.to_account_page", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/to_account_page", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.A2 打开店铺", + "statement": "process.invoke_activity", + "title": "打开店铺", + "keywords": "", + "description": "该指令实现了根据店铺名称打开店铺的功能,调用这个指令会关闭正在打开的所有店铺", + "comment": "从紫鸟浏览器控制台打开店铺:%店铺名称%,%打开账号%打开账号,保存完整店铺名称至%完整店铺名称%,保存网页对象至%web_page%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/c0/44/c044ac003bfe6ff01f7876413092de94.png", + "function": "xbot_extensions.super_browser.open_store", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/open_store", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "店铺名称", + "label": "店铺名称", + "required": true, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "店铺名称" + }, + "category": "general" + }, + { + "name": "匹配类型", + "label": "匹配类型", + "required": true, + "tips": "", + "type": "str", + "default": "10:相等", + "editor": { + "kind": "select", + "useVariableOptions": false, + "options": [ + { + "display": "相等", + "value": "相等", + "Unicode": null + }, + { + "display": "模糊", + "value": "模糊", + "Unicode": null + } + ] + }, + "category": "general" + }, + { + "name": "打开账号", + "label": "打开账号", + "required": true, + "tips": "点击,打开店铺后,点击打开账号按钮\r\n不点击,打开店铺后,直接返回,需要注意这个时候网页对象为空", + "type": "str", + "default": "10:点击", + "editor": { + "kind": "select", + "useVariableOptions": false, + "options": [ + { + "display": "点击", + "value": "点击", + "Unicode": null + }, + { + "display": "不点击", + "value": "不点击", + "Unicode": null + } + ] + }, + "category": "general" + }, + { + "name": "隐私模式", + "label": "", + "required": false, + "tips": "使用隐私模式打开店铺", + "type": "bool", + "default": "13:False", + "editor": { + "kind": "checkbox", + "label": "隐私模式" + }, + "category": "general" + }, + { + "name": "超时时间", + "label": "超时时间", + "required": false, + "tips": "", + "type": "int", + "default": "13:50", + "editor": { + "kind": "spin" + }, + "category": "advanced" + } + ], + "outputs": [ + { + "id": "完整店铺名称", + "label": "完整店铺名称", + "name": "完整店铺名称", + "type": "str" + }, + { + "id": "web_page", + "label": "返回网页对象至", + "name": "web_page", + "type": "xbot._web.browser.WebBrowser" + } + ] + }, + { + "name": "xbot_extensions.super_browser.api", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.api", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.A3 获取下载文件保存位置", + "statement": "process.invoke_activity", + "title": "获取下载文件保存位置", + "keywords": "", + "description": "获取紫鸟浏览器默认下载文件保存位置", + "comment": "获取紫鸟浏览器默认下载文件保存位置,保存路径至:%download_path%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/icons/activity-icons/01%E9%80%9A%E7%94%A8/installing_updates.png", + "function": "xbot_extensions.super_browser.get_download_path", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/get_download_path", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [ + { + "id": "download_path", + "label": "保存位置", + "name": "download_path", + "type": "str" + }, + { + "id": "is_check", + "label": "是否询问保存位置", + "name": "is_check", + "type": "bool" + } + ] + }, + { + "name": "xbot_extensions.super_browser.A4 紫鸟登录", + "statement": "process.invoke_activity", + "title": "紫鸟登录", + "keywords": "", + "description": "该指令实现了自动打开紫鸟控制台,并登录企业号的操作", + "comment": "使用企业%企业名称%的账号%企业用户名%登录紫鸟控制台", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/86/5f/865f2062562ad9786b5a5feecf7173a2.png", + "function": "xbot_extensions.super_browser.process1", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/login", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "紫鸟版本", + "label": "紫鸟版本", + "required": false, + "tips": "", + "type": "str", + "default": "10:V5", + "editor": { + "kind": "select", + "useVariableOptions": false, + "options": [ + { + "display": "V5", + "value": "V5", + "Unicode": null + }, + { + "display": "V6", + "value": "V6", + "Unicode": null + } + ] + }, + "category": "general" + }, + { + "name": "企业名称", + "label": "企业名称", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "企业用户名", + "label": "企业用户名", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "密码", + "label": "密码", + "required": false, + "tips": "如果不填,则不会填写密码框", + "type": "str", + "default": "10:", + "editor": { + "kind": "password" + }, + "category": "general" + }, + { + "name": "是否填写账号密码", + "label": "", + "required": false, + "tips": "", + "type": "bool", + "default": "13:False", + "editor": { + "kind": "checkbox", + "label": "是否填写账号密码" + }, + "category": "general" + }, + { + "name": "是否退出登录", + "label": "", + "required": false, + "tips": "", + "type": "bool", + "default": "13:False", + "editor": { + "kind": "checkbox", + "label": "是否退出登录" + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.A5 紫鸟文件下载", + "statement": "process.invoke_activity", + "title": "紫鸟文件下载", + "keywords": "", + "description": "该指令实现了紫鸟浏览器网页端的文件下载操作", + "comment": "在网页%网页对象%中,通过下载按钮%下载按钮%下载文件,保存至文件夹%保存文件夹%,文件命名为%保存文件名%,输出下载文件路径至%download_file_name%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/images/be/3f/be3fdad2be1e3bbac93eeb86a4d94202.png", + "function": "xbot_extensions.super_browser.process2", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/superbrowser_download", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "网页对象", + "label": "网页对象", + "required": true, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [] + }, + "category": "general" + }, + { + "name": "下载按钮", + "label": "下载按钮", + "required": true, + "tips": "", + "type": "xbot._web.element.WebElement", + "default": "13:None", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "onlySelector": false + }, + "category": "general" + }, + { + "name": "保存文件夹", + "label": "保存文件夹", + "required": true, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null, + "dialog": { + "type": "SelectFolder", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "保存文件名", + "label": "保存文件名", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "非必填, 如果不填使用下载资源默认文件名, 若无默认文件名则自动为下载资源生成不重复的文件名" + }, + "category": "general" + }, + { + "name": "超时时间", + "label": "超时时间", + "required": true, + "tips": "等待文件下载超时时间,单位秒", + "type": "str", + "default": "10:100", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "等待对话框出现", + "label": "等待对话框出现", + "required": false, + "tips": "", + "type": "str", + "default": "10:20", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "download_file_name", + "label": "download_file_name", + "name": "download_file_name", + "type": "str" + } + ] + }, + { + "name": "xbot_extensions.super_browser.A6 获取店铺列表", + "statement": "process.invoke_activity", + "title": "获取店铺列表", + "keywords": "", + "description": "该指令实现了在紫鸟浏览器上获取指定平台的所有店铺名称操作", + "comment": "在紫鸟浏览器控制台上获取%所属平台%平台的所有店铺名称,输出至%store_name_list%", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.process6", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/zsdzf6rxhhbcw369", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "所属平台", + "label": "所属平台", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": "选填,不填获取所有平台店铺。填写示例:亚马逊" + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "store_name_list", + "label": "店铺名称列表", + "name": "store_name_list", + "type": "list" + } + ] + }, + { + "name": "xbot_extensions.super_browser.utils", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.utils", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.download_api", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.download_api", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser._core_beta", + "statement": "process.invoke_activity", + "title": "module2", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser._core_beta", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.tool", + "statement": "process.invoke_activity", + "title": "module2", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.tool", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.A7 上传文件到紫鸟", + "statement": "process.invoke_activity", + "title": "上传文件到紫鸟", + "keywords": "", + "description": "该指令实现了从本地上传文件到紫鸟网页端的操作", + "comment": "在网页%网页对象%中点击%上传按钮%,在弹出的文件选择对话框中输入文件%上传文件路径%", + "icon": "https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/icons/activity-icons/01%E9%80%9A%E7%94%A8/upload_to_the_cloud.png", + "function": "xbot_extensions.super_browser.process7", + "helpUrl": "https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/super_browser-upload", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "网页对象", + "label": "网页对象", + "required": true, + "tips": "", + "type": "xbot._web.browser.WebBrowser", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [] + }, + "category": "general" + }, + { + "name": "上传按钮", + "label": "上传按钮", + "required": true, + "tips": "选择要点击上传按钮对应的网页元素", + "type": "xbot._web.element.WebElement", + "default": "13:None", + "editor": { + "kind": "uitarget", + "selectorType": "simple", + "onlySelector": false + }, + "category": "general" + }, + { + "name": "上传文件路径", + "label": "上传文件路径", + "required": false, + "tips": "待上传文件完整路径, 若要选择多个文件,切换到Python模式下,输入文件列表,比如:[\"文件1路径\", \"文件2路径\"]", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null, + "dialog": { + "type": "OpenFile", + "filter": "所有文件|*.*", + "defaultFileName": null, + "maxSize": null + } + }, + "category": "general" + }, + { + "name": "等待对话框超时时间", + "label": "等待对话框超时时间", + "required": false, + "tips": "", + "type": "str", + "default": "10:20", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.ziniao_v6", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.ziniao_v6", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.utils_v6", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.utils_v6", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.测试-打开店铺", + "statement": "process.invoke_activity", + "title": "子流程1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.process8", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.ziniao_v5", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.ziniao_v5", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.create_instance_api", + "statement": "process.invoke_activity", + "title": "连接紫鸟开放平台(API)🆕", + "keywords": "", + "description": "该指令通过紫鸟开放平台创建实例用于接口调用", + "comment": "通%app_id%连接紫鸟开放平台, 并返回实例保存至%ziniao_instance%", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.create_instance_api", + "helpUrl": "yddoc/rpa/811841706059862016", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "app_id", + "label": "应用 ID", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "private_key", + "label": "应用 Key", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "password" + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "ziniao_instance", + "label": "紫鸟对象", + "name": "ziniao_instance", + "type": "any" + } + ] + }, + { + "name": "xbot_extensions.super_browser.get_user_list_api", + "statement": "process.invoke_activity", + "title": "获取用户列表(API)🆕", + "keywords": "", + "description": "通过紫鸟开放平台获取公司全部的账号信息", + "comment": "获取%ziniao_instance%对象的全部紫鸟账号保存至%user_list%", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.get_user_list_api", + "helpUrl": "yddoc/rpa/811841790265470976", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "ziniao_instance", + "label": "紫鸟对象", + "required": false, + "tips": "", + "type": "any", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [] + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "user_list", + "label": "用户列表", + "name": "user_list", + "type": "list" + } + ] + }, + { + "name": "xbot_extensions.super_browser.get_store_list_api", + "statement": "process.invoke_activity", + "title": "获取店铺列表(API)🆕", + "keywords": "", + "description": "通过接口获取指定账号下的全部店铺ID", + "comment": "通过%ziniao_instance%获取%user_id%账号下的全部店铺保存至%store_list%", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.get_store_list_api", + "helpUrl": "yddoc/rpa/811841836088242176", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "ziniao_instance", + "label": "紫鸟对象", + "required": false, + "tips": "", + "type": "any", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [] + }, + "category": "general" + }, + { + "name": "user_id", + "label": "用户ID", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "store_list", + "label": "店铺列表", + "name": "store_list", + "type": "list" + } + ] + }, + { + "name": "xbot_extensions.super_browser.open_store_api", + "statement": "process.invoke_activity", + "title": "打开店铺(API)🆕", + "keywords": "", + "description": "该指令通过开放接口打开紫鸟店铺", + "comment": "通过%ziniao_instance%打开ID为%strore_id%的店铺", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.open_store_api", + "helpUrl": "yddoc/rpa/811841875958067200", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "ziniao_instance", + "label": "紫鸟对象", + "required": false, + "tips": "", + "type": "any", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [] + }, + "category": "general" + }, + { + "name": "user_id", + "label": "用户ID", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "strore_id", + "label": "店铺ID", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "timeout", + "label": "超时时间", + "required": false, + "tips": "单位, 为秒", + "type": "int", + "default": "13:30", + "editor": { + "kind": "spin" + }, + "category": "advanced" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.close_store_api", + "statement": "process.invoke_activity", + "title": "关闭店铺(API)🆕", + "keywords": "", + "description": "该指令通过接口关闭指点的店铺", + "comment": "通过%ziniao_instance%关闭ID为%store_id%的店铺", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.close_store_api", + "helpUrl": "yddoc/rpa/811841916295155712", + "extension": "紫鸟控制台操作", + "hidden": false, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "ziniao_instance", + "label": "紫鸟对象", + "required": false, + "tips": "", + "type": "any", + "default": "13:None", + "editor": { + "kind": "select", + "useVariableOptions": true, + "options": [] + }, + "category": "general" + }, + { + "name": "store_id", + "label": "店铺 ID", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.ziniaoapi", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.ziniaoapi", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.ziniaogui", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.ziniaogui", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.close_app_api", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.close_app_api", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + }, + { + "name": "xbot_extensions.super_browser.open_store_beta", + "statement": "process.invoke_activity", + "title": "打开店铺(V6_Beta)", + "keywords": "", + "description": "测试紫鸟V6使用情况,并不是最终结果,试用!!", + "comment": "", + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.open_store_beta", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [ + { + "name": "store_name", + "label": "店铺名称", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + }, + { + "name": "locate_type", + "label": "匹配类型", + "required": false, + "tips": "", + "type": "str", + "default": "10:", + "editor": { + "kind": "textbox", + "placeholder": null + }, + "category": "general" + } + ], + "outputs": [ + { + "id": "web_page", + "label": "网页", + "name": "web_page", + "type": "xbot._web.browser.WebBrowser" + } + ] + }, + { + "name": "xbot_extensions.super_browser.test_tmp", + "statement": "process.invoke_activity", + "title": "module1", + "keywords": "", + "description": null, + "comment": null, + "icon": "BlockIcons/21-2.png", + "function": "xbot_extensions.super_browser.test_tmp", + "helpUrl": null, + "extension": "紫鸟控制台操作", + "hidden": true, + "canDebug": true, + "isCondition": false, + "isLoop": false, + "isPseudo": false, + "inputs": [], + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/src/assert/block_settings/zip.blocks.json b/src/assert/block_settings/zip.blocks.json new file mode 100644 index 0000000..2fb3956 --- /dev/null +++ b/src/assert/block_settings/zip.blocks.json @@ -0,0 +1,146 @@ +{ + "types": [], + "blocks": [ + { + "name": "xzip.zip", + "function": "xbot_visual.xzip.zip", + "title": "压缩文件/文件夹", + "description": "这个指令用于压缩文件/文件夹", + "comment": "将%file_folder_path%压缩到%zip_file_path%", + "icon": "BlockIcons/30-1.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/压缩、解压/压缩文件(文件夹).html", + "inputs": [ + { + "name": "file_folder_path", + "label": "要压缩的文件(夹)", + "required": true, + "tips": "输入或选择要压缩的文件或文件夹路径", + "type": "str", + "editor": { + "placeholder": "待压缩的文件/文件夹", + "kind": "textbox", + "dialog": { + "type": "OpenFiles" + } + } + }, + { + "name": "password", + "label": "密码", + "required": false, + "tips": "输入密码;若不设置密码,请留空", + "type": "str", + "editor": { + "placeholder": "输入压缩文件路径", + "kind": "password" + } + }, + { + "name": "compress_level", + "label": "压缩方式", + "required": true, + "default": "10:5", + "defaultDisplay": "通用", + "tips": "请选择压缩方式", + "type": "str", + "editor": { + "kind": "select", + "options": [ + { + "display": "通用", + "value": "5" + }, + { + "display": "压缩最快", + "value": "1" + }, + { + "display": "压缩最多", + "value": "9" + } + ] + } + }, + { + "name": "zip_file_path", + "label": "压缩文件保存至", + "required": true, + "tips": "请输入压缩文件保存路径,只支持压缩成zip文件", + "type": "str", + "editor": { + "kind": "textbox" + } + } + ] + }, + { + "name": "xzip.unzip", + "function": "xbot_visual.xzip.unzip", + "title": "解压文件/文件夹", + "description": "这个指令用于解压文件/文件夹", + "comment": "将%zip_file_path%解压到%unzip_dir_path%,将解压文件夹路径保存到%folder%", + "icon": "BlockIcons/30-2.png", + "helpUrl": "yddoc/language/zh-cn/指令文档/操作系统/压缩、解压/解压文件(文件夹).html", + "inputs": [ + { + "name": "zip_file_path", + "label": "压缩文件路径", + "required": true, + "tips": "请输入压缩文件路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "OpenFile", + "filter": "zip文件 (.zip)|*.zip" + } + } + }, + { + "name": "password", + "label": "解压密码", + "required": false, + "tips": "输入解压密码,若没有则留空", + "type": "str", + "editor": { + "kind": "password" + } + }, + { + "name": "unzip_dir_path", + "label": "解压文件夹路径", + "required": true, + "tips": "请输入解压文件夹路径", + "type": "str", + "editor": { + "kind": "textbox", + "dialog": { + "type": "SelectFolder" + } + } + }, + { + "name": "create_dedicated_folder", + "label": "", + "default": "13:True", + "tips": "解压至与压缩文件同名的文件夹中", + "type": "bool", + "editor": { + "label": "创建同名文件夹", + "kind": "checkbox" + } + } + ], + "outputs": [ + { + "id": "folder", + "label": "保存文件夹路径至", + "variableLabel": "解压后的文件夹路径", + "tips": "指定一个变量名称,该变量用于保存文件夹路径", + "name": "folder", + "type": "str" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/assert/icon-big.ico b/src/assert/icon-big.ico new file mode 100644 index 0000000000000000000000000000000000000000..b4a88b7e5cdd034d29b756b5c09a9cc3d0dd6f11 GIT binary patch literal 198272 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 z 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