folder 与 tag API:文件夹与标签的增删改查
文件夹和标签是素材库的两套组织系统:文件夹表达「归属」(树形、互斥),标签表达「属性」(扁平、可多选)。两套 API 的设计风格很像,但能力分布很不一样,这一节把差异讲清楚。
folder:树形结构
创建
// 创建顶层文件夹
let newFolder = await eagle.folder.create({
name: 'New Folder',
description: 'Folder\'s description.',
});
// 创建子文件夹(显式版)
let parentFolder = await eagle.folder.getById('folder_id');
let subFolder = await eagle.folder.createSubfolder(parentFolder.id, {
name: 'Subfolder',
description: 'Subfolder description.',
});
// 创建时直接指定父级(简写版)
let another = await eagle.folder.create({
name: 'Nested',
parent: 'parent_folder_id'
});
create() 的 parent 参数等价于 createSubfolder(parentId, options)。功能上没差别,但可读性上:明确要建子目录时用 createSubfolder,能让读代码的人一眼看出层级意图。
查询
let byIds = await eagle.folder.get({ ids: ['folder_id1', 'folder_id2'] });
let selected = await eagle.folder.get({ isSelected: true });
let recent = await eagle.folder.get({ isRecent: true });
let all = await eagle.folder.getAll();
let one = await eagle.folder.getById('folder_id');
let some = await eagle.folder.getByIds(['folder_id1', 'folder_id2']);
let current = await eagle.folder.getSelected();
let recents = await eagle.folder.getRecents();
查询条件只有 id、ids、isSelected、isRecent 四项——比 item 的 get() 简单得多。文件夹本身没有标签、评分这类元数据,可筛选的维度就那么几个。
修改与移动
let folder = await eagle.folder.getById('folder_id');
folder.name = 'New Folder Name';
folder.description = 'New description...';
folder.iconColor = eagle.folder.IconColor.Blue;
await folder.save();
改 parent 属性就是移动文件夹:
// 移到另一个父文件夹下
folder.parent = 'parent_folder_id';
await folder.save();
// 移到根目录
folder.parent = null;
await folder.save();
移动文件夹为什么不用 fs.rename?因为文件夹在 Eagle 里不只是磁盘上的目录,它的 id 被所有素材的 folders 数组引用着。直接移动磁盘目录,Eagle 的索引和实际路径就对不上了。改 parent 让主应用去处理,它才知道要连带更新哪些素材记录。
parent 和 iconColor 两项在 Eagle 4.0 build12 之前是只读的,从 build12 开始支持修改。
children 是只读的,要给文件夹加子级必须用 createSubfolder,不能 folder.children.push(...)。
图标颜色常量
eagle.folder.IconColor.Red // 'red'
eagle.folder.IconColor.Orange // 'orange'
eagle.folder.IconColor.Yellow // 'yellow'
eagle.folder.IconColor.Green // 'green'
eagle.folder.IconColor.Aqua // 'aqua'
eagle.folder.IconColor.Blue // 'blue'
eagle.folder.IconColor.Purple // 'purple'
eagle.folder.IconColor.Pink // 'pink'
这八个常量也可以直接写字符串 'red',但官方建议用常量,理由是能获得更好的代码提示和类型安全——写错 eagle.folder.IconColor.R 时编辑器会立刻提示,而不是等运行时报一个无效颜色。
tag:扁平标签
查询
const all = await eagle.tag.get(); // 全部标签
const design = await eagle.tag.get({ name: "design" }); // 按名称模糊搜索,不区分大小写
const recents = await eagle.tag.getRecentTags(); // 最近使用
const starred = await eagle.tag.getStarredTags(); // 常用(收藏)标签
get() 的 options 是可选的,不传就返回全部。name 参数做的是模糊匹配且不区分大小写——查 "design" 会把 Design、design-works 都捞出来。做「精确查找某个名字的标签」时,要在结果里自己再过滤一次:
const tags = await eagle.tag.get({ name: "design" });
const exact = tags.filter(t => t.name === 'design');
getStarredTags() 需要 Eagle 4.0 build18 以上。
重命名与合并
// 重命名:改 name 然后 save,所有用到该标签的素材自动跟着更新
const tags = await eagle.tag.get();
const tag = tags.find(t => t.name === 'old-name');
tag.name = 'new-name';
await tag.save();
// 合并:把来源标签并入目标标签,来源标签消失
const result = await eagle.tag.merge({
source: 'UI Design',
target: 'UI'
});
console.log(`已合并 ${result.affectedItems} 个素材的标签`);
merge() 返回一个对象,含 affectedItems(受影响的素材数量)和 sourceRemoved(来源标签是否已移除)两个字段。
merge() 是不可逆的。 官方明确警告:合并操作会更新所有使用来源标签的素材、标签群组、收藏标签和历史标签。做整理类功能时,UI 上必须让用户二次确认。
Tag 实例属性
name 可写(改完要 save());count、groups、pinyin 都是只读,分别对应该标签的素材数量、所属分组、名称拼音(搜索排序用)。color 属性可以读取标签颜色。
save() 目前只支持修改标签名称这一件事。标签颜色在 Eagle 主界面里可以点选设置,但 API 没有开放对应的写入方法——这是个明显的能力缺口。
tagGroup:给标签分组
标签一多,检索就成了灾难。标签群组就是为此设计的:
// 创建群组
await eagle.tagGroup.create({
name: "new group",
color: "red",
tags: ["tag1", "tag2"],
description: "群组描述" // Eagle 4.0 build18+
});
// 读取全部群组
const tagGroups = await eagle.tagGroup.get();
// 修改群组
const group = tagGroups[0];
group.name = "new name";
group.color = "red"; // red, orange, yellow, green, aqua, blue, purple, pink
group.tags = ["tag1", "tag2"];
group.description = "群组描述";
await group.save();
// 移除群组
await group.remove();
addTags() 和 removeTags() 是增量操作,比「取出完整数组、改、再整体保存」安全得多:
// 只添加,允许标签同时存在于多个群组
await group.addTags({ tags: ['UI', 'UX', 'Typography'] });
// 移动:从原群组移除后再添加
await group.addTags({
tags: ['Branding'],
removeFromSource: true
});
// 从群组移除指定标签
await group.removeTags({ tags: ['Outdated', 'Draft'] });
removeFromSource 这个参数的设计很实用:false 时一个标签可以同时属于多个群组(像多维分类),true 时是移动(标签只有归属一个群组,像文件夹)。
⚠️ removeTags() 只从群组移除标签,不会删除标签本身,也不会影响素材上的标签。 官方特别强调过这一点——很多人会误以为从这里移除等于删标签。
组织策略:什么时候用哪个
- 表达归属关系(这张图属于哪个项目)→ 用文件夹。文件夹树是唯一的,一个素材在一个文件夹里。建目录层级用
folder.create()加parent。 - 表达属性特征(横版、已审、需二次处理)→ 用标签。标签可以多选,一个素材可以有任意多个。
- 标签多到难以浏览 → 用
tagGroup分组,或者用eagle.smartFolder建智能文件夹(按条件自动归类,无需手动打标)。
一个实用模式是「文件夹放项目,标签放状态」:每个项目一个文件夹,文件夹内素材统一打上「已交付」「待修改」这类标签。这样加一个新项目不会污染标签体系。
开发流程
- 先确认素材组织需求是「归属」还是「属性」,决定用 folder 还是 tag。
- 建目录结构时逐层调用
folder.create()并传parent,或者先建父级再用createSubfolder。 - 批量归档素材时,读出素材改
folders或tags,逐个save()。 - 清理标签体系前,先用
tag.merge()合并近义标签,UI 上必须二次确认。 - 标签数量超过三十个就开始考虑
tagGroup分组。 - 任何删除或合并操作都用
showMessageBox让用户确认影响范围。
常见坑
folder.create()忘了传name。name是唯一必填字段,漏了会创建失败。description才是可选的。用
children数组增删子文件夹。children是只读的,直接 push 不生效。用createSubfolder创建,移动用改parent。延伸注意: * 指望
tag.save()改颜色。save()目前只支持改名称。标签颜色在 API 层面没有写入方法,只能通过主界面操作。 * 用children数组增删子文件夹。children是只读的。创建用createSubfolder,移动用改parent。整理人:WorkBuddy
