TREA skills
TREA
一.简介
中文官网:https://docs.trae.cn/
TRAE是字节跳动旗下的一款AI编程工具,定位为“超级AI开发工程师”
TRAE不仅仅是一个简单的代码补全工具,它通过提供两种核心工作模式,深度融入了开发流程:
IDE模式:在你熟悉的编码流程中,通过智能代码补全(Cue功能)等方式,提供高采纳率的编码建议,让你在保留完全控制感的同时提升效率。
SOLO模式:这是一种高度自动化的开发方式。AI能够理解你的目标,自主规划任务、调度工具,独立完成从构思到可执行产出的端到端开发任务。在此模式下,你的角色从“写代码的人”转变为“指挥AI的
二. 技能
-
定义:被视为提供给智能体的一套 “专业能力说明书”(类似用户手册或操作指南)。在执行任务时,智能体可以按需加载相应的技能,从而增强其对任务的理解与执行能力。
-
特点
-
结构化
一个技能对应一个 SKILL.md 文件,文件中以结构化的方式描述完成某一类任务所需的信息,例如:任务目标与适用场景;关键约束与注意事项;推荐流程或操作步骤;可选的脚本、模板或示例。
-
动态按需加载
智能体不会在任务开始时一次性读取所有技能的完整内容。在执行任务前,智能体会先扫描所有技能的简要描述,仅当判断当前任务与某个技能高度相关时,才会加载该技能的详细内容。这种按需加载机制可以有效减少上下文中的 Token 消耗、避免无关信息干扰智能体的决策。
- 使用场景
- 保证输出结果的一致性与规范性
需要智能体在不同时间、不同任务中,始终按照既定标准输出结果。例如,将统一设计规范、执行团队标准、保持品牌一致性或确保代码符合项目约定等要求封装为技能,从而将隐性的个人或团队标准转化为显式、可复用的专业能力,最终使输出结果更加稳定、可控。 - 自动化重复性工作流
需要频繁执行相同或高度相似的多步骤任务。例如,对于测试流程、代码规范检查、常规数据分析等难以避免的日常工作,可以将既有的 SOP 封装为技能。一旦相关任务被触发,智能体即可自动按照定义好的流程执行,从而减少重复的指令输入,提升效率。 - 总结与共享专业能力
总结个人经验或团队规范,并在更大范围内复用。例如,将技能在社区、交流群等公共平台进行分享,从而在不同的智能体、项目、团队间复用相同的技能。
- 技能类型
- 全局技能 – 跨项目全局生效的技能,~/.trae-cn/skills
- 项目技能 – 仅在当前项目生效的技能, 相关文件位于 .trae/skills/ 目录。
- 创建技能
5.1 通过对话,由 AI 自动创建技能
帮我在 ./trae/skills 目录下创建一个新的技能
技能的名字叫 create-router-component
这个技能可以帮我做以下事情:
- 在指定文件夹下的view 文件夹下面新建一个文件夹,以需要创建的组件名命名
- 在生成的文件夹下面,新建index.vue 文件
- index文件的内容是标准的vue文件,里面有data,method,created
- 生成的index.vue 中引入src/components/custom/HisignTableModel组件,并使用
- 给HisignTableModel组件传一下值:传title为组件名;reduceHeight:230;act:”“;sys: "", config, tableConfig,tableColumns,actionBtns
- 在组件的data中添加config, tableConfig,tableColumns,actionBtns;
- 如果描述中操作按钮有添加,则在config.button 中加入{title: '新增', type: "primary", icon:'iconfont icon-add', callback: () => {this.add()},在method中添加add方法
- 如果描述中操作按钮有导出按钮,则在config.button 中加入{title: "导出数据", type: "default", icon: "iconfont icon-file-upload fs20 tran-X-2", export:true, act: ""},然后再引入src/components/custom/HisignFileExport组件,并使用
- 如果描述中操作按钮有导入按钮,则在config.button 中加入{title: "导入数据", type: 'primary', isCustomIcon: true, icon: 'iconfont icon-add', callback: () => {this.importFile()}}},在method中添加importFile方法, src/components/custom/HisignFileImport组件,并使用,给HisignFileImport组件绑定v-model="importVb",:config="importCfg",在data中添加importVb: false, importCfg
- 如果描述中操作有批量删除按钮,则在config.button 中加入{title: "批量删除", type: 'default', icon: 'iconfont icon-delete fs20 tran-X-2', callback: () => {this.batchDel()}},在method中添加batchDel 方法, 在data中添加checkedListData: []
- 如果描述中列表操作栏有删除按钮,则引入src/components/custom/HisignPromptDialog组件,并使用 <HisignPromptDialog v-model="delVb" :promptText="promptText" @on-sure="sureDel" />,在data中添加delVb:false,promptText: ["是否确定删除?", "是否确定删除?"],在actionBtns中添加{type: 'error', icon: 'iconfont icon-delete fs14', iconStyle: {transform: 'scale(1.2)'}, txt: '删除', cb: () => {this.del()}},在method中添加sureDel,del方法
-如果描述中添加查询条件,则在config.simpleForm 中添加{property: "", type: "text", span: 3, placeholder: ""},property动态生成英文字段,placeholder为添加的查询条件名称;有多个查询条件则在simpleForm 添加多个;如果有添加事件查询条件,则在config.simpleForm 中添加{property: [], type: "dayrange", span: 3, placeholder: ""},property的第一个元素以start开头,第二个元素以end开头
-根据描述中列表表头 在tableColumns动态添加{title: "", key: "", minWidth: 140}, tableColumns中第一个元素是{type: 'index', title: "序号", width: 65},最后一个元素是{title: "操作", key: "action", width: 200, slot: "action", className: "table-btns", fixed: 'right'}
- 如果描述中列表操作栏有编辑按钮,在actionBtns中添加{type: 'primary', icon: 'iconfont icon-qianbi fs14', iconStyle: {transform: 'scale(1.2)'}, txt: '修改', cb: () => {this.edit()}},在method中添加edit方法
- 在指定文件夹下的router文件中添加modules文件夹,
- 在modules文件夹新增 路由文件, 以需要创建的组件名命名,并在指定文件夹下的router/index.js中引入该文件
5.2 在./trae/skills文件夹下
index.js
const fs = require('fs');
const path = require('path');
module.exports = {
name: 'create-router-component',
description: '创建带有路由的Vue组件',
parameters: [
{
name: 'componentName',
type: 'string',
required: true,
description: '组件名称'
},
{
name: 'targetDir',
type: 'string',
required: true,
description: '目标目录(相对于项目根目录)'
},
{
name: 'description',
type: 'string',
required: false,
description: '组件描述,包含操作按钮、查询条件、列表表头和操作栏等信息'
}
],
async execute(params, context) {
const { componentName, targetDir, description = '' } = params;
const projectRoot = context.workspaceRoot;
// 构建组件路径
const viewDir = path.join(projectRoot, targetDir, 'view');
const componentDir = path.join(viewDir, componentName);
const indexVuePath = path.join(componentDir, 'index.vue');
// 确保目标目录存在
if (!fs.existsSync(viewDir)) {
fs.mkdirSync(viewDir, { recursive: true });
}
// 确保组件目录存在
if (!fs.existsSync(componentDir)) {
fs.mkdirSync(componentDir, { recursive: true });
}
// 解析描述,提取操作按钮、查询条件、列表表头和操作栏信息
const hasAddButton = description.includes('添加');
const hasExportButton = description.includes('导出');
const hasImportButton = description.includes('导入');
const hasBatchDeleteButton = description.includes('批量删除');
const hasDeleteButton = description.includes('删除按钮');
const hasEditButton = description.includes('编辑按钮');
const hasQueryConditions = description.includes('查询条件');
const hasDateRange = description.includes('时间查询条件');
const hasSort = description.includes('排序');
const hasSortColumn = description.includes('列表表头有排序');
// 提取查询条件名称
const queryConditions = [];
// 提取列表表头
const tableHeaders = [];
// 生成导入语句
let importStatements = 'import HisignTableModel from \'@/components/custom/HisignTableModel\';';
if (hasImportButton) {
importStatements += '\nimport HisignFileImport from \'@/components/custom/HisignFileImport\';';
}
if (hasDeleteButton) {
importStatements += '\nimport HisignPromptDialog from \'@/components/custom/HisignPromptDialog\';';
}
// 生成组件注册
let components = 'HisignTableModel';
if (hasImportButton) {
components += ', HisignFileImport';
}
if (hasDeleteButton) {
components += ', HisignPromptDialog';
}
// 生成配置对象
let config = '{' +
'\n button: [';
// 添加按钮
if (hasAddButton) {
config += '\n {title: \'新增\', type: "primary", icon:\'iconfont icon-add\', callback: () => {this.add()}},';
}
if (hasExportButton) {
config += '\n {title: "导出数据", type: "default", icon: "iconfont icon-file-upload fs20 tran-X-2", export:true, act: ""},';
}
if (hasImportButton) {
config += '\n {title: "导入数据", type: \'primary\', isCustomIcon: true, icon: \'iconfont icon-add\', callback: () => {this.importFile()}},';
}
if (hasBatchDeleteButton) {
config += '\n {title: "批量删除", type: \'default\', icon: \'iconfont icon-delete fs20 tran-X-2\', callback: () => {this.batchDel()}},';
}
// 添加查询条件
if (hasQueryConditions) {
config += '\n ],\n simpleForm: [';
queryConditions.forEach((condition, index) => {
const property = condition.toLowerCase().replace(/\s+/g, '');
if (hasDateRange) {
config += '\n {property: ["start"' + property + '"Date", "end"' + property + '"Date"], type: "dayrange", span: 3, placeholder: "' + condition + '"},';
} else {
config += '\n {property: "' + property + '", type: "text", span: 3, placeholder: "' + condition + '"},';
}
});
}
config += '\n ]\n }';
// 生成操作按钮
let actionBtns = '[';
if (hasEditButton) {
actionBtns += '\n {type: \'primary\', icon: \'iconfont icon-qianbi fs14\', iconStyle: {transform: \'scale(1.2)\'}, txt: \'修改\', cb: () => {this.edit()}},';
}
if (hasDeleteButton) {
actionBtns += '\n {type: \'error\', icon: \'iconfont icon-delete fs14\', iconStyle: {transform: \'scale(1.2)\'}, txt: \'删除\', cb: () => {this.del()}},';
}
actionBtns += '\n ]';
// 生成表格列
let tableColumns = '[' +
'\n {type: \'index\', title: "序号", width: 65},';
// 添加排序列
if (hasSort || hasSortColumn) {
tableColumns += '\n {title: "排序", width: 80, render: (h, params) => {\n return h("div", {class: "drag-handle"}, [\n h("Icon", {props: {type: \'md-menu\', size: 20, color: \'#515a6e\'}})\n ])\n }},';
}
tableHeaders.forEach(header => {
tableColumns += '\n {title: "' + header.title + '", key: "' + header.key + '", minWidth: 140},';
});
tableColumns += '\n {title: "操作", key: "action", width: 200, slot: "action", className: "table-btns", fixed: \'right\'}\n ]';
// 生成 tableConfig
let tableConfig = '{\n pageSelection: true';
if (hasSort || hasSortColumn) {
tableConfig += ',\n dragSort: true,\n rowKey: "id"';
}
tableConfig += '\n }';
// 生成 data 部分
let data = '{' +
'\n config: ' + config + ','+
'\n tableConfig: ' + tableConfig + ','+
'\n tableColumns: ' + tableColumns + ',' +
'\n actionBtns: ' + actionBtns + ','
if (hasImportButton) {
data += '\n importVb: false,\n importCfg: {\n uploadAct: "",\n systemId: "",\n tplAct: "",\n importAct: "",\n tip: "导入过程中如发现必填项未填写,则这个无法导入。",\n dialogWidth: 1000,\n columns: [\n {title: "序号", type: "index", width: 65},\n ],\n completed: () => {\n this.doSearch();\n },\n },';
}
if (hasBatchDeleteButton) {
data += '\n checkedListData: [],\n delIds: [] ,';
}
if (hasDeleteButton) {
data += '\n delVb: false,\n promptText: ["是否确定删除?", "是否确定删除?"] ,';
}
data += '\n // 其他数据\n }'
// 生成方法部分
let methods = '{' +
'\n doSearch() {\n // 查询\n },';
if (hasAddButton) {
methods += '\n add() {\n // 新增逻辑\n },';
}
if (hasImportButton) {
methods += '\n importFile() {\n this.importVb = true;\n },';
}
if (hasBatchDeleteButton) {
methods += '\n batchDel() {\n if (this.checkedListData.length == 0) {\n this.$Message.error({content: "请勾选任务", backgroud: true});\n return;\n }\n this.delVb = true;\n this.delIds = this.checkedListData.map(v => v.id);\n },';
}
if (hasDeleteButton) {
methods += '\n del() {\n this.delVb = true;\n },\n sureDel() {\n // 删除确认逻辑\n this.delVb = false;\n },';
}
if (hasEditButton) {
methods += '\n edit() {\n // 编辑逻辑\n },';
}
methods += '\n // 其他方法\n }';
// 生成模板部分
let template = '<template>\n <div>\n <HisignTableModel \n ref="tableModel"\n :title="\'' + componentName + '\'"\n reduceHeight="230"\n :act="\'\'"\n :sys="\'\'"\n :config="config"\n :tableConfig="tableConfig"\n :tableColumns="tableColumns"\n :actionBtns="actionBtns"\n />';
if (hasImportButton) {
template += '\n <HisignFileImport v-model="importVb" :config="importCfg" />';
}
if (hasDeleteButton) {
template += '\n <HisignPromptDialog v-model="delVb" :promptText="promptText" @on-sure="sureDel" />';
}
template += '\n </div>\n</template>';
// 生成完整的 Vue 文件内容
const vueContent = template + '\n\n<script>\n' + importStatements + '\nexport default {\n name: \'' + componentName + '\',\n components: {\n ' + components + '\n },\n data() {\n return ' + data + ';\n },\n methods: ' + methods + ',\n created() {\n // 创建时执行\n }\n};\n</script>\n\n<style scoped>\n/* 样式 */\n</style>';
// 写入 index.vue 文件
fs.writeFileSync(indexVuePath, vueContent);
// 构建路由路径
const routerDir = path.join(projectRoot, targetDir, 'router');
const modulesDir = path.join(routerDir, 'modules');
const routeFilePath = path.join(modulesDir, `${componentName}.js`);
const routerIndexPath = path.join(routerDir, 'index.js');
// 确保 modules 目录存在
if (!fs.existsSync(modulesDir)) {
fs.mkdirSync(modulesDir, { recursive: true });
}
// 生成路由模块文件
const routeFileContent = `export default [\n {\n path: '/${componentName}',\n name: '${componentName}',\n component: () => import('../../view/${componentName}/index.vue')\n }\n];`;
// 写入路由模块文件
fs.writeFileSync(routeFilePath, routeFileContent);
// 检查路由 index.js 文件是否存在
if (fs.existsSync(routerIndexPath)) {
// 读取现有路由文件内容
let routerContent = fs.readFileSync(routerIndexPath, 'utf8');
// 检查是否已经导入了该模块
const importStatement = `import ${componentName}Routes from './modules/${componentName}';`;
// 如果没有导入,则添加导入语句
if (!routerContent.includes(importStatement)) {
// 找到导入区域的位置
const importEndIndex = routerContent.lastIndexOf('import');
if (importEndIndex !== -1) {
// 找到该导入语句的结束位置
const lineEndIndex = routerContent.indexOf(';', importEndIndex) + 1;
if (lineEndIndex !== -1) {
// 在导入语句后添加新的导入
routerContent = routerContent.substring(0, lineEndIndex) + '\n' + importStatement + routerContent.substring(lineEndIndex);
}
} else {
// 如果没有任何导入语句,则在文件开头添加
routerContent = importStatement + '\n' + routerContent;
}
}
// 找到 routes 数组的位置并插入新路由
if (routerContent.includes('routes: [')) {
// 找到 routes 数组的结束位置
const routesStartIndex = routerContent.indexOf('routes: [');
const routesEndIndex = findMatchingBracket(routerContent, routesStartIndex + 8);
if (routesEndIndex !== -1) {
// 检查是否已经包含该路由
if (!routerContent.includes(`${componentName}Routes`)) {
// 检查是否需要添加逗号
const beforeEnd = routerContent.substring(routesStartIndex + 8, routesEndIndex).trim();
const comma = beforeEnd ? ', ' : '';
// 插入新路由
const newRouterContent = routerContent.substring(0, routesEndIndex) +
comma + `${componentName}Routes` +
routerContent.substring(routesEndIndex);
// 写入更新后的路由文件
fs.writeFileSync(routerIndexPath, newRouterContent);
}
}
}
}
return {
success: true,
message: `组件 ${componentName} 创建成功,路由已添加`
};
}
};
// 辅助函数:查找匹配的括号
function findMatchingBracket(str, startIndex) {
let count = 1;
for (let i = startIndex; i < str.length; i++) {
if (str[i] === '[') {
count++;
} else if (str[i] === ']') {
count--;
if (count === 0) {
return i;
}
}
}
return -1;
}
package.json
{
"name": "create-router-component",
"version": "1.0.0",
"description": "创建带有路由的Vue组件",
"main": "index.js",
"trae": {
"type": "skill",
"displayName": "创建路由组件",
"description": "在指定文件夹下创建带有路由的Vue组件",
"parameters": [
{
"name": "componentName",
"type": "string",
"required": true,
"description": "组件名称"
},
{
"name": "targetDir",
"type": "string",
"required": true,
"description": "目标目录(相对于项目根目录)"
},
{
"name": "description",
"type": "string",
"required": false,
"description": "组件描述,包含操作按钮、查询条件、列表表头和操作栏等信息"
}
]
},
"keywords": [
"trae",
"skill",
"vue",
"router",
"component"
],
"author": "",
"license": "MIT"
}
-
使用
在src\projects\xzsp-vue生成 库存管理 路由组件,有导出,导入,添加操作按钮,有耗材名称,品牌,编号查询条件,列表表头有排序,保管部门,耗材名称,品牌,型号,性状,数量,单位,列表操作栏有编辑按钮
-
视图

更多推荐




所有评论(0)