/** * 工作流解析:getActionName、calculateSwipeCoordinates、parseOldFormatAction * parseWorkflow / parseActions / parseNewFormatAction 仍由主机实现(依赖 state、actionRegistry 与 resolver) */ function getActionName(action) { const typeNames = { 'schedule': '定时执行', 'adb': 'ADB操作', 'press': '点击图片', 'input': '输入文本', 'swipe': '滑动', 'string-press': '点击文字', 'scroll': '滚动', 'locate': '定位', 'click': '点击', 'ocr': '文字识别', 'extract-messages': '提取消息记录', 'save-messages': '保存消息记录', 'generate-summary': '生成总结', 'ocr-chat': 'OCR识别对话', 'ocr-chat-history': 'OCR提取消息记录', 'extract-chat-history': '提取消息记录', 'generate-history-summary': '生成总结', 'img-bounding-box-location': '图像区域定位', 'img-center-point-location': '图像中心点定位', 'img-cropping': '裁剪图片区域', 'read-last-message': '读取最后一条消息', 'read-txt': '读取文本文件', 'read-text': '读取文本文件', 'save-txt': '保存文本文件', 'save-text': '保存文本文件', 'smart-chat-append': '智能合并聊天记录', 'ai-generate': 'AI生成', 'if': '条件判断', 'for': '循环', 'while': '循环', 'delay': '延迟', 'set': '设置变量', 'random': '生成随机数', 'echo': '打印信息', 'log': '打印信息', } const typeName = typeNames[action.type] || action.type const value = action.value || action.target || '' const displayValue = typeof value === 'string' ? value : JSON.stringify(value) if (action.type === 'schedule') { const condition = action.condition || {} const interval = condition.interval || '0s' const repeat = condition.repeat !== undefined ? condition.repeat : 1 const repeatText = repeat === -1 ? '无限循环' : `重复${repeat}次` return `${typeName}: ${interval}, ${repeatText}` } if (action.type === 'input') { return `${typeName}: ${displayValue.length > 20 ? displayValue.substring(0, 20) + '...' : displayValue}` } if (action.type === 'string-press' || action.type === 'click') { return `${typeName}: ${displayValue.length > 20 ? displayValue.substring(0, 20) + '...' : displayValue}` } if (action.type === 'if') return `${typeName}: ${action.condition || ''}` if (action.type === 'for') return `${typeName}: ${action.variable || ''}` if (action.type === 'set') return `${typeName}: ${action.variable || ''}` return `${typeName}: ${displayValue}` } function calculateSwipeCoordinates(direction, width, height) { const margin = 0.15 const swipeDistance = 0.7 let x1, y1, x2, y2 switch (direction) { case 'up-down': x1 = x2 = Math.round(width / 2) y1 = Math.round(height * margin) y2 = Math.round(height * (margin + swipeDistance)) break case 'down-up': x1 = x2 = Math.round(width / 2) y1 = Math.round(height * (margin + swipeDistance)) y2 = Math.round(height * margin) break case 'left-right': y1 = y2 = Math.round(height / 2) x1 = Math.round(width * margin) x2 = Math.round(width * (margin + swipeDistance)) break case 'right-left': y1 = y2 = Math.round(height / 2) x1 = Math.round(width * (margin + swipeDistance)) x2 = Math.round(width * margin) break default: throw new Error(`未知的滑动方向: ${direction}`) } return { x1, y1, x2, y2 } } function parseOldFormatAction(action) { const times = action.times && action.times > 0 ? parseInt(action.times, 10) : 1 const data = action.data || '' const delay = action.delay || '' if (action.press) { return { type: 'press', value: action.press, times, data, delay } } if (action.input !== undefined) { return { type: 'input', value: action.input, times, data, delay } } if (action.swipe) { const valid = ['up-down', 'down-up', 'left-right', 'right-left'] if (!valid.includes(action.swipe)) return null return { type: 'swipe', value: action.swipe, times, data, delay } } if (action['string-press']) { return { type: 'string-press', value: action['string-press'], times, data, delay } } if (action.scroll) { const valid = ['up-down', 'down-up', 'left-right', 'right-left'] if (!valid.includes(action.scroll)) return null return { type: 'scroll', value: action.scroll, times, data, delay } } return null } module.exports = { getActionName, calculateSwipeCoordinates, parseOldFormatAction, }