关于 custom-angular-component-creator
custom-angular-component-creator 是用于在 Datex Studio 中编写或编辑自定义 Angular 组件的技能,面向需要定制界面的开发者。它通过 dxs ng 创建本地轻量 harness、预览截图,并在 push 后写入 Studio;数据采用真实类型化数据源,预览使用模拟数据。
主要功能
- 01编写独立 Angular 组件
- 02通过 dxs ng 创建和拉取组件
- 03本地 harness 预览并生成截图
- 04嵌入现有应用配置组件
- 05使用类型化数据源及模拟预览数据
- 06推送组件至 Datex Studio
适用场景
- 01构建定制图表、仪表板或可视化
- 02在自定义界面中嵌入生成控件
- 03将自定义组件用作容器标签页内容
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ datex/ skills --skill custom-angular-component-creator安装后在 Claude Code 中输入/custom-angular-component-creator确认已加载。
附带文件references/custom-angular-components.md
详细介绍
自定义 Angular 组件创建器
在分支上创作或编辑 Datex Studio 自定义 Angular 组件(CAC,configurationTypeId: 36)。CAC 是由作者编写的独立 Angular 组件——你需要编写实际的 component.ts / .html / .scss,而不是声明式 JSON 配置。它在生成的应用中运行,并注入真实的平台上下文($datasources、$flows、$shell 等),因此可用于实现声明式组件(grid / form / hub / selector / editor)无法表达的 UI:定制图表、仪表板、可视化和自定义布局。
CAC 也可以在模板中嵌入现有应用配置——将其声明为组件引用(先从 selectors 开始;此契约适用于各种组件类型),代码生成器便会将生成的组件导入 CAC 的作用域,让真正生成的控件(例如 selector 下拉菜单)在自定义 UI 中渲染。
嵌入提示:selector 会生成两个变体——_single 和 _multi——因此引用一个 selector,就能获得单选和多选控件供你选择。嵌入的控件会将配置本身的属性作为组件输入/输出公开(例如,selector 会将其每个 datasource 参数作为输入公开,输入名称由参数 ID 决定,并公开其选中值和显示文本输出)。要查找被引用配置公开的确切标签和输入/输出,请读取物化 harness 中生成的组件——@Component 的 selector 就是要使用的标签,@Input / @Output 成员就是要绑定的内容——不要靠猜。
此技能使用的 CLI 接口与其他所有创建器都不同。 这里没有 dxs configuration upsert customangularcomponent 这种手动创作路径——CAC 创作通过 dxs ng 命令系列完成。该命令会物化一个轻量 harness(由服务器为该分支生成,包含单个组件、真实的类型化上下文和存根服务),让你在本地编辑两个作者区域,并在每次迭代时渲染一张截图。只有执行 dxs ng push 后,内容才会在 Studio 中创建。
数据模式(固定默认值——绝不询问)
无论 CAC 何时显示数据,这些数据都来自真实的类型化 datasource——而且如何接入数据不是要询问用户的问题。不要询问是否使用真实数据、示例数据、@Input 或其他数据来源:所有组件都使用固定模式。
- 创作循环(CLI /
dxs ng preview): 组件通过类型化的this.$datasources.<ref>存根读取数据,但预览使用的是模拟数据——dxs ng data generate会生成mocks/harness-mocks.json,你再用有代表性的值填充它(这些值来自真实的dxs查询)。创作预览绝不会访问真实数据。 push之后(生成的 Studio 应用): 相同的类型化$datasources.<ref>调用会在运行中的应用里访问真实 datasource / 真实数据。组件在运行时始终依赖 datasource。- 分支上缺少 datasource? 先用
schema-explorer探查,再用datasource-creator创建一个与真实 schema 匹配的 datasource,并在物化 harness 之前执行 upsert,以便 harness 为存根生成类型。绝不要在组件主体中回退到内嵌示例行,也不要使用类型转换($datasources as any)。
一句话概括:真实的类型化 datasource + 创作时使用模拟数据,push 后使用真实数据——每个 CAC 都遵循此模式,无需询问。示例数据只存放在 mocks/harness-mocks.json 中(临时使用,绝不 push);组件主体应保持简洁,并提供真实的空数据、加载和错误状态。具体操作请参见第 3 阶段。
CLI 优先——禁止变通(硬性规则)
dxs CLI 是此技能唯一获准使用的操作界面——所有 Studio 状态的读取和写入,以及创作循环的每个步骤(create/pull、data generate、preview、push),都必须通过 dxs 完成。如果 CLI 功能不足,应将这一缺口报告为待修复的 CLI 问题,不要绕过 CLI——能够“完成任务”的变通做法会掩盖缺陷,而之后的每次会话都会再次遇到这个缺陷。
- 从
dxs获取事实,不要依赖其他渠道。 字段形状、配置内容、架构、分支状态都有对应的dxs命令。对命令输出使用普通的head/grep没问题;但不允许通过脚本解析配置 JSON(jq/python),也不允许读取原始平台构件。 - 根据 CLI 可观察到的证据推断服务端约定。
validate/upsert的拒绝信息会指出预期的服务类型,而分支上现有的有效配置(dxs configuration get)会展示被接受的形状——这两者已足够。不要打开平台源代码仓库来逆向分析约定。 - 需要变通时,应提交 Bug 报告,而不是把变通当作技巧。 如果任务看似需要终止残留进程、编写脚本绕过 CLI 输出格式、驱动 CLI 已封装的工具(例如,在
dxs ng preview之外截取屏幕截图),或手动编辑生成的 JSON——请停下来,告知用户 CLI 存在的缺口或 Bug,并协商后续步骤。 - 挂起和孤儿进程属于应报告的缺陷。 如果
dxs命令阻塞终端、遗留持有文件锁的子进程,或泄漏临时状态,这就是 CLI 生命周期 Bug。记录完整的症状链(命令、错误代码、遗留进程/文件),以便修复;解除阻塞的终止操作必须在报告之后进行,不能当作未加说明的常规操作。
每个屏幕仅使用一个 CAC(硬性规则)
一个设计/屏幕应作为一个 CAC 来编写——绝不能拆分成多个 CAC 再组合。组合应通过嵌入式平台组件(组件引用:优先使用选择器)和 $shell 对话框打开器实现,而不是将 CAC 嵌套在 CAC 中。如果设计对单个组件来说过于庞大,应精简设计,而不是增加组件数量。
将 CAC 用作标签页内容
CAC 可以作为中心页、编辑器、卡片或仪表板中标签页的内容——与承载网格和表单的插槽相同。在容器的标签页设计器中,选择 Custom Angular Component 作为标签页内容类型,引用已推送的 CAC,并通过标签页的参数绑定其 @Inputs(标签页连接的是 CAC 的 inParams/outParams)。平台会为每个 CAC 生成标签页内容约定,预留三个成员名称——refresh、$refreshEvent 和 outParamsChange。切勿将这些名称声明为 outParam 或 @Output,也不要在主体中重新声明两个生成的 @Output($refreshEvent、outParamsChange)——名称冲突会导致重复成员编译错误。唯一的例外是主体中的 refresh() 方法,它是获准的重写方式:若要在容器刷新时重新加载 CAC,请在主体区域实现 refresh(),它会替换生成的默认实现(默认实现会重新运行 ngOnInit())。
参考资料
- ../datex-studio-shared/branch-setup.md — 分支/连接选择(各项技能通用)。绝不要假定分支 ID。
- references/custom-angular-components.md — CAC 权威参考:两个作者区域、轻量测试框架/预览模型、注入的
$上下文、模拟数据、manifest.json结构、先决条件、耗时和注意事项 - ../datex-studio-shared/design-system/README.md — Datex 设计系统(Fluent 2):主题令牌、实际的
datex-*组件类名、模式和编译后 CSS 陷阱。CAC 不会自动获得任何样式——请阅读本文并应用其中的设计,让手动编写的 UI 看起来与原生界面一致。 - ../datex-studio-runtime/runtime-globals.md — 组件构造函数接收的平台
$全局对象($datasources、$flows、$shell、$utils、$settings等) - ../datex-studio-runtime/calling-conventions.md — 组件运行的代码所适用的 UI 层调用规则(调用工作流/数据源,而非原始 HTTP)
- ../datex-studio-conventions/naming-conventions.md — 引用名称/显示名称规则(传给
dxs ng create的名称采用 PascalCase;引用名称采用 camelCase) - ../datasource-creator/references/datasources.md — 组件通过
$datasources/$flows读取真实数据时参考
依赖项
requirements-gathering技能 — 如果对话上下文中尚无简报(或目标截图),则调用该技能来生成简报(或收集目标截图)。CAC 的核心价值就是定制 UI,因此具体的视觉目标对 CAC 的价值高于对任何其他组件的价值。schema-explorer技能 — 当组件通过$datasources读取 Footprint 数据时调用,以确认实体/字段存在,再进行连接。datasource-creator技能 — 当组件需要的某个数据源/工作流在分支上尚不存在时调用(先创建,再从组件中引用,并为预览添加模拟数据)。
先决条件(一次性,由宿主提供)
dxs ng 循环需要可访问的 Datex API——开始前请确认以下事项(参见 references/custom-angular-components.md → Prerequisites):
- 目标分支对应的 Datex API 可访问。 测试框架端点会在服务端运行代码生成,且不受环境限制——部署的映像会在其运行时阶段安装 Node 和
codegen/node_modules,正是为了让 API 能够按需运行代码生成。因此,create/pull会针对 CLI 配置的任何 Datex Application API 工作,无论是 dev、qa 还是 prod。 (请勿与应用发布混淆,发布确实受 dev 环境限制——在 Development 之外,发布会交由 Azure DevOps 管道处理。此限制不适用于测试框架端点。) - 已通过身份验证——
dxs auth status会显示已登录的身份。 - agent-browser(无头截图)——通过非作用域 npm 包安装:
npm install -g agent-browser,然后运行agent-browser install。(包名不是@anthropic-ai/agent-browser——该名称会返回 404。)
CLI 生命周期 — dxs ng 系列
| 命令 | 是否联网? | 是否操作 Studio? | 功能 |
|---|---|---|---|
dxs ng create <Name> -b <branch> [-d <dir>] | 是 | 否 | 构建起始配置 → 服务端为分支生成轻量测试架构 → 在本地生成 <name>/angularapp/… + manifest.json + mocks/。不会在 Studio 中创建任何内容。 |
dxs ng pull <name> -b <branch> [-d <dir>] [--force] | 是 | 否 | 为现有 CAC 执行相同的生成操作(用于编辑现有内容的入口)。如果文件夹已存在,会报出结构化的 DXS-NG-048 错误;--force 会删除整个文件夹(先停止正在运行的预览服务本身),然后根据服务端的实际状态重新生成。 |
dxs ng data generate <folder> -b <branch> | 是 | 否 | 使用组件所用 $datasources/$flows 的类型化占位符填充 <folder>/mocks/harness-mocks.json。 |
dxs ng preview <folder> [-o out.png] [--refresh] [--clean] | 否(本地) | 否 | 在本地运行测试架构,并为组件截图 → <folder>/render.png。--refresh -b <branch> 会在 manifest/IO 变更后重新获取测试架构;--clean 会重置卡住的服务,并拆除 agent-browser 会话(守护进程、Chrome 进程树、过期状态文件)。 |
dxs ng push <folder> -b <branch> | 是 | 是 | 提取两个区域 + manifest.json → 执行 type-36 的 upsert。首次 push 会在 Studio 中创建组件;服务端会在 upsert 时进行验证(强制门禁)。 |
dxs ng stop <folder> | 否(本地) | 否 | 停止文件夹的常驻预览开发服务及其 agent-browser 会话(通过身份校验的锁终止操作,并移除锁)。此操作幂等(没有正在运行的进程时,stopped: false)——完成后用于清理;切勿手动读取锁或运行 taskkill。 |
dxs ng list -b <branch> | 是 | 否 | 列出分支的 type-36 组件。 |
传给 create 的 <Name> 必须使用帕斯卡命名法(OutboundCommandCenter);引用名称会转换为驼峰命名法(outboundCommandCenter),选择器使用 kebab-case app-outbound-command-center(自动生成——即 create 输出并存储在 manifest.json 中的值),文件名为 app.outboundCommandCenter.component.{ts,html,scss}。
工作流
[Phase 1: Setup + Requirements]
Follow branch-setup.md for branch selection (NEVER assume a branch ID)
Confirm prerequisites (API reachable, auth, agent-browser)
|
[requirements brief / TARGET SCREENSHOT in context?]
+-----+-----+
| |
YES NO -> invoke `requirements-gathering` (capture the visual target)
+-----+------+
|
[Phase 2: Materialize the harness]
dxs ng create <Name> -b <branch> (new component)
-- or --
dxs ng pull <name> -b <branch> (edit an existing one)
|
[Phase 3: Author the two regions]
Edit <name>/angularapp/src/app/app.<ref>.component.ts:
__COMPONENT_TYPES__ region -> imports / interfaces / types
__COMPONENT_BODY__ region -> fields / methods / getters / lifecycle
Edit app.<ref>.component.html and .scss.
NEVER touch the wrapper class line, the @Component decorator, the
constructor, or the //#region ... //#endregion sentinels.
|
[real data?] -> dxs ng data generate <folder> -b <branch> (seed mocks)
|
[Phase 4: Preview loop (screenshot-driven)]
dxs ng preview <folder> -> writes <folder>/render.png
Read render.png. Compare to the target. Edit regions. Re-preview.
Repeat until it matches. (First preview ~15-46s cold; each later ~10s.)
|
[Phase 5: Push + verify]
dxs ng push <folder> -b <branch> (creates in Studio; server validates)
dxs ng list -b <branch> (confirm it landed)
dxs ng pull <name> -b <branch> -d ./roundtrip (optional round-trip check)
阶段详情
阶段 1:设置 + 需求
- 按照 ../datex-studio-shared/branch-setup.md 选择分支。切勿假定或重复使用分支 ID——即使本次会话中较早时出现过,也要让用户确认。确认上述前置条件。
- 检查上下文中是否有需求说明。对于 CAC,价值最高的输入是具体的视觉目标——目标截图,或对布局、数据和交互的精确描述。如果没有,请调用
requirements-gathering。目标截图能让阶段 4 成为以目标为基准、逐步收敛的过程。
阶段 2:生成轻量框架
运行 dxs ng create <Name> -b <branch>(新建)或 dxs ng pull <name> -b <branch>(已有)。传入 -d components,让工作副本位于共享的 components/<Name>/ 目录下(这是 CAC 工作目录的约定),而不是当前目录。此命令会让服务为分支生成轻量框架,并在本地生成文件:
<name>/
angularapp/… # the runnable light harness (one component + real typed context + stub services)
manifest.json # identity + IO (inputs/outputs) + datasource/flow refs + displayModes
mocks/ # fixtures the harness $datasources/$flows read during preview
此步骤不会在 Studio 中创建任何内容。请参阅 references/custom-angular-components.md → The light harness。
编辑已有组件(pull)。 pull 是编辑已有组件的入口,它会忠实地往返同步 Studio 中的两个作者区域以及 .html/.scss。如果目标文件夹已存在,则会报出结构化的 DXS-NG-048 错误,并列出两种获准的处理方式——明确选择同步方向:
- 保留我的本地工作,刷新轻量框架 →
dxs ng preview <folder> --refresh -b <branch>— 唯一保留区域内容的同步方式(保留作者编写的区域、模板、样式、manifest.json、mocks/、node_modules)。 - 丢弃本地内容,采用服务端版本 →
dxs ng pull <name> -b <branch> -d <dir> --force— 删除整个文件夹(与dxs report download --force的行为一致),然后重新生成文件。CLI 会通过经过身份校验的 serve 锁自行停止仍在运行的预览开发服务器——切勿手动终止进程——如果目标看起来不像 CAC 工作副本,则会拒绝操作(DXS-NG-049)。
有三项内容永远不会通过服务端往返同步,因此使用 --force 拉取后,请恢复它们:(1) manifest.datasources 会变为空(持久化配置只存储标识以及 inParams/outParams)——请将条目重新添加为对象 { "name": "<ref>", "ref": "<ref>" },切勿使用裸字符串(字符串会导致下一条 dxs ng 命令中的 manifest 验证失败);(2) mocks/ 会变为空——请使用 dxs ng data generate 重新生成数据并填充,或还原之前的文件;(3) node_modules 会被删除——下次运行 preview 时会重新执行 npm install(耗时数分钟)。重新添加 manifest 条目后的首次 preview 会报告 refetched: true(manifest 编辑改变了 IO 签名,从而触发自动重新生成)——这是预期行为,并非错误。
阶段 3:编写两个区域
你只能编辑 <name>/angularapp/src/app/app.<ref>.component.ts 中的两个作者区域,以及同级的 .html 和 .scss:
//#region __COMPONENT_TYPES__
// imports, interfaces, type declarations (spliced verbatim on push)
//#endregion __COMPONENT_TYPES__
// ...generated @Component + class wrapper + constructor (DO NOT EDIT)...
//#region __COMPONENT_BODY__
// fields, methods, getters, lifecycle body (spliced verbatim on push)
//#endregion __COMPONENT_BODY__
切勿更改包装器的 class 行、@Component 装饰器、构造函数或 //#region … //#endregion 标记行——push 会从标记之间提取你的工作,因此损坏这些内容会导致提取失败。构造函数已注入真实上下文($datasources、$flows、$shell、$utils、$settings、$reports、$localization、$operations、$userSettings、$frontendFlows),并使用真实分支类型,因此代码体中应使用 this.$datasources.… 等写法——切勿直接使用 HttpClient。已导入 SharedModule,因此模板中可使用 Angular 指令(*ngFor、*ngIf、[ngClass]、[style.*])以及 Material/AG-Grid/ApexCharts。
遵循 Datex 设计系统进行样式设计——CAC 不会自动获得任何样式,因此必须应用设计系统,否则外观会显得格格不入。不可妥协的原则:参考现有设计,不要自行发明(复制最相近的现有组件的标记结构和类);使用 var(--…) 主题令牌,绝不硬编码十六进制值(硬编码的十六进制值会破坏深色模式,也会破坏填充式控件系统所依赖的令牌);组合使用真实的 datex-* 类名(datex-button primary、field-container、grid-table-*、card datex-card、widget-container 等),而不是编写专用 CSS;Fluent 图标只能放在 <i> 上;使用句首字母大写的大小写格式,每个屏幕只放一个主按钮。有关令牌变量、完整的组件类名列表以及编译后 CSS 的陷阱,请阅读 ../datex-studio-shared/design-system/(从 02-tokens、03-components、06-traps 开始)。
如果组件会读取真实数据,请运行 dxs ng data generate <folder> -b <branch>,为 mocks/harness-mocks.json 填充初始数据,然后填入逼真的值,让预览呈现有代表性的数据。如果不确定数据源或实体是否存在,请先调用 schema-explorer;如果需要创建数据源或实体,请调用 datasource-creator。
对清单进行 IO 更改(新增 @Input/@Output)需要配置代码生成:编辑 manifest.json,然后使用 --refresh -b <branch> 重新预览;重新生成的 harness 会为 this.inParams.<name> 指定类型,并通过 this.<output> 发出事件。区域、模板和样式的编辑完全在本地进行(无需 --refresh)。
生命周期钩子要写在主体中。 直接在 __COMPONENT_BODY__ 中实现 ngOnInit / ngOnChanges / ngOnDestroy(例如,使用 async ngOnInit() 加载数据)。代码生成只会为你未实现的钩子生成存根,因此,重新获取会使二者保持一致;但如果 IO 未发生变化,直接运行 preview 不会重新获取,导致你的钩子与仍存在的生成存根重复(产生编译错误)。因此,请在触发重新获取的 IO 更改中一并添加钩子,或者添加钩子后运行一次 preview --refresh -b <branch>。对于非 @Input 的组件内交互状态(例如模式切换),请保留一个普通字段,并在 ngOnInit 中用输入值初始化它——无需更改清单,因此预览会保持就绪。
数据源——先创建,再通过带类型的访问方式引用,不使用固定样例数据。 数据源是真实的分支配置:在物化 harness 之前,使用 datasource-creator 创建数据源(dxs datasource generate → validate → dxs configuration upsert datasource),这样生成的 harness 才会为 this.$datasources.<ref> 存根指定类型。manifest.datasources 只会声明依赖项,不会创建数据源。请使用带类型的访问方式读取它(await this.$datasources.<ref>.getList({…})),不要进行类型转换。如果缺少数据源,该带类型的引用会导致编译错误——这正是你想要的快速失败行为:修复配置(创建并 upsert,然后重新物化),不要通过类型转换绕过错误($datasources as any),也不要回退到内嵌样例数据。如果在物化后才添加了数据源,而存根尚未出现,请重新物化(dxs ng pull / preview --refresh -b <branch>),并在依赖它之前确认它已列在 angularapp/src/app/app.datasource.index.ts 中。样例/预览数据只能放在 mocks/harness-mocks.json 中(临时数据,绝不推送)——不要放在组件主体中,因为组件主体会原样插入 Studio 配置。**如需了解数据源的字段结构,以便映射行数据,请使用 CLI——切勿手动解析配置 JSON:**既然你无论如何都会在物化之前执行 upsert,就可以使用 dxs report datasource-fields <ref> -b <branch> 读取权威字段结构(结果类型 + 参数 + 扁平字段路径 + 集合),并使用 dxs datasource validate <file> -b <branch> 验证本地文件(发现错误时会以 1 退出——这表示验证报告发现了问题,并非 CLI 出故障:读取 validation_errors、修复后重新运行);不要用 jq/python 从 outParams/queryOptionsObjectTypeDef 中提取字段,并记住,执行 dxs ng create 后,this.$datasources.<ref> 已带类型。参见 references/custom-angular-components.md → 读取真实数据。
阶段 4:预览循环(基于截图)
dxs ng preview <folder> # -> <folder>/render.png
读取 render.png,将其与目标进行比较,编辑区域、模板或样式,然后重新运行 preview。这是核心循环,也是 Agent 发挥价值的地方:读取 PNG,与目标截图进行比较,进行调整,然后重复,直到匹配为止。类型/模板错误也会在此处显现(测试工具会编译真实组件)。耗时(本地):create 后首次运行 preview 时,需要一次性执行 npm install(几分钟),然后编译约需 15–46 秒;此后每次运行 preview 约需 10 秒,编辑后热重载约需 4 秒。冷编译等待由内部处理(没有超时参数);如果服务或浏览器会话卡住,请使用 --clean——它会重置二者,包括崩溃运行遗留的过期 agent-browser 会话状态。
preview 会捕获组件的默认渲染状态,不会点击。如果某个模式/变体是通过组件内 UI(而非 @Input)切换的,请临时设置该默认状态(或通过 @Input/模拟数据驱动),以便对每个变体截图。对于真正的交互状态(点击选择、切换开关、面板),请改为使用 agent-browser 操作已提供的测试工具:从 <folder>/.dxs-serve.lock 读取端口,然后执行 agent-browser open http://127.0.0.1:<port> → wait '<css>' → click '<css>' → screenshot out.png——这样验证的是真实处理程序的接线,而非模拟的默认状态。
阶段 5:推送并验证
dxs ng push <folder> -b <branch> # first push CREATES it in Studio; server validates on upsert
dxs ng list -b <branch> # confirm it appears
dxs ng pull <name> -b <branch> -d ./roundtrip # optional: confirm the regions round-trip
dxs ng stop <folder> # done for now? dispose of the warm dev server + browser session
push 是唯一会写入 Studio 的命令。服务器会在创建或更新时运行配置验证器(这是硬性门槛——它能识别 CAC 配置);如果组件引用了分支上不存在的数据源,或以其他方式未通过验证,就会被拒绝。请修复报告的问题,然后再次推送。如果区域哨兵标记受损,push 也会在本地失败(发起任何网络调用之前)——这就是“不要触碰哨兵标记”规则生效的情形。
数据源连接预检(DXS-NG-047)。 在创建或更新之前,push 会验证 CAC 使用的每个本分支数据源——包括 manifest.datasources 和组件正文中未限定名称的 $datasources.<ref> 调用的并集(因此过期的清单无法绕过检查)——是否存在于该分支上,并且是否指定了该分支实际定义的 API 连接设置。这一点很重要,因为测试工具中的模拟不会触及连接:即使 Studio 会在数据源上标记 “Missing API Connection setting <name>”,预览仍会显示为绿色;而推送成功也绝不应让人误以为真实的代码生成构建可行。遇到 DXS-NG-047 时:检查 dxs source branch settings <branch>;使用 dxs datasource generate 针对此分支重新生成数据源(它会自动解析设置);如果应用完全没有 API 连接,请先在 Studio 中接入一个(CLI 不会创建连接)。在尚无任何连接的应用上进行有意的纯模拟开发时,可用 --skip-connection-check 跳过此门槛。包数据源(Module/ref、$datasources.<Module>.<ref>)不受此检查限制——其设置会通过引用重映射进行解析。
预检清单
- 已与用户确认分支(绝不自行假定);前置条件已就绪(API 可访问、身份验证正常、
agent-browser可用)。 - 仅编辑了两个区域、
.html和.scss——包装类所在行、@Component、构造函数和//#region标记均未改动。 - 没有使用原始
HttpClient/ 直接调用后端——数据通过this.$datasources/this.$flows获取;UI 操作通过$shell/$flows执行(参见 calling-conventions)。 - 已填充 Mock 数据(
dxs ng data generate);如果组件会读取$datasources/$flows,还需填入有代表性的数据,让预览渲染出贴近真实的数据。 - 修改
manifest.json的 IO 后,运行preview --refresh -b <branch>(新增@Input/@Output需要重新连线代码生成)。引用的数据源必须已存在于分支上(最好在物化前先用datasource-creator创建),并通过$datasources的类型化访问读取——缺少数据源会导致编译错误,必须修复,绝不能通过强制类型转换绕过;示例数据保留在mocks/中。参见 Phase 3 中的数据源说明。 - 预览 PNG 与目标一致——循环迭代已收敛,渲染中不再有编译/模板错误。
displayName不超过 100 个字符——它会成为配置的title/description(没有单独的 manifestdescription字段)。- 推送后已验证——
dxs ng list -b <branch>会显示该项;也可选择运行dxs ng pull … -d ./roundtrip,往返验证这些区域。
清理——工作副本占用空间较大
物化后的工作文件夹约占 700 MB,其中约 85% 是 angularapp/node_modules。文件夹不是交付物——push 后,Studio 中的配置才是。
成功 push 后(通过 dxs ng list -b <branch> 验证),询问用户是否清理——绝不默默清理。首先使用 dxs ng stop <folder> 停止常驻开发服务器及其 agent-browser 会话——该命令会进行身份校验后再停止(验证 PID + 映像,绝不盲目终止),并清理浏览器会话/守护进程和锁文件;该操作可重复执行,因此无论如何都应调用。绝不要手动读取 .dxs-serve.lock 或运行 taskkill——对于早于 stop 命令的 CLI,手动操作只是权宜之计,并非推荐方法。(dxs ng preview <folder> --clean 是另一个生命周期命令:它执行的是重置,而不是停止——采用相同的清理流程,然后启动新服务器;预览卡住时使用它,释放资源时使用 stop。)然后提供以下两种清理级别。分两级释放磁盘空间:
- **精简(会话之间的默认操作):**删除
<folder>/angularapp/node_modules(约 600 MB)、<folder>/angularapp/.angular(构建缓存,约 100 MB)和<folder>/.dxs-install-ok标记文件(它与node_modules配套——只有两者都存在时,preview才不会重新安装)。所有编写的内容都会保留,可恢复,约占 16 MB;下次运行preview时会重新执行npm install(需要几分钟),并进行冷编译。数据丢失风险为零。 - 完全删除(组件已完成时):仅在确认配置已存在于 Studio 中(
dxs ng list -b <branch>)后执行。如果目标是获取全新的工作副本,完全不要手动删除——dxs ng pull <name> -b <branch> -d <dir> --force会完成整个操作(自行停止运行中的开发服务器、删除并重新物化);若残留锁定文件导致失败,会显示结构化错误DXS-NG-049。若删除后不再重新拉取(最终清理):先运行dxs ng stop <folder>,再删除文件夹。少见的残留情况:之前崩溃的服务器可能遗留锁文件已不再跟踪的孤立子进程(node.exe、esbuild.exe),因此,如果删除仍因文件被锁定而失败,请清理命令行中引用该文件夹的进程,并将此问题报告为 CLI 生命周期错误。dxs ng pull会忠实地重新物化两个区域、.html和.scss,但mocks/harness-mocks.json、捕获的目标/备注文件以及manifest.datasources/componentRefs不会往返保留——重新拉取后需重新填充/添加它们。
绝不要完全删除尚未推送的工作副本——编写的区域不会在其他地方留存。
常见错误
| 错误做法 | 修正方法 |
|---|---|
询问用户组件应如何获取数据(真实数据还是示例数据、使用 @Input 还是 datasource) | 不要询问——数据模式是固定的。使用真实的类型化 datasource + mocks/ 数据用于创作预览;push 后使用真实数据。请参阅数据模式(固定默认值——切勿询问)。 |
手动编写 JSON 请求体并运行 dxs configuration upsert customangularcomponent | CAC 通过 dxs ng(regions + harness + preview)创作,而非通过 JSON 往返。请使用 dxs ng create / preview / push。 |
编辑两个 regions 以外的内容(触碰 wrapper class、@Component、constructor 或 //#region 哨兵标记) | push 会提取哨兵标记之间的代码。其他位置的编辑会在 push 时丢失,或导致提取失败。请只修改 __COMPONENT_TYPES__、__COMPONENT_BODY__、.html、.scss。 |
安装 @anthropic-ai/agent-browser(404) | 该软件包的名称不带作用域,即 agent-browser:npm i -g agent-browser && agent-browser install。 |
preview 报告 ng serve did not become ready(DXS-NG-042) | 通常是首次冷编译耗时较长——可通过 DXS_NG_SERVE_TIMEOUT(秒)延长超时时间,然后重新运行;使用 --clean 重置卡住的服务。在 CLI ≤0.4.13 中,相对文件夹参数也会导致此问题(开发服务器因脚本路径解析错误而立即退出;此问题已修复——在该版本中可传入绝对路径作为变通方法)。如果在当前 CLI 中仍然出现此问题,那就确实是编译问题——检查 ng build。 |
preview 因 DXS-NG-053 失败(agent-browser 'wait' timed out)——并由此认定组件已损坏 | 截图超时 ≠ 渲染失败:组件通常已成功编译并提供服务(与 DXS-NG-042 ng serve did not become ready 不同,后者才是编译失败)。预热的服务也可能已过期。使用 --clean 重新运行,然后用 agent-browser 打开 .dxs-serve.lock 中的端口,并检查 app-<ref> 是否有内容,以验证实际渲染——不要追查不存在的代码错误。 |
期望预览/打开其他组件(或通过 $shell 打开它们的对话框) | harness 只会将你的候选组件设为真实组件;对其他组件调用 $shell.open<X>Dialog(...) 时,会生成可编译但无法在预览中打开的 stub。$datasources/$flows(真实分支)和你自己的 UI 均可正常使用。 |
期望组件在 create / preview 后出现在 Studio 中 | create/pull/data generate/preview 都只是临时操作。只有 push 会写入 Studio(首次 push 时会创建组件)。 |
在 body 中使用 HttpClient 或 fetch | 请使用注入的 $datasources / $flows;它们是真实、类型化的,并且可在预览中使用 mock。原始 HTTP 请求无法获得分支的 auth/context。 |
| 组件使用了 datasource,但预览渲染为空 | 运行 dxs ng data generate 并填充 mocks/harness-mocks.json——预览时 harness 的 $datasources/$flows 会读取这些 fixture(无需后端)。 |
添加了 @Input/@Output,但 preview 没有体现 | IO 更改需要重新执行 codegen 连接:更新 manifest.json,然后运行 dxs ng preview <folder> --refresh -b <branch>。 |
期望 manifest.datasources 创建或连接 datasource | 它两者都不会做。请先使用 datasource-creator 创建 datasource(运行 dxs datasource generate/validate/configuration upsert datasource),最好在实例化之前完成,这样 harness 才能为 $datasources.<ref> stub 生成类型;manifest.datasources 只声明依赖项。 |
通过类型转换绕过缺失的 datasource($datasources as any)或使用 fixture 备用数据 | 这是反模式:它会将假数据发布到 Studio,并掩盖连接问题。缺失的 datasource 应当导致编译错误——请创建/更新 datasource 并重新实例化(pull/--refresh)来修复,然后使用类型化的 this.$datasources.<ref>。 |
| 在 body 中嵌入示例/fixture 行(或添加“之后会被真实 datasource 替换”的注释) | body 会原样拼接到推送的 type-36 配置中,因此 fixture 和 WIP 注释都会进入生产环境。请保持 body 简洁——使用类型化 datasource 读取,并提供真实的空数据/加载中/错误状态;示例数据只放在 mocks/harness-mocks.json 中。 |
手动解析 datasource 配置 JSON(使用 jq/python,或查看 outParams/queryOptionsObjectTypeDef 来了解字段结构) | 请使用 CLI。先执行 upsert(这本来就是实例化前的必要步骤),然后运行 dxs report datasource-fields <ref> -b <branch> 获取字段列表;对于本地文件,使用 dxs datasource validate/context <file> -b <branch>。运行 dxs ng create 后,this.$datasources.<ref> 已有类型——你很少需要手写行类型。切勿编写脚本解析 JSON。 |
--refresh 渲染正常,但之后的 preview 显示编译错误 | --refresh 重启时可能会在重新编译错误提示层显示之前就截图。请再次运行普通 preview 确认,并 grep harness 的 app.datasource.index.ts,查看实际连接了哪些 datasources。 |
服务器拒绝 push | 该操作运行了 validator(硬性门槛)。请修复它报告的问题(通常是分支中缺少 datasource ref——调用 schema-explorer/datasource-creator),然后再次 push。 |
push 因 DXS-NG-047 失败(datasource connection 预检) | CAC 使用的 datasource 在分支中缺失,或者其 apiSettingName 指向了分支中未定义的 API connection setting——即使预览渲染正常,Studio 仍会报告此问题(mock 不会访问 connections)。请针对此分支重新生成 datasource(dxs datasource generate 会自动解析该 setting),或先在 Studio 中连接对应的 connection;只有在有意仅使用 mock 开发时,才使用 --skip-connection-check。请参阅 Phase 5。 |
将 preview 成功显示为绿色视为 datasource 连接在 Studio 中正常工作的证明 | 预览数据来自 mocks/——harness 不会访问 API connection,因此损坏的 apiSettingName 连接在 Studio(或 push 预检)报告之前不会显现。push 上的 DXS-NG-047 门槛才是可靠的检查;不要轻易绕过。 |
push 在任何网络请求发出前就在本地失败 | 某个 region 哨兵标记已损坏。请准确恢复 //#region __COMPONENT_TYPES__/__COMPONENT_BODY__ 标记,或重新 pull 并重新应用编辑。 |
pull 返回的 mocks/ 为空且没有 manifest.datasources(正在编辑现有 CAC) | 这是预期行为——有三项内容不会往返:manifest.datasources、mocks/、node_modules。请重新添加 datasources(使用对象而非字符串),重新填充 mocks/(运行 data generate 并填写),让 preview 重新安装。两个 regions 和 .html/.scss 均可正常往返。请参阅 Phase 2。 |
手动删除工作文件夹(或终止开发服务器进程)以绕过 pull 的文件夹已存在错误 | 使用 flags,而非手动清理:preview --refresh 会保留本地工作;pull --force 会丢弃本地工作,并自行停止正在运行的开发服务器(通过身份检查的 lock kill)。残留的锁定文件错误会以结构化的 DXS-NG-049 报告,而非原始 WinError。 |
预览结束后手动读取 .dxs-serve.lock 并用 taskkill 终止开发服务器 | 这是 stop 命令出现之前的变通方法。dxs ng stop <folder> 是用于清理的命令:通过身份检查终止进程树 + teardown agent-browser session + 移除 lock,可重复执行(没有正在运行的服务时返回 stopped: false)。完整生命周期由 CLI 管理:替换时 pull --force 会清理,preview --clean 会重置,stop 会清理。 |
将 manifest.datasources 条目写成裸 ref 字符串 | 条目必须是 ManifestDatasourceRef 对象:{ "name": "<ref>", "ref": "<ref>" }。裸字符串会导致下一条 dxs ng 命令(data generate、preview、push)中的 manifest 验证失败。 |
push 在 .../config/<ref>/lock 处因 DXS-API-TIMEOUT 失败(约 600 秒) | 不一定是卡住或 stale lock:在调试器下运行 API 的开发人员可能暂停在 lock/upsert 路径的断点处,或者 token 在调用过程中失效。请继续执行断点后的操作(或重新运行 dxs auth login),然后重试 push。 |
dxs ng data generate 留下了 $frontendFlows ref,或内嵌 componentRef selector 的 datasource 没有 mock key | generator 不会为所有 key 生成初始值:$frontendFlows refs 完全不会生成;如果生成期间分支解析失败,它也会静默跳过 componentRef selector 对应的 datasource(不会报错)。生成后,请打开 mocks/harness-mocks.json,手动添加所有缺失的 key。 |
为 $frontendFlows ref 填入 mock 值,并期望预览使用该值 | $frontendFlows 会在 harness 中作为真实的、在客户端计算的代码运行——永远不会被 mock。预览始终显示 flow 实际计算的结果;针对 frontendFlow key 的 mock 条目不会生效。 |
全页面/仪表板 CAC 的 render.png 只显示了页面上半部分 | 平台 shell 强制设置 html, body { overflow: hidden },因此 preview 的截图最多只覆盖一个 viewport(通常约为 569px)——无论内容多高,它都无法越过你自己的内部 overflow-y: auto 容器。这是平台 shell 的限制,并非布局错误。若要验证首个 viewport 之外的内容,请直接使用 agent-browser 访问 harness 提供服务的端口,并设置更高的 viewport,而不要只依赖 render.png。 |
使用 dxs source explore configs/trace 确认 CAC 是否存在或追踪其引用 | 这两个命令都不会索引 type-36 组件——它们的 type filters 或输出中没有 CAC/customangularcomponent 类别。请使用 dxs ng list -b <branch> 确认组件是否存在;使用 dxs configuration get customangularcomponent <id> -b <branch> 或直接读取 manifest/harness source,追踪声明的 datasource/flow/componentRefs。 |
声明名为 refresh / $refreshEvent / outParamsChange 的 outParam 或 @Output,或者在 body 中重新声明两个生成的 @Output | 这些名称为保留名称——平台会在每个 CAC 上生成这些成员(这是 tab-content contract,使 CAC 能充当 hub/editor/card/dashboard tab);名称冲突会导致重复成员编译错误。例外情况是 body 中的 refresh() 方法——这是获准的覆盖方式;它会替换生成的默认实现(该默认实现会重新运行 ngOnInit)。 |
| CAC 的价值在于定制化视觉效果——将预览截图视为验收测试,并在推送前使其与目标效果一致。 |