这是一段J扣子工作流代码节点 avaScript代码,接收分组文案时间轴、单双行组等参数,按类型分单句/双行/推荐/书名轨道,处理时间信息,生成各轨道数据及画面提示词数组。
📝 提示词原文
累计复制 0 次
// 定义异步主函数main,接收参数对象{params}(无显式类型,简化写法),返回Promise包裹的输出结果
async function main({ params }) {
// 从参数中解构提取变量,设默认值避免报错:wenan_group_timeline(分组文案时间轴)、singleLineGroups(单行组)、keywordsList(关键词列表)、doubleLineGroups(双行组)
const {
wenan_group_timeline = [],
singleLineGroups = [],
keywordsList = [],
doubleLineGroups = []
} = params;
// 创建时间映射对象:键=文案内容,值={start, end}时间信息(方便快速查时间)
const timelineMap = {};
for (const { content, start, end } of wenan_group_timeline) {
timelineMap[content] = { start, end }; // 用文案内容当“钥匙”存时间
}
// 处理关键词列表:提取每个item的keywords字段,转成数组后用|拼接成字符串(如["A","B"]→"A|B")
const keywordArr = keywordsList.map(item => item.keywords);
const keywordStr = keywordArr.join('|');
// === 轨道1:单句字幕(处理单行组文案)===
const track_1_texts = []; // 存单句文案内容
const track_1_timelines = []; // 存单句时间{start,end}
const track_1_otherInfo = []; // 存单句样式(对齐、颜色等)
// 遍历单行组每个文案text
for (const text of singleLineGroups) {
const time = timelineMap[text]; // 从timelineMap查text的时间
if (!time) continue; // 没找到时间就跳过(不处理)
track_1_texts.push(text); // 加内容到轨道1文本
track_1_timelines.push(time); // 加时间到轨道1时间
track_1_otherInfo.push({ // 加样式:居中对齐、绿色、无偏移
alignment: 1, text_color: "#61862b", transform_x: 0, transform_y: 0
});
}
// === 轨道2/3:普通双行字幕(处理双行组文案)===
const track_2_texts = []; const track_2_timelines = []; const track_2_otherInfo = []; // 轨道2(双行上句)
const track_3_texts = []; const track_3_timelines = []; const track_3_otherInfo = []; // 轨道3(双行下句)
const track_4_texts = []; const track_4_timelines = []; const track_4_otherInfo = []; // 轨道4(推荐文案)
const track_5_texts = []; const track_5_timelines = []; const track_5_otherInfo = []; // 轨道5(书名文案)
const doubleLinePairs = []; // 存普通双行字幕配对(用于生成画面提示词)
// 遍历双行组(每个组含wenan数组,如["上句","下句"])
for (const { wenan } of doubleLineGroups) {
const [line1, line2] = wenan; // 拆成上句line1、下句line2
const time1 = timelineMap[line1]; // 查上句时间
const time2 = timelineMap[line2]; // 查下句时间
if (!time1 || !time2) continue; // 任一时间缺失则跳过
// 定义判断“书籍推荐文案”的关键词(推荐/孩子/读一读等短语)
const recommendPhrases = ['推荐', '强烈推荐', '建议', '安利', '一定要试试', '必须看看', '良心推荐', '超适合', '很适合', '值得一读', '分享', '别错过', '可以入手'];
const childrenPhrases = ['孩子', '宝贝', '小朋友', '宝宝', '小宝', '小孩', '娃', '娃娃', '儿童', '幼儿', '学龄前', '小男孩', '小女孩', '小弟弟', '小妹妹', '小公主', '小王子'];
const actionPhrases = ['读一读', '看一看', '读读看', '看看', '共读', '阅读'];
const unitPhrases = ['这套', '这一套', '这本', '这一册', '这册'];
// 判断line1是否为书籍推荐文案(用正则组合关键词)
function isBookRecommendation(line) {
const pattern = new RegExp( // 正则:推荐词+(陪/给)+孩子词+动作词+单位词(灵活匹配)
`(?:${recommendPhrases.join('|')}).*?(?:陪|给)?.*?(?:${childrenPhrases.join('|')})?.*?(?:${actionPhrases.join('|')}).{0,5}(?:${unitPhrases.join('|')})`
);
return pattern.test(line); // 匹配成功则返回true
}
if (isBookRecommendation(line1)) {
// 若为推荐文案:line1→轨道4(推荐),line2→轨道5(书名)
track_4_texts.push(line1); track_4_timelines.push(time1); track_4_otherInfo.push({ alignment:1, text_color:"#000000", transform_x:0, transform_y:100 });
track_5_texts.push(line2); track_5_timelines.push(time2); track_5_otherInfo.push({ alignment:1, text_color:"#db7431", transform_x:0, transform_y:-100 });
} else {
// 普通双行:line1→轨道2(上句),line2→轨道3(下句)
track_2_texts.push(line1); track_2_timelines.push({ start: time1.start, end: time1.end }); track_2_otherInfo.push({ alignment:1, text_color:"#61862b", transform_x:0, transform_y:140 });
track_3_texts.push(line2); track_3_timelines.push({ start: time2.start, end: time2.end }); track_3_otherInfo.push({ alignment:1, text_color:"#db7431", transform_x:0, transform_y:-140 });
doubleLinePairs.push({ line1: { text: line1, time: time1 }, line2: { text: line2, time: time2 } }); // 存配对用于画面提示词
}
}
// === 生成画面提示词数据(visualPromptGroups)===
const visualPromptGroups = [];
// 加单句字幕提示词(轨道1内容)
for (let i = 0; i < track_1_texts.length; i++) {
visualPromptGroups.push({ start: track_1_timelines[i].start, end: track_1_timelines[i].end, content: track_1_texts[i] });
}
// 加双行字幕提示词(普通双行配对,用\n分隔上下句)
for (const pair of doubleLinePairs) {
visualPromptGroups.push({ start: pair.line1.time.start, end: pair.line2.time.end, content: `${pair.line1.text}\n${pair.line2.text}` });
}
// 返回所有轨道数据+画面提示词
return {
track_1: { texts: track_1_texts, timelines: track_1_timelines, otherInfo: track_1_otherInfo, keywords: track_1_texts.map(() => keywordStr), keyword_color: "#db7431" },
track_2: { texts: track_2_texts, timelines: track_2_timelines, otherInfo: track_2_otherInfo },
track_3: { texts: track_3_texts, timelines: track_3_timelines, otherInfo: track_3_otherInfo },
track_4: { texts: track_4_texts, timelines: track_4_timelines, otherInfo: track_4_otherInfo },
track_5: { texts: track_5_texts, timelines: track_5_timelines, otherInfo: track_5_otherInfo },
visualPromptGroups // 画面提示词数组(含start/end/content)
};
}
async function main({ params }) {
// 从参数中解构提取变量,设默认值避免报错:wenan_group_timeline(分组文案时间轴)、singleLineGroups(单行组)、keywordsList(关键词列表)、doubleLineGroups(双行组)
const {
wenan_group_timeline = [],
singleLineGroups = [],
keywordsList = [],
doubleLineGroups = []
} = params;
// 创建时间映射对象:键=文案内容,值={start, end}时间信息(方便快速查时间)
const timelineMap = {};
for (const { content, start, end } of wenan_group_timeline) {
timelineMap[content] = { start, end }; // 用文案内容当“钥匙”存时间
}
// 处理关键词列表:提取每个item的keywords字段,转成数组后用|拼接成字符串(如["A","B"]→"A|B")
const keywordArr = keywordsList.map(item => item.keywords);
const keywordStr = keywordArr.join('|');
// === 轨道1:单句字幕(处理单行组文案)===
const track_1_texts = []; // 存单句文案内容
const track_1_timelines = []; // 存单句时间{start,end}
const track_1_otherInfo = []; // 存单句样式(对齐、颜色等)
// 遍历单行组每个文案text
for (const text of singleLineGroups) {
const time = timelineMap[text]; // 从timelineMap查text的时间
if (!time) continue; // 没找到时间就跳过(不处理)
track_1_texts.push(text); // 加内容到轨道1文本
track_1_timelines.push(time); // 加时间到轨道1时间
track_1_otherInfo.push({ // 加样式:居中对齐、绿色、无偏移
alignment: 1, text_color: "#61862b", transform_x: 0, transform_y: 0
});
}
// === 轨道2/3:普通双行字幕(处理双行组文案)===
const track_2_texts = []; const track_2_timelines = []; const track_2_otherInfo = []; // 轨道2(双行上句)
const track_3_texts = []; const track_3_timelines = []; const track_3_otherInfo = []; // 轨道3(双行下句)
const track_4_texts = []; const track_4_timelines = []; const track_4_otherInfo = []; // 轨道4(推荐文案)
const track_5_texts = []; const track_5_timelines = []; const track_5_otherInfo = []; // 轨道5(书名文案)
const doubleLinePairs = []; // 存普通双行字幕配对(用于生成画面提示词)
// 遍历双行组(每个组含wenan数组,如["上句","下句"])
for (const { wenan } of doubleLineGroups) {
const [line1, line2] = wenan; // 拆成上句line1、下句line2
const time1 = timelineMap[line1]; // 查上句时间
const time2 = timelineMap[line2]; // 查下句时间
if (!time1 || !time2) continue; // 任一时间缺失则跳过
// 定义判断“书籍推荐文案”的关键词(推荐/孩子/读一读等短语)
const recommendPhrases = ['推荐', '强烈推荐', '建议', '安利', '一定要试试', '必须看看', '良心推荐', '超适合', '很适合', '值得一读', '分享', '别错过', '可以入手'];
const childrenPhrases = ['孩子', '宝贝', '小朋友', '宝宝', '小宝', '小孩', '娃', '娃娃', '儿童', '幼儿', '学龄前', '小男孩', '小女孩', '小弟弟', '小妹妹', '小公主', '小王子'];
const actionPhrases = ['读一读', '看一看', '读读看', '看看', '共读', '阅读'];
const unitPhrases = ['这套', '这一套', '这本', '这一册', '这册'];
// 判断line1是否为书籍推荐文案(用正则组合关键词)
function isBookRecommendation(line) {
const pattern = new RegExp( // 正则:推荐词+(陪/给)+孩子词+动作词+单位词(灵活匹配)
`(?:${recommendPhrases.join('|')}).*?(?:陪|给)?.*?(?:${childrenPhrases.join('|')})?.*?(?:${actionPhrases.join('|')}).{0,5}(?:${unitPhrases.join('|')})`
);
return pattern.test(line); // 匹配成功则返回true
}
if (isBookRecommendation(line1)) {
// 若为推荐文案:line1→轨道4(推荐),line2→轨道5(书名)
track_4_texts.push(line1); track_4_timelines.push(time1); track_4_otherInfo.push({ alignment:1, text_color:"#000000", transform_x:0, transform_y:100 });
track_5_texts.push(line2); track_5_timelines.push(time2); track_5_otherInfo.push({ alignment:1, text_color:"#db7431", transform_x:0, transform_y:-100 });
} else {
// 普通双行:line1→轨道2(上句),line2→轨道3(下句)
track_2_texts.push(line1); track_2_timelines.push({ start: time1.start, end: time1.end }); track_2_otherInfo.push({ alignment:1, text_color:"#61862b", transform_x:0, transform_y:140 });
track_3_texts.push(line2); track_3_timelines.push({ start: time2.start, end: time2.end }); track_3_otherInfo.push({ alignment:1, text_color:"#db7431", transform_x:0, transform_y:-140 });
doubleLinePairs.push({ line1: { text: line1, time: time1 }, line2: { text: line2, time: time2 } }); // 存配对用于画面提示词
}
}
// === 生成画面提示词数据(visualPromptGroups)===
const visualPromptGroups = [];
// 加单句字幕提示词(轨道1内容)
for (let i = 0; i < track_1_texts.length; i++) {
visualPromptGroups.push({ start: track_1_timelines[i].start, end: track_1_timelines[i].end, content: track_1_texts[i] });
}
// 加双行字幕提示词(普通双行配对,用\n分隔上下句)
for (const pair of doubleLinePairs) {
visualPromptGroups.push({ start: pair.line1.time.start, end: pair.line2.time.end, content: `${pair.line1.text}\n${pair.line2.text}` });
}
// 返回所有轨道数据+画面提示词
return {
track_1: { texts: track_1_texts, timelines: track_1_timelines, otherInfo: track_1_otherInfo, keywords: track_1_texts.map(() => keywordStr), keyword_color: "#db7431" },
track_2: { texts: track_2_texts, timelines: track_2_timelines, otherInfo: track_2_otherInfo },
track_3: { texts: track_3_texts, timelines: track_3_timelines, otherInfo: track_3_otherInfo },
track_4: { texts: track_4_texts, timelines: track_4_timelines, otherInfo: track_4_otherInfo },
track_5: { texts: track_5_texts, timelines: track_5_timelines, otherInfo: track_5_otherInfo },
visualPromptGroups // 画面提示词数组(含start/end/content)
};
}
扣子工作流代码节点常见问题
代码节点支持哪些编程语言?
目前扣子工作流代码节点主要支持 JavaScript(Node.js 环境)和 Python。您可以在节点设置中选择语言,推荐使用 JavaScript 以更好地与前端交互。
如何在代码节点中引入第三方库?
扣子代码节点内置了常用库(如 axios、lodash),无需额外安装。如果需要其他库,可使用动态导入(ES6)或通过在线依赖注入。具体可参考官方文档的“允许的依赖列表”。
代码节点如何获取上游节点的输出数据?
通过代码节点的输入参数对象
inputs 获取,例如 const data = inputs.user_query。确保上游节点的输出字段名与代码中引用的名称一致。
代码节点如何返回数据给下游节点?
使用
return 语句返回一个对象,对象的属性将成为输出字段。例如 return { result: "处理完成" };。下游节点可通过 {{节点名.result}} 引用。
代码节点执行超时或内存不足怎么办?
扣子代码节点默认超时时间较短(通常 5-10 秒),避免在代码中执行大量同步循环或大数据处理。建议将复杂任务拆分为多个节点,或使用异步流处理。如果必须处理大数据,考虑分批或调用外部API。
代码节点能访问环境变量或工作流全局变量吗?
可以通过
process.env 访问系统环境变量(仅限内置变量)。工作流全局变量(如工作流ID、用户ID)可通过 inputs 中的特定字段获取,具体需查看平台文档。
代码节点出错后如何定位问题?
利用
console.log() 打印关键变量,然后在工作流运行日志中查看输出。也可以使用 try-catch 捕获错误并返回自定义错误信息,便于调试。