@mybricks/plugin-ai 0.0.1 → 0.0.3

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 (203) hide show
  1. package/dist/_virtual/_rollupPluginBabelHelpers.js +164 -0
  2. package/dist/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
  3. package/dist/agents/app.js +335 -0
  4. package/dist/agents/app.js.map +1 -0
  5. package/dist/agents/common.js +483 -0
  6. package/dist/agents/common.js.map +1 -0
  7. package/dist/agents/custom.js +16 -0
  8. package/dist/agents/custom.js.map +1 -0
  9. package/dist/agents/index.js +38 -0
  10. package/dist/agents/index.js.map +1 -0
  11. package/dist/agents/knowledges/knowledge-base.js +579 -0
  12. package/dist/agents/knowledges/knowledge-base.js.map +1 -0
  13. package/dist/agents/knowledges/knowledge-node.js +228 -0
  14. package/dist/agents/knowledges/knowledge-node.js.map +1 -0
  15. package/dist/agents/knowledges/types.js +105 -0
  16. package/dist/agents/knowledges/types.js.map +1 -0
  17. package/dist/agents/utils/config.js +229 -0
  18. package/dist/agents/utils/config.js.map +1 -0
  19. package/dist/agents/workspace/coding-manager.js +20 -0
  20. package/dist/agents/workspace/coding-manager.js.map +1 -0
  21. package/dist/agents/workspace/components-manager.js +113 -0
  22. package/dist/agents/workspace/components-manager.js.map +1 -0
  23. package/dist/agents/workspace/outline-focus.js +167 -0
  24. package/dist/agents/workspace/outline-focus.js.map +1 -0
  25. package/dist/agents/workspace/outline-info.js +430 -0
  26. package/dist/agents/workspace/outline-info.js.map +1 -0
  27. package/dist/agents/workspace/page-tree-generator.js +70 -0
  28. package/dist/agents/workspace/page-tree-generator.js.map +1 -0
  29. package/dist/agents/workspace/workspace.js +251 -0
  30. package/dist/agents/workspace/workspace.js.map +1 -0
  31. package/dist/agents/workspace-by-knowledges/providers/component-docs-provider.js +100 -0
  32. package/dist/agents/workspace-by-knowledges/providers/component-docs-provider.js.map +1 -0
  33. package/dist/agents/workspace-by-knowledges/providers/focus-info-provider.js +120 -0
  34. package/dist/agents/workspace-by-knowledges/providers/focus-info-provider.js.map +1 -0
  35. package/dist/agents/workspace-by-knowledges/providers/project-info-provider.js +146 -0
  36. package/dist/agents/workspace-by-knowledges/providers/project-info-provider.js.map +1 -0
  37. package/dist/agents/workspace-by-knowledges/test.js +242 -0
  38. package/dist/agents/workspace-by-knowledges/test.js.map +1 -0
  39. package/dist/agents/workspace-by-knowledges/utils/components-manager.js +132 -0
  40. package/dist/agents/workspace-by-knowledges/utils/components-manager.js.map +1 -0
  41. package/dist/agents/workspace-by-knowledges/utils/outline-focus.js +167 -0
  42. package/dist/agents/workspace-by-knowledges/utils/outline-focus.js.map +1 -0
  43. package/dist/agents/workspace-by-knowledges/utils/outline-info.js +430 -0
  44. package/dist/agents/workspace-by-knowledges/utils/outline-info.js.map +1 -0
  45. package/dist/agents/workspace-by-knowledges/workspace.js +169 -0
  46. package/dist/agents/workspace-by-knowledges/workspace.js.map +1 -0
  47. package/dist/api/cloud-components.js +85 -0
  48. package/dist/api/cloud-components.js.map +1 -0
  49. package/dist/api-record-replay/manager.js +168 -0
  50. package/dist/api-record-replay/manager.js.map +1 -0
  51. package/dist/api-record-replay/recorder.js +107 -0
  52. package/dist/api-record-replay/recorder.js.map +1 -0
  53. package/dist/api-record-replay/replayer.js +136 -0
  54. package/dist/api-record-replay/replayer.js.map +1 -0
  55. package/dist/components/attachments/index.js +124 -0
  56. package/dist/components/attachments/index.js.map +1 -0
  57. package/dist/components/attachments/index.less.js +8 -0
  58. package/dist/components/attachments/index.less.js.map +1 -0
  59. package/dist/components/icons/index.js +112 -0
  60. package/dist/components/icons/index.js.map +1 -0
  61. package/dist/components/icons/index.less.js +8 -0
  62. package/dist/components/icons/index.less.js.map +1 -0
  63. package/dist/components/mention/index.js +19 -0
  64. package/dist/components/mention/index.js.map +1 -0
  65. package/dist/components/mention/index.less.js +8 -0
  66. package/dist/components/mention/index.less.js.map +1 -0
  67. package/dist/components/messages/index.js +429 -0
  68. package/dist/components/messages/index.js.map +1 -0
  69. package/dist/components/messages/index.less.js +8 -0
  70. package/dist/components/messages/index.less.js.map +1 -0
  71. package/dist/components/sender/index.js +244 -0
  72. package/dist/components/sender/index.js.map +1 -0
  73. package/dist/components/sender/index.less.js +8 -0
  74. package/dist/components/sender/index.less.js.map +1 -0
  75. package/dist/context/RequestStatusTracker.js +44 -0
  76. package/dist/context/RequestStatusTracker.js.map +1 -0
  77. package/dist/context/index.js +45 -0
  78. package/dist/context/index.js.map +1 -0
  79. package/dist/data.js +4 -0
  80. package/dist/data.js.map +1 -0
  81. package/dist/index.js +306 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/plugin-ai/node_modules/style-inject/dist/style-inject.es.js +27 -0
  84. package/dist/plugin-ai/node_modules/style-inject/dist/style-inject.es.js.map +1 -0
  85. package/dist/plugin-ai/package.json.js +8 -0
  86. package/dist/plugin-ai/package.json.js.map +1 -0
  87. package/dist/plugin-ai/test/index.js +206 -0
  88. package/dist/plugin-ai/test/index.js.map +1 -0
  89. package/dist/preset/createTemplates.js +29 -0
  90. package/dist/preset/createTemplates.js.map +1 -0
  91. package/dist/preset/index.js +13 -0
  92. package/dist/preset/index.js.map +1 -0
  93. package/dist/preset/prompts.js +34 -0
  94. package/dist/preset/prompts.js.map +1 -0
  95. package/dist/preset/user.js +7 -0
  96. package/dist/preset/user.js.map +1 -0
  97. package/dist/requestAsStream.js +269 -0
  98. package/dist/requestAsStream.js.map +1 -0
  99. package/dist/rxai/node_modules/idb/build/index.js +277 -0
  100. package/dist/rxai/node_modules/idb/build/index.js.map +1 -0
  101. package/dist/rxai/src/agent/base.js +16 -0
  102. package/dist/rxai/src/agent/base.js.map +1 -0
  103. package/dist/rxai/src/agent/planning.js +1076 -0
  104. package/dist/rxai/src/agent/planning.js.map +1 -0
  105. package/dist/rxai/src/agent/rxai.js +254 -0
  106. package/dist/rxai/src/agent/rxai.js.map +1 -0
  107. package/dist/rxai/src/error/base.js +39 -0
  108. package/dist/rxai/src/error/base.js.map +1 -0
  109. package/dist/rxai/src/prompt/base.js +11 -0
  110. package/dist/rxai/src/prompt/base.js.map +1 -0
  111. package/dist/rxai/src/prompt/planning.js +23 -0
  112. package/dist/rxai/src/prompt/planning.js.map +1 -0
  113. package/dist/rxai/src/prompt/tool.js +14 -0
  114. package/dist/rxai/src/prompt/tool.js.map +1 -0
  115. package/dist/rxai/src/request/request.js +123 -0
  116. package/dist/rxai/src/request/request.js.map +1 -0
  117. package/dist/rxai/src/tool/getHistoryRecords.js +65 -0
  118. package/dist/rxai/src/tool/getHistoryRecords.js.map +1 -0
  119. package/dist/rxai/src/tool/util.js +424 -0
  120. package/dist/rxai/src/tool/util.js.map +1 -0
  121. package/dist/rxai/src/utils/events.js +43 -0
  122. package/dist/rxai/src/utils/events.js.map +1 -0
  123. package/dist/rxai/src/utils/idb.js +240 -0
  124. package/dist/rxai/src/utils/idb.js.map +1 -0
  125. package/dist/rxai/src/utils/retry.js +32 -0
  126. package/dist/rxai/src/utils/retry.js.map +1 -0
  127. package/dist/rxai/src/utils/uuid.js +7 -0
  128. package/dist/rxai/src/utils/uuid.js.map +1 -0
  129. package/dist/startView/components/header/header.js +12 -0
  130. package/dist/startView/components/header/header.js.map +1 -0
  131. package/dist/startView/components/header/header.less.js +8 -0
  132. package/dist/startView/components/header/header.less.js.map +1 -0
  133. package/dist/startView/index.js +62 -0
  134. package/dist/startView/index.js.map +1 -0
  135. package/dist/startView/index.less.js +8 -0
  136. package/dist/startView/index.less.js.map +1 -0
  137. package/dist/tools/analyze-and-expand-prd.js +116 -0
  138. package/dist/tools/analyze-and-expand-prd.js.map +1 -0
  139. package/dist/tools/analyze-requirement-and-components.js +208 -0
  140. package/dist/tools/analyze-requirement-and-components.js.map +1 -0
  141. package/dist/tools/answer.js +33 -0
  142. package/dist/tools/answer.js.map +1 -0
  143. package/dist/tools/build-process.js +550 -0
  144. package/dist/tools/build-process.js.map +1 -0
  145. package/dist/tools/coding-subagent-as-tool.js +101 -0
  146. package/dist/tools/coding-subagent-as-tool.js.map +1 -0
  147. package/dist/tools/generate-ui-content.js +528 -0
  148. package/dist/tools/generate-ui-content.js.map +1 -0
  149. package/dist/tools/index.js +31 -0
  150. package/dist/tools/index.js.map +1 -0
  151. package/dist/tools/open-dsl.js +49 -0
  152. package/dist/tools/open-dsl.js.map +1 -0
  153. package/dist/tools/refactor-ui-content.js +292 -0
  154. package/dist/tools/refactor-ui-content.js.map +1 -0
  155. package/dist/tools/utils.js +832 -0
  156. package/dist/tools/utils.js.map +1 -0
  157. package/dist/types/index.js +8 -0
  158. package/dist/types/index.js.map +1 -0
  159. package/dist/view/components/header/header.js +59 -0
  160. package/dist/view/components/header/header.js.map +1 -0
  161. package/dist/view/components/header/header.less.js +8 -0
  162. package/dist/view/components/header/header.less.js.map +1 -0
  163. package/dist/view/index.js +184 -0
  164. package/dist/view/index.js.map +1 -0
  165. package/dist/view/index.less.js +8 -0
  166. package/dist/view/index.less.js.map +1 -0
  167. package/package.json +33 -6
  168. package/src/agents/app.ts +0 -173
  169. package/src/agents/common.ts +0 -111
  170. package/src/agents/index.ts +0 -7
  171. package/src/components/icons/index.less +0 -8
  172. package/src/components/icons/index.tsx +0 -24
  173. package/src/components/messages/index.less +0 -806
  174. package/src/components/messages/index.tsx +0 -236
  175. package/src/context/index.ts +0 -21
  176. package/src/data.ts +0 -5
  177. package/src/index.tsx +0 -84
  178. package/src/mock.ts +0 -1267
  179. package/src/startView/index.less +0 -216
  180. package/src/startView/index.tsx +0 -229
  181. package/src/tools/analyze-and-expand-prd.ts +0 -166
  182. package/src/tools/answer-user.ts +0 -35
  183. package/src/tools/focus-element.ts +0 -47
  184. package/src/tools/generate-page.ts +0 -750
  185. package/src/tools/get-component-info-by-ids.ts +0 -166
  186. package/src/tools/get-component-info.ts +0 -53
  187. package/src/tools/get-components-doc-and-prd.ts +0 -137
  188. package/src/tools/get-focus-mybricks-dsl.ts +0 -26
  189. package/src/tools/get-mybricks-dsl.ts +0 -73
  190. package/src/tools/index.ts +0 -25
  191. package/src/tools/modify-component.ts +0 -385
  192. package/src/tools/type.d.ts +0 -12
  193. package/src/tools/utils.ts +0 -62
  194. package/src/types.d.ts +0 -65
  195. package/src/view/components/header/header.less +0 -17
  196. package/src/view/components/header/header.tsx +0 -15
  197. package/src/view/components/index.ts +0 -3
  198. package/src/view/components/messages/messages.less +0 -228
  199. package/src/view/components/messages/messages.tsx +0 -172
  200. package/src/view/components/sender/sender.less +0 -44
  201. package/src/view/components/sender/sender.tsx +0 -62
  202. package/src/view/index.less +0 -5
  203. package/src/view/index.tsx +0 -18
@@ -1,750 +0,0 @@
1
- import { fileFormat } from '@mybricks/rxai'
2
- import { jsonrepair } from 'jsonrepair'
3
- import { getFiles } from './utils'
4
-
5
- interface GeneratePageToolParams {
6
- /** 当前根组件信息 */
7
- getFocusRootComponentDoc: () => string;
8
- getTargetId: () => string;
9
- /** 应用特殊上下文信息 */
10
- appendPrompt: string;
11
- /** 返回示例 */
12
- examples: string;
13
- /** 当所有actions返回时 */
14
- onActions: (actions: any[], status: string) => void
15
- /** 清空当前画布信息 */
16
- onClearPage: () => void
17
- }
18
-
19
- const actionsParser = createActionsParser();
20
-
21
- export default function generatePage(config: GeneratePageToolParams): any {
22
- return {
23
- name: "generate-page",
24
- displayName: "生成页面",
25
- description: `根据需求/附件图片,一次性搭建并生成符合需求的 MyBricks 页面。
26
- 前置要求:当前聚焦到一个页面上
27
- 前置信息依赖:需求文档、组件选型
28
- 适用场景:完成页面级需求,特别是聚焦到页面时`,
29
- aiRole: "expert",
30
- getPrompts(params) {
31
- return `<工具总览>
32
- 你是一个生成 MyBricks 页面的工具,你作为MyBricks的资深页面搭建助手及客服专家,经验丰富、实事求是、逻辑严谨。
33
- 你的任务是通过 actions 从0到1生成符合用户需求的页面。
34
- </工具总览>
35
-
36
- <特别注意>
37
- 注意:
38
- - 对话可能由多轮构成,每轮对话中,用户会提出不同的问题或给与信息补充,你需要根据用户的问题、逐步分析处理。
39
- - 在多轮对话中,消息数组的可能结构如下:
40
- 位置0:system消息,包含了当前对话的上下文信息;
41
- 位置1:用户消息,如果以【知识库】开头,表示用户提供了使用与组件相关的内容知识(知识库为空也是符合预期的),这里的内容将作为后续搭建的重要参考;
42
-
43
- 其他为最近的消息记录,可能包含了用户的问题、需求、附件图片,以及你的回复内容;
44
-
45
- 注意:
46
- - 你所面向的用户是MyBricks平台上的用户,这些用户不是专业的开发人员,因此你需要以简洁、易懂的方式,回答用户的问题。
47
-
48
- 注意:
49
- - 如果附件中有图片,需要在搭建过程中作为重要的参考,要注意分辨设计稿(或者截图)或者用户绘制的线框图,对于前者、要求最大程度还原图片中的各项功能要素与视觉设计要素、可以做适度的创作发挥,总体要求考虑到功能一致完整与合理性、注意外观视觉美观大方、富有现代感.
50
- </特别注意>
51
-
52
- <当前根组件信息>
53
- ${config.getFocusRootComponentDoc()}
54
- </当前根组件信息>
55
-
56
- <如何搭建以及修改>
57
- 实际上,在手动搭建过程中,通过一系列的action来分步骤完成对于面向组件或其中插槽的添加及修改,下面的actions文件即通过模拟用户行为的方式来完成页面的搭建或修改。
58
- 当需要完成页面搭建或修改时,你需要按照如下格式返回actions操作步骤文件:
59
-
60
- ${fileFormat({
61
- content: `[comId, target, type, params]`,
62
- fileName: '操作步骤.json'
63
- })}
64
-
65
- <关于actions>
66
- actions.json文件由多个action构成,每个 action 在结构上都严格遵循以下格式:[comId, target, type, params];
67
- - comId 代表要操作的目标组件的id(对于需要生成的新的id,必须采用u_xxxxx,xxxxx是3-7位唯一的字母数字组合);
68
- - target 指的是组件的整体或某个部分,以选择器的形式表示,注意当type=addChild时,target为插槽id;
69
- - type action的类型,包括了 setLayout、doConfig、addChild 三类动作;
70
- - params 为不同type类型对应的参数;
71
-
72
- 综合而言,每个action的语义是:对某个组件(comId)的整体或某个部分(target),执行某个动作(type),并传入参数(params)。
73
-
74
- 注意:
75
- - 在返回多个步骤时,务必注意其逻辑顺序,例如有些action需要先完成,后续的action(可能受控于ifVisible,只有ifVislble返回true才能使用)才能进行;
76
- - 有些修改需要先完成整体、再进行局部的修改;
77
-
78
- 各action详细说明如下:
79
-
80
- <setLayout>
81
- - 设置组件的布局和尺寸信息,params的格式以Typescript的形式说明如下:
82
-
83
- \`\`\`typescript
84
- /**
85
- * 宽高尺寸
86
- * number - 具体的px值
87
- * fit-content - 适应内容
88
- * 100% - 填充
89
- * 只能是三者其一,明确不允许使用其他属性,比如calc等方法
90
- */
91
- type Size = number | "fit-content" | "100%"
92
-
93
- /** flex中子组件定位,可配置如下layout */
94
- type setLayout_flex_params = {
95
- /** 宽 */
96
- width: Size;
97
- /** 高 */
98
- height: Size;
99
- /** 上外边距 */
100
- marginTop?: number;
101
- /** 右外边距 */
102
- marginRight?: number;
103
- /** 下外边距 */
104
- marginBottom?: number;
105
- /** 左外边距 */
106
- marginLeft?: number;
107
- }
108
-
109
- 注意:
110
- - 1. 只有在flex布局中的组件,可以在layout中使用margin相关配置;
111
-
112
- /** 如果组件本身是fixed类型定位,可配置如下layout */
113
- type setLayout_fixed_params = {
114
- position: 'fixed';
115
- /** 宽 */
116
- width: Size;
117
- /** 高 */
118
- height: Size;
119
- /** 距离左侧 */
120
- left?: number;
121
- /** 距离右侧 */
122
- right?: number;
123
- /** 距离上方 */
124
- top?: number;
125
- /** 距离下方 */
126
- bottom?: number;
127
- }
128
-
129
- 例如,当用户要求将当前组件的宽度设置为200px,可以返回以下内容:
130
- ${fileFormat({
131
- content: `["u_ou1rs",":root","setLayout",{"width":200}]`,
132
- fileName: '样式配置步骤.json'
133
- })}
134
-
135
- 注意:当需要修改布局和尺寸信息时,仅返回用户要求的内容即可,无需返回所有的布局和尺寸信息属性。
136
- </setLayout>
137
-
138
- <doConfig>
139
- - 配置组件,使用<组件可配置的内容/>的配置项,对组件的属性或样式进行配置;
140
- - 如果配置项的type在 <常见editType的使用 /> 中有说明,务必遵守其中的说明及注意事项;
141
-
142
- - params的格式以Typescript的形式说明如下:
143
-
144
- \`\`\`typescript
145
- //配置样式
146
- type configStyle_params = {
147
- path:string,//在<当前组件可配置的内容/>中对应的配置项path
148
- style: {
149
- [key: string]: propertyValue; //元素的内联样式对象,仅能配置style编辑器description中声明的属性,不要超出范围。
150
- }
151
- }
152
-
153
- //配置属性
154
- type configProperty_params = {
155
- path:string,//在<当前组件可配置的内容/>中对应的配置项path
156
- value: any//需要配置的value
157
- }
158
- \`\`\`
159
-
160
- 例如:
161
- - 属性的配置:
162
- ${fileFormat({
163
- content: `["u_ou1rs",":root","doConfig",{"path":"常规/标题","value":"标题内容"}]`,
164
- fileName: '样式配置步骤.json'
165
- })}
166
-
167
- - 样式的配置:
168
- ${fileFormat({
169
- content: `["u_ou1rs",":root","doConfig",{"path":"常规/banner样式","style":{"backgroundColor":"red"}}]`,
170
- fileName: '样式配置步骤.json'
171
- })}
172
-
173
- 注意:
174
- - 当需要修改组件的样式时,只允许修改style编辑器description中声明的属性;
175
- - 当需要修改组件的样式时,背景统一使用background,而非backgroundColor等属性;
176
- </doConfig>
177
-
178
- <addChild>
179
- - addChild代表向目标组件的插槽中添加内容,需要满足两个条件:
180
- 1. 目标组件中目前有定义插槽,且已知插槽的id是什么;
181
- 2. 被添加的组件只能使用 <允许添加的组件/> 中声明的组件;
182
-
183
- - 第三个参数target代表要添加子组件的插槽id;
184
- - params的格式以Typescript的形式说明如下:
185
-
186
- \`\`\`typescript
187
- type add_params = {
188
- title:string //被添加组件的标题
189
- ns:string //在 <允许添加的组件 /> 中声明的组件namespace
190
- comId:string //新添加的组件id
191
- layout?: setLayout_flex_params | setLayout_fixed_params //可选,添加组件时可以指定位置和尺寸信息
192
- configs?: Array<configStyle_params | configProperty_params> // 添加组件可以配置的信息
193
- // 辅助标记
194
- ignore: boolean //可选,是否添加ignore标记
195
- }
196
- \`\`\`
197
-
198
- 例如:
199
- ${fileFormat({
200
- content: `["u_ou1rs","content","addChild",{"title":"添加的文本组件","ns":"namespace占位","comId":"u_iiusd7"}]`,
201
- fileName: '添加文本组件步骤.json'
202
- })}
203
-
204
- ${fileFormat({
205
- content: `["u_ou1rs","content","addChild",{"title":"背景图","ns":"namespace占位","comId":"u_iiusd7","layout":{"width":"100%","height":200,"marginTop":8,"marginLeft":12,"marginRight":12},"configs":[{"path":"常规/图片地址","value":"https://ai.mybricks.world/image-search?term=风景"},{"path":"样式/图片","style":{"borderRadius":"8px"}}]}]`,
206
- fileName: '添加带配置属性的步骤.json'
207
- })}
208
-
209
- ${fileFormat({
210
- content: `["u_ou1rs","content","addChild",{"title":"添加的布局组件","ns":"namespace占位","comId":"u_iiusd7","ignore": true}]`,
211
- fileName: '添加带ignore标记的步骤.json'
212
- })}
213
-
214
- 注意:
215
- - 要充分考虑被添加的组件与其他组件之间的间距以及位置关系,确保添加的组件的美观度的同时、且不会与其他组件重叠或冲突;
216
- </addChild>
217
-
218
- 注意:actions文件每一行遵循 JSON 语法,禁止非法代码,禁止出现内容省略提示、单行注释、省略字符。
219
- - actions返回的内容格式需要一行一个action,每一个action需要压缩,不要包含缩进等多余的空白字符;
220
- - 禁止包含任何注释(包括单行//和多行/* */)
221
- - 禁止出现省略号(...)或任何占位符
222
- - 确保所有代码都是完整可执行的,不包含示例片段
223
- - 禁止使用{}、{{}}这类变量绑定语法,并不支持此语法
224
- - 禁止使用非法字符或特殊符号
225
- - 所有内容均为静态数据,禁止解构,禁止使用变量
226
-
227
- 其中,target选择器的组成可以是组件id + 选择器的形式,例如:
228
- - :root - 组件整体;
229
- - :btn - 组件的按钮部分;
230
- - #u_iiusd7 :root - 组件id为u_iiusd7的组件整体;
231
- - #u_iiusd7 :btn - 组件id为u_iiusd7的按钮部分;
232
- 组件id可以从上下文中获取。
233
-
234
- 注意:
235
- - 返回actions文件内容时,务必注意操作步骤的先后顺序;
236
- - 有些操作需要在前面操作完成后才能进行;
237
- - 有些操作需要在其他操作开启(布尔类型的配置项)后才能进行;
238
- - 禁止重复使用相同的action;
239
- </关于actions>
240
-
241
- <UI搭建原则>
242
- 界面只有两类基本要素:组件、以及组件的插槽,组件的插槽可以嵌套其他组件。
243
-
244
- <组件的定位原则>
245
- 组件的定位有三种方式:flex定位、fixed定位。
246
-
247
- **flex定位**
248
- - 组件会相对于所在的插槽进行定位;
249
- - 通过尺寸(width、height) + 外间距(margin)来进行定位;
250
- - flex布局下的组件不允许使用left、top、right、bottom等定位属性;
251
-
252
- **fixed定位**
253
- - 组件会相对于当前组件的插槽进行定位,且脱离文档流;
254
- - 通过尺寸(width、height) + 位置(left、top、right、bottom)来进行定位;
255
- - fixed定位的组件不允许使用margin;
256
-
257
- 使用fixed定位的例子:
258
- ${fileFormat({
259
- content: `["_root_","_rootSlot_","addChild",{"title":"添加一个固定定位组件","comId":"u_fixed","ns":"组件","layout":{"position":"fixed","width":"100%","height":84,"bottom":0,"left":0},"configs":[]}]`,
260
- fileName: '添加一个fixed定位组件.json'
261
- })}
262
-
263
- 在插槽的不同布局下,组件的定位由所在插槽的布局方式决定:
264
- - 在当前组件的插槽中,可以添加fixed定位的组件,禁止在其他插槽中添加fixed定位的组件;
265
- - 如果插槽是flex布局,则子组件只能使用flex定位;
266
- - 如果插槽是absolute布局,则子组件只能使用absolute定位;
267
- </组件的定位原则>
268
-
269
- <布局原则>
270
- 插槽的布局(display=flex)指的是对于内部组件(仅对其直接子组件,对于子组件插槽中的子组件无影响)的布局约束:
271
-
272
- **flex布局**
273
- (基本等同于CSS3规范中的flex布局)插槽中的所有子组件通过宽高和margin进行布局。
274
-
275
- <辅助标记使用>
276
- 在mybricks中,组件最终会绘制到搭建画布上,确定所有组件的尺寸和位置,可以将多余的嵌套布局组件优化掉,所以需要通过辅助标记ignore来忽略多余的嵌套布局。
277
- 配置流程如下:
278
- 当布局组件的父组件也为布局组件时,观察当前组件是否配置样式(边框、背景、内间距等),是否可能需要支持事件(点击),父组件是否也是布局组件?
279
- - 1. 如果布局组件不配置样式也不需要点击功能,可以添加ignore标记,表示该布局组件仅承担布局功能,可以被优化掉;
280
- - 2. 如果布局组件配置了样式或者有可能需要点击功能,不能添加ignore标记,表示该布局组件承担样式功能,不能被优化掉;
281
- - 2.1 如何判断有没有可能需要支持事件?
282
- - 2.1.1 如果当前布局为图标+文本等常见的导航入口,猜测该布局组件后续需要支持点击功能,不能添加ignore标记;
283
- - 3. 如果布局组件的父组件不是布局组件,或者是根组件,不能添加ignore标记,不能被优化掉;
284
-
285
- 例子:第一个布局组件仅承担布局功能,可以添加ignore标记;第二个布局组件承担样式功能,不能添加ignore标记。
286
- ${fileFormat({
287
- content: `["目标组件id","插槽id占位","addChild",{"title":"添加一个布局组件","comId":"u_layout","ignore":true,"ns":"组件","layout":{"width":"100%","height":120},"configs":[{"path":"常规/布局","value":{"display":"flex","flexDirection":"row","alignItems":"center"}}]}]
288
- ["目标组件id","插槽id占位","addChild",{"title":"添加一个布局组件","comId":"u_layout","ns":"组件","layout":{"width":"100%","height":120},"configs":[{"path":"常规/布局","value":{"display":"flex","flexDirection":"row","alignItems":"center"}},{"path":"样式/样式","style":{"background":"#FFFFFF"}}]}]
289
- `,
290
- fileName: '辅助标记.json'
291
- })}
292
-
293
- </辅助标记使用>
294
-
295
- <布局使用示例>
296
- **flex布局**
297
- 子组件通过嵌套来搭建,无需考虑子组件的宽度和高度。
298
-
299
- 下面的例子使用flex实现左侧固定宽度,右侧自适应布局:
300
- ${fileFormat({
301
- content: `["目标组件id","插槽id占位","addChild",{"title":"添加一个布局组件","comId":"u_flex1","ns":"布局组件","layout":{"width":"100%","height":60},"configs":[{"path":"常规/布局","value":{"display":"flex","flexDirection":"row","alignItems":"center"}}]}]
302
- ["u_flex1","插槽id占位","addChild",{"title":"左侧固定宽度组件","comId":"u_leftFixed","ns":"组件","layout":{"width":60,"height":40,"marginRight":8},"configs":[]}]
303
- ["u_flex1","插槽id占位","addChild",{"title":"右侧自适应组件","comId":"u_rightFlex","ns":"组件","layout":{"width":'100%',"height":40},"configs":[]}]
304
- `,
305
- fileName: '左侧固定右侧自适应.json'
306
- })}
307
- 在上例中:
308
- - 声明布局编辑器的值,注意布局编辑器必须声明,其中flexDirection也必须声明,关注justifyContent效果,默认为flex-start;
309
- - 左侧组件使用固定宽度,右侧组件使用width=100%(效果等同于flex=1)实现自适应宽度;
310
- - 通过marginRight配置左侧组件与右侧组件的间距;
311
-
312
-
313
- 下面的例子使用flex进行嵌套,来实现左侧图标+文本,右侧箭头的布局:
314
- ${fileFormat({
315
- content: `["目标组件id","插槽id占位","addChild",{"title":"添加一个布局组件","comId":"u_flex1","ns":"布局组件","layout":{"width":"100%","height":60},"configs":[{"path":"常规/布局","value":{"display":"flex","flexDirection":"row","justifyContent":"space-between","alignItems":"center"}}]}]
316
- ["u_flex1","插槽id占位","addChild",{"title":"左侧布局组件","comId":"u_leftLayout","ignore": true,"ns":"布局组件","layout":{"width":"fit-content","height":"fit-content"},"configs":[{"path":"常规/布局","value":{"display":"flex","flexDirection":"row","alignItems":"center", "justifyContent": "flex-start"}}]}]
317
- ["u_leftLayout","插槽id占位","addChild",{"title":"图标组件","comId":"u_icon","ns":"图标组件","layout":{"width":24,"height":24,"marginRight":8},"configs":[]}]
318
- ["u_leftLayout","插槽id占位","addChild",{"title":"文本组件","comId":"u_text","ns":"文本组件","layout":{"width":"fit-content","height":"fit-content"},"configs":[]}]
319
- ["u_flex1","插槽id占位","addChild",{"title":"箭头图标组件","comId":"u_arrowIcon","ns":"图标组件","layout":{"width":24,"height":24},"configs":[]}]
320
- `,
321
- fileName: 'flex嵌套实现左右布局.json'
322
- })}
323
- 在上例中:
324
- - 声明布局编辑器的值,注意布局编辑器必须声明,其中flexDirection也必须声明;
325
- - 使用嵌套布局来完成左侧多元素 + 右侧单元素的布局,默认justifyContent=flex-start,所以左侧布局无需设置;
326
- - 左侧的图标+文本使用嵌套布局实现,且添加ignore标记,表示仅承担布局功能;
327
-
328
- 下面的例子使用flex实现垂直居中布局:
329
- ${fileFormat({
330
- content: `["目标组件id","插槽id占位","addChild",{"title":"添加一个布局组件","comId":"u_flex2","ns":"布局组件","layout":{"width":"100%","height":120},"configs":[{"path":"常规/布局","value":{"display":"flex","flexDirection":"column","alignItems":"center"}}]}]
331
- ["u_flex2","插槽id占位","addChild",{"title":"子组件","comId":"u_child","ns":"组件","layout":{"width":80,"height":80},"configs":[]}]
332
- `,
333
- fileName: '垂直居中布局.json'
334
- })}
335
- 在上例中:
336
- - 声明布局编辑器的值,注意布局编辑器必须声明,其中flexDirection声明成column;
337
- - 通过alignItems来实现子组件的垂直居中;
338
-
339
- 下面的例子使用flex进行横向均分或等分布局,实现一行N列的效果:
340
- ${fileFormat({
341
- content: `["目标组件id","插槽id占位","addChild",{"title":"添加一个布局组件","comId":"u_flex0","ignore": true,"ns":"布局组件","layout":{"width":"100%","height":120},"configs":[{"path":"常规/布局","value":{"display":"flex","flexDirection":"row","justifyContent":"space-between","alignItems":"center"}}]}]
342
- ["u_flex0","插槽id占位","addChild",{"title":"A组件","comId":"u_a","ns":"组件","layout":{"width":40,"height":40},"configs":[]}]
343
- ["u_flex0","插槽id占位","addChild",{"title":"B组件","comId":"u_b","ns":"组件","layout":{"width":40,"height":40},"configs":[]}]
344
- ["u_flex0","插槽id占位","addChild",{"title":"C组件","comId":"u_c","ns":"组件","layout":{"width":40,"height":40},"configs":[]}]
345
- `,
346
- fileName: '一行N列布局.json'
347
- })}
348
- 在上例中:
349
- - 声明布局编辑器的值,注意布局编辑器必须声明,其中flexDirection也必须声明;
350
- - 针对内容元素的尺寸,配置合理的高度,防止内容溢出;
351
- - 为了实现均分,请对子元素配置宽度和高度的固定值,保证卡片之间存在间距,避免大小不一导致的非均分效果;
352
- - 判断仅布局,添加ignore标记,优化搭建内容。
353
-
354
- 特殊地,在flex布局中的元素还可以配置position=absolute,用于实现绝对定位效果:
355
- ${fileFormat({
356
- content: `["目标组件id","插槽id占位","addChild",{"title":"添加一个布局组件","comId":"u_flex3","ns":"布局组件","layout":{"width":"100%","height":200},"configs":[{"path":"常规/布局","value":{"display":"flex","flexDirection":"row","alignItems":"center"}}]}]
357
- ["u_flex3","插槽id占位","addChild",{"title":"绝对定位组件","comId":"u_absolute","ns":"组件","layout":{"position":"absolute","width":100,"height":40,"top":20,"left":20},"configs":[]}]
358
- ["u_flex3","插槽id占位","addChild",{"title":"普通组件","comId":"u_normal","ns":"组件","layout":{"width":80,"height":80},"configs":[]}]
359
- `,
360
- fileName: '绝对定位效果.json'
361
- })}
362
- 在上例中:
363
- - 声明布局编辑器的值,注意布局编辑器必须声明,其中flexDirection也必须声明;
364
- - 通过layout中的属性,设置成绝对定位效果,在一些特殊的角标等场景下很有效果;
365
-
366
- </布局使用示例>
367
-
368
- <布局注意事项>
369
- - 布局相关组件在添加时必须配置布局编辑器的值,同时注意flexDirection和justifyContent的配置;
370
- - 优先考虑fit-content,如果要使用固定宽高,必须考虑到固定宽高会不会溢出导出布局错乱的问题;
371
- <布局注意事项>
372
-
373
- </布局原则>
374
-
375
- <最佳实践>
376
- 1. 对每一个组件,都仔细考虑是否要使用<辅助标记 />,按照<辅助标记使用 />来配置标记;
377
- 2. 对于文本、图片、图标、按钮等基础组件,任何情况下都可以优先使用,即使不在允许使用的组件里;
378
- 3. 对于图标,图标禁止使用emoji或者特殊符号,必须使用图标组件来搭建;
379
- 4. 关于图片
380
- 4.1 如果是常规图片,使用https://ai.mybricks.world/image-search?term=dog&w=100&h=200,其中term代表搜索词,w和h可以配置图片宽高;
381
- 4.2 如果是Logo,可以使用https://placehold.co来配置一个带文本和颜色的图标,其中text需要为图标的英文搜索词,禁止使用emoji或者特殊符号;
382
- 5. 对于文本,尺寸的计算
383
- - 宽度和高度要根据fontSize等样式来计算,预留更多的空间;
384
- - 尽量配置文本省略参数,防止一行换行后变多行带来的布局变化;
385
- - 文本最小大小可以配置到fontSize=10,在一些文字内容特别多的场景可以配置小文字;
386
- 6. 注意参考图片/设计稿里元素是否互相遮挡,避免出现遮挡(注意忽略角标);
387
- 7. 配置位置信息时,始终考虑父元素(插槽、父组件或祖先插槽及组件)的高度与宽度信息,防止出现遮挡或重叠;
388
- 8. 子组件计算尺寸(宽度与高度)的时候,需要向上考虑父元素(插槽、父组件或祖先插槽及组件)所有的尺寸与间距等样式,否则容易计算错误;
389
- 9. 对于横向排列或者竖向排列的多个相似元素,考虑如下情况:
390
- - 如果猜测是动态项,使用列表类组件来搭建;
391
- - 如果猜测是静态内容,优先使用布局,N行M列来搭建;
392
- - 如果是属于某个组件的内容,使用组件来搭建;
393
- </最佳实践>
394
- </UI搭建原则>
395
- </如何搭建以及修改>
396
-
397
- ${config.appendPrompt}
398
-
399
- <按照以下情况分别处理>
400
- 请根据以下情况逐步思考给出答案,首先,判断需求属于以下哪种情况:
401
-
402
- <以下问题做特殊处理>
403
- 当用户询问以下类型的问题时,给出拒绝的回答:
404
- 1、与种族、宗教、色情等敏感话题相关的问题,直接回复“抱歉,我作为智能开发助手,无法回答此类问题。”;
405
- </以下问题做特殊处理>
406
-
407
- <当用户询问自己搭建思路的问题>
408
- 按照以下步骤完成:
409
- 1、总体分析,详细拆分所需要的页面、UI组件、逻辑组件;
410
- 2、针对UI以及交互两个方面,给出搭建思路;
411
-
412
- 注意:
413
- - 根据业务类型选择合理的组件,注意不要超出允许的范围;
414
- - 禁止主观臆造不存在的组件;
415
- - 对于交互逻辑的回答,组件之间的编排按照 ->(输入项)组件名称(关联输出端口)-> 的格式给出
416
- </当用户询问自己搭建思路的问题>
417
-
418
- <当用户希望了解某个组件的具体情况>
419
- 提示其在画布中添加该组件,然后选中该组件了解详情
420
- </当用户希望了解某个组件的具体情况>
421
-
422
- <当用户希望搭建页面或修改页面时>
423
- 按照以下步骤完成:
424
- 1、总体分析,按照以下步骤进行:
425
- 1)确定总体的功能;
426
- 2)保持总体UI设计简洁大方、符合现代审美、布局紧凑;
427
- 3) 如果需要还原附件图片中的视觉设计效果:
428
- 特别关注整体的布局、定位、颜色、字体颜色、背景色、尺寸、间距、边框、圆角等UI信息,按照以下的流程还原参考图片:
429
- - 提取图片中的关键UI信息并总结;
430
- - 根据总结和图片将所有UI信息细节使用actions一比一还原出来,注意适配画布尺寸;
431
- - 忠于图片/设计稿进行搭建,而不是文字性的总结,文字总结会有歧义;
432
- - 注意每一个元素的以及邻近元素的位置,上下左右元素,以及子组件的布局方式,务必保证与设计稿对齐;
433
-
434
- 2、选择合适的组件与插槽,留意(知识库有更新)的提示,注意使用的组件不要超出当前【知识库】的范围:
435
- 1)按照自上而下、从左向右的方式分析形成组件方案以及采用的插槽;
436
- 2)选用合理的布局;
437
-
438
- 3、详细分析各个组件,按照以下要点展开:
439
- - 标题(title):组件的标题;
440
- - 布局(layout):组件的宽高与外间距信息,只能声明width、height、margin,不允许使用padding、position等属性;
441
- - 样式(styleAry):根据组件声明的css给出合理的设计实现;
442
- - 数据(data):根据【知识库】中该组件的data声明进行实现,尤其要注意:
443
- - 使用图片:如果data中需要给出新的图片,否则一律使用https://ai.mybricks.world/image-search?term={关键词}&w={图片宽度}&h={图片高度}做代替,不允许使用base64或者其他的;
444
-
445
- 4、最后,返回页面更新后的actions操作步骤文件内容,注意:
446
- - 每一个action符合JSON规范,每一行为一个action
447
- - 禁止包含任何注释(包括单行//和多行/* */)
448
- - 禁止出现省略号(...)或任何占位符
449
- - 确保所有代码都是完整可执行的,不包含示例片段
450
- - 禁止使用非法字符或特殊符号
451
- - 所有内容均为静态数据,禁止解构,禁止使用变量
452
- </当用户希望搭建页面或修改页面时>
453
-
454
- 整个过程中要注意:
455
- - 对于不清楚的问题,一定要和用户做详细的确认;
456
- - 如果没有合适的组件,务必直接返回、并提示用户;
457
- - 回答务必简洁明了,尽量用概要的方式回答;
458
- - 在回答与逻辑编排相关的内容时,无需给出示例流程;
459
- - 回答问题请确保结果合理严谨、言简意赅,不要出现任何错误;
460
- - 回答语气要谦和、慎用叹号等表达较强烈语气的符号等;
461
- </按照以下情况分别处理>
462
-
463
- <examples>
464
-
465
- ${config.examples}
466
-
467
- </examples>`
468
- },
469
- stream({ files, status }) {
470
- let actions: any = [];
471
- const actionsFile = getFiles(files, {extName: 'json' })
472
-
473
- if (actionsFile) {
474
- actions = actionsParser(actionsFile.content ?? "");
475
- }
476
-
477
- if (status === 'start') {
478
- config.onClearPage()
479
- }
480
-
481
- if (actions.length > 0 || status === 'start' || status === 'complete') {
482
- config.onActions(actions, status)
483
- }
484
- },
485
- execute({ files }) {
486
- // let actions: any = [];
487
- // const actionsFile = getFiles(files, {extName: 'json' })
488
- // if (actionsFile) {
489
- // actions = actionsParser(actionsFile.content ?? "");
490
- // }
491
- // config.onActions(actions)
492
- return `generate-page 调用完成,已根据需求将内容生成到页面id=${config.getTargetId()}中。`
493
- },
494
- }
495
- }
496
-
497
-
498
-
499
- interface Config {
500
- path: string;
501
- value: any;
502
- style: any;
503
- }
504
-
505
- interface AddChildActionParams {
506
- namespace?: string;
507
- ns?: string;
508
- layout?: any;
509
- configs: Config[];
510
- }
511
-
512
- interface DoConfigActionParams {
513
- path: string;
514
- value: any;
515
- }
516
-
517
- type ActionParams = AddChildActionParams | DoConfigActionParams;
518
-
519
- interface Action {
520
- comId: string;
521
- type: string;
522
- target: string;
523
- params: ActionParams;
524
- }
525
-
526
- const formatAction = (_action: string) => {
527
- let action;
528
- try {
529
- action = JSON.parse(_action);
530
- } catch (error) {
531
- console.log("error", error, _action);
532
- try {
533
- const repairedAction = jsonrepair(_action)
534
- action = JSON.parse(repairedAction)
535
- } catch (error) {
536
- console.error("repair action error", error);
537
- }
538
- }
539
-
540
- if (!Array.isArray(action)) {
541
- return action;
542
- }
543
-
544
- const [comId, target, type, params] = action;
545
- const newAct: Action = {
546
- comId,
547
- type,
548
- target,
549
- params,
550
- };
551
-
552
- // ns => namespace
553
- if (newAct.type === "addChild") {
554
- if (newAct.params?.ns) {
555
- newAct.params.namespace = newAct.params.ns;
556
- delete newAct.params.ns;
557
- }
558
- }
559
-
560
- // absolute 布局的转化
561
- if (newAct.params?.value?.display === "absolute") {
562
- newAct.params.value.position = "smart";
563
- delete newAct.params.value.display;
564
- }
565
-
566
- // absolute 布局的转化
567
- if (newAct.type === "addChild" && Array.isArray(newAct.params?.configs)) {
568
- newAct.params.configs.forEach((config) => {
569
- if (config?.value?.display === "absolute") {
570
- config.value.position = "smart";
571
- delete config.value.display;
572
- }
573
-
574
- if (config?.style) {
575
- // 兼容background
576
- transformToValidBackground(config?.style);
577
- }
578
- });
579
- }
580
-
581
- // 对样式幻觉的兼容
582
- if (newAct.type === "doConfig" && newAct.params?.style) {
583
- // 兼容background
584
- transformToValidBackground(newAct.params?.style);
585
- }
586
- if (newAct.type === "addChild" && newAct.params?.layout) {
587
- // 兼容margin
588
- transformToValidMargins(newAct.params?.layout);
589
- }
590
-
591
- return newAct;
592
- };
593
-
594
- /**
595
- * 将background转换为有效的backgroundColor和backgroundImage
596
- * @param styles 需要转换的样式对象
597
- */
598
- function transformToValidBackground(styles: any): void {
599
- // 兼容下把渐变色配置到backgroundColor的情况
600
- if (
601
- styles?.backgroundColor &&
602
- styles?.backgroundColor?.indexOf("gradient") > -1
603
- ) {
604
- const imageRegex =
605
- /(url\([^)]+\)|linear-gradient\([^)]+\)|radial-gradient\([^)]+\)|conic-gradient\([^)]+\))/;
606
- const imageMatch = styles.backgroundColor.match(imageRegex);
607
-
608
- if (imageMatch && !styles.backgroundImage) {
609
- styles.backgroundImage = imageMatch[0];
610
- }
611
-
612
- delete styles.backgroundColor;
613
- }
614
-
615
- // 如果没有background属性,直接返回
616
- if (!styles.background) {
617
- return;
618
- }
619
-
620
- const background = styles.background.toString();
621
-
622
- // 提取颜色值
623
- // 匹配颜色格式: #XXX, #XXXXXX, rgb(), rgba(), hsl(), hsla(), 颜色关键字
624
- const colorRegex =
625
- /(#[0-9A-Fa-f]{3,6}|rgb\([^)]+\)|rgba\([^)]+\)|hsl\([^)]+\)|hsla\([^)]+\)|[a-zA-Z]+)/;
626
- const colorMatch = background.match(colorRegex);
627
-
628
- // 提取图片url或渐变
629
- // 匹配url()或各种渐变函数
630
- const imageRegex =
631
- /(url\([^)]+\)|linear-gradient\([^)]+\)|radial-gradient\([^)]+\)|conic-gradient\([^)]+\))/;
632
- const imageMatch = background.match(imageRegex);
633
-
634
- // 删除原有的background属性
635
- delete styles.background;
636
-
637
- // 如果找到颜色值,设置backgroundColor
638
- if (colorMatch && !styles.backgroundColor) {
639
- styles.backgroundColor = colorMatch[0];
640
- }
641
-
642
- // 如果找到图片或渐变,设置backgroundImage
643
- if (imageMatch && !styles.backgroundImage) {
644
- styles.backgroundImage = imageMatch[0];
645
- }
646
- }
647
-
648
- /**
649
- * 将margin简写转换为marginTop/Right/Bottom/Left
650
- * @param styles 需要转换的样式对象
651
- */
652
- function transformToValidMargins(styles: any): void {
653
- // 如果没有margin属性,直接返回
654
- if (!styles.margin) {
655
- return;
656
- }
657
-
658
- const margin = styles.margin.toString().trim();
659
- const values = margin.split(/\s+/); // 按空格分割
660
-
661
- // 根据值的数量设置不同方向的margin
662
- switch (values.length) {
663
- case 1: // margin: 10px;
664
- styles.marginTop = values[0];
665
- styles.marginRight = values[0];
666
- styles.marginBottom = values[0];
667
- styles.marginLeft = values[0];
668
- break;
669
- case 2: // margin: 10px 20px;
670
- styles.marginTop = values[0];
671
- styles.marginRight = values[1];
672
- styles.marginBottom = values[0];
673
- styles.marginLeft = values[1];
674
- break;
675
- case 3: // margin: 10px 20px 30px;
676
- styles.marginTop = values[0];
677
- styles.marginRight = values[1];
678
- styles.marginBottom = values[2];
679
- styles.marginLeft = values[1];
680
- break;
681
- case 4: // margin: 10px 20px 30px 40px;
682
- styles.marginTop = values[0];
683
- styles.marginRight = values[1];
684
- styles.marginBottom = values[2];
685
- styles.marginLeft = values[3];
686
- break;
687
- }
688
-
689
- // 删除原有的margin属性
690
- delete styles.margin;
691
- }
692
-
693
- /**
694
- * 创建actions解析器
695
- * @returns {Function} 解析函数
696
- */
697
- function createActionsParser() {
698
- const processedLines = new Set();
699
-
700
- return function parseActions(text: string) {
701
- const newActions = [];
702
- const lines = text.split("\n");
703
-
704
- // 只处理除了最后一行之外的所有行(最后一行可能不完整)
705
- const linesToProcess = lines.slice(0, -1);
706
- const lastLine = lines[lines.length - 1];
707
-
708
- // 处理完整的行
709
- for (const line of linesToProcess) {
710
- const trimmedLine = line.trim();
711
-
712
- // 跳过空行和已处理的行
713
- if (!trimmedLine || processedLines.has(trimmedLine)) {
714
- continue;
715
- }
716
-
717
- try {
718
- const parsedAction = formatAction(trimmedLine);
719
- if (parsedAction.comId) {
720
- newActions.push(parsedAction);
721
- processedLines.add(trimmedLine);
722
- }
723
- } catch (error) {
724
- // 这是真正的解析错误(完整的行但格式错误)
725
- processedLines.add(trimmedLine); // 标记为已处理,避免重复尝试
726
- }
727
- }
728
-
729
- // 检查最后一行是否完整(如果以换行符结尾,说明最后一行是空的)
730
- if (lastLine && lastLine.trim() && text.endsWith("\n")) {
731
- const trimmedLastLine = lastLine.trim();
732
-
733
- if (!processedLines.has(trimmedLastLine)) {
734
- try {
735
- const parsedAction = formatAction(trimmedLastLine);
736
- if (parsedAction.comId) {
737
- newActions.push(parsedAction);
738
- processedLines.add(trimmedLastLine);
739
- }
740
- } catch (error) {
741
- processedLines.add(trimmedLastLine);
742
- }
743
- }
744
- } else if (lastLine && lastLine.trim()) {
745
- // 最后一行不完整,等待更多数据
746
- }
747
-
748
- return newActions;
749
- };
750
- }