feat: Variable Splitting Node and Parameter Extraction Node
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
Typos Check / Spell Check with Typos (push) Waiting to run

This commit is contained in:
wangdan-fit2cloud 2025-10-21 19:30:15 +08:00
parent 727c8bfa98
commit 09c5c9c042
47 changed files with 292 additions and 319 deletions

View File

@ -55,7 +55,7 @@ const view_card = computed(() => {
</script>
<style lang="scss" scoped>
@mixin valueScss() {
color: rgba(31, 35, 41, 1);
color: var(--el-text-color-primary);
font-weight: 500;
font-size: 12px;
line-height: 22px;

View File

@ -24,11 +24,11 @@
@blur="folderForm.name = folderForm.name.trim()"
/>
</el-form-item>
<el-form-item :label="$t('components.folder.description')" prop="desc">
<el-form-item :label="$t('common.desc')" prop="desc">
<el-input
v-model="folderForm.desc"
type="textarea"
:placeholder="$t('components.folder.descriptionPlaceholder')"
:placeholder="$t('common.descPlaceholder')"
maxlength="128"
show-word-limit
:autosize="{ minRows: 3 }"
@ -133,7 +133,7 @@ const submitHandle = async () => {
.then((res) => {
return user.profile().then(() => {
return res
})
})
})
.then((res) => {
MsgSuccess(t('common.createSuccess'))

View File

@ -56,7 +56,7 @@ const showBack = computed(() => {
position: absolute;
top: 36px;
right: -12px;
box-shadow: 0px 5px 10px 0px rgba(31, 35, 41, 0.1);
box-shadow: 0px 5px 10px 0px var(--app-text-color-light-1);
z-index: 1;
}

View File

@ -78,6 +78,8 @@ export default {
selectPlaceholder: 'Please select',
title: 'Title',
content: 'Content',
desc: 'Description',
descPlaceholder: 'Please enter description',
rename: 'Rename',
renameSuccess: 'Successful',
EditAvatarDialog: {
@ -114,4 +116,5 @@ export default {
label: 'Prompt',
placeholder: 'Please enter prompt',
},
variable: 'Variable',
}

View File

@ -15,8 +15,6 @@ export default {
addChildFolder: 'Add Child Folder',
editFolder: 'Edit Folder',
folderNamePlaceholder: 'Please enter a name',
description: 'Description',
descriptionPlaceholder: 'Please enter a description',
requiredMessage: 'Please select a folder',
deleteConfirmMessage: 'Folders with resources will be deleted, please be cautious.',
},

View File

@ -432,23 +432,21 @@ You are a master of problem optimization, adept at accurately inferring user int
text: 'Used to split variables',
result: 'Result',
splitVariables: 'Split Variables',
inputVariables: 'Input Variable',
addVariables: 'Add Variables',
editVariables: 'Edit Variables',
variablePlaceholder: 'Please enter variable',
expression: {
label: 'Expression',
placeholder: 'Please enter expression',
},
},
parameterExtractionNode: {
label: '參數提取',
text: '利用 AI 模型提取結構化參數',
result: '結果',
selectVariables: {
label: '選擇變數',
placeholder: '請選擇變數',
},
label: 'Parameter Extraction',
text: 'Use AI models to extract structured parameters',
extractParameters: {
label: '提取參數',
desc: '描述',
parameterType: '參數類型',
label: 'Extract Parameters',
parameterType: 'Parameter Type',
},
},
},

View File

@ -43,7 +43,6 @@ export default {
requiredMessage: 'APP name is required',
},
appDescription: {
label: 'Description',
placeholder:
'Describe the APP scenario and use, e.g.: XXX assistant answering user questions about XXX product usage',
},

View File

@ -54,11 +54,9 @@ export default {
requiredMessage: 'Please enter the MCP name',
},
toolDescription: {
label: 'Description',
placeholder: 'Please enter a description of the tool',
},
mcpDescription: {
label: 'Description',
placeholder: 'Please enter a description of the MCP',
},
paramName: {

View File

@ -82,6 +82,8 @@ export default {
selectPlaceholder: '请选择',
title: '标题',
content: '内容',
desc: '描述',
descPlaceholder: '请输入描述',
rename: '重命名',
renameSuccess: '重命名成功',
EditAvatarDialog: {
@ -117,4 +119,5 @@ export default {
label: '提示词',
placeholder: '请输入提示词',
},
variable: '变量',
}

View File

@ -15,9 +15,7 @@ export default {
addChildFolder: '添加子文件夹',
editFolder: '编辑文件夹',
folderNamePlaceholder: '请输入名称',
description: '描述',
descriptionPlaceholder: '请输入描述',
requiredMessage: '请选择文件夹',
deleteConfirmMessage: '文件夹下的资源会被删除,请谨慎操作。'
deleteConfirmMessage: '文件夹下的资源会被删除,请谨慎操作。',
},
}

View File

@ -28,9 +28,6 @@ export default {
placeholder: '请输入关键字搜索',
},
paramForm: {
variable: {
label: '变量',
},
field: {
label: '参数',
placeholder: '请输入参数',

View File

@ -50,7 +50,6 @@ export default {
beautify: '一键美化',
},
variable: {
label: '变量',
global: '全局变量',
chat: '会话变量',
Referencing: '引用变量',
@ -443,25 +442,22 @@ export default {
variableSplittingNode: {
label: '变量拆分',
text: '用于拆分变量',
result: '结果',
splitVariables: '拆分变量',
inputVariables: '输入变量',
addVariables: '添加变量',
editVariables: '编辑变量',
variablePlaceholder: '请输入变量',
expression: {
label: '表达式',
placeholder: '请输入表达式',
},
},
parameterExtractionNode: {
label: '參數提取',
text: '利用 AI 模型提取結構化參數',
result: '結果',
selectVariables: {
label: '選擇變量',
placeholder: '請選擇變量',
},
parameterExtractionNode: {
label: '参数提取',
text: '利用 AI 模型提取结构化参数',
extractParameters: {
label: '提取參數',
desc: '描述',
parameterType: '參數類型',
label: '提取参数',
parameterType: '参数类型',
},
},
},

View File

@ -42,7 +42,6 @@ export default {
requiredMessage: '请输入应用名称',
},
appDescription: {
label: '描述',
placeholder: '描述该应用的应用场景及用途XXX 小助手回答用户提出的 XXX 产品使用问题',
},
appType: {

View File

@ -48,11 +48,9 @@ export default {
requiredMessage: '请输入MCP名称',
},
toolDescription: {
label: '描述',
placeholder: '请输入工具的描述',
},
mcpDescription: {
label: '描述',
placeholder: '请输入MCP的描述',
},
paramName: {

View File

@ -78,6 +78,8 @@ export default {
selectPlaceholder: '請選擇',
title: '標題',
content: '内容',
desc: '描述',
descPlaceholder: '請輸入描述',
rename: '重命名',
renameSuccess: '重命名成功',
EditAvatarDialog: {
@ -113,4 +115,5 @@ export default {
label: '提示詞',
placeholder: '請輸入提示詞',
},
variable: '變量',
}

View File

@ -15,8 +15,6 @@ export default {
addChildFolder: '添加子文件夾',
editFolder: '編輯文件夾',
folderNamePlaceholder: '請輸入名稱',
description: '描述',
descriptionPlaceholder: '請輸入描述',
requiredMessage: '請選擇文件夾',
deleteConfirmMessage: '文件夹下的資源會被刪除,請謹慎操作。',
},

View File

@ -418,6 +418,10 @@ export default {
text: '用於拆分變量',
result: '結果',
splitVariables: '拆分變量',
inputVariables: '輸入變量',
addVariables: '添加變量',
editVariables: '編輯變量',
variablePlaceholder: '請輸入變量',
expression: {
label: '表達式',
placeholder: '請輸入表達式',
@ -425,16 +429,10 @@ export default {
},
parameterExtractionNode: {
label: '參數提取',
text: ' ',
result: '結果',
selectVariables: {
label: ' ',
placeholder: '請選擇要提取的參數',
},
text: '利用 AI 模型提取結構化參數',
extractParameters: {
label: '提取參數',
desc: '從文本中提取參數',
parameterType: 'Parameter Type',
parameterType: '參數類型',
},
},
},

View File

@ -39,7 +39,6 @@ export default {
requiredMessage: '請輸入應用名稱',
},
appDescription: {
label: '描述',
placeholder: '描述該應用的應用場景及用途XXX 小助手回答用戶提出的 XXX 產品使用問題',
},
appType: {

View File

@ -51,11 +51,9 @@ export default {
requiredMessage: '請輸入MCP名稱',
},
toolDescription: {
label: '描述',
placeholder: '請輸入工具的描述',
},
mcpDescription: {
label: '描述',
placeholder: '請輸入MCP的描述',
},
paramName: {

View File

@ -4,6 +4,7 @@
--el-text-color-primary: #1f2329;
--el-border-radius-base: 6px;
--el-menu-item-height: 45px;
--el-border-color: rgba(31, 35, 41, 0.15);
}
.el-avatar {
@ -183,6 +184,7 @@
.el-table {
--el-table-header-bg-color: var(--app-layout-bg-color);
--el-table-text-color: var(--app-text-color);
--el-table-border-color: #DEE0E3;
font-weight: 400;
thead {
color: var(--app-text-color-secondary);

View File

@ -706,7 +706,7 @@ defineExpose({ open })
background-repeat: no-repeat;
background-position: center;
background-size: auto 100%;
box-shadow: 0px 4px 8px 0px rgba(31, 35, 41, 0.1);
box-shadow: 0px 4px 8px 0px var(--app-text-color-light-1);
overflow: hidden;
width: 330px;
height: 520px;

View File

@ -28,7 +28,7 @@
</div>
<div v-else>
<el-button @click="showPopover = !showPopover">
<AppIcon iconName="app-add-outlined" class="mr-4"/>
<AppIcon iconName="app-add-outlined" class="mr-4" />
{{ $t('views.applicationWorkflow.setting.addComponent') }}
</el-button>
<el-button @click="clickShowDebug" :disabled="showDebug" v-if="permissionPrecise.debug(id)">
@ -673,7 +673,7 @@ onBeforeUnmount(() => {
border-radius: 8px;
border: 1px solid #ffffff;
background: var(--dialog-bg-gradient-color);
box-shadow: 0px 4px 8px 0px rgba(31, 35, 41, 0.1);
box-shadow: 0px 4px 8px 0px var(--app-text-color-light-1);
position: fixed;
bottom: 16px;
right: 16px;

View File

@ -61,7 +61,7 @@
@blur="applicationForm.name = applicationForm.name?.trim()"
/>
</el-form-item>
<el-form-item :label="$t('views.application.form.appDescription.label')">
<el-form-item :label="$t('common.desc')">
<el-input
v-model="applicationForm.desc"
type="textarea"

View File

@ -23,7 +23,7 @@
show-word-limit
/>
</el-form-item>
<el-form-item :label="$t('views.application.form.appDescription.label')">
<el-form-item :label="$t('common.desc')">
<el-input
v-model="applicationForm.desc"
type="textarea"

View File

@ -28,7 +28,7 @@
@blur="applicationForm.name = applicationForm.name?.trim()"
/>
</el-form-item>
<el-form-item :label="$t('views.application.form.appDescription.label')">
<el-form-item :label="$t('common.desc')">
<el-input
v-model="applicationForm.desc"
type="textarea"

View File

@ -50,11 +50,7 @@
</el-tooltip>
</div>
</div>
<div
v-show="!isPcCollapse"
class="left-height"
v-if="showHistory"
>
<div v-show="!isPcCollapse" class="left-height" v-if="showHistory">
<el-scrollbar>
<div class="p-16 pt-0">
<common-list
@ -111,11 +107,7 @@
<template #title>{{ $t('chat.createChat') }}</template>
</el-menu-item>
<el-sub-menu
v-show="isPcCollapse"
index="2"
v-if="showHistory"
>
<el-sub-menu v-show="isPcCollapse" index="2" v-if="showHistory">
<template #title>
<AppIcon iconName="app-history-outlined" />
</template>
@ -285,7 +277,7 @@ function refreshFieldTitle(chatId: string, abstract: string) {
padding-left: 8px;
padding-right: 8px;
&:hover {
background-color: rgba(31, 35, 41, 0.1);
background-color: var(--app-text-color-light-1);
}
&.is-active {
background-color: #ffffff;

View File

@ -10,7 +10,7 @@
>
<el-button class="collapse cursor" circle @click="show = !show">
<el-icon>
<component :is="!show ? 'ArrowRightBold' : 'ArrowLeftBold'"/>
<component :is="!show ? 'ArrowRightBold' : 'ArrowLeftBold'" />
</el-icon>
</el-button>
<HistoryPanel
@ -32,12 +32,12 @@
chatUser.chat_profile.authentication_type === 'password'
"
>
<img src="@/assets/user-icon.svg" style="width: 54%" alt=""/>
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
</el-avatar>
<el-dropdown v-else trigger="click" type="primary" class="w-full">
<div class="flex align-center">
<el-avatar :size="32">
<img src="@/assets/user-icon.svg" style="width: 54%" alt=""/>
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
</el-avatar>
<span class="ml-8 color-text-primary">{{ chatUser.chatUserProfile?.nick_name }}</span>
</div>
@ -47,7 +47,7 @@
<div class="flex align-center p-8">
<div class="mr-8 flex align-center">
<el-avatar :size="40">
<img src="@/assets/user-icon.svg" style="width: 54%" alt=""/>
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
</el-avatar>
</div>
<div>
@ -72,7 +72,7 @@
style="padding-top: 8px; padding-bottom: 8px"
@click="logout"
>
<AppIcon iconName="app-export" class="color-secondary"/>
<AppIcon iconName="app-export" class="color-secondary" />
{{ $t('layout.logout') }}
</el-dropdown-item>
</el-dropdown-menu>
@ -91,13 +91,13 @@
</template>
<script setup lang="ts">
import {ref, computed, defineModel} from 'vue'
import { ref, computed, defineModel } from 'vue'
import useStore from '@/stores'
import HistoryPanel from '@/views/chat/component/HistoryPanel.vue'
import ResetPassword from '@/layout/layout-header/avatar/ResetPassword.vue'
import type {ResetCurrentUserPasswordRequest} from '@/api/type/user'
import type { ResetCurrentUserPasswordRequest } from '@/api/type/user'
import chatAPI from '@/api/chat/chat'
import {useRoute, useRouter} from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
@ -112,7 +112,7 @@ const props = defineProps<{
const emit = defineEmits(['newChat', 'clickLog', 'deleteLog', 'refreshFieldTitle', 'clearChat'])
const {chatUser} = useStore()
const { chatUser } = useStore()
const clearChat = () => {
emit('clearChat')
@ -141,7 +141,7 @@ const openResetPassword = () => {
const handleResetPassword = (param: ResetCurrentUserPasswordRequest) => {
chatAPI.resetCurrentPassword(param).then(() => {
router.push({name: 'login'})
router.push({ name: 'login' })
})
}
@ -149,10 +149,9 @@ const logout = () => {
chatUser.logout().then(() => {
router.push({
name: 'login',
params: {accessToken: chatUser.accessToken},
params: { accessToken: chatUser.accessToken },
query: route.query,
})
})
}
</script>
@ -168,7 +167,7 @@ const logout = () => {
position: absolute;
top: 20px;
right: -13px;
box-shadow: 0px 5px 10px 0px rgba(31, 35, 41, 0.1);
box-shadow: 0px 5px 10px 0px var(--app-text-color-light-1);
z-index: 1;
width: 24px;
height: 24px;

View File

@ -542,7 +542,7 @@ function closeExecutionDetail() {
position: absolute;
top: 20px;
right: -13px;
box-shadow: 0px 5px 10px 0px rgba(31, 35, 41, 0.1);
box-shadow: 0px 5px 10px 0px var(--app-text-color-light-1);
z-index: 1;
width: 24px;
height: 24px;

View File

@ -97,7 +97,7 @@ defineExpose({ open })
}
.active-breadcrumb {
font-size: 16px;
color: rgba(31, 35, 41, 1);
color: var(--el-text-color-primary);
font-weight: 500;
line-height: 24px;
}

View File

@ -139,9 +139,7 @@
:description="$t('views.model.tip.emptyMessage1')"
/>
<el-empty
v-else-if="
base_form_data.model_type === 'RERANKER'
"
v-else-if="base_form_data.model_type === 'RERANKER'"
:description="$t('views.model.tip.emptyMessage2')"
/>
<div class="flex-between mb-8" v-else>
@ -149,9 +147,13 @@
<el-button
type="text"
@click.stop="openAddDrawer()"
:disabled="!['TTS', 'LLM', 'IMAGE', 'TTI', 'TTV', 'ITV','STT', 'EMBEDDING'].includes(base_form_data.model_type)"
:disabled="
!['TTS', 'LLM', 'IMAGE', 'TTI', 'TTV', 'ITV', 'STT', 'EMBEDDING'].includes(
base_form_data.model_type,
)
"
>
<AppIcon iconName="app-add-outlined" class="mr-4"/> {{ $t('common.add') }}
<AppIcon iconName="app-add-outlined" class="mr-4" /> {{ $t('common.add') }}
</el-button>
</div>
<el-table
@ -464,7 +466,7 @@ defineExpose({ open, close })
.active-breadcrumb {
font-size: 16px;
color: rgba(31, 35, 41, 1);
color: var(--el-text-color-primary);
font-weight: 500;
line-height: 24px;
}

View File

@ -289,7 +289,7 @@ defineExpose({ open, close })
.active-breadcrumb {
font-size: 16px;
color: rgba(31, 35, 41, 1);
color: var(--el-text-color-primary);
font-weight: 500;
line-height: 24px;
}

View File

@ -33,11 +33,7 @@
v-if="permissionPrecise.doc_edit(id)"
>
<el-button text @click.stop="editParagraph(data)">
<AppIcon
iconName="app-edit"
:size="16"
class="color-secondary"
></AppIcon>
<AppIcon iconName="app-edit" :size="16" class="color-secondary"></AppIcon>
</el-button>
</el-tooltip>
</span>
@ -227,7 +223,7 @@ async function changeState(row: any) {
})
}
function getDetail() {
loadSharedApi({ type: 'knowledge', systemType: apiType.value, isShared: shareDisabled.value})
loadSharedApi({ type: 'knowledge', systemType: apiType.value, isShared: shareDisabled.value })
.getKnowledgeDetail(id, loading)
.then((res: any) => {
knowledgeDetail.value = res.data
@ -324,7 +320,7 @@ watch(dialogVisible, (val: boolean) => {
position: relative;
overflow: inherit;
&:hover {
background: rgba(31, 35, 41, 0.1);
background: var(--app-text-color-light-1);
border: 1px solid #dee0e3;
}
&.disabled {

View File

@ -63,7 +63,7 @@
</div>
</el-form-item>
<el-form-item :label="$t('views.tool.form.mcpDescription.label')">
<el-form-item :label="$t('common.desc')">
<el-input
v-model="form.desc"
type="textarea"
@ -78,7 +78,7 @@
{{ $t('views.tool.form.mcp.title') }}
</h4>
<el-form-item :label="$t('views.tool.form.mcpDescription.label')" prop="code">
<el-form-item prop="code">
<template #label>
{{ $t('views.tool.form.mcp.label') }}
<span class="color-danger">*</span>
@ -98,7 +98,9 @@
<template #footer>
<div>
<el-button :loading="loading" @click="testConnection">{{ $t('views.system.test') }}</el-button>
<el-button :loading="loading" @click="testConnection">{{
$t('views.system.test')
}}</el-button>
<el-button :loading="loading" @click="visible = false">{{ $t('common.cancel') }}</el-button>
<el-button
type="primary"

View File

@ -60,7 +60,7 @@
</div>
</el-form-item>
<el-form-item :label="$t('views.tool.form.toolDescription.label')">
<el-form-item :label="$t('common.desc')">
<el-input
v-model="form.desc"
type="textarea"

View File

@ -52,7 +52,7 @@ defineExpose({ open })
position: absolute;
top: 12px;
right: 12px;
box-shadow: 0px 4px 8px 0px rgba(31, 35, 41, 0.1);
box-shadow: 0px 4px 8px 0px var(--app-text-color-light-1);
z-index: 2;
}
.config-textarea {

View File

@ -166,15 +166,15 @@ export const questionNode = {
}
export const variableSplittingNode = {
type: WorkflowType.VariableSplittingNode,
text: t('views.applicationWorkflow.nodes.variableSplittingNode.text', '变量拆分'),
label: t('views.applicationWorkflow.nodes.variableSplittingNode.label', '变量拆分'),
text: t('views.applicationWorkflow.nodes.variableSplittingNode.text'),
label: t('views.applicationWorkflow.nodes.variableSplittingNode.label'),
height: 345,
properties: {
stepName: t('views.applicationWorkflow.nodes.variableSplittingNode.label', '变量拆分'),
stepName: t('views.applicationWorkflow.nodes.variableSplittingNode.label'),
config: {
fields: [
{
label: t('views.applicationWorkflow.nodes.variableSplittingNode.result', '结果'),
label: t('common.result'),
value: 'result',
},
],
@ -184,15 +184,16 @@ export const variableSplittingNode = {
export const parameterExtractionNode = {
type: WorkflowType.ParameterExtractionNode,
text: t('views.applicationWorkflow.nodes.parameterExtractionNode.text', '变量拆分'),
label: t('views.applicationWorkflow.nodes.parameterExtractionNode.label', '变量拆分'),
text: t('views.applicationWorkflow.nodes.parameterExtractionNode.text'),
label: t('views.applicationWorkflow.nodes.parameterExtractionNode.label'),
height: 345,
properties: {
stepName: t('views.applicationWorkflow.nodes.parameterExtractionNode.label', '变量拆分'),
width: 430,
stepName: t('views.applicationWorkflow.nodes.parameterExtractionNode.label'),
config: {
fields: [
{
label: t('views.applicationWorkflow.nodes.parameterExtractionNode.result', '结果'),
label: t('common.result'),
value: 'result',
},
],
@ -633,11 +634,16 @@ export const menuNodes = [
},
{
label: t('views.applicationWorkflow.nodes.classify.businessLogic'),
list: [conditionNode, formNode, variableAssignNode, replyNode, loopNode],
list: [conditionNode, formNode, replyNode, loopNode],
},
{
label: t('views.applicationWorkflow.nodes.classify.dataProcessing', '数据处理'),
list: [variableSplittingNode, parameterExtractionNode, variableAggregationNode],
label: t('views.applicationWorkflow.nodes.classify.dataProcessing'),
list: [
variableAssignNode,
variableAggregationNode,
variableSplittingNode,
parameterExtractionNode,
],
},
{
label: t('views.applicationWorkflow.nodes.classify.other'),

View File

@ -1,6 +1,6 @@
<template>
<el-avatar shape="square" style="background: #7F3BF5">
<el-avatar shape="square" class="avatar-blue">
<img src="@/assets/workflow/icon_aggregation.svg" style="width: 100%" alt="" />
</el-avatar>
</template>
<script setup lang="ts"></script>
<script setup lang="ts"></script>

View File

@ -1,6 +1,6 @@
<template>
<el-avatar shape="square" class="avatar-blue">
<img src="@/assets/workflow/icon_variable_splitting.svg" style="width: 65%" alt="" />
<img src="@/assets/workflow/icon_variable_splitting.svg" style="width: 100%" alt="" />
</el-avatar>
</template>
<script setup lang="ts"></script>

View File

@ -44,12 +44,12 @@
/>
</el-form-item>
<el-form-item
:label="$t('views.application.form.appDescription.label')"
:label="$t('common.desc')"
prop="desc"
:rules="{
required: form.is_required,
message:
$t('common.inputPlaceholder') + $t('views.application.form.appDescription.label'),
$t('common.inputPlaceholder') + $t('common.desc'),
trigger: 'blur',
}"
>

View File

@ -20,7 +20,7 @@
</span>
</template>
</el-table-column>
<el-table-column prop="desc" :label="$t('views.application.form.appDescription.label')">
<el-table-column prop="desc" :label="$t('common.desc')">
<template #default="{ row }">
<span class="ellipsis-1" :title="row.desc">
{{ row.desc }}

View File

@ -69,27 +69,13 @@
/>
</el-select>
</el-form-item>
<el-form-item
:label="
$t(
'views.applicationWorkflow.nodes.parameterExtractionNode.extractParameters.desc',
'描述',
)
"
prop="desc"
>
<el-form-item :label="$t('common.desc')" prop="desc">
<el-input
v-model="form.desc"
style="width: 100%"
:rows="2"
type="textarea"
:placeholder="
$t('common.inputPlaceholder') +
$t(
'views.applicationWorkflow.nodes.parameterExtractionNode.extractParameters.desc',
'描述',
)
"
:placeholder="$t('common.descPlaceholder')"
/>
</el-form-item>
</el-form>
@ -97,7 +83,7 @@
<span class="dialog-footer">
<el-button @click.prevent="close"> {{ $t('common.cancel') }} </el-button>
<el-button type="primary" @click="submit(fieldFormRef)" :loading="loading">
{{ isEdit ? $t('common.save') : $t('common.add') }}
{{ $t('common.save') }}
</el-button>
</span>
</template>

View File

@ -1,34 +1,23 @@
<template>
<div class="flex-between mb-16">
<h5 class="break-all ellipsis lighter" style="max-width: 80%">
{{
$t(
'views.applicationWorkflow.nodes.parameterExtractionNode.extractParameters.label',
'提取参数',
)
}}
<div class="flex-between w-full">
<h5 class="break-all lighter">
{{ $t('views.applicationWorkflow.nodes.parameterExtractionNode.extractParameters.label') }}
<span class="color-danger">*</span>
</h5>
<div>
<span class="ml-4">
<el-button link type="primary" @click="openAddDialog()">
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
{{ $t('common.add') }}
</el-button>
</span>
</div>
<span class="ml-4" style="margin-top: -4px">
<el-button link type="primary" @click="openAddDialog()">
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
</el-button>
</span>
</div>
<el-table
v-if="props.nodeModel.properties.node_data.variable_list?.length > 0"
:data="props.nodeModel.properties.node_data.variable_list"
class="mb-16"
ref="tableRef"
row-key="field"
class="border-l border-r"
>
<el-table-column
prop="field"
:label="$t('dynamicsForm.paramForm.field.label', '变量')"
width="95"
>
<el-table-column prop="field" :label="$t('dynamicsForm.paramForm.field.label')" width="90">
<template #default="{ row }">
<span :title="row.field" class="ellipsis-1">{{ row.field }}</span>
</template>
@ -52,14 +41,10 @@
"
>
<template #default="{ row }">
<span>
<span :title="row.parameter_type" class="ellipsis-1">
{{ row.parameter_type }}
</span></span
>
<el-tag type="info" class="info-tag"> {{ row.parameter_type }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('common.operation')" align="left" width="90">
<el-table-column :label="$t('common.operation')" align="left" width="80">
<template #default="{ row, $index }">
<span class="mr-4">
<el-tooltip effect="dark" :content="$t('common.modify')" placement="top">
@ -103,7 +88,7 @@ function deleteField(index: any) {
inputFieldList.value.splice(index, 1)
const fields = [
{
label: t('views.applicationWorkflow.nodes.variableSplittingNode.result', '结果'),
label: t('common.result'),
value: 'result',
},
...inputFieldList.value.map((item) => ({ label: item.label, value: item.field })),
@ -126,7 +111,7 @@ function refreshFieldList(data: any, index: any) {
ParametersFieldDialogRef.value.close()
const fields = [
{
label: t('views.applicationWorkflow.nodes.variableSplittingNode.result', '结果'),
label: t('common.result'),
value: 'result',
},
...inputFieldList.value.map((item) => ({ label: item.label, value: item.field })),
@ -141,7 +126,7 @@ onMounted(() => {
set(props.nodeModel.properties.node_data, 'variable_list', inputFieldList)
const fields = [
{
label: t('views.applicationWorkflow.nodes.variableSplittingNode.result', '结果'),
label: t('common.result'),
value: 'result',
},
...inputFieldList.value.map((item) => ({ label: item.label, value: item.field })),

View File

@ -1,93 +1,96 @@
<template>
<NodeContainer :nodeModel="nodeModel">
<el-form
@submit.prevent
:model="form_data"
label-position="top"
require-asterisk-position="right"
label-width="auto"
ref="VariableSplittingRef"
hide-required-asterisk
>
<el-form-item
:label="$t('views.application.form.aiModel.label')"
prop="model_id"
:rules="{
required: true,
message: $t('views.application.form.aiModel.placeholder'),
trigger: 'change',
}"
<h5 class="title-decoration-1 mb-8">{{ $t('views.applicationWorkflow.nodeSetting') }}</h5>
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
<el-form
@submit.prevent
:model="form_data"
label-position="top"
require-asterisk-position="right"
label-width="auto"
ref="VariableSplittingRef"
hide-required-asterisk
>
<template #label>
<div class="flex-between w-full">
<div>
<span
>{{ $t('views.application.form.aiModel.label')
}}<span class="color-danger">*</span></span
>
</div>
<el-form-item
:label="$t('views.application.form.aiModel.label')"
prop="model_id"
:rules="{
required: true,
message: $t('views.application.form.aiModel.placeholder'),
trigger: 'change',
}"
>
<template #label>
<div class="flex-between w-full">
<div>
<span
>{{ $t('views.application.form.aiModel.label')
}}<span class="color-danger ml-4">*</span></span
>
</div>
<el-button
:disabled="!form_data.model_id"
type="primary"
link
@click="openAIParamSettingDialog(form_data.model_id)"
@refreshForm="refreshParam"
>
<AppIcon iconName="app-setting"></AppIcon>
</el-button>
</div>
</template>
<ModelSelect
@change="model_change"
@wheel="wheel"
:teleported="false"
v-model="form_data.model_id"
:placeholder="$t('views.application.form.aiModel.placeholder')"
:options="modelOptions"
@submitModel="getSelectModel"
showFooter
:model-type="'LLM'"
></ModelSelect>
</el-form-item>
<el-form-item
:label="
$t(
'views.applicationWorkflow.nodes.parameterExtractionNode.selectVariables.label',
'选择变量',
)
"
>
<template #label>
<div class="flex-between">
<div>
{{
$t(
'views.applicationWorkflow.nodes.parameterExtractionNode.selectVariables.label',
'选择变量',
)
}}
<span class="color-danger">*</span>
<el-button
:disabled="!form_data.model_id"
type="primary"
link
@click="openAIParamSettingDialog(form_data.model_id)"
@refreshForm="refreshParam"
>
<AppIcon iconName="app-setting"></AppIcon>
</el-button>
</div>
</div>
</template>
<NodeCascader
ref="nodeCascaderRef"
:nodeModel="nodeModel"
class="w-full"
:placeholder="
$t(
'views.applicationWorkflow.nodes.parameterExtractionNode.selectVariables.placeholder',
)
"
v-model="form_data.input_variable"
/>
</el-form-item>
<ParametersFieldTable
ref="ParametersFieldTableRef"
:node-model="nodeModel"
></ParametersFieldTable>
</el-form>
</template>
<ModelSelect
@change="model_change"
@wheel="wheel"
:teleported="false"
v-model="form_data.model_id"
:placeholder="$t('views.application.form.aiModel.placeholder')"
:options="modelOptions"
@submitModel="getSelectModel"
showFooter
:model-type="'LLM'"
></ModelSelect>
</el-form-item>
<el-form-item
prop="input_variable"
:rules="{
message: $t('views.applicationWorkflow.variable.placeholder'),
trigger: 'blur',
required: true,
}"
>
<template #label>
<div class="flex-between">
<div>
{{ $t('views.applicationWorkflow.nodes.variableSplittingNode.inputVariables') }}
<span class="color-danger">*</span>
</div>
</div>
</template>
<NodeCascader
ref="nodeCascaderRef"
:nodeModel="nodeModel"
class="w-full"
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
v-model="form_data.input_variable"
/>
</el-form-item>
<el-form-item
prop="variable_list"
:rules="{
message: $t('views.applicationWorkflow.nodes.parameterExtractionNode.extractParameters.label'),
trigger: 'blur',
required: true,
}"
>
<ParametersFieldTable
ref="ParametersFieldTableRef"
:node-model="nodeModel"
></ParametersFieldTable>
</el-form-item>
</el-form>
</el-card>
<AIModeParamSettingDialog ref="AIModeParamSettingDialogRef" @refresh="refreshParam" />
</NodeContainer>
</template>
@ -95,7 +98,6 @@
import { computed, onMounted, ref, inject } from 'vue'
import NodeContainer from '@/workflow/common/NodeContainer.vue'
import NodeCascader from '@/workflow/common/NodeCascader.vue'
import VariableFieldTable from '@/workflow/nodes/variable-splitting/component/VariableFieldTable.vue'
import AIModeParamSettingDialog from '@/views/application/component/AIModeParamSettingDialog.vue'
import ParametersFieldTable from '@/workflow/nodes/parameter-extraction-node/component/ParametersFieldTable.vue'
import { useRoute } from 'vue-router'

View File

@ -11,11 +11,11 @@
>
<template v-for="(item, index) in form_data.variable_list" :key="item.id">
<el-card shadow="never" class="card-never mb-8" style="--el-card-padding: 12px">
<el-form-item :label="$t('views.applicationWorkflow.variable.label')">
<el-form-item >
<template #label>
<div class="flex-between">
<div>
{{ $t('views.applicationWorkflow.variable.label') }}
{{ $t('common.variable') }}
<span class="color-danger">*</span>
</div>
<el-button

View File

@ -1,6 +1,10 @@
<template>
<el-dialog
:title="isEdit ? $t('common.param.editParam') : $t('common.param.addParam')"
:title="
isEdit
? $t('views.applicationWorkflow.nodes.variableSplittingNode.editVariables')
: $t('views.applicationWorkflow.nodes.variableSplittingNode.addVariables')
"
v-model="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@ -16,7 +20,7 @@
require-asterisk-position="right"
>
<el-form-item
:label="$t('dynamicsForm.paramForm.field.label')"
:label="$t('common.variable')"
:required="true"
prop="field"
:rules="rules.field"
@ -24,7 +28,9 @@
<el-input
v-model="form.field"
:maxlength="64"
:placeholder="$t('dynamicsForm.paramForm.field.placeholder')"
:placeholder="
$t('views.applicationWorkflow.nodes.variableSplittingNode.variablePlaceholder')
"
show-word-limit
/>
</el-form-item>
@ -42,9 +48,7 @@
/>
</el-form-item>
<el-form-item
:label="
$t('views.applicationWorkflow.nodes.variableSplittingNode.expression.label', '表达式')
"
:label="$t('views.applicationWorkflow.nodes.variableSplittingNode.expression.label')"
:required="true"
prop="label"
:rules="rules.label"
@ -54,10 +58,7 @@
:maxlength="64"
show-word-limit
:placeholder="
$t(
'views.applicationWorkflow.nodes.variableSplittingNode.expression.placeholder',
'请输入表达式',
)
$t('views.applicationWorkflow.nodes.variableSplittingNode.expression.placeholder')
"
/>
</el-form-item>
@ -66,7 +67,7 @@
<span class="dialog-footer">
<el-button @click.prevent="close"> {{ $t('common.cancel') }} </el-button>
<el-button type="primary" @click="submit(fieldFormRef)" :loading="loading">
{{ isEdit ? $t('common.save') : $t('common.add') }}
{{ $t('common.save') }}
</el-button>
</span>
</template>

View File

@ -1,27 +1,25 @@
<template>
<div class="flex-between mb-16">
<h5 class="break-all ellipsis lighter" style="max-width: 80%">
{{ $t('views.applicationWorkflow.nodes.variableSplittingNode.splitVariables', '拆分变量') }}
<div class="flex-between w-full">
<h5 class="break-all lighter">
{{ $t('views.applicationWorkflow.nodes.variableSplittingNode.splitVariables') }}
<span class="color-danger">*</span>
</h5>
<div>
<span class="ml-4">
<el-button link type="primary" @click="openAddDialog()">
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
{{ $t('common.add') }}
</el-button>
</span>
</div>
<span class="ml-4" style="margin-top: -4px">
<el-button link type="primary" @click="openAddDialog()">
<AppIcon iconName="app-add-outlined"></AppIcon>
</el-button>
</span>
</div>
<el-table
v-if="props.nodeModel.properties.node_data.variable_list?.length > 0"
:data="props.nodeModel.properties.node_data.variable_list"
class="mb-16"
ref="tableRef"
row-key="field"
class="border-l border-r"
>
<el-table-column
prop="field"
:label="$t('dynamicsForm.paramForm.variable.label', '变量')"
:label="$t('common.variable')"
width="95"
>
<template #default="{ row }">
@ -31,11 +29,9 @@
<el-table-column prop="label" :label="$t('dynamicsForm.paramForm.name.label')">
<template #default="{ row }">
<span>
<span :title="row.label" class="ellipsis-1">
{{ row.label }}
</span></span
>
<span :title="row.label" class="ellipsis-1">
{{ row.label }}
</span>
</template>
</el-table-column>
<el-table-column :label="$t('common.operation')" align="left" width="90">
@ -82,7 +78,7 @@ function deleteField(index: any) {
inputFieldList.value.splice(index, 1)
const fields = [
{
label: t('views.applicationWorkflow.nodes.variableSplittingNode.result', '结果'),
label: t('common.result'),
value: 'result',
},
...inputFieldList.value.map((item) => ({ label: item.label, value: item.field })),
@ -105,7 +101,7 @@ function refreshFieldList(data: any, index: any) {
VariableFieldDialogRef.value.close()
const fields = [
{
label: t('views.applicationWorkflow.nodes.variableSplittingNode.result', '结果'),
label: t('common.result'),
value: 'result',
},
...inputFieldList.value.map((item) => ({ label: item.label, value: item.field })),
@ -120,7 +116,7 @@ onMounted(() => {
set(props.nodeModel.properties.node_data, 'variable_list', inputFieldList)
const fields = [
{
label: t('views.applicationWorkflow.nodes.variableSplittingNode.result', '结果'),
label: t('common.result'),
value: 'result',
},
...inputFieldList.value.map((item) => ({ label: item.label, value: item.field })),

View File

@ -1,35 +1,56 @@
<template>
<NodeContainer :nodeModel="nodeModel">
<el-form
@submit.prevent
:model="form_data"
label-position="top"
require-asterisk-position="right"
label-width="auto"
ref="VariableSplittingRef"
hide-required-asterisk
>
<el-form-item
:label="$t('views.applicationWorkflow.nodes.variableSplittingNode.label', '输入变量')"
<h5 class="title-decoration-1 mb-8">{{ $t('views.applicationWorkflow.nodeSetting') }}</h5>
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
<el-form
@submit.prevent
:model="form_data"
label-position="top"
require-asterisk-position="right"
label-width="auto"
ref="VariableSplittingRef"
hide-required-asterisk
>
<template #label>
<div class="flex-between">
<div>
{{ $t('views.applicationWorkflow.nodes.variableSplittingNode.label', '输入变量') }}
<span class="color-danger">*</span>
<el-form-item
prop="input_variable"
:rules="{
message: $t('views.applicationWorkflow.variable.placeholder'),
trigger: 'blur',
required: true,
}"
>
<template #label>
<div class="flex-between">
<div>
{{ $t('views.applicationWorkflow.nodes.variableSplittingNode.inputVariables') }}
<span class="color-danger">*</span>
</div>
</div>
</div>
</template>
<NodeCascader
ref="nodeCascaderRef"
:nodeModel="nodeModel"
class="w-full"
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
v-model="form_data.input_variable"
/>
</el-form-item>
<VariableFieldTable ref="VariableFieldTableRef" :node-model="nodeModel"></VariableFieldTable>
</el-form>
</template>
<NodeCascader
ref="nodeCascaderRef"
:nodeModel="nodeModel"
class="w-full"
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
v-model="form_data.input_variable"
/>
</el-form-item>
<el-form-item
prop="variable_list"
:rules="{
message: $t('views.applicationWorkflow.variable.placeholder'),
trigger: 'blur',
required: true,
}"
>
<VariableFieldTable
ref="VariableFieldTableRef"
:node-model="nodeModel"
></VariableFieldTable>
</el-form-item>
</el-form>
</el-card>
</NodeContainer>
</template>
<script setup lang="ts">