一文搞定 AML 操作方法:从查询到创建的完整指南
在企业级 PLM 系统中,AML(SCSAI Markup Language)是实现自动化和集成操作的核心工具。无论你是刚接触 SCSAI 平台的新手,还是希望提升操作效率的开发者,掌握 AML 的标准化写法都能让你事半功倍。本文将从基础格式讲起,配合实际模板代码,帮你快速上手 AML 的增删改查操作。
一、AML 基础:先看懂骨架
AML 本质是一种基于 XML 的声明式语言,通过定义 节点来指定操作对象和动作。标准格式如下:
<AML>
<Item type="[对象类型]" action="[操作类型]" [属性]>
<!-- 对象属性 -->
</Item>
</AML>
关键字段说明:
type:要操作的对象类型,如ECR、Part、Vendor等action:操作类型,支持以下四种:
| 操作 | 说明 | 典型场景 |
|------|------|----------|
| get | 查询 | 获取对象列表或单个对象详情 |
| add | 创建 | 新增一条 ECR、Part 等 |
| edit | 编辑 | 修改对象的部分属性 |
| delete | 删除 | 根据 ID 删除对象 |
所有 AML 指令都需要包裹在 根节点中,一个请求可包含��个 操作。
二、实战模板:四类操作代码详解
接下来我们按操作类型拆解实际代码,所有模板均来自项目中的 /app/lib/aml/ 目录。你将看到如何用最少的代码实现常用业务逻辑。
2.1 查询操作(get)
查询是最频繁的操作。通常我们会封装成一个函数,接受过滤参数并返回完整的 AML 字符串。
文件位置:/app/lib/aml/queries.ts
export const queryTemplates = {
// 查询所有 ECR,可选按状态过滤
ecrList: (status?: string) => `
<AML>
<Item type="ECR" action="get" select="id,change_number,title,description,status,created_by,created_on">
${status ? `<status>${status}</status>` : ''}
</Item>
</AML>
`,
// 根据 ID 查询单个 ECR
ecrById: (id: string) => `
<AML>
<Item type="ECR" action="get" id="${id}" select="id,change_number,title,description,status,created_by,created_on">
</Item>
</AML>
`,
// 查询 Part 列表,可按部件号过滤
partList: (partNumber?: string) => `
<AML>
<Item type="Part" action="get" select="id,part_number,name,description,unit_cost,weight">
${partNumber ? `<part_number>${partNumber}</part_number>` : ''}
</Item>
</AML>
`,
// 查询所有供应商
vendorList: () => `
<AML>
<Item type="Vendor" action="get" select="id,name,contact,phone,email,address">
</Item>
</AML>
`,
// 查询 BOM 清单,可按父零件 ID 过滤
bomList: (partId?: string) => `
<AML>
<Item type="BOM" action="get" select="id,part_id,item_id,quantity,unit">
${partId ? `<part_id>${partId}</part_id>` : ''}
</Item>
</AML>
`,
};
要点: select 属性指定返回的字段,可有效减少传输数据量。条件字段直接作为子标签传入。
2.2 创建操作(add)
创建新对象时,需要提供所有必填字段。注意用 包裹可能包含特殊字符的文本内容,避免 XML 解析错误。
文件位置:/app/lib/aml/creates.ts
export const createTemplates = {
// 创建 ECR:必填项 change_number、title、description,默认状态为 new
ecr: (data: { changeNumber: string; title: string; description: string }) => `
<AML>
<Item type="ECR" action="add">
<change_number>${data.changeNumber}</change_number>
<title><![CDATA[${data.title}]]></title>
<description><![CDATA[${data.description}]]></description>
<status>new</status>
</Item>
</AML>
`,
// 创建 Part:必填 part_number、name;可选描述、单价、重量
part: (data: { partNumber: string; name: string; description?: string; unitCost?: number; weight?: number }) => `
<AML>
<Item type="Part" action="add">
<part_number>${data.partNumber}</part_number>
<name><![CDATA[${data.name}]]></name>
${data.description ? `<description><![CDATA[${data.description}]]></description>` : ''}
${data.unitCost ? `<unit_cost>${data.unitCost}</unit_cost>` : ''}
${data.weight ? `<weight>${data.weight}</weight>` : ''}
</Item>
</AML>
`,
// 创建供应商:必填 name;可选联系人、电话、邮箱、地址
vendor: (data: { name: string; contact?: string; phone?: string; email?: string; address?: string }) => `
<AML>
<Item type="Vendor" action="add">
<name><![CDATA[${data.name}]]></name>
${data.contact ? `<contact><![CDATA[${data.contact}]]></contact>` : ''}
${data.phone ? `<phone>${data.phone}</phone>` : ''}
${data.email ? `<email>${data.email}</email>` : ''}
${data.address ? `<address><![CDATA[${data.address}]]></address>` : ''}
</Item>
</AML>
`,
// 创建 BOM 行:必填 part_id(父零件)、item_id(子零件)、quantity;可选单位
bom: (data: { partId: string; itemId: string; quantity: number; unit?: string }) => `
<AML>
<Item type="BOM" action="add">
<part_id>${data.partId}</part_id>
<item_id>${data.itemId}</item_id>
<quantity>${data.quantity}</quantity>
${data.unit ? `<unit>${data.unit}</unit>` : ''}
</Item>
</AML>
`,
};
注意: 创建时系统会自动生成 id,因此不需要在 AML 中指定。
2.3 编辑操作(edit)
编辑时通过 id 定位要修改的对象,只传需要变更的字段即可。
文件位置:/app/lib/aml/edits.ts
export const editTemplates = {
// 更新 ECR:可改状态和描述
ecr: (id: string, data: { status?: string; description?: string }) => `
<AML>
<Item type="ECR" action="edit" id="${id}">
${data.status ? `<status>${data.status}</status>` : ''}
${data.description ? `<description><![CDATA[${data.description}]]></description>` : ''}
</Item>
</AML>
`,
// 更新 Part:可改名称、描述、单价、重量
part: (id: string, data: { name?: string; description?: string; unitCost?: number; weight?: number }) => `
<AML>
<Item type="Part" action="edit" id="${id}">
${data.name ? `<name><![CDATA[${data.name}]]></name>` : ''}
${data.description ? `<description><![CDATA[${data.description}]]></description>` : ''}
${data.unitCost ? `<unit_cost>${data.unitCost}</unit_cost>` : ''}
${data.weight ? `<weight>${data.weight}</weight>` : ''}
</Item>
</AML>
`,
// 更新供应商:可改名称、联系人、电话、邮箱、地址
vendor: (id: string, data: { name?: string; contact?: string; phone?: string; email?: string; address?: string }) => `
<AML>
<Item type="Vendor" action="edit" id="${id}">
${data.name ? `<name><![CDATA[${data.name}]]></name>` : ''}
${data.contact ? `<contact><![CDATA[${data.contact}]]></contact>` : ''}
${data.phone ? `<phone>${data.phone}</phone>` : ''}
${data.email ? `<email>${data.email}</email>` : ''}
${data.address ? `<address><![CDATA[${data.address}]]></address>` : ''}
</Item>
</AML>
`,
};
2.4 删除操作(delete)
删除最简单,只需指定 action="delete" 和对象 id。
文件位置:/app/lib/aml/deletes.ts
export const deleteTemplates = {
ecr: (id: string) => `
<AML>
<Item type="ECR" action="delete" id="${id}">
</Item>
</AML>
`,
part: (id: string) => `
<AML>
<Item type="Part" action="delete" id="${id}">
</Item>
</AML>
`,
vendor: (id: string) => `
<AML>
<Item type="Vendor" action="delete" id="${id}">
</Item>
</AML>
`,
};
三、封装调用:让代码更优雅
在实际项目中,我们通常不会在业务代码中直接拼接 AML 字符串,而是通过统一的工具函数来执行并处理结果。例如下面的 executeAmlWithFallback 函数(位于 /app/lib/SCSAI/fallback.ts)支持主备地址切换,提升系统可用性。
import { executeAmlWithFallback } from '../SCSAI/fallback';
import { queryTemplates, createTemplates, editTemplates, deleteTemplates } from '../aml';
// 查询示例:获取所有状态为 "in_review" 的 ECR
const ecrQuery = queryTemplates.ecrList('in_review');
const ecrResult = await executeAmlWithFallback(ecrQuery);
// 创建示例:新增一个 Part
const partCreate = createTemplates.part({
partNumber: 'P001',
name: '电阻-10KΩ',
description: 'SMD 0805 10KΩ ±1%',
unitCost: 0.02,
});
const partResult = await executeAmlWithFallback(partCreate);
// 编辑示例:修改供应商手机号
const vendorEdit = editTemplates.vendor('12345', { phone: '18601921816' });
await executeAmlWithFallback(vendorEdit);
// 删除示例:删除一个 ECR
const ecrDelete = deleteTemplates.ecr('67890');
await executeAmlWithFallback(ecrDelete);
四、最佳实践总结
- 统一模板管理:将所有 AML 字符串放在独立的
.ts文件中,按操作类型分模块,便于维护和复用。 - 使用 CDATA:任何包含特殊字符(如
<、>、&)的文本字段,务必用包裹,否则会导致 XML 解析失败。 - 选择必要字段:查询时通过
select指定返回列,避免一次拉取过多数据。 - ���误处理:调用
executeAmlWithFallback后,需检查返回结果中的错误码或异常信息,确保操作成功。 - 参数化防注入:使用模板字符串动态传参时,确保参数是可信来源或经过转义,防止 AML 注入攻击(虽然 SCSAI 服务端已做处理,但前端仍应保持警惕)。
掌握以上模板和封装思路,你就能轻松实现 SCSAI 系统的自动化操作。无论是日常数据维护,还是集成开发,AML 都是你不可或缺的利器。希望这篇指南能帮你少走弯路,快速上手!
如需获取完整代码,欢迎在公众号后台回复“AML”获取项目示例。
BossAgents