Files
Artemis-Eapil/apps/showcase_ui/src/app/utils/native-action-labels.util.ts
T

103 lines
4.9 KiB
TypeScript

import { ActionParam } from '../core/models/stream.model';
// Display-only translations. Protocol names and original trace payloads stay intact.
const ACTION_LABELS = new Map(Object.entries({
pinch: '双指缩放/旋转',
touch_gesture: '连续多指手势',
read_control: '读取原生控件',
control_action: '操作原生控件',
wait_until: '等待控件条件',
scroll_to: '滚动查找控件',
action_sequence: '动作序列'
}));
const CONTROL_LABELS = new Map(Object.entries({
click: '原生点击', long_click: '原生长按', focus: '聚焦控件',
show_on_screen: '显示控件', set_progress: '设置控件值',
scroll_forward: '向前滚动', scroll_backward: '向后滚动',
scroll_up: '向上滚动', scroll_down: '向下滚动',
scroll_left: '向左滚动', scroll_right: '向右滚动',
set_selection: '设置文本选区', replace_selection: '替换选区文本',
set_text: '设置文本', ime_enter: '提交输入法操作'
}));
const STEP_LABELS = new Map(Object.entries({
click: '点击元素', long_press: '长按元素', drag: '拖动屏幕', wait: '等待'
}));
const PARAM_LABELS = new Map(Object.entries({
center: '中心点', start_span: '起始指间距', end_span: '结束指间距',
angle_degrees: '起始角度', rotation_degrees: '旋转角度',
duration_ms: '持续时间(毫秒)', coordinate_space: '坐标空间',
frames: '触摸轨迹', at_ms: '时间点(毫秒)', points: '触点',
selector: '控件选择器', container: '滚动容器', target: '目标控件',
resource_id: '资源 ID', text: '文本', content_desc: '控件描述',
class_name: '控件类名', package_name: '应用包名', bounds: '控件边界',
expected_token: '预期控件标识', value: '目标值',
selection_start: '选区起点', selection_end: '选区终点',
state: '等待条件', expected_text: '预期文本', expected_value: '预期值',
tolerance: '允许误差', timeout_ms: '超时(毫秒)',
poll_interval_ms: '检查间隔(毫秒)', stable_ms: '稳定时长(毫秒)',
direction: '滚动方向', max_scrolls: '最多滚动次数', settle_ms: '停稳时长(毫秒)',
require_visible: '可见条件', unless_visible: '跳过条件',
steps: '动作步骤', action: '操作', args: '参数',
time_in_ms: '等待时长(毫秒)', target_description: '目标说明',
execution: '执行状态', verification: '验证状态'
}));
const ENUM_LABELS: Record<string, Map<string, string>> = {
coordinate_space: new Map(Object.entries({ normalized: '归一化坐标', pixel: '像素坐标' })),
state: new Map(Object.entries({
visible: '可见', absent: '消失', enabled: '可用', disabled: '禁用',
checked: '已勾选', unchecked: '未勾选', selected: '已选中',
unselected: '未选中', text: '文本匹配', value: '数值匹配', stable: '持续稳定'
})),
direction: new Map(Object.entries({
forward: '向前', backward: '向后', up: '向上', down: '向下', left: '向左', right: '向右'
})),
execution: new Map(Object.entries({
not_started: '未开始', observed: '已观测', completed: '已完成',
partial: '部分完成', cancelled: '已取消', unknown: '结果未知'
})),
verification: new Map(Object.entries({ pending_observation: '等待观测' }))
};
export function getNativeActionTitle(name: string, args: any = {}): string | null {
const clean = String(name).toLowerCase().replace(/^_?(?:self\.)?exec_/, '')
.replace(/^action_sequence\./, '');
if (clean === 'control_action') {
const request = getNativeActionArgs(args);
return CONTROL_LABELS.get(request.action) ?? ACTION_LABELS.get(clean)!;
}
return ACTION_LABELS.get(clean) ?? null;
}
export function getNativeActionArgs(args: any): any {
return args?.action === 'control_action' && args.args ? args.args : (args ?? {});
}
function localizedValue(value: any, key: string, controlAction = false): any {
if (Array.isArray(value)) return value.map(item => localizedValue(item, key, controlAction));
if (value && typeof value === 'object') {
return Object.fromEntries(Object.entries(value).map(([field, item]) => [
PARAM_LABELS.get(field) ?? field,
localizedValue(item, field, field === 'action' ? controlAction : field === 'args' && value.action === 'control_action')
]));
}
if (typeof value === 'string') {
if (key === 'action') {
return ACTION_LABELS.get(value) ?? (controlAction ? CONTROL_LABELS : STEP_LABELS).get(value) ?? value;
}
if (Object.hasOwn(ENUM_LABELS, key)) return ENUM_LABELS[key].get(value) ?? value;
}
return value;
}
export function formatNativeActionParam(key: string, value: any): ActionParam {
const localized = localizedValue(value, key);
return {
key: PARAM_LABELS.get(key) ?? key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
value: typeof localized === 'object' ? JSON.stringify(localized) : String(localized)
};
}