android-midscene-automation 0.2.1 → 0.2.2

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +9 -1
  3. package/package.json +1 -1
  4. package/server/analytics.test.ts +46 -0
  5. package/server/analytics.ts +24 -0
  6. package/server/api-safety-analytics.test.ts +57 -0
  7. package/server/appium-auto-save.test.ts +6 -0
  8. package/server/appium-recorder/appium-version.test.ts +55 -0
  9. package/server/appium-recorder/managed-appium.ts +37 -1
  10. package/server/appium-recorder/routes.ts +2 -12
  11. package/server/appium-recorder/run-history.ts +11 -0
  12. package/server/config-access.test.ts +27 -0
  13. package/server/config-access.ts +27 -0
  14. package/server/http-api.ts +63 -54
  15. package/server/operations/repository.ts +8 -0
  16. package/server/remote-agents/routes.ts +2 -12
  17. package/server/request-body.test.ts +40 -0
  18. package/server/request-body.ts +48 -0
  19. package/src/App.vue +96 -758
  20. package/src/analytics/summary.ts +75 -0
  21. package/src/api.ts +11 -0
  22. package/src/appium-recorder/AppiumPage.vue +4 -1
  23. package/src/components/AppSidebar.vue +31 -0
  24. package/src/components/analytics/AnalysisCharts.vue +189 -0
  25. package/src/components/analytics/ReportAnalysis.vue +78 -0
  26. package/src/components/config/AppiumConfigPanel.vue +4 -1
  27. package/src/components/config/AppiumModelSettings.vue +1 -1
  28. package/src/components/config/BaseConfigPanel.vue +6 -2
  29. package/src/components/config/MidsceneConfigPanel.vue +4 -5
  30. package/src/components/help/HelpCenter.vue +185 -0
  31. package/src/composables/use-device-preview.ts +279 -0
  32. package/src/composables/use-initial-resource.ts +17 -0
  33. package/src/composables/use-script-execution.ts +277 -0
  34. package/src/config/credentials.ts +2 -0
  35. package/src/config/use-appium-auto-save.ts +22 -11
  36. package/src/config/use-model-config.ts +157 -0
  37. package/src/main.ts +2 -2
  38. package/src/pages/AnalysisPage.vue +60 -0
  39. package/src/pages/ConfigPage.vue +36 -5
  40. package/src/style.css +711 -123
  41. package/src/types.ts +7 -1
  42. package/src/components/help/HelpCenterDialog.vue +0 -160
  43. package/src/ui-refresh.css +0 -677
package/src/types.ts CHANGED
@@ -5,9 +5,15 @@ import type { MidsceneModelProvider } from './config/midscene-model-presets';
5
5
  import type { AiRecognitionModel } from './appium-recorder/ai-recognition';
6
6
  import type { AiDeduplicationConfig } from './appium-recorder/ai-deduplication';
7
7
 
8
- export type MenuKey = 'generator' | 'automation' | 'config' | 'appium';
8
+ export type MenuKey = 'analysis' | 'generator' | 'automation' | 'config' | 'appium' | 'about';
9
9
  export type GeneratorMode = 'ai' | 'manual';
10
10
 
11
+ export type AppiumVersionInfo = {
12
+ version: string | null;
13
+ source: 'local' | 'server';
14
+ message: string;
15
+ };
16
+
11
17
  export type GeneratorForm = {
12
18
  promptTitle: string;
13
19
  testName: string;
@@ -1,160 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed, shallowRef } from 'vue';
3
- import { InfoFilled, QuestionFilled, Tools } from '@element-plus/icons-vue';
4
- import changelog from '../../../CHANGELOG.md?raw';
5
- import faq from '../../../FAQ.md?raw';
6
- import aiRecognitionGuide from '../../../AI识别操作说明.md?raw';
7
- import appiumGuide from '../../../流程节点操作说明.md?raw';
8
- import operationGuide from '../../../USAGE.md?raw';
9
- import packageText from '../../../package.json?raw';
10
- import MarkdownDocument from './MarkdownDocument.vue';
11
-
12
- type PackageInfo = { version?: string; dependencies?: Record<string, string> };
13
- type OperationSection = { id: string; title: string; content: string };
14
-
15
- const visible = defineModel<boolean>({ required: true });
16
- const activeTab = shallowRef('about');
17
- type OperationType = 'midscene' | 'appium' | 'aiRecognition' | 'faq';
18
-
19
- const operationType = shallowRef<OperationType>('midscene');
20
- const activeOperation = shallowRef('');
21
- const packageInfo = JSON.parse(packageText) as PackageInfo;
22
- const dependencyVersion = (name: string) => packageInfo.dependencies?.[name]?.match(/(\d+\.\d+\.\d+)/)?.[1] ?? '未知';
23
- const appVersion = packageInfo.version ?? '未知';
24
- const midsceneVersion = dependencyVersion('@midscene/core');
25
-
26
- const technologies = computed(() => [
27
- { name: 'Vue', version: dependencyVersion('vue'), description: '界面与交互框架' },
28
- { name: 'Element Plus', version: dependencyVersion('element-plus'), description: '界面组件库' },
29
- { name: 'Appium', version: '2.x', description: 'Android 原生自动化与回放' },
30
- { name: 'Midscene', version: midsceneVersion, description: 'AI 驱动的界面理解与自动化' },
31
- { name: 'Vue Flow', version: dependencyVersion('@vue-flow/core'), description: 'Appium 流程画布' },
32
- { name: 'OpenCV.js', version: dependencyVersion('@techstark/opencv-js'), description: '本地图像检测' },
33
- { name: 'Vite', version: dependencyVersion('vite'), description: '开发与构建工具' },
34
- { name: 'TypeScript', version: dependencyVersion('typescript'), description: '类型与工程开发语言' },
35
- ]);
36
-
37
- const extractOperationSections = (startHeading: string, endHeading: string) => {
38
- const start = operationGuide.indexOf(`## ${startHeading}`);
39
- const end = operationGuide.indexOf(`## ${endHeading}`, start + 1);
40
- if (start < 0) return [];
41
- const source = operationGuide.slice(start, end < 0 ? undefined : end);
42
- const matches = [...source.matchAll(/^###\s+(.+)$/gm)];
43
- return matches.map<OperationSection>((match, index) => ({
44
- id: `${startHeading}-${index}`,
45
- title: match[1]!.trim(),
46
- content: source.slice(match.index! + match[0].length, matches[index + 1]?.index).trim(),
47
- }));
48
- };
49
-
50
- const extractDocumentSections = (source: string, prefix: string) => {
51
- const matches = [...source.matchAll(/^##\s+(.+)$/gm)];
52
- return matches.map<OperationSection>((match, index) => ({
53
- id: `${prefix}-${index}`,
54
- title: match[1]!.trim(),
55
- content: source.slice(match.index! + match[0].length, matches[index + 1]?.index).trim(),
56
- }));
57
- };
58
-
59
- const midsceneOperations = computed(() => extractOperationSections('Midscene 操作说明', 'Appium 使用前准备'));
60
- const appiumOperations = computed(() => extractDocumentSections(appiumGuide, 'appium'));
61
- const aiRecognitionOperations = computed(() => extractDocumentSections(aiRecognitionGuide, 'ai-recognition'));
62
- const faqOperations = computed(() => extractDocumentSections(faq, 'faq'));
63
- const visibleOperations = computed(() => {
64
- if (operationType.value === 'midscene') return midsceneOperations.value;
65
- if (operationType.value === 'appium') return appiumOperations.value;
66
- if (operationType.value === 'aiRecognition') return aiRecognitionOperations.value;
67
- return faqOperations.value;
68
- });
69
-
70
- const switchOperationType = (value: OperationType) => {
71
- operationType.value = value;
72
- activeOperation.value = '';
73
- };
74
- </script>
75
-
76
- <template>
77
- <el-dialog
78
- v-model="visible"
79
- title="帮助与版本"
80
- width="min(960px, calc(100vw - 48px))"
81
- class="help-center-dialog"
82
- top="5vh"
83
- draggable
84
- destroy-on-close
85
- >
86
- <el-tabs v-model="activeTab" class="help-center">
87
- <el-tab-pane name="about">
88
- <template #label><el-icon><InfoFilled /></el-icon><span>关于</span></template>
89
- <el-scrollbar height="min(620px, calc(100vh - 230px))">
90
- <div class="help-center__content">
91
- <div class="help-center__versions">
92
- <div><span>当前版本</span><strong>v{{ appVersion }}</strong></div>
93
- <div><span>Midscene 版本</span><strong>v{{ midsceneVersion }}</strong></div>
94
- </div>
95
- <h3 class="help-center__section-title">使用技术</h3>
96
- <div class="help-center__technology-grid">
97
- <div v-for="item in technologies" :key="item.name" class="help-center__technology">
98
- <div><strong>{{ item.name }}</strong><el-tag size="small" effect="plain">{{ item.version }}</el-tag></div>
99
- <p>{{ item.description }}</p>
100
- </div>
101
- </div>
102
- </div>
103
- </el-scrollbar>
104
- </el-tab-pane>
105
- <el-tab-pane name="guide">
106
- <template #label><el-icon><QuestionFilled /></el-icon><span>操作说明</span></template>
107
- <el-scrollbar height="min(620px, calc(100vh - 230px))">
108
- <div class="help-center__operations">
109
- <el-radio-group :model-value="operationType" class="help-center__operation-types" @change="switchOperationType">
110
- <el-radio-button value="midscene">Midscene</el-radio-button>
111
- <el-radio-button value="appium">Appium</el-radio-button>
112
- <el-radio-button value="aiRecognition">AI 识别</el-radio-button>
113
- <el-radio-button value="faq">常见问题</el-radio-button>
114
- </el-radio-group>
115
- <el-collapse v-model="activeOperation" accordion class="help-center__operation-menu">
116
- <el-collapse-item v-for="item in visibleOperations" :key="item.id" :name="item.id">
117
- <template #title><span class="help-center__operation-title">{{ item.title }}</span></template>
118
- <MarkdownDocument :content="item.content" />
119
- </el-collapse-item>
120
- </el-collapse>
121
- </div>
122
- </el-scrollbar>
123
- </el-tab-pane>
124
- <el-tab-pane name="changelog">
125
- <template #label><el-icon><Tools /></el-icon><span>更新记录</span></template>
126
- <el-scrollbar height="min(620px, calc(100vh - 230px))">
127
- <div class="help-center__document"><MarkdownDocument :content="changelog" /></div>
128
- </el-scrollbar>
129
- </el-tab-pane>
130
- </el-tabs>
131
- </el-dialog>
132
- </template>
133
-
134
- <style scoped>
135
- .help-center :deep(.el-tabs__header) { margin-bottom: 0; }
136
- .help-center :deep(.el-tabs__item) { display: inline-flex; align-items: center; gap: 6px; }
137
- .help-center__content,
138
- .help-center__document { padding: 22px 6px 18px 2px; }
139
- .help-center__versions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
140
- .help-center__versions div { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px; border: 1px solid #e2e8f0; border-radius: 10px; background: #fff; }
141
- .help-center__versions span { color: #64748b; }
142
- .help-center__versions strong { color: #1677ff; font-size: 18px; }
143
- .help-center__section-title { margin: 24px 0 12px; color: #1f2937; font-size: 17px; }
144
- .help-center__technology-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
145
- .help-center__technology { padding: 14px 16px; border: 1px solid #e2e8f0; border-radius: 9px; background: #fff; }
146
- .help-center__technology > div { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
147
- .help-center__technology p { margin: 6px 0 0; color: #64748b; font-size: 13px; }
148
- .help-center__operations { padding: 18px 6px 18px 2px; }
149
- .help-center__operation-types { margin-bottom: 16px; }
150
- .help-center__operation-menu { border-top: 1px solid #e5e7eb; }
151
- .help-center__operation-title { color: #334155; font-size: 14px; font-weight: 600; }
152
- .help-center__operation-menu :deep(.el-collapse-item__header) { min-height: 48px; padding: 0 14px; border-right: 1px solid #e5e7eb; border-left: 1px solid #e5e7eb; }
153
- .help-center__operation-menu :deep(.el-collapse-item__wrap) { border-right: 1px solid #e5e7eb; border-left: 1px solid #e5e7eb; }
154
- .help-center__operation-menu :deep(.el-collapse-item__content) { padding: 4px 18px 18px; }
155
- :global(.help-center-dialog.el-dialog) { margin-top: 5vh; }
156
- @media (max-width: 760px) {
157
- .help-center__versions,
158
- .help-center__technology-grid { grid-template-columns: 1fr; }
159
- }
160
- </style>