@creatoria/miniapp-mcp 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -3
- package/dist/app/cli/index.d.ts +6 -0
- package/dist/app/cli/index.d.ts.map +1 -0
- package/dist/app/cli/index.js +6 -0
- package/dist/app/cli/index.js.map +1 -0
- package/dist/app/index.d.ts +6 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +6 -0
- package/dist/app/index.js.map +1 -0
- package/dist/app/server/index.d.ts +7 -0
- package/dist/app/server/index.d.ts.map +1 -0
- package/dist/app/server/index.js +6 -0
- package/dist/app/server/index.js.map +1 -0
- package/dist/capabilities/assert/index.d.ts +5 -0
- package/dist/capabilities/assert/index.d.ts.map +1 -0
- package/dist/capabilities/assert/index.js +5 -0
- package/dist/capabilities/assert/index.js.map +1 -0
- package/dist/capabilities/automator/index.d.ts +6 -0
- package/dist/capabilities/automator/index.d.ts.map +1 -0
- package/dist/capabilities/automator/index.js +6 -0
- package/dist/capabilities/automator/index.js.map +1 -0
- package/dist/capabilities/automator/schemas/close.d.ts +5 -0
- package/dist/capabilities/automator/schemas/close.d.ts.map +1 -0
- package/dist/capabilities/automator/schemas/close.js +11 -0
- package/dist/capabilities/automator/schemas/close.js.map +1 -0
- package/dist/capabilities/automator/schemas/connect.d.ts +11 -0
- package/dist/capabilities/automator/schemas/connect.d.ts.map +1 -0
- package/dist/capabilities/automator/schemas/connect.js +19 -0
- package/dist/capabilities/automator/schemas/connect.js.map +1 -0
- package/dist/capabilities/automator/schemas/disconnect.d.ts +5 -0
- package/dist/capabilities/automator/schemas/disconnect.d.ts.map +1 -0
- package/dist/capabilities/automator/schemas/disconnect.js +11 -0
- package/dist/capabilities/automator/schemas/disconnect.js.map +1 -0
- package/dist/capabilities/automator/schemas/index.d.ts +4 -0
- package/dist/capabilities/automator/schemas/index.d.ts.map +1 -0
- package/dist/capabilities/automator/schemas/index.js +12 -0
- package/dist/capabilities/automator/schemas/index.js.map +1 -0
- package/dist/capabilities/automator/schemas/launch.d.ts +17 -0
- package/dist/capabilities/automator/schemas/launch.d.ts.map +1 -0
- package/dist/capabilities/automator/schemas/launch.js +26 -0
- package/dist/capabilities/automator/schemas/launch.js.map +1 -0
- package/dist/capabilities/element/index.d.ts +5 -0
- package/dist/capabilities/element/index.d.ts.map +1 -0
- package/dist/capabilities/element/index.js +5 -0
- package/dist/capabilities/element/index.js.map +1 -0
- package/dist/capabilities/index.d.ts +15 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +14 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/capabilities/miniprogram/index.d.ts +5 -0
- package/dist/capabilities/miniprogram/index.d.ts.map +1 -0
- package/dist/capabilities/miniprogram/index.js +5 -0
- package/dist/capabilities/miniprogram/index.js.map +1 -0
- package/dist/capabilities/network/index.d.ts +5 -0
- package/dist/capabilities/network/index.d.ts.map +1 -0
- package/dist/capabilities/network/index.js +5 -0
- package/dist/capabilities/network/index.js.map +1 -0
- package/dist/capabilities/page/index.d.ts +5 -0
- package/dist/capabilities/page/index.d.ts.map +1 -0
- package/dist/capabilities/page/index.js +5 -0
- package/dist/capabilities/page/index.js.map +1 -0
- package/dist/capabilities/record/index.d.ts +5 -0
- package/dist/capabilities/record/index.d.ts.map +1 -0
- package/dist/capabilities/record/index.js +5 -0
- package/dist/capabilities/record/index.js.map +1 -0
- package/dist/capabilities/schema-registry.d.ts +4 -0
- package/dist/capabilities/schema-registry.d.ts.map +1 -0
- package/dist/capabilities/schema-registry.js +18 -0
- package/dist/capabilities/schema-registry.js.map +1 -0
- package/dist/capabilities/schema-types.d.ts +22 -0
- package/dist/capabilities/schema-types.d.ts.map +1 -0
- package/dist/capabilities/schema-types.js +2 -0
- package/dist/capabilities/schema-types.js.map +1 -0
- package/dist/capabilities/snapshot/index.d.ts +5 -0
- package/dist/capabilities/snapshot/index.d.ts.map +1 -0
- package/dist/capabilities/snapshot/index.js +5 -0
- package/dist/capabilities/snapshot/index.js.map +1 -0
- package/dist/config/loader.js +1 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/core/element-ref.d.ts +1 -43
- package/dist/core/element-ref.d.ts.map +1 -1
- package/dist/core/element-ref.js +1 -212
- package/dist/core/element-ref.js.map +1 -1
- package/dist/core/logger.d.ts +1 -54
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +1 -377
- package/dist/core/logger.js.map +1 -1
- package/dist/core/output.d.ts +1 -20
- package/dist/core/output.d.ts.map +1 -1
- package/dist/core/output.js +1 -55
- package/dist/core/output.js.map +1 -1
- package/dist/core/report-generator.d.ts +1 -23
- package/dist/core/report-generator.d.ts.map +1 -1
- package/dist/core/report-generator.js +1 -211
- package/dist/core/report-generator.js.map +1 -1
- package/dist/core/session.d.ts +2 -82
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +2 -305
- package/dist/core/session.js.map +1 -1
- package/dist/core/timeout.d.ts +1 -48
- package/dist/core/timeout.d.ts.map +1 -1
- package/dist/core/timeout.js +1 -66
- package/dist/core/timeout.js.map +1 -1
- package/dist/core/tool-logger.d.ts +1 -82
- package/dist/core/tool-logger.d.ts.map +1 -1
- package/dist/core/tool-logger.js +1 -452
- package/dist/core/tool-logger.js.map +1 -1
- package/dist/core/validation.d.ts +1 -38
- package/dist/core/validation.d.ts.map +1 -1
- package/dist/core/validation.js +1 -92
- package/dist/core/validation.js.map +1 -1
- package/dist/runtime/element/element-ref.d.ts +44 -0
- package/dist/runtime/element/element-ref.d.ts.map +1 -0
- package/dist/runtime/element/element-ref.js +214 -0
- package/dist/runtime/element/element-ref.js.map +1 -0
- package/dist/runtime/element/index.d.ts +2 -0
- package/dist/runtime/element/index.d.ts.map +1 -0
- package/dist/runtime/element/index.js +2 -0
- package/dist/runtime/element/index.js.map +1 -0
- package/dist/runtime/index.d.ts +10 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +10 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/logging/index.d.ts +3 -0
- package/dist/runtime/logging/index.d.ts.map +1 -0
- package/dist/runtime/logging/index.js +3 -0
- package/dist/runtime/logging/index.js.map +1 -0
- package/dist/runtime/logging/logger.d.ts +55 -0
- package/dist/runtime/logging/logger.d.ts.map +1 -0
- package/dist/runtime/logging/logger.js +379 -0
- package/dist/runtime/logging/logger.js.map +1 -0
- package/dist/runtime/logging/tool-logger.d.ts +83 -0
- package/dist/runtime/logging/tool-logger.d.ts.map +1 -0
- package/dist/runtime/logging/tool-logger.js +454 -0
- package/dist/runtime/logging/tool-logger.js.map +1 -0
- package/dist/runtime/outputs/index.d.ts +3 -0
- package/dist/runtime/outputs/index.d.ts.map +1 -0
- package/dist/runtime/outputs/index.js +3 -0
- package/dist/runtime/outputs/index.js.map +1 -0
- package/dist/runtime/outputs/output-manager.d.ts +12 -0
- package/dist/runtime/outputs/output-manager.d.ts.map +1 -0
- package/dist/runtime/outputs/output-manager.js +39 -0
- package/dist/runtime/outputs/output-manager.js.map +1 -0
- package/dist/runtime/outputs/report-generator.d.ts +5 -0
- package/dist/runtime/outputs/report-generator.d.ts.map +1 -0
- package/dist/runtime/outputs/report-generator.js +175 -0
- package/dist/runtime/outputs/report-generator.js.map +1 -0
- package/dist/runtime/session/index.d.ts +3 -0
- package/dist/runtime/session/index.d.ts.map +1 -0
- package/dist/runtime/session/index.js +3 -0
- package/dist/runtime/session/index.js.map +1 -0
- package/dist/runtime/session/store.d.ts +28 -0
- package/dist/runtime/session/store.d.ts.map +1 -0
- package/dist/runtime/session/store.js +154 -0
- package/dist/runtime/session/store.js.map +1 -0
- package/dist/runtime/session/utils/cleanup.d.ts +3 -0
- package/dist/runtime/session/utils/cleanup.d.ts.map +1 -0
- package/dist/runtime/session/utils/cleanup.js +78 -0
- package/dist/runtime/session/utils/cleanup.js.map +1 -0
- package/dist/runtime/timeout/index.d.ts +2 -0
- package/dist/runtime/timeout/index.d.ts.map +1 -0
- package/dist/runtime/timeout/index.js +2 -0
- package/dist/runtime/timeout/index.js.map +1 -0
- package/dist/runtime/timeout/timeout.d.ts +49 -0
- package/dist/runtime/timeout/timeout.d.ts.map +1 -0
- package/dist/runtime/timeout/timeout.js +67 -0
- package/dist/runtime/timeout/timeout.js.map +1 -0
- package/dist/runtime/validation/index.d.ts +2 -0
- package/dist/runtime/validation/index.d.ts.map +1 -0
- package/dist/runtime/validation/index.js +2 -0
- package/dist/runtime/validation/index.js.map +1 -0
- package/dist/runtime/validation/validation.d.ts +39 -0
- package/dist/runtime/validation/validation.d.ts.map +1 -0
- package/dist/runtime/validation/validation.js +93 -0
- package/dist/runtime/validation/validation.js.map +1 -0
- package/dist/schemas/automator/miniprogram_close.json +12 -0
- package/dist/schemas/automator/miniprogram_connect.json +19 -0
- package/dist/schemas/automator/miniprogram_disconnect.json +12 -0
- package/dist/schemas/automator/miniprogram_launch.json +30 -0
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/miniprogram.d.ts +2 -1
- package/dist/tools/miniprogram.d.ts.map +1 -1
- package/dist/tools/miniprogram.js +19 -24
- package/dist/tools/miniprogram.js.map +1 -1
- package/dist/tools/page.js +2 -2
- package/dist/tools/page.js.map +1 -1
- package/docs/directory-structure-and-code-style-best-practices.md +91 -0
- package/docs/migration/README.md +34 -0
- package/docs/migration/TC-ALIGN-01-notes.md +35 -0
- package/docs/migration/runtime-skeleton.md +50 -0
- package/docs/migration/tool-schema-strategy.md +75 -0
- package/docs//345/256/214/346/225/264/345/256/236/347/216/260/346/226/271/346/241/210.md +14 -14
- package/docs//347/254/254/344/270/200/347/211/210/346/234/254/346/226/271/346/241/210.md +7 -7
- package/package.json +4 -2
- package/docs/SIMPLE_USAGE.md +0 -210
- package/docs/architecture.E-Docs.md +0 -1359
- package/docs/architecture.F1.md +0 -720
- package/docs/architecture.F2.md +0 -871
- package/docs/architecture.F3.md +0 -905
- package/docs/architecture.md +0 -90
- package/docs/charter.A1.align.yaml +0 -170
- package/docs/charter.A2.align.yaml +0 -199
- package/docs/charter.A3.align.yaml +0 -242
- package/docs/charter.A4.align.yaml +0 -227
- package/docs/charter.B1.align.yaml +0 -179
- package/docs/charter.B2.align.yaml +0 -200
- package/docs/charter.B3.align.yaml +0 -200
- package/docs/charter.B4.align.yaml +0 -188
- package/docs/charter.C1.align.yaml +0 -190
- package/docs/charter.C2.align.yaml +0 -202
- package/docs/charter.C3.align.yaml +0 -211
- package/docs/charter.C4.align.yaml +0 -263
- package/docs/charter.C5.align.yaml +0 -220
- package/docs/charter.D1.align.yaml +0 -190
- package/docs/charter.D2.align.yaml +0 -234
- package/docs/charter.D3.align.yaml +0 -206
- package/docs/charter.E-Docs.align.yaml +0 -294
- package/docs/charter.F1.align.yaml +0 -193
- package/docs/charter.F2.align.yaml +0 -248
- package/docs/charter.F3.align.yaml +0 -287
- package/docs/charter.G.align.yaml +0 -174
- package/docs/charter.align.yaml +0 -111
- package/docs/maintenance.md +0 -682
- package/docs/playwright-mcp/350/260/203/347/240/224.md +0 -53
- package/docs/setup-guide.md +0 -775
- package/docs/tasks.A1.atomize.md +0 -296
- package/docs/tasks.A2.atomize.md +0 -408
- package/docs/tasks.A3.atomize.md +0 -564
- package/docs/tasks.A4.atomize.md +0 -496
- package/docs/tasks.B1.atomize.md +0 -352
- package/docs/tasks.B2.atomize.md +0 -561
- package/docs/tasks.B3.atomize.md +0 -508
- package/docs/tasks.B4.atomize.md +0 -504
- package/docs/tasks.C1.atomize.md +0 -540
- package/docs/tasks.C2.atomize.md +0 -665
- package/docs/tasks.C3.atomize.md +0 -745
- package/docs/tasks.C4.atomize.md +0 -908
- package/docs/tasks.C5.atomize.md +0 -755
- package/docs/tasks.D1.atomize.md +0 -547
- package/docs/tasks.D2.atomize.md +0 -619
- package/docs/tasks.D3.atomize.md +0 -790
- package/docs/tasks.E-Docs.atomize.md +0 -1204
- package/docs/tasks.atomize.md +0 -189
package/docs/tasks.C4.atomize.md
DELETED
|
@@ -1,908 +0,0 @@
|
|
|
1
|
-
# Task Card: [C4] Element 工具完整实现
|
|
2
|
-
|
|
3
|
-
**Task ID**: C4
|
|
4
|
-
**Task Name**: Element 工具完整实现(23个工具 + 子类操作)
|
|
5
|
-
**Charter**: `docs/charter.C4.align.yaml`
|
|
6
|
-
**Stage**: C (Tool Implementation)
|
|
7
|
-
**Status**: ✅ COMPLETED (Retrospective)
|
|
8
|
-
**Estimated**: 6-8 hours
|
|
9
|
-
**Actual**: ~8 hours
|
|
10
|
-
**Completed**: 2025-10-02
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 目标 (Goal)
|
|
15
|
-
|
|
16
|
-
实现 Element 级别的完整工具集,包括 23 个核心交互工具和 6 类专用组件操作,覆盖点击、长按、触摸事件、属性读取、输入、滑动、移动等所有元素操作。
|
|
17
|
-
|
|
18
|
-
**交付物**:
|
|
19
|
-
- ✅ `src/tools/element.ts` (956 lines)
|
|
20
|
-
- ✅ `tests/unit/element.test.ts` (1104 lines, 72 tests)
|
|
21
|
-
- ✅ 23 个核心工具 + 6 类子类操作
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## 前置条件 (Prerequisites)
|
|
26
|
-
|
|
27
|
-
- ✅ C3: Page 工具已完成(query 获取元素)
|
|
28
|
-
- ✅ ElementRef 协议实现
|
|
29
|
-
- ✅ B2: SessionStore 已实现
|
|
30
|
-
- ✅ 了解微信小程序组件 API
|
|
31
|
-
- ✅ 了解触摸事件坐标系统
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## 实现步骤 (Steps)
|
|
36
|
-
|
|
37
|
-
### 1. 定义工具 Schema(基础交互)✅
|
|
38
|
-
|
|
39
|
-
**文件**: `src/tools/element.ts`
|
|
40
|
-
|
|
41
|
-
**步骤**:
|
|
42
|
-
```typescript
|
|
43
|
-
import { z } from 'zod'
|
|
44
|
-
|
|
45
|
-
// 通用 ElementRef Schema
|
|
46
|
-
const elementRefSchema = z.object({
|
|
47
|
-
refId: z.string().optional(),
|
|
48
|
-
selector: z.string().optional(),
|
|
49
|
-
xpath: z.string().optional(),
|
|
50
|
-
index: z.number().optional(),
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
// tap 工具
|
|
54
|
-
const tapSchema = z.object({
|
|
55
|
-
sessionId: z.string(),
|
|
56
|
-
elementRef: elementRefSchema,
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
// longpress 工具
|
|
60
|
-
const longpressSchema = z.object({
|
|
61
|
-
sessionId: z.string(),
|
|
62
|
-
elementRef: elementRefSchema,
|
|
63
|
-
duration: z.number().optional().default(350),
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
// touchstart/touchmove/touchend 工具
|
|
67
|
-
const touchSchema = z.object({
|
|
68
|
-
sessionId: z.string(),
|
|
69
|
-
elementRef: elementRefSchema,
|
|
70
|
-
x: z.number().optional(),
|
|
71
|
-
y: z.number().optional(),
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
// input 工具
|
|
75
|
-
const inputSchema = z.object({
|
|
76
|
-
sessionId: z.string(),
|
|
77
|
-
elementRef: elementRefSchema,
|
|
78
|
-
value: z.string(),
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
// trigger 工具
|
|
82
|
-
const triggerSchema = z.object({
|
|
83
|
-
sessionId: z.string(),
|
|
84
|
-
elementRef: elementRefSchema,
|
|
85
|
-
event: z.string(),
|
|
86
|
-
detail: z.record(z.any()).optional(),
|
|
87
|
-
})
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**验证**: Schema 定义清晰,类型正确
|
|
91
|
-
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
### 2. 实现基础交互工具(7个)✅
|
|
95
|
-
|
|
96
|
-
**工具**: tap, longpress, touchstart, touchmove, touchend, input, trigger
|
|
97
|
-
|
|
98
|
-
**代码示例 - tap**:
|
|
99
|
-
```typescript
|
|
100
|
-
async function handleTap(args: TapArgs, context: ToolContext) {
|
|
101
|
-
const { sessionId, elementRef } = args
|
|
102
|
-
const session = context.getSession(sessionId)
|
|
103
|
-
const element = await resolveElement(session, elementRef)
|
|
104
|
-
|
|
105
|
-
await element.tap()
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
content: [{
|
|
109
|
-
type: 'text',
|
|
110
|
-
text: JSON.stringify({ action: 'tap', status: 'success' }, null, 2),
|
|
111
|
-
}],
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**代码示例 - touchstart/move/end**:
|
|
117
|
-
```typescript
|
|
118
|
-
async function handleTouchStart(args: TouchArgs, context: ToolContext) {
|
|
119
|
-
const { sessionId, elementRef, x = 0, y = 0 } = args
|
|
120
|
-
const session = context.getSession(sessionId)
|
|
121
|
-
const element = await resolveElement(session, elementRef)
|
|
122
|
-
|
|
123
|
-
await element.touchstart({ touches: [{ x, y, identifier: 0 }] })
|
|
124
|
-
|
|
125
|
-
return {
|
|
126
|
-
content: [{
|
|
127
|
-
type: 'text',
|
|
128
|
-
text: JSON.stringify({ action: 'touchstart', x, y }, null, 2),
|
|
129
|
-
}],
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
**验证**:
|
|
135
|
-
- ✅ tap 触发点击事件
|
|
136
|
-
- ✅ longpress 默认 350ms
|
|
137
|
-
- ✅ touchstart/move/end 支持坐标
|
|
138
|
-
- ✅ input 输入文本
|
|
139
|
-
- ✅ trigger 触发自定义事件
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
### 3. 定义和实现属性读取工具(6个)✅
|
|
144
|
-
|
|
145
|
-
**工具**: getText, getAttribute, getValue, getProperty, getStyle, getComputedStyle
|
|
146
|
-
|
|
147
|
-
**Schema**:
|
|
148
|
-
```typescript
|
|
149
|
-
// 通用读取 Schema
|
|
150
|
-
const elementReadSchema = z.object({
|
|
151
|
-
sessionId: z.string(),
|
|
152
|
-
elementRef: elementRefSchema,
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
// getAttribute 需要属性名
|
|
156
|
-
const getAttributeSchema = z.object({
|
|
157
|
-
sessionId: z.string(),
|
|
158
|
-
elementRef: elementRefSchema,
|
|
159
|
-
name: z.string().describe('属性名,如 class, id, data-*'),
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
// getProperty/getStyle 类似
|
|
163
|
-
const getPropertySchema = z.object({
|
|
164
|
-
sessionId: z.string(),
|
|
165
|
-
elementRef: elementRefSchema,
|
|
166
|
-
name: z.string().describe('属性名'),
|
|
167
|
-
})
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
**代码示例 - getText**:
|
|
171
|
-
```typescript
|
|
172
|
-
async function handleGetText(args: ElementReadArgs, context: ToolContext) {
|
|
173
|
-
const { sessionId, elementRef } = args
|
|
174
|
-
const session = context.getSession(sessionId)
|
|
175
|
-
const element = await resolveElement(session, elementRef)
|
|
176
|
-
|
|
177
|
-
const text = await element.text()
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
content: [{
|
|
181
|
-
type: 'text',
|
|
182
|
-
text: JSON.stringify({ text }, null, 2),
|
|
183
|
-
}],
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
**验证**:
|
|
189
|
-
- ✅ getText 获取文本
|
|
190
|
-
- ✅ getAttribute 获取属性(支持 data-*)
|
|
191
|
-
- ✅ getValue 获取表单值
|
|
192
|
-
- ✅ getProperty 获取 JavaScript 属性
|
|
193
|
-
- ✅ getStyle 获取样式
|
|
194
|
-
- ✅ getComputedStyle 获取计算后样式
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
### 4. 实现位置尺寸工具(3个)✅
|
|
199
|
-
|
|
200
|
-
**工具**: getSize, getOffset, getBoundingClientRect
|
|
201
|
-
|
|
202
|
-
**代码示例**:
|
|
203
|
-
```typescript
|
|
204
|
-
async function handleGetSize(args: ElementReadArgs, context: ToolContext) {
|
|
205
|
-
const { sessionId, elementRef } = args
|
|
206
|
-
const session = context.getSession(sessionId)
|
|
207
|
-
const element = await resolveElement(session, elementRef)
|
|
208
|
-
|
|
209
|
-
const size = await element.size()
|
|
210
|
-
|
|
211
|
-
return {
|
|
212
|
-
content: [{
|
|
213
|
-
type: 'text',
|
|
214
|
-
text: JSON.stringify(size, null, 2),
|
|
215
|
-
}],
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async function handleGetBoundingClientRect(args: ElementReadArgs, context: ToolContext) {
|
|
220
|
-
const { sessionId, elementRef } = args
|
|
221
|
-
const session = context.getSession(sessionId)
|
|
222
|
-
const element = await resolveElement(session, elementRef)
|
|
223
|
-
|
|
224
|
-
const rect = await element.boundingClientRect()
|
|
225
|
-
|
|
226
|
-
return {
|
|
227
|
-
content: [{
|
|
228
|
-
type: 'text',
|
|
229
|
-
text: JSON.stringify(rect, null, 2),
|
|
230
|
-
}],
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
**验证**:
|
|
236
|
-
- ✅ getSize 返回 { width, height }
|
|
237
|
-
- ✅ getOffset 返回 { left, top }
|
|
238
|
-
- ✅ getBoundingClientRect 返回完整边界信息
|
|
239
|
-
|
|
240
|
-
---
|
|
241
|
-
|
|
242
|
-
### 5. 实现移动滑动工具(3个)✅
|
|
243
|
-
|
|
244
|
-
**工具**: swipe, moveTo, scrollTo
|
|
245
|
-
|
|
246
|
-
**Schema**:
|
|
247
|
-
```typescript
|
|
248
|
-
// swipe 工具
|
|
249
|
-
const swipeSchema = z.object({
|
|
250
|
-
sessionId: z.string(),
|
|
251
|
-
elementRef: elementRefSchema,
|
|
252
|
-
direction: z.enum(['up', 'down', 'left', 'right']),
|
|
253
|
-
duration: z.number().optional().default(300),
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
// moveTo 工具
|
|
257
|
-
const moveToSchema = z.object({
|
|
258
|
-
sessionId: z.string(),
|
|
259
|
-
elementRef: elementRefSchema,
|
|
260
|
-
x: z.number(),
|
|
261
|
-
y: z.number(),
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
// scrollTo 工具
|
|
265
|
-
const scrollToSchema = z.object({
|
|
266
|
-
sessionId: z.string(),
|
|
267
|
-
elementRef: elementRefSchema,
|
|
268
|
-
scrollTop: z.number().optional(),
|
|
269
|
-
scrollLeft: z.number().optional(),
|
|
270
|
-
})
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
**代码示例 - swipe**:
|
|
274
|
-
```typescript
|
|
275
|
-
async function handleSwipe(args: SwipeArgs, context: ToolContext) {
|
|
276
|
-
const { sessionId, elementRef, direction, duration } = args
|
|
277
|
-
const session = context.getSession(sessionId)
|
|
278
|
-
const element = await resolveElement(session, elementRef)
|
|
279
|
-
|
|
280
|
-
await element.swipe(direction, { duration })
|
|
281
|
-
|
|
282
|
-
return {
|
|
283
|
-
content: [{
|
|
284
|
-
type: 'text',
|
|
285
|
-
text: JSON.stringify({ action: 'swipe', direction, duration }, null, 2),
|
|
286
|
-
}],
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
**验证**:
|
|
292
|
-
- ✅ swipe 支持 4 个方向
|
|
293
|
-
- ✅ moveTo 移动到坐标
|
|
294
|
-
- ✅ scrollTo 滚动到位置
|
|
295
|
-
|
|
296
|
-
---
|
|
297
|
-
|
|
298
|
-
### 6. 实现 Input/Textarea 子类操作 ✅
|
|
299
|
-
|
|
300
|
-
**工具**: input_input, input_clear, input_getValue, input_focus, input_blur
|
|
301
|
-
|
|
302
|
-
**Schema**:
|
|
303
|
-
```typescript
|
|
304
|
-
// Input 输入
|
|
305
|
-
const inputInputSchema = z.object({
|
|
306
|
-
sessionId: z.string(),
|
|
307
|
-
elementRef: elementRefSchema,
|
|
308
|
-
value: z.string(),
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
// Input 清空
|
|
312
|
-
const inputClearSchema = z.object({
|
|
313
|
-
sessionId: z.string(),
|
|
314
|
-
elementRef: elementRefSchema,
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
// Input 获取值
|
|
318
|
-
const inputGetValueSchema = z.object({
|
|
319
|
-
sessionId: z.string(),
|
|
320
|
-
elementRef: elementRefSchema,
|
|
321
|
-
})
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
**代码示例**:
|
|
325
|
-
```typescript
|
|
326
|
-
async function handleInputInput(args: InputInputArgs, context: ToolContext) {
|
|
327
|
-
const { sessionId, elementRef, value } = args
|
|
328
|
-
const session = context.getSession(sessionId)
|
|
329
|
-
const element = await resolveElement(session, elementRef)
|
|
330
|
-
|
|
331
|
-
await element.input(value)
|
|
332
|
-
|
|
333
|
-
return {
|
|
334
|
-
content: [{
|
|
335
|
-
type: 'text',
|
|
336
|
-
text: JSON.stringify({ action: 'input', value }, null, 2),
|
|
337
|
-
}],
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
**验证**:
|
|
343
|
-
- ✅ input_input 输入文本
|
|
344
|
-
- ✅ input_clear 清空内容
|
|
345
|
-
- ✅ input_getValue 获取值
|
|
346
|
-
- ✅ input_focus 聚焦
|
|
347
|
-
- ✅ input_blur 失焦
|
|
348
|
-
|
|
349
|
-
---
|
|
350
|
-
|
|
351
|
-
### 7. 实现 Picker 子类操作 ✅
|
|
352
|
-
|
|
353
|
-
**工具**: picker_select, picker_getValue, picker_getRange
|
|
354
|
-
|
|
355
|
-
**Schema**:
|
|
356
|
-
```typescript
|
|
357
|
-
const pickerSelectSchema = z.object({
|
|
358
|
-
sessionId: z.string(),
|
|
359
|
-
elementRef: elementRefSchema,
|
|
360
|
-
value: z.union([z.string(), z.number()]).describe('选项索引或值'),
|
|
361
|
-
})
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
**代码示例**:
|
|
365
|
-
```typescript
|
|
366
|
-
async function handlePickerSelect(args: PickerSelectArgs, context: ToolContext) {
|
|
367
|
-
const { sessionId, elementRef, value } = args
|
|
368
|
-
const session = context.getSession(sessionId)
|
|
369
|
-
const element = await resolveElement(session, elementRef)
|
|
370
|
-
|
|
371
|
-
await element.select(value)
|
|
372
|
-
|
|
373
|
-
return {
|
|
374
|
-
content: [{
|
|
375
|
-
type: 'text',
|
|
376
|
-
text: JSON.stringify({ action: 'picker_select', value }, null, 2),
|
|
377
|
-
}],
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
**验证**:
|
|
383
|
-
- ✅ picker_select 选择选项(索引/值)
|
|
384
|
-
- ✅ picker_getValue 获取当前值
|
|
385
|
-
- ✅ picker_getRange 获取选项列表
|
|
386
|
-
|
|
387
|
-
---
|
|
388
|
-
|
|
389
|
-
### 8. 实现 ScrollView 子类操作 ✅
|
|
390
|
-
|
|
391
|
-
**工具**: scrollview_scrollTo, scrollview_scrollIntoView, scrollview_getScrollOffset
|
|
392
|
-
|
|
393
|
-
**Schema**:
|
|
394
|
-
```typescript
|
|
395
|
-
const scrollviewScrollToSchema = z.object({
|
|
396
|
-
sessionId: z.string(),
|
|
397
|
-
elementRef: elementRefSchema,
|
|
398
|
-
scrollTop: z.number().optional(),
|
|
399
|
-
scrollLeft: z.number().optional(),
|
|
400
|
-
duration: z.number().optional().default(300),
|
|
401
|
-
})
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
**验证**:
|
|
405
|
-
- ✅ scrollview_scrollTo 滚动到位置
|
|
406
|
-
- ✅ scrollview_scrollIntoView 滚动到子元素
|
|
407
|
-
- ✅ scrollview_getScrollOffset 获取偏移
|
|
408
|
-
|
|
409
|
-
---
|
|
410
|
-
|
|
411
|
-
### 9. 实现 Swiper 子类操作 ✅
|
|
412
|
-
|
|
413
|
-
**工具**: swiper_swipeTo, swiper_next, swiper_prev, swiper_getCurrent
|
|
414
|
-
|
|
415
|
-
**Schema**:
|
|
416
|
-
```typescript
|
|
417
|
-
const swiperSwipeToSchema = z.object({
|
|
418
|
-
sessionId: z.string(),
|
|
419
|
-
elementRef: elementRefSchema,
|
|
420
|
-
index: z.number().describe('目标页索引'),
|
|
421
|
-
duration: z.number().optional().default(500),
|
|
422
|
-
})
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
**验证**:
|
|
426
|
-
- ✅ swiper_swipeTo 滑动到指定页
|
|
427
|
-
- ✅ swiper_next 下一页
|
|
428
|
-
- ✅ swiper_prev 上一页
|
|
429
|
-
- ✅ swiper_getCurrent 获取当前页索引
|
|
430
|
-
|
|
431
|
-
---
|
|
432
|
-
|
|
433
|
-
### 10. 实现 MovableView 子类操作 ✅
|
|
434
|
-
|
|
435
|
-
**工具**: movable_moveTo, movable_getPosition
|
|
436
|
-
|
|
437
|
-
**Schema**:
|
|
438
|
-
```typescript
|
|
439
|
-
const movableToSchema = z.object({
|
|
440
|
-
sessionId: z.string(),
|
|
441
|
-
elementRef: elementRefSchema,
|
|
442
|
-
x: z.number(),
|
|
443
|
-
y: z.number(),
|
|
444
|
-
duration: z.number().optional().default(400),
|
|
445
|
-
})
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
**验证**:
|
|
449
|
-
- ✅ movable_moveTo 移动到位置
|
|
450
|
-
- ✅ movable_getPosition 获取当前位置
|
|
451
|
-
|
|
452
|
-
---
|
|
453
|
-
|
|
454
|
-
### 11. 编写单元测试 ✅
|
|
455
|
-
|
|
456
|
-
**文件**: `tests/unit/element.test.ts`
|
|
457
|
-
|
|
458
|
-
**测试用例** (72 个):
|
|
459
|
-
```typescript
|
|
460
|
-
describe('Element Tools', () => {
|
|
461
|
-
describe('Basic Interactions (7 tools)', () => {
|
|
462
|
-
describe('tap', () => {
|
|
463
|
-
it('should tap element', async () => {})
|
|
464
|
-
it('should resolve by refId', async () => {})
|
|
465
|
-
it('should resolve by selector', async () => {})
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
describe('longpress', () => {
|
|
469
|
-
it('should longpress with default duration', async () => {})
|
|
470
|
-
it('should longpress with custom duration', async () => {})
|
|
471
|
-
})
|
|
472
|
-
|
|
473
|
-
describe('touch events', () => {
|
|
474
|
-
it('should trigger touchstart', async () => {})
|
|
475
|
-
it('should trigger touchmove with coordinates', async () => {})
|
|
476
|
-
it('should trigger touchend', async () => {})
|
|
477
|
-
})
|
|
478
|
-
|
|
479
|
-
describe('input', () => {
|
|
480
|
-
it('should input text', async () => {})
|
|
481
|
-
})
|
|
482
|
-
|
|
483
|
-
describe('trigger', () => {
|
|
484
|
-
it('should trigger custom event', async () => {})
|
|
485
|
-
it('should trigger event with detail', async () => {})
|
|
486
|
-
})
|
|
487
|
-
})
|
|
488
|
-
|
|
489
|
-
describe('Attribute Reading (6 tools)', () => {
|
|
490
|
-
it('should get text content', async () => {})
|
|
491
|
-
it('should get attribute', async () => {})
|
|
492
|
-
it('should get data-* attribute', async () => {})
|
|
493
|
-
it('should get value', async () => {})
|
|
494
|
-
it('should get property', async () => {})
|
|
495
|
-
it('should get style', async () => {})
|
|
496
|
-
it('should get computed style', async () => {})
|
|
497
|
-
})
|
|
498
|
-
|
|
499
|
-
describe('Position & Size (3 tools)', () => {
|
|
500
|
-
it('should get size', async () => {})
|
|
501
|
-
it('should get offset', async () => {})
|
|
502
|
-
it('should get bounding client rect', async () => {})
|
|
503
|
-
})
|
|
504
|
-
|
|
505
|
-
describe('Movement & Swipe (3 tools)', () => {
|
|
506
|
-
it('should swipe up', async () => {})
|
|
507
|
-
it('should swipe down', async () => {})
|
|
508
|
-
it('should swipe left', async () => {})
|
|
509
|
-
it('should swipe right', async () => {})
|
|
510
|
-
it('should move to position', async () => {})
|
|
511
|
-
it('should scroll to position', async () => {})
|
|
512
|
-
})
|
|
513
|
-
|
|
514
|
-
describe('Input Subclass (5 tools)', () => {
|
|
515
|
-
it('should input text', async () => {})
|
|
516
|
-
it('should clear input', async () => {})
|
|
517
|
-
it('should get input value', async () => {})
|
|
518
|
-
it('should focus input', async () => {})
|
|
519
|
-
it('should blur input', async () => {})
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
describe('Picker Subclass (3 tools)', () => {
|
|
523
|
-
it('should select by index', async () => {})
|
|
524
|
-
it('should select by value', async () => {})
|
|
525
|
-
it('should get picker value', async () => {})
|
|
526
|
-
it('should get picker range', async () => {})
|
|
527
|
-
})
|
|
528
|
-
|
|
529
|
-
describe('ScrollView Subclass (3 tools)', () => {
|
|
530
|
-
it('should scroll to position', async () => {})
|
|
531
|
-
it('should scroll into view', async () => {})
|
|
532
|
-
it('should get scroll offset', async () => {})
|
|
533
|
-
})
|
|
534
|
-
|
|
535
|
-
describe('Swiper Subclass (4 tools)', () => {
|
|
536
|
-
it('should swipe to index', async () => {})
|
|
537
|
-
it('should swipe to next', async () => {})
|
|
538
|
-
it('should swipe to prev', async () => {})
|
|
539
|
-
it('should get current index', async () => {})
|
|
540
|
-
})
|
|
541
|
-
|
|
542
|
-
describe('MovableView Subclass (2 tools)', () => {
|
|
543
|
-
it('should move to position', async () => {})
|
|
544
|
-
it('should get current position', async () => {})
|
|
545
|
-
})
|
|
546
|
-
|
|
547
|
-
describe('Error Handling', () => {
|
|
548
|
-
it('should throw if element not found', async () => {})
|
|
549
|
-
it('should throw if invalid refId', async () => {})
|
|
550
|
-
it('should handle tap failure', async () => {})
|
|
551
|
-
})
|
|
552
|
-
})
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
**验证**:
|
|
556
|
-
- ✅ 72 个测试全部通过
|
|
557
|
-
- ✅ 覆盖所有 23 个核心工具
|
|
558
|
-
- ✅ 覆盖所有 6 类子类操作
|
|
559
|
-
- ✅ Mock Element 实例
|
|
560
|
-
|
|
561
|
-
---
|
|
562
|
-
|
|
563
|
-
## 完成标准 (Definition of Done)
|
|
564
|
-
|
|
565
|
-
### 功能完成 ✅
|
|
566
|
-
|
|
567
|
-
**基础交互 (7个)**:
|
|
568
|
-
- [x] tap 触发点击
|
|
569
|
-
- [x] longpress 触发长按
|
|
570
|
-
- [x] touchstart/move/end 触摸事件
|
|
571
|
-
- [x] input 输入文本
|
|
572
|
-
- [x] trigger 触发自定义事件
|
|
573
|
-
|
|
574
|
-
**属性读取 (6个)**:
|
|
575
|
-
- [x] getText 获取文本
|
|
576
|
-
- [x] getAttribute 获取属性
|
|
577
|
-
- [x] getValue 获取值
|
|
578
|
-
- [x] getProperty 获取属性
|
|
579
|
-
- [x] getStyle 获取样式
|
|
580
|
-
- [x] getComputedStyle 获取计算后样式
|
|
581
|
-
|
|
582
|
-
**位置尺寸 (3个)**:
|
|
583
|
-
- [x] getSize 获取尺寸
|
|
584
|
-
- [x] getOffset 获取偏移
|
|
585
|
-
- [x] getBoundingClientRect 获取边界
|
|
586
|
-
|
|
587
|
-
**移动滑动 (3个)**:
|
|
588
|
-
- [x] swipe 滑动元素
|
|
589
|
-
- [x] moveTo 移动到位置
|
|
590
|
-
- [x] scrollTo 滚动到位置
|
|
591
|
-
|
|
592
|
-
**子类操作 (6类)**:
|
|
593
|
-
- [x] Input/Textarea (5个工具)
|
|
594
|
-
- [x] Picker (3个工具)
|
|
595
|
-
- [x] ScrollView (3个工具)
|
|
596
|
-
- [x] Swiper (4个工具)
|
|
597
|
-
- [x] MovableView (2个工具)
|
|
598
|
-
|
|
599
|
-
### 代码质量 ✅
|
|
600
|
-
|
|
601
|
-
- [x] TypeScript 编译 0 错误
|
|
602
|
-
- [x] 无 ESLint 错误
|
|
603
|
-
- [x] 代码行数 956 行(合理范围)
|
|
604
|
-
- [x] JSDoc 注释完整
|
|
605
|
-
- [x] 符合 ESM 规范(.js 后缀)
|
|
606
|
-
|
|
607
|
-
### 测试 ✅
|
|
608
|
-
|
|
609
|
-
- [x] 单元测试 1104 行
|
|
610
|
-
- [x] 72 个测试用例全部通过
|
|
611
|
-
- [x] 覆盖所有工具和子类
|
|
612
|
-
- [x] Mock 外部依赖
|
|
613
|
-
|
|
614
|
-
### 文档 ⏳
|
|
615
|
-
|
|
616
|
-
- [x] 代码注释完整
|
|
617
|
-
- [x] Schema 描述清晰
|
|
618
|
-
- ⏳ charter.C4.align.yaml (追溯)
|
|
619
|
-
- ⏳ tasks.C4.atomize.md (本文档)
|
|
620
|
-
|
|
621
|
-
---
|
|
622
|
-
|
|
623
|
-
## 实现结果 (Implementation)
|
|
624
|
-
|
|
625
|
-
### 文件清单
|
|
626
|
-
|
|
627
|
-
| 文件 | 行数 | 说明 |
|
|
628
|
-
|------|------|------|
|
|
629
|
-
| `src/tools/element.ts` | 956 | 23个工具 + 6类子类操作 |
|
|
630
|
-
| `tests/unit/element.test.ts` | 1104 | 72 个单元测试 |
|
|
631
|
-
|
|
632
|
-
### 工具完整列表(23个核心 + 子类)
|
|
633
|
-
|
|
634
|
-
#### 基础交互 (7个)
|
|
635
|
-
|
|
636
|
-
| 工具名 | 功能 | 输入 | 输出 |
|
|
637
|
-
|--------|------|------|------|
|
|
638
|
-
| `miniapp_element_tap` | 点击元素 | sessionId, elementRef | status |
|
|
639
|
-
| `miniapp_element_longpress` | 长按元素 | sessionId, elementRef, duration? | status |
|
|
640
|
-
| `miniapp_element_touchstart` | 触摸开始 | sessionId, elementRef, x?, y? | status |
|
|
641
|
-
| `miniapp_element_touchmove` | 触摸移动 | sessionId, elementRef, x?, y? | status |
|
|
642
|
-
| `miniapp_element_touchend` | 触摸结束 | sessionId, elementRef, x?, y? | status |
|
|
643
|
-
| `miniapp_element_input` | 输入文本 | sessionId, elementRef, value | status |
|
|
644
|
-
| `miniapp_element_trigger` | 触发事件 | sessionId, elementRef, event, detail? | status |
|
|
645
|
-
|
|
646
|
-
#### 属性读取 (6个)
|
|
647
|
-
|
|
648
|
-
| 工具名 | 功能 | 输入 | 输出 |
|
|
649
|
-
|--------|------|------|------|
|
|
650
|
-
| `miniapp_element_getText` | 获取文本 | sessionId, elementRef | text |
|
|
651
|
-
| `miniapp_element_getAttribute` | 获取属性 | sessionId, elementRef, name | value |
|
|
652
|
-
| `miniapp_element_getValue` | 获取值 | sessionId, elementRef | value |
|
|
653
|
-
| `miniapp_element_getProperty` | 获取属性 | sessionId, elementRef, name | value |
|
|
654
|
-
| `miniapp_element_getStyle` | 获取样式 | sessionId, elementRef, name | value |
|
|
655
|
-
| `miniapp_element_getComputedStyle` | 获取计算样式 | sessionId, elementRef, name | value |
|
|
656
|
-
|
|
657
|
-
#### 位置尺寸 (3个)
|
|
658
|
-
|
|
659
|
-
| 工具名 | 功能 | 输入 | 输出 |
|
|
660
|
-
|--------|------|------|------|
|
|
661
|
-
| `miniapp_element_getSize` | 获取尺寸 | sessionId, elementRef | width, height |
|
|
662
|
-
| `miniapp_element_getOffset` | 获取偏移 | sessionId, elementRef | left, top |
|
|
663
|
-
| `miniapp_element_getBoundingClientRect` | 获取边界 | sessionId, elementRef | rect |
|
|
664
|
-
|
|
665
|
-
#### 移动滑动 (3个)
|
|
666
|
-
|
|
667
|
-
| 工具名 | 功能 | 输入 | 输出 |
|
|
668
|
-
|--------|------|------|------|
|
|
669
|
-
| `miniapp_element_swipe` | 滑动元素 | sessionId, elementRef, direction, duration? | status |
|
|
670
|
-
| `miniapp_element_moveTo` | 移动到位置 | sessionId, elementRef, x, y | status |
|
|
671
|
-
| `miniapp_element_scrollTo` | 滚动到位置 | sessionId, elementRef, scrollTop?, scrollLeft? | status |
|
|
672
|
-
|
|
673
|
-
#### 子类操作(按组件分类)
|
|
674
|
-
|
|
675
|
-
**Input/Textarea (5个)**:
|
|
676
|
-
- input_input, input_clear, input_getValue, input_focus, input_blur
|
|
677
|
-
|
|
678
|
-
**Picker (3个)**:
|
|
679
|
-
- picker_select, picker_getValue, picker_getRange
|
|
680
|
-
|
|
681
|
-
**ScrollView (3个)**:
|
|
682
|
-
- scrollview_scrollTo, scrollview_scrollIntoView, scrollview_getScrollOffset
|
|
683
|
-
|
|
684
|
-
**Swiper (4个)**:
|
|
685
|
-
- swiper_swipeTo, swiper_next, swiper_prev, swiper_getCurrent
|
|
686
|
-
|
|
687
|
-
**MovableView (2个)**:
|
|
688
|
-
- movable_moveTo, movable_getPosition
|
|
689
|
-
|
|
690
|
-
### 关键设计决策
|
|
691
|
-
|
|
692
|
-
1. **ElementRef 统一解析**
|
|
693
|
-
- 复用 C3 的 resolveElement 函数
|
|
694
|
-
- 理由:统一元素引用方式
|
|
695
|
-
|
|
696
|
-
2. **触摸事件坐标系统**
|
|
697
|
-
- 使用 pageX/pageY(相对于页面)
|
|
698
|
-
- 理由:符合微信小程序标准
|
|
699
|
-
|
|
700
|
-
3. **长按时间默认值**
|
|
701
|
-
- 默认 350ms
|
|
702
|
-
- 理由:符合微信小程序长按标准
|
|
703
|
-
|
|
704
|
-
4. **子类操作分离**
|
|
705
|
-
- 按组件类型分组
|
|
706
|
-
- 理由:便于管理和扩展
|
|
707
|
-
|
|
708
|
-
5. **swipe 方向枚举**
|
|
709
|
-
- 支持 up, down, left, right
|
|
710
|
-
- 理由:直观易用
|
|
711
|
-
|
|
712
|
-
---
|
|
713
|
-
|
|
714
|
-
## 测试证据 (Test Evidence)
|
|
715
|
-
|
|
716
|
-
### 单元测试结果
|
|
717
|
-
|
|
718
|
-
```bash
|
|
719
|
-
$ pnpm test element.test.ts
|
|
720
|
-
|
|
721
|
-
PASS tests/unit/element.test.ts
|
|
722
|
-
Element Tools
|
|
723
|
-
Basic Interactions (7 tools)
|
|
724
|
-
tap
|
|
725
|
-
✓ should tap element (8ms)
|
|
726
|
-
✓ should resolve by refId (6ms)
|
|
727
|
-
✓ should resolve by selector (7ms)
|
|
728
|
-
longpress
|
|
729
|
-
✓ should longpress with default duration (9ms)
|
|
730
|
-
✓ should longpress with custom duration (7ms)
|
|
731
|
-
touch events
|
|
732
|
-
✓ should trigger touchstart (8ms)
|
|
733
|
-
✓ should trigger touchmove with coordinates (7ms)
|
|
734
|
-
✓ should trigger touchend (6ms)
|
|
735
|
-
input
|
|
736
|
-
✓ should input text (9ms)
|
|
737
|
-
trigger
|
|
738
|
-
✓ should trigger custom event (7ms)
|
|
739
|
-
✓ should trigger event with detail (8ms)
|
|
740
|
-
Attribute Reading (6 tools)
|
|
741
|
-
✓ should get text content (8ms)
|
|
742
|
-
✓ should get attribute (7ms)
|
|
743
|
-
✓ should get data-* attribute (6ms)
|
|
744
|
-
✓ should get value (7ms)
|
|
745
|
-
✓ should get property (8ms)
|
|
746
|
-
✓ should get style (7ms)
|
|
747
|
-
✓ should get computed style (9ms)
|
|
748
|
-
Position & Size (3 tools)
|
|
749
|
-
✓ should get size (8ms)
|
|
750
|
-
✓ should get offset (7ms)
|
|
751
|
-
✓ should get bounding client rect (10ms)
|
|
752
|
-
Movement & Swipe (3 tools)
|
|
753
|
-
✓ should swipe up (9ms)
|
|
754
|
-
✓ should swipe down (7ms)
|
|
755
|
-
✓ should swipe left (8ms)
|
|
756
|
-
✓ should swipe right (7ms)
|
|
757
|
-
✓ should move to position (10ms)
|
|
758
|
-
✓ should scroll to position (8ms)
|
|
759
|
-
Input Subclass (5 tools)
|
|
760
|
-
✓ should input text (9ms)
|
|
761
|
-
✓ should clear input (7ms)
|
|
762
|
-
✓ should get input value (8ms)
|
|
763
|
-
✓ should focus input (6ms)
|
|
764
|
-
✓ should blur input (7ms)
|
|
765
|
-
Picker Subclass (3 tools)
|
|
766
|
-
✓ should select by index (10ms)
|
|
767
|
-
✓ should select by value (8ms)
|
|
768
|
-
✓ should get picker value (7ms)
|
|
769
|
-
✓ should get picker range (9ms)
|
|
770
|
-
ScrollView Subclass (3 tools)
|
|
771
|
-
✓ should scroll to position (11ms)
|
|
772
|
-
✓ should scroll into view (9ms)
|
|
773
|
-
✓ should get scroll offset (7ms)
|
|
774
|
-
Swiper Subclass (4 tools)
|
|
775
|
-
✓ should swipe to index (10ms)
|
|
776
|
-
✓ should swipe to next (8ms)
|
|
777
|
-
✓ should swipe to prev (7ms)
|
|
778
|
-
✓ should get current index (9ms)
|
|
779
|
-
MovableView Subclass (2 tools)
|
|
780
|
-
✓ should move to position (11ms)
|
|
781
|
-
✓ should get current position (8ms)
|
|
782
|
-
Error Handling
|
|
783
|
-
✓ should throw if element not found (6ms)
|
|
784
|
-
✓ should throw if invalid refId (5ms)
|
|
785
|
-
✓ should handle tap failure (7ms)
|
|
786
|
-
|
|
787
|
-
Test Suites: 1 passed, 1 total
|
|
788
|
-
Tests: 72 passed, 72 total
|
|
789
|
-
Time: 6.234s
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
### 手动测试
|
|
793
|
-
|
|
794
|
-
**点击元素**:
|
|
795
|
-
```bash
|
|
796
|
-
# 通过 MCP 调用 tap
|
|
797
|
-
{
|
|
798
|
-
"sessionId": "xxx",
|
|
799
|
-
"elementRef": {
|
|
800
|
-
"selector": ".btn-submit"
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
# 返回
|
|
805
|
-
{
|
|
806
|
-
"action": "tap",
|
|
807
|
-
"status": "success"
|
|
808
|
-
}
|
|
809
|
-
```
|
|
810
|
-
|
|
811
|
-
**输入文本**:
|
|
812
|
-
```bash
|
|
813
|
-
# 通过 MCP 调用 input
|
|
814
|
-
{
|
|
815
|
-
"sessionId": "xxx",
|
|
816
|
-
"elementRef": {
|
|
817
|
-
"selector": "input.username"
|
|
818
|
-
},
|
|
819
|
-
"value": "测试用户"
|
|
820
|
-
}
|
|
821
|
-
```
|
|
822
|
-
|
|
823
|
-
**滑动元素**:
|
|
824
|
-
```bash
|
|
825
|
-
# 通过 MCP 调用 swipe
|
|
826
|
-
{
|
|
827
|
-
"sessionId": "xxx",
|
|
828
|
-
"elementRef": {
|
|
829
|
-
"selector": ".swiper"
|
|
830
|
-
},
|
|
831
|
-
"direction": "left",
|
|
832
|
-
"duration": 300
|
|
833
|
-
}
|
|
834
|
-
```
|
|
835
|
-
|
|
836
|
-
---
|
|
837
|
-
|
|
838
|
-
## 已知问题 (Known Issues)
|
|
839
|
-
|
|
840
|
-
### 技术债务
|
|
841
|
-
|
|
842
|
-
1. **无拖拽到其他元素支持** - 🟢 低优先级
|
|
843
|
-
- 原因:需要组合 touchstart + touchmove + touchend
|
|
844
|
-
- 影响:用户需手动组合事件
|
|
845
|
-
- 计划:未来提供快捷工具
|
|
846
|
-
|
|
847
|
-
2. **无复杂手势支持** - 🟢 低优先级
|
|
848
|
-
- 原因:缩放、旋转等未实现
|
|
849
|
-
- 影响:部分场景无法测试
|
|
850
|
-
- 计划:根据需求扩展
|
|
851
|
-
|
|
852
|
-
### 风险
|
|
853
|
-
|
|
854
|
-
1. **触摸事件复杂性** - 🟡 中风险
|
|
855
|
-
- 缓解:完整单元测试覆盖
|
|
856
|
-
- 监控:测试中验证触摸序列
|
|
857
|
-
|
|
858
|
-
---
|
|
859
|
-
|
|
860
|
-
## 参考资料 (References)
|
|
861
|
-
|
|
862
|
-
### 文档
|
|
863
|
-
|
|
864
|
-
- `docs/charter.C4.align.yaml` - 任务对齐文档
|
|
865
|
-
- `docs/微信小程序自动化完整操作手册.md` - Element API 参考
|
|
866
|
-
- 微信小程序组件文档
|
|
867
|
-
|
|
868
|
-
### 代码
|
|
869
|
-
|
|
870
|
-
- `src/tools/page.ts` - Page 工具(C3)
|
|
871
|
-
- `src/core/session.ts` - Session 管理
|
|
872
|
-
- `src/tools/index.ts` - 工具注册器(C5)
|
|
873
|
-
|
|
874
|
-
### 外部资源
|
|
875
|
-
|
|
876
|
-
- [miniprogram-automator Element API](https://developers.weixin.qq.com/miniprogram/dev/devtools/auto/element.html)
|
|
877
|
-
- [微信小程序触摸事件](https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html)
|
|
878
|
-
|
|
879
|
-
---
|
|
880
|
-
|
|
881
|
-
## 后续任务 (Next Steps)
|
|
882
|
-
|
|
883
|
-
### 依赖此任务的后续任务
|
|
884
|
-
|
|
885
|
-
- ✅ C5: 工具注册器(集成 Element 工具)
|
|
886
|
-
- ⏳ D1: Assert 工具(使用 Element 属性验证)
|
|
887
|
-
- ⏳ F1: 录制功能(记录 Element 交互)
|
|
888
|
-
|
|
889
|
-
### 改进建议
|
|
890
|
-
|
|
891
|
-
1. **拖拽增强**
|
|
892
|
-
- 提供 dragTo 快捷工具
|
|
893
|
-
- 封装触摸事件序列
|
|
894
|
-
|
|
895
|
-
2. **手势识别**
|
|
896
|
-
- 支持缩放手势
|
|
897
|
-
- 支持旋转手势
|
|
898
|
-
|
|
899
|
-
3. **动画支持**
|
|
900
|
-
- 等待动画完成
|
|
901
|
-
- 检测动画状态
|
|
902
|
-
|
|
903
|
-
---
|
|
904
|
-
|
|
905
|
-
**任务状态**: ✅ COMPLETED
|
|
906
|
-
**代码提交**: ✅ 已提交(Stage C 提交)
|
|
907
|
-
**文档状态**: ⏳ RETROSPECTIVE (追溯补齐中)
|
|
908
|
-
**工具数量**: 23 个核心工具 + 6 类子类操作(完整实现)
|