perf: Variable aggregation node adds sorting and modifies some styling issues

This commit is contained in:
wangdan-fit2cloud 2025-10-29 18:26:24 +08:00
parent ebb3c74dc5
commit 3c7e5ff3b6
9 changed files with 104 additions and 71 deletions

View File

@ -126,7 +126,7 @@ function changeState(bool: boolean, row: any) {
const obj = {
is_active: bool,
}
const str = bool ? t('common.enabled') : t('common.disabled')
const str = bool ? t('common.status.enabled') : t('common.status.disabled')
systemKeyApi.putAPIKey(row.id, obj, loading).then((res) => {
MsgSuccess(str)
getApiKeyList()

View File

@ -259,7 +259,7 @@ You are a master of problem optimization, adept at accurately inferring user int
},
variableAggregationNode: {
label: 'Variable Aggregation',
text: 'Perform aggregation processing on the outputs of multiple branches',
text: 'Aggregate variables of each group according to the aggregation strategy',
Strategy: 'Aggregation Strategy',
placeholder: 'Return the first non-null value of each group',
placeholder1: 'Return the set of variables for each group',

View File

@ -260,7 +260,7 @@ export default {
},
variableAggregationNode: {
label: '变量聚合',
text: '对多个分支的输出进行聚合处理',
text: '按聚合策略聚合每组的变量',
Strategy: '聚合策略',
placeholder: '返回每组的第一个非空值',
placeholder1: '返回每组变量的集合',

View File

@ -259,7 +259,7 @@ export default {
},
variableAggregationNode: {
label: '變量聚合',
text: '對多個分支的輸出進行聚合處理',
text: '按聚合策略聚合每組的變量',
Strategy: '聚合策略',
placeholder: '返回每組的第一個非空值',
placeholder1: '返回每組變量的集合',

View File

@ -262,3 +262,23 @@
padding: 4px 16px 12px 12px;
}
}
// 拖拽排序
.drag-card.no-drag {
.handle {
.handle-img {
display: none;
}
}
}
.drag-card:not(.no-drag) {
.handle {
.handle-img {
display: none;
}
&:hover {
.handle-img {
display: block;
}
}
}
}

View File

@ -259,11 +259,18 @@ function editTagValue(row: any) {
}
function delTagValue(row: any) {
loadSharedApi({ type: 'knowledge', systemType: apiType.value })
.delTag(id, row.id, 'one')
MsgConfirm(t('views.document.tag.deleteConfirm') + row.value, t('views.document.tag.deleteTip'), {
confirmButtonText: t('common.delete'),
confirmButtonClass: 'danger',
})
.then(() => {
getList()
loadSharedApi({ type: 'knowledge', systemType: apiType.value })
.delTag(id, row.id, 'one')
.then(() => {
getList()
})
})
.catch(() => {})
}
function getList() {

View File

@ -636,7 +636,7 @@ export const menuNodes = [
},
{
label: t('views.knowledge.title'),
list: [searchKnowledgeNode, searchDocumentNode, rerankerNode],
list: [searchKnowledgeNode, searchDocumentNode, rerankerNode, documentExtractNode],
},
{
label: t('views.applicationWorkflow.nodes.classify.businessLogic'),
@ -653,7 +653,7 @@ export const menuNodes = [
},
{
label: t('views.applicationWorkflow.nodes.classify.other'),
list: [mcpNode, documentExtractNode, toolNode],
list: [mcpNode, toolNode],
},
]
export const applicationLoopMenuNodes = [
@ -674,7 +674,7 @@ export const applicationLoopMenuNodes = [
},
{
label: t('views.knowledge.title'),
list: [searchKnowledgeNode, searchDocumentNode, rerankerNode],
list: [searchKnowledgeNode, searchDocumentNode, rerankerNode, documentExtractNode],
},
{
label: t('views.applicationWorkflow.nodes.classify.businessLogic'),
@ -682,11 +682,16 @@ export const applicationLoopMenuNodes = [
},
{
label: t('views.applicationWorkflow.nodes.classify.dataProcessing', '数据处理'),
list: [variableAssignNode, variableSplittingNode, parameterExtractionNode, variableAggregationNode],
list: [
variableAssignNode,
variableSplittingNode,
parameterExtractionNode,
variableAggregationNode,
],
},
{
label: t('views.applicationWorkflow.nodes.classify.other'),
list: [mcpNode, documentExtractNode, toolNode],
list: [mcpNode, toolNode],
},
]

View File

@ -11,7 +11,7 @@
<VueDraggable
ref="el"
v-bind:modelValue="form_data.branch"
:disabled="form_data.branch === 2"
:disabled="form_data.branch.length === 2"
handle=".handle"
:animation="150"
ghostClass="ghost"
@ -347,23 +347,5 @@ onMounted(() => {
})
</script>
<style lang="scss" scoped>
.drag-card.no-drag {
.handle {
.handle-img {
display: none;
}
}
}
.drag-card:not(.no-drag) {
.handle {
.handle-img {
display: none;
}
&:hover {
.handle-img {
display: block;
}
}
}
}
</style>

View File

@ -42,8 +42,8 @@
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
<div class="flex-between mb-12">
<span class="ellipsis" :title="group.label">{{ group.label }}</span>
<div class="flex align-center" style="margin-right: -3px;">
<el-button @click="openAddOrEditDialog(group, gIndex)" link>
<div class="flex align-center" style="margin-right: -3px">
<el-button @click="openAddOrEditDialog(group, gIndex)" link>
<el-icon><EditPen /></el-icon>
</el-button>
<el-button
@ -55,43 +55,50 @@
</el-button>
</div>
</div>
<div v-for="(item, vIndex) in group.variable_list" :key="item.v_id">
<el-row>
<el-col :span="22">
<el-form-item
:prop="`group_list.${gIndex}.variable_list.${vIndex}.variable`"
:rules="{
type: 'array',
required: true,
message: $t(
'views.applicationWorkflow.variable.placeholder',
),
trigger: 'change',
}"
>
<NodeCascader
ref="nodeCascaderRef"
:nodeModel="nodeModel"
class="w-full"
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
v-model="item.variable"
/>
</el-form-item>
</el-col>
<el-col :span="2">
<el-button
link
class="mt-4 ml-4"
:disabled="group.variable_list.length <= 1"
@click="deleteVariable(gIndex, vIndex)"
>
<AppIcon iconName="app-delete"></AppIcon>
</el-button>
</el-col>
</el-row>
</div>
<VueDraggable
ref="el"
v-bind:modelValue="group.variable_list"
:disabled="group.variable_list.length === 1"
handle=".handle"
:animation="150"
ghostClass="ghost"
@end="onEnd($event, gIndex)"
>
<div v-for="(item, vIndex) in group.variable_list" :key="item.v_id" class="drag-card">
<el-row class="handle">
<el-col :span="22" class="flex">
<img src="@/assets/sort.svg" alt="" height="15" class="mr-4 mt-8" />
<el-form-item
:prop="`group_list.${gIndex}.variable_list.${vIndex}.variable`"
:rules="{
type: 'array',
required: true,
message: $t('views.applicationWorkflow.variable.placeholder'),
trigger: 'change',
}"
>
<NodeCascader
ref="nodeCascaderRef"
:nodeModel="nodeModel"
style="width: 200px"
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
v-model="item.variable"
/>
</el-form-item>
</el-col>
<el-col :span="2">
<el-button
link
class="mt-4 ml-4"
:disabled="group.variable_list.length <= 1"
@click="deleteVariable(gIndex, vIndex)"
>
<AppIcon iconName="app-delete"></AppIcon>
</el-button>
</el-col>
</el-row>
</div>
</VueDraggable>
<el-button @click="addVariable(gIndex)" type="primary" size="large" link>
<AppIcon iconName="app-add-outlined" class="mr-4" />
{{ $t('common.add') }}
@ -116,6 +123,7 @@ import { isLastNode } from '@/workflow/common/data'
import { t } from '@/locales'
import { randomId } from '@/utils/common'
import { MsgError } from '@/utils/message'
import { VueDraggable } from 'vue-draggable-plus'
const props = defineProps<{ nodeModel: any }>()
const VariableAggregationRef = ref()
@ -241,6 +249,17 @@ const validate = async () => {
})
}
function onEnd(event: any, gIndex: number) {
const { oldIndex, newIndex } = event
if (oldIndex === undefined || newIndex === undefined) return
const list = cloneDeep(props.nodeModel.properties.node_data.group_list[gIndex].variable_list)
const newInstance = { ...list[oldIndex] }
const oldInstance = { ...list[newIndex] }
list[newIndex] = newInstance
list[oldIndex] = oldInstance
set(props.nodeModel.properties.node_data.group_list[gIndex], 'variable_list', list)
}
onMounted(() => {
if (typeof props.nodeModel.properties.node_data?.is_result === 'undefined') {
if (isLastNode(props.nodeModel)) {