mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 10:12:51 +00:00
feat: loop node
This commit is contained in:
parent
31c6154e7a
commit
4b52d5f232
|
|
@ -1,11 +1,3 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_5178_28485)">
|
||||
<path d="M0 10C0 5.28595 0 2.92893 1.46447 1.46447C2.92893 0 5.28595 0 10 0C14.714 0 17.0711 0 18.5355 1.46447C20 2.92893 20 5.28595 20 10C20 14.714 20 17.0711 18.5355 18.5355C17.0711 20 14.714 20 10 20C5.28595 20 2.92893 20 1.46447 18.5355C0 17.0711 0 14.714 0 10Z" fill="#34C724"/>
|
||||
<path d="M15.7291 9.99992C15.7291 13.164 13.164 15.7291 9.99998 15.7291C6.83592 15.7291 4.27081 13.164 4.27081 9.99992C4.27081 6.83586 6.83592 4.27075 9.99998 4.27075C13.164 4.27075 15.7291 6.83586 15.7291 9.99992ZM14.6875 9.99992C14.6875 7.41112 12.5885 5.31242 9.99998 5.31242C7.41144 5.31242 5.31248 7.41112 5.31248 9.99992C5.31248 12.5887 7.41144 14.6874 9.99998 14.6874C12.5885 14.6874 14.6875 12.5887 14.6875 9.99992ZM8.43748 7.91659H11.5625C11.8489 7.91659 12.0833 8.14966 12.0833 8.43742V11.5624C12.0833 11.8502 11.8489 12.0833 11.5625 12.0833H8.43748C8.15102 12.0833 7.91665 11.8502 7.91665 11.5624V8.43742C7.91665 8.14966 8.15102 7.91659 8.43748 7.91659Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_5178_28485">
|
||||
<rect width="20" height="20" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.7291 6.99992C12.7291 10.164 10.164 12.7291 6.99998 12.7291C3.83592 12.7291 1.27081 10.164 1.27081 6.99992C1.27081 3.83586 3.83592 1.27075 6.99998 1.27075C10.164 1.27075 12.7291 3.83586 12.7291 6.99992ZM11.6875 6.99992C11.6875 4.41112 9.58852 2.31242 6.99998 2.31242C4.41144 2.31242 2.31248 4.41112 2.31248 6.99992C2.31248 9.58872 4.41144 11.6874 6.99998 11.6874C9.58852 11.6874 11.6875 9.58872 11.6875 6.99992ZM5.43748 4.91659H8.56248C8.84894 4.91659 9.08332 5.14966 9.08332 5.43742V8.56242C9.08332 8.85018 8.84894 9.08325 8.56248 9.08325H5.43748C5.15102 9.08325 4.91665 8.85018 4.91665 8.56242V5.43742C4.91665 5.14966 5.15102 4.91659 5.43748 4.91659Z" fill="white"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 784 B |
|
|
@ -0,0 +1,862 @@
|
|||
<template>
|
||||
<el-card class="mb-8" shadow="never" style="--el-card-padding: 12px 16px">
|
||||
<div class="flex-between cursor" @click="data['show'] = !data['show']">
|
||||
<div class="flex align-center">
|
||||
<el-icon class="mr-8 arrow-icon" :class="data['show'] ? 'rotate-90' : ''">
|
||||
<CaretRight />
|
||||
</el-icon>
|
||||
<component
|
||||
:is="iconComponent(`${data.type}-icon`)"
|
||||
class="mr-8"
|
||||
:size="24"
|
||||
:item="data.info"
|
||||
/>
|
||||
<h4>{{ data.name }}</h4>
|
||||
</div>
|
||||
<div class="flex align-center">
|
||||
<span
|
||||
class="mr-16 color-secondary"
|
||||
v-if="
|
||||
data.type === WorkflowType.Question ||
|
||||
data.type === WorkflowType.AiChat ||
|
||||
data.type === WorkflowType.ImageUnderstandNode ||
|
||||
data.type === WorkflowType.ImageGenerateNode ||
|
||||
data.type === WorkflowType.Application
|
||||
"
|
||||
>{{ data?.message_tokens + data?.answer_tokens }} tokens</span
|
||||
>
|
||||
<span class="mr-16 color-secondary">{{ data?.run_time?.toFixed(2) || 0.0 }} s</span>
|
||||
<el-icon class="color-success" :size="16" v-if="data.status === 200">
|
||||
<CircleCheck />
|
||||
</el-icon>
|
||||
<el-icon class="color-danger" :size="16" v-else>
|
||||
<CircleClose />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<el-collapse-transition>
|
||||
<div class="mt-12" v-if="data['show']">
|
||||
<template v-if="data.status === 200">
|
||||
<!-- 开始 -->
|
||||
<template
|
||||
v-if="
|
||||
data.type === WorkflowType.Start ||
|
||||
data.type === WorkflowType.Application ||
|
||||
data.type === WorkflowType.LoopStartNode
|
||||
"
|
||||
>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
</h5>
|
||||
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="mb-8">
|
||||
<span class="color-secondary"> {{ $t('chat.paragraphSource.question') }}:</span>
|
||||
|
||||
{{ data.question || '-' }}
|
||||
</div>
|
||||
|
||||
<div v-for="(f, i) in data.global_fields" :key="i" class="mb-8">
|
||||
<span class="color-secondary">{{ f.label }}:</span> {{ f.value }}
|
||||
</div>
|
||||
<div v-if="data.document_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">{{ $t('common.fileUpload.document') }}:</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in data.document_list" :key="i">
|
||||
<el-card shadow="never" style="--el-card-padding: 8px" class="file cursor">
|
||||
<div class="flex align-center">
|
||||
<img :src="getImgUrl(f && f?.name)" alt="" width="24" />
|
||||
<div class="ml-4 ellipsis" :title="f && f?.name">
|
||||
{{ f && f?.name }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-if="data.image_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">{{ $t('common.fileUpload.image') }}:</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in data.image_list" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-if="data.audio_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">{{ $t('chat.executionDetails.audioFile') }}:</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in data.audio_list" :key="i">
|
||||
<audio
|
||||
:src="f.url"
|
||||
controls
|
||||
style="width: 300px; height: 43px"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-if="data.other_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">{{ $t('common.fileUpload.document') }}:</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in data.other_list" :key="i">
|
||||
<el-card shadow="never" style="--el-card-padding: 8px" class="file cursor">
|
||||
<div class="flex align-center">
|
||||
<img :src="getImgUrl(f && f?.name)" alt="" width="24" />
|
||||
<div class="ml-4 ellipsis" :title="f && f?.name">
|
||||
{{ f && f?.name }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 知识库检索 -->
|
||||
<template v-if="data.type == WorkflowType.SearchKnowledge">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.searchContent') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">{{ data.question || '-' }}</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.searchResult') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="data.paragraph_list?.length > 0">
|
||||
<template
|
||||
v-for="(paragraph, paragraphIndex) in arraySort(
|
||||
data.paragraph_list,
|
||||
'similarity',
|
||||
true,
|
||||
)"
|
||||
:key="paragraphIndex"
|
||||
>
|
||||
<ParagraphCard
|
||||
:data="paragraph"
|
||||
:content="paragraph.content"
|
||||
:index="paragraphIndex"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 判断器 -->
|
||||
<template v-if="data.type == WorkflowType.Condition">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.conditionResult') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
{{ data.branch_name || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- AI 对话 / 问题优化-->
|
||||
<template
|
||||
v-if="
|
||||
data.type == WorkflowType.AiChat ||
|
||||
data.type == WorkflowType.Question ||
|
||||
data.type == WorkflowType.Application
|
||||
"
|
||||
>
|
||||
<div class="card-never border-r-6" v-if="data.type !== WorkflowType.Application">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.application.form.roleSettings.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
{{ data.system || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8" v-if="data.type !== WorkflowType.Application">
|
||||
<h5 class="p-8-12">{{ $t('chat.history') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="data.history_message?.length > 0">
|
||||
<p
|
||||
class="mt-4 mb-4"
|
||||
v-for="(history, historyIndex) in data.history_message"
|
||||
:key="historyIndex"
|
||||
>
|
||||
<span class="color-secondary mr-4">{{ history.role }}:</span
|
||||
><span>{{ history.content }}</span>
|
||||
</p>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8" v-if="data.type !== WorkflowType.Application">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8" v-if="data.type == WorkflowType.AiChat">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.aiChatNode.think') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.reasoning_content || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
data.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="data.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="data.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 指定回复 -->
|
||||
<template v-if="data.type === WorkflowType.Reply">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.replyContent') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<el-scrollbar height="150">
|
||||
<MdPreview
|
||||
v-if="data.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="data.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 文档内容提取 -->
|
||||
<template v-if="data.type === WorkflowType.DocumentExtractNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12 flex align-center">
|
||||
<span class="mr-4"> {{ $t('common.param.outputParam') }}</span>
|
||||
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('chat.executionDetails.paramOutputTooltip')"
|
||||
placement="right"
|
||||
>
|
||||
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
|
||||
</el-tooltip>
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<el-scrollbar height="150">
|
||||
<el-card
|
||||
shadow="never"
|
||||
style="--el-card-padding: 8px"
|
||||
v-for="(file_content, index) in data.content"
|
||||
:key="index"
|
||||
class="mb-8"
|
||||
>
|
||||
<MdPreview
|
||||
v-if="file_content"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="file_content"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</el-card>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="data.type === WorkflowType.SpeechToTextNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="mb-8">
|
||||
<div v-if="data.audio_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">{{ $t('chat.executionDetails.audioFile') }}:</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in data.audio_list" :key="i">
|
||||
<audio
|
||||
:src="f.url"
|
||||
controls
|
||||
style="width: 300px; height: 43px"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<el-card
|
||||
shadow="never"
|
||||
style="--el-card-padding: 8px"
|
||||
v-for="(file_content, index) in data.content"
|
||||
:key="index"
|
||||
class="mb-8"
|
||||
>
|
||||
<MdPreview
|
||||
v-if="file_content"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="file_content"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="data.type === WorkflowType.TextToSpeechNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<p class="mb-8 color-secondary">{{ $t('chat.executionDetails.textContent') }}:</p>
|
||||
<div v-if="data.content">
|
||||
<MdPreview
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="data.content"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<p class="mb-8 color-secondary">{{ $t('chat.executionDetails.audioFile') }}:</p>
|
||||
<div v-if="data.answer" v-html="data.answer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 工具库 -->
|
||||
<template
|
||||
v-if="data.type === WorkflowType.ToolLib || data.type === WorkflowType.ToolLibCustom"
|
||||
>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">{{ $t('chat.executionDetails.input') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.params || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">{{ $t('chat.executionDetails.output') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.result || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 多路召回 -->
|
||||
<template v-if="data.type == WorkflowType.RerankerNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.searchContent') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">{{ data.question || '-' }}</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.rerankerContent') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="data.document_list?.length > 0">
|
||||
<template
|
||||
v-for="(paragraph, paragraphIndex) in data.document_list"
|
||||
:key="paragraphIndex"
|
||||
>
|
||||
<ParagraphCard
|
||||
:data="paragraph.metadata"
|
||||
:content="paragraph.page_content"
|
||||
:index="paragraphIndex"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.rerankerResult') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="data.result_list?.length > 0">
|
||||
<template
|
||||
v-for="(paragraph, paragraphIndex) in data.result_list"
|
||||
:key="paragraphIndex"
|
||||
>
|
||||
<ParagraphCard
|
||||
:data="paragraph.metadata"
|
||||
:content="paragraph.page_content"
|
||||
:index="paragraphIndex"
|
||||
:score="paragraph.metadata?.relevance_score"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表单收集 -->
|
||||
<template v-if="data.type === WorkflowType.FormNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam')
|
||||
}}<span style="color: #f54a45">{{
|
||||
data.is_submit ? '' : `(${$t('chat.executionDetails.noSubmit')})`
|
||||
}}</span>
|
||||
</h5>
|
||||
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<DynamicsForm
|
||||
:disabled="true"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
ref="dynamicsFormRef"
|
||||
:render_data="data.form_field_list"
|
||||
label-suffix=":"
|
||||
v-model="data.form_data"
|
||||
:model="data.form_data"
|
||||
></DynamicsForm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 图片理解 -->
|
||||
<template v-if="data.type == WorkflowType.ImageUnderstandNode">
|
||||
<div class="card-never border-r-6" v-if="data.type !== WorkflowType.Application">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.application.form.roleSettings.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
{{ data.system || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8" v-if="data.type !== WorkflowType.Application">
|
||||
<h5 class="p-8-12">{{ $t('chat.history') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="data.history_message?.length > 0">
|
||||
<p
|
||||
class="mt-4 mb-4"
|
||||
v-for="(history, historyIndex) in data.history_message"
|
||||
:key="historyIndex"
|
||||
>
|
||||
<span class="color-secondary mr-4">{{ history.role }}:</span>
|
||||
|
||||
<span v-if="Array.isArray(history.content)">
|
||||
<template v-for="(h, i) in history.content" :key="i">
|
||||
<el-image
|
||||
v-if="h.type === 'image_url'"
|
||||
:src="h.image_url.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: inline-block"
|
||||
class="border-r-6 mr-8"
|
||||
/>
|
||||
|
||||
<span v-else>{{ h.text }}<br /></span>
|
||||
</template>
|
||||
</span>
|
||||
|
||||
<span v-else>{{ history.content }}</span>
|
||||
</p>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
<div v-if="data.image_list?.length > 0">
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in data.image_list" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div>
|
||||
{{ data.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
data.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="data.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="data.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 图片生成 -->
|
||||
<template v-if="data.type == WorkflowType.ImageGenerateNode">
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.imageGenerateNode.negative_prompt.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.negative_prompt || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
data.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="data.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="data.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="data.type == WorkflowType.TextToVideoGenerateNode">
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.imageGenerateNode.negative_prompt.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.negative_prompt || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
data.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="data.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="data.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="data.type == WorkflowType.ImageToVideoGenerateNode">
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.imageGenerateNode.negative_prompt.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ data.negative_prompt || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.imageToVideoGenerate.first_frame.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
<div v-if="typeof data.first_frame_url === 'string'">
|
||||
<el-image
|
||||
:src="data.first_frame_url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="Array.isArray(data.first_frame_url)">
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in data.first_frame_url" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.imageToVideoGenerate.last_frame.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
<div v-if="typeof data.last_frame_url === 'string'">
|
||||
<el-image
|
||||
:src="data.last_frame_url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="Array.isArray(data.last_frame_url)">
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in data.last_frame_url" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-else>-</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
data.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="data.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="data.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 变量赋值 -->
|
||||
<template v-if="data.type === WorkflowType.VariableAssignNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(f, i) in data.result_list" :key="i" class="mb-8">
|
||||
<span class="color-secondary">{{ f.name }}:</span> {{ f.input_value }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(f, i) in data.result_list" :key="i" class="mb-8">
|
||||
<span class="color-secondary">{{ f.name }}:</span> {{ f.output_value }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- MCP 节点 -->
|
||||
<template v-if="data.type === WorkflowType.McpNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.tool.title') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="mb-8">
|
||||
<span class="color-secondary"> {{ $t('views.tool.title') }}: </span>
|
||||
{{ data.mcp_tool }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.mcpNode.toolParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(value, name) in data.tool_params" :key="name" class="mb-8">
|
||||
<span class="color-secondary">{{ name }}:</span> {{ value }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(f, i) in data.result" :key="i" class="mb-8">
|
||||
<span class="color-secondary">result:</span> {{ f }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 循环 节点 -->
|
||||
<div class="card-never border-r-6" v-if="data.type === WorkflowType.LoopNode">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.loopNode.loopSetting') }}
|
||||
</h5>
|
||||
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="mb-8">
|
||||
<span class="color-secondary">
|
||||
{{ $t('views.applicationWorkflow.nodes.loopNode.loopType.label') }}:</span
|
||||
>
|
||||
{{ data.loop_type || '-' }}
|
||||
</div>
|
||||
<div>
|
||||
<span class="color-secondary">
|
||||
{{ $t('views.applicationWorkflow.nodes.loopNode.loopArray.label') }}:</span
|
||||
>
|
||||
{{ data.value || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.loopNode.loopDetail') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="data.type === WorkflowType.LoopNode">
|
||||
<el-radio-group v-model="currentLoopNode" class="app-radio-button-group mb-8">
|
||||
<template v-for="(loop, loopIndex) in data.loop_node_data" :key="loopIndex">
|
||||
<el-radio-button :label="loopIndex" :value="loopIndex" />
|
||||
</template>
|
||||
</el-radio-group>
|
||||
<template
|
||||
v-for="(cLoop, cIndex) in Object.values(data.loop_node_data[currentLoopNode])"
|
||||
:key="cIndex"
|
||||
>
|
||||
<ExecutionDetailCard :data="cLoop"></ExecutionDetailCard>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">{{ $t('chat.executionDetails.errMessage') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">{{ data.err_message || '-' }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</el-card>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import ParagraphCard from '@/components/ai-chat/component/knowledge-source-component/ParagraphCard.vue'
|
||||
import DynamicsForm from '@/components/dynamics-form/index.vue'
|
||||
import { iconComponent } from '@/workflow/icons/utils'
|
||||
import { WorkflowType } from '@/enums/application'
|
||||
import { getImgUrl } from '@/utils/common'
|
||||
import { arraySort } from '@/utils/array'
|
||||
|
||||
import { t } from '@/locales'
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
})
|
||||
const currentLoopNode = ref(0)
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -3,863 +3,7 @@
|
|||
<div class="execution-details p-8">
|
||||
<div v-if="isWorkFlow(props.appType)">
|
||||
<template v-for="(item, index) in arraySort(props.detail ?? [], 'index')" :key="index">
|
||||
<el-card class="mb-8" shadow="never" style="--el-card-padding: 12px 16px">
|
||||
<div class="flex-between cursor" @click="item['show'] = !item['show']">
|
||||
<div class="flex align-center">
|
||||
<el-icon class="mr-8 arrow-icon" :class="item['show'] ? 'rotate-90' : ''">
|
||||
<CaretRight/>
|
||||
</el-icon>
|
||||
<component
|
||||
:is="iconComponent(`${item.type}-icon`)"
|
||||
class="mr-8"
|
||||
:size="24"
|
||||
:item="item.info"
|
||||
/>
|
||||
<h4>{{ item.name }}</h4>
|
||||
</div>
|
||||
<div class="flex align-center">
|
||||
<span
|
||||
class="mr-16 color-secondary"
|
||||
v-if="
|
||||
item.type === WorkflowType.Question ||
|
||||
item.type === WorkflowType.AiChat ||
|
||||
item.type === WorkflowType.ImageUnderstandNode ||
|
||||
item.type === WorkflowType.ImageGenerateNode ||
|
||||
item.type === WorkflowType.Application
|
||||
"
|
||||
>{{ item?.message_tokens + item?.answer_tokens }} tokens</span
|
||||
>
|
||||
<span class="mr-16 color-secondary">{{ item?.run_time?.toFixed(2) || 0.0 }} s</span>
|
||||
<el-icon class="color-success" :size="16" v-if="item.status === 200">
|
||||
<CircleCheck/>
|
||||
</el-icon>
|
||||
<el-icon class="color-danger" :size="16" v-else>
|
||||
<CircleClose/>
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<el-collapse-transition>
|
||||
<div class="mt-12" v-if="item['show']">
|
||||
<template v-if="item.status === 200">
|
||||
<!-- 开始 -->
|
||||
<template
|
||||
v-if="
|
||||
item.type === WorkflowType.Start || item.type === WorkflowType.Application
|
||||
"
|
||||
>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
</h5>
|
||||
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="mb-8">
|
||||
<span class="color-secondary">
|
||||
{{ $t('chat.paragraphSource.question') }}:</span
|
||||
>
|
||||
|
||||
{{ item.question || '-' }}
|
||||
</div>
|
||||
|
||||
<div v-for="(f, i) in item.global_fields" :key="i" class="mb-8">
|
||||
<span class="color-secondary">{{ f.label }}:</span> {{ f.value }}
|
||||
</div>
|
||||
<div v-if="item.document_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">
|
||||
{{ $t('common.fileUpload.document') }}:
|
||||
</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.document_list" :key="i">
|
||||
<el-card
|
||||
shadow="never"
|
||||
style="--el-card-padding: 8px"
|
||||
class="file cursor"
|
||||
>
|
||||
<div class="flex align-center">
|
||||
<img :src="getImgUrl(f && f?.name)" alt="" width="24"/>
|
||||
<div class="ml-4 ellipsis" :title="f && f?.name">
|
||||
{{ f && f?.name }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-if="item.image_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">{{ $t('common.fileUpload.image') }}:</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.image_list" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-if="item.audio_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">
|
||||
{{ $t('chat.executionDetails.audioFile') }}:
|
||||
</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.audio_list" :key="i">
|
||||
<audio
|
||||
:src="f.url"
|
||||
controls
|
||||
style="width: 300px; height: 43px"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-if="item.other_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">
|
||||
{{ $t('common.fileUpload.document') }}:
|
||||
</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.other_list" :key="i">
|
||||
<el-card
|
||||
shadow="never"
|
||||
style="--el-card-padding: 8px"
|
||||
class="file cursor"
|
||||
>
|
||||
<div class="flex align-center">
|
||||
<img :src="getImgUrl(f && f?.name)" alt="" width="24"/>
|
||||
<div class="ml-4 ellipsis" :title="f && f?.name">
|
||||
{{ f && f?.name }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 知识库检索 -->
|
||||
<template v-if="item.type == WorkflowType.SearchKnowledge">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.searchContent') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">{{ item.question || '-' }}</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.searchResult') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="item.paragraph_list?.length > 0">
|
||||
<template
|
||||
v-for="(paragraph, paragraphIndex) in arraySort(
|
||||
item.paragraph_list,
|
||||
'similarity',
|
||||
true,
|
||||
)"
|
||||
:key="paragraphIndex"
|
||||
>
|
||||
<ParagraphCard
|
||||
:data="paragraph"
|
||||
:content="paragraph.content"
|
||||
:index="paragraphIndex"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 判断器 -->
|
||||
<template v-if="item.type == WorkflowType.Condition">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.conditionResult') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
{{ item.branch_name || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- AI 对话 / 问题优化-->
|
||||
<template
|
||||
v-if="
|
||||
item.type == WorkflowType.AiChat ||
|
||||
item.type == WorkflowType.Question ||
|
||||
item.type == WorkflowType.Application
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="card-never border-r-6"
|
||||
v-if="item.type !== WorkflowType.Application"
|
||||
>
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.application.form.roleSettings.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
{{ item.system || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="card-never border-r-6 mt-8"
|
||||
v-if="item.type !== WorkflowType.Application"
|
||||
>
|
||||
<h5 class="p-8-12">{{ $t('chat.history') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="item.history_message?.length > 0">
|
||||
<p
|
||||
class="mt-4 mb-4"
|
||||
v-for="(history, historyIndex) in item.history_message"
|
||||
:key="historyIndex"
|
||||
>
|
||||
<span class="color-secondary mr-4">{{ history.role }}:</span
|
||||
><span>{{ history.content }}</span>
|
||||
</p>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="card-never border-r-6 mt-8"
|
||||
v-if="item.type !== WorkflowType.Application"
|
||||
>
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8" v-if="item.type == WorkflowType.AiChat">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.aiChatNode.think') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.reasoning_content || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
item.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="item.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="item.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 指定回复 -->
|
||||
<template v-if="item.type === WorkflowType.Reply">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.replyContent') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<el-scrollbar height="150">
|
||||
<MdPreview
|
||||
v-if="item.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="item.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 文档内容提取 -->
|
||||
<template v-if="item.type === WorkflowType.DocumentExtractNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12 flex align-center">
|
||||
<span class="mr-4"> {{ $t('common.param.outputParam') }}</span>
|
||||
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('chat.executionDetails.paramOutputTooltip')"
|
||||
placement="right"
|
||||
>
|
||||
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
|
||||
</el-tooltip>
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<el-scrollbar height="150">
|
||||
<el-card
|
||||
shadow="never"
|
||||
style="--el-card-padding: 8px"
|
||||
v-for="(file_content, index) in item.content"
|
||||
:key="index"
|
||||
class="mb-8"
|
||||
>
|
||||
<MdPreview
|
||||
v-if="file_content"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="file_content"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</el-card>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.type === WorkflowType.SpeechToTextNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="mb-8">
|
||||
<div v-if="item.audio_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">
|
||||
{{ $t('chat.executionDetails.audioFile') }}:
|
||||
</p>
|
||||
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.audio_list" :key="i">
|
||||
<audio
|
||||
:src="f.url"
|
||||
controls
|
||||
style="width: 300px; height: 43px"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<el-card
|
||||
shadow="never"
|
||||
style="--el-card-padding: 8px"
|
||||
v-for="(file_content, index) in item.content"
|
||||
:key="index"
|
||||
class="mb-8"
|
||||
>
|
||||
<MdPreview
|
||||
v-if="file_content"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="file_content"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="item.type === WorkflowType.TextToSpeechNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<p class="mb-8 color-secondary">
|
||||
{{ $t('chat.executionDetails.textContent') }}:
|
||||
</p>
|
||||
<div v-if="item.content">
|
||||
<MdPreview
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="item.content"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<p class="mb-8 color-secondary">
|
||||
{{ $t('chat.executionDetails.audioFile') }}:
|
||||
</p>
|
||||
<div v-if="item.answer" v-html="item.answer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 工具库 -->
|
||||
<template
|
||||
v-if="
|
||||
item.type === WorkflowType.ToolLib || item.type === WorkflowType.ToolLibCustom
|
||||
"
|
||||
>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">{{ $t('chat.executionDetails.input') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.params || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">{{ $t('chat.executionDetails.output') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.result || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 多路召回 -->
|
||||
<template v-if="item.type == WorkflowType.RerankerNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.searchContent') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">{{ item.question || '-' }}</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.rerankerContent') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="item.document_list?.length > 0">
|
||||
<template
|
||||
v-for="(paragraph, paragraphIndex) in item.document_list"
|
||||
:key="paragraphIndex"
|
||||
>
|
||||
<ParagraphCard
|
||||
:data="paragraph.metadata"
|
||||
:content="paragraph.page_content"
|
||||
:index="paragraphIndex"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.rerankerResult') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="item.result_list?.length > 0">
|
||||
<template
|
||||
v-for="(paragraph, paragraphIndex) in item.result_list"
|
||||
:key="paragraphIndex"
|
||||
>
|
||||
<ParagraphCard
|
||||
:data="paragraph.metadata"
|
||||
:content="paragraph.page_content"
|
||||
:index="paragraphIndex"
|
||||
:score="paragraph.metadata?.relevance_score"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表单收集 -->
|
||||
<template v-if="item.type === WorkflowType.FormNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
$t('common.param.outputParam')
|
||||
}}<span style="color: #f54a45">{{
|
||||
item.is_submit ? '' : `(${$t('chat.executionDetails.noSubmit')})`
|
||||
}}</span>
|
||||
</h5>
|
||||
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<DynamicsForm
|
||||
:disabled="true"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
ref="dynamicsFormRef"
|
||||
:render_data="item.form_field_list"
|
||||
label-suffix=":"
|
||||
v-model="item.form_data"
|
||||
:model="item.form_data"
|
||||
></DynamicsForm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 图片理解 -->
|
||||
<template v-if="item.type == WorkflowType.ImageUnderstandNode">
|
||||
<div
|
||||
class="card-never border-r-6"
|
||||
v-if="item.type !== WorkflowType.Application"
|
||||
>
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.application.form.roleSettings.label') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
{{ item.system || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="card-never border-r-6 mt-8"
|
||||
v-if="item.type !== WorkflowType.Application"
|
||||
>
|
||||
<h5 class="p-8-12">{{ $t('chat.history') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="item.history_message?.length > 0">
|
||||
<p
|
||||
class="mt-4 mb-4"
|
||||
v-for="(history, historyIndex) in item.history_message"
|
||||
:key="historyIndex"
|
||||
>
|
||||
<span class="color-secondary mr-4">{{ history.role }}:</span>
|
||||
|
||||
<span v-if="Array.isArray(history.content)">
|
||||
<template v-for="(h, i) in history.content" :key="i">
|
||||
<el-image
|
||||
v-if="h.type === 'image_url'"
|
||||
:src="h.image_url.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: inline-block"
|
||||
class="border-r-6 mr-8"
|
||||
/>
|
||||
|
||||
<span v-else>{{ h.text }}<br/></span>
|
||||
</template>
|
||||
</span>
|
||||
|
||||
<span v-else>{{ history.content }}</span>
|
||||
</p>
|
||||
</template>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
<div v-if="item.image_list?.length > 0">
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.image_list" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div>
|
||||
{{ item.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
item.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="item.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="item.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 图片生成 -->
|
||||
<template v-if="item.type == WorkflowType.ImageGenerateNode">
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
$t(
|
||||
'views.applicationWorkflow.nodes.imageGenerateNode.negative_prompt.label',
|
||||
)
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.negative_prompt || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
item.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="item.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="item.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="item.type == WorkflowType.TextToVideoGenerateNode">
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
$t(
|
||||
'views.applicationWorkflow.nodes.imageGenerateNode.negative_prompt.label',
|
||||
)
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.negative_prompt || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
item.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="item.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="item.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="item.type == WorkflowType.ImageToVideoGenerateNode">
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('chat.executionDetails.currentChat') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
$t(
|
||||
'views.applicationWorkflow.nodes.imageGenerateNode.negative_prompt.label',
|
||||
)
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
{{ item.negative_prompt || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
$t('views.applicationWorkflow.nodes.imageToVideoGenerate.first_frame.label')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
|
||||
<div v-if="typeof item.first_frame_url === 'string'">
|
||||
<el-image
|
||||
:src="item.first_frame_url"
|
||||
alt=""
|
||||
fit="cover" style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="Array.isArray(item.first_frame_url)">
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.first_frame_url" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover" style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
$t('views.applicationWorkflow.nodes.imageToVideoGenerate.last_frame.label')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
|
||||
<div v-if="typeof item.last_frame_url === 'string'">
|
||||
<el-image
|
||||
:src="item.last_frame_url"
|
||||
alt=""
|
||||
fit="cover" style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="Array.isArray(item.last_frame_url)">
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.last_frame_url" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover" style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-6"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div v-else>
|
||||
-
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-never border-r-6 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{
|
||||
item.type == WorkflowType.Application
|
||||
? $t('common.param.outputParam')
|
||||
: $t('chat.executionDetails.answer')
|
||||
}}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="item.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="item.answer"
|
||||
style="background: none"
|
||||
noImgZoomIn
|
||||
/>
|
||||
<template v-else> -</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 变量赋值 -->
|
||||
<template v-if="item.type === WorkflowType.VariableAssignNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.inputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(f, i) in item.result_list" :key="i" class="mb-8">
|
||||
<span class="color-secondary">{{ f.name }}:</span> {{ f.input_value }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(f, i) in item.result_list" :key="i" class="mb-8">
|
||||
<span class="color-secondary">{{ f.name }}:</span> {{ f.output_value }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- MCP 节点 -->
|
||||
<template v-if="item.type === WorkflowType.McpNode">
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.tool.title') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div class="mb-8">
|
||||
<span class="color-secondary">
|
||||
{{ $t('views.tool.title') }}:
|
||||
</span>
|
||||
{{ item.mcp_tool }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('views.applicationWorkflow.nodes.mcpNode.toolParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(value, name) in item.tool_params" :key="name" class="mb-8">
|
||||
<span class="color-secondary">{{ name }}:</span> {{ value }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">
|
||||
{{ $t('common.param.outputParam') }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(f, i) in item.result" :key="i" class="mb-8">
|
||||
<span class="color-secondary">result:</span> {{ f }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="card-never border-r-6">
|
||||
<h5 class="p-8-12">{{ $t('chat.executionDetails.errMessage') }}</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">{{ item.err_message || '-' }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</el-card>
|
||||
<ExecutionDetailCard :data="item"> </ExecutionDetailCard>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
|
|
@ -928,15 +72,10 @@
|
|||
</el-scrollbar>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {ref, computed} from 'vue'
|
||||
import ParagraphCard
|
||||
from '@/components/ai-chat/component/knowledge-source-component/ParagraphCard.vue'
|
||||
import {arraySort} from '@/utils/array'
|
||||
import {iconComponent} from '@/workflow/icons/utils'
|
||||
import {WorkflowType} from '@/enums/application'
|
||||
import {getImgUrl} from '@/utils/common'
|
||||
import DynamicsForm from '@/components/dynamics-form/index.vue'
|
||||
import {isWorkFlow} from '@/utils/application'
|
||||
import { ref, computed } from 'vue'
|
||||
import ExecutionDetailCard from '@/components/ai-chat/component/knowledge-source-component/ExecutionDetailCard.vue'
|
||||
import { arraySort } from '@/utils/array'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
|
||||
const props = defineProps<{
|
||||
detail?: any[]
|
||||
|
|
@ -1006,6 +145,8 @@ const AiResponse = computed(() => {
|
|||
const messages = messageList.value?.filter((item: any) => item.role != 'system')
|
||||
return messages.slice(messages.length - 1, messages.length)
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.execution-details {
|
||||
|
|
|
|||
|
|
@ -262,12 +262,15 @@ export default {
|
|||
},
|
||||
prompt: {
|
||||
label: 'Prompt (Positive)',
|
||||
tooltip: 'Positive prompt, used to describe elements and visual features expected in the generated video',
|
||||
tooltip:
|
||||
'Positive prompt, used to describe elements and visual features expected in the generated video',
|
||||
},
|
||||
negative_prompt: {
|
||||
label: 'Prompt (Negative)',
|
||||
tooltip: 'Negative prompt, used to describe content you don\'t want to see in the video, which can restrict the video generation',
|
||||
placeholder: 'Please describe video content you don\'t want to generate, such as: colors, bloody content',
|
||||
tooltip:
|
||||
"Negative prompt, used to describe content you don't want to see in the video, which can restrict the video generation",
|
||||
placeholder:
|
||||
"Please describe video content you don't want to generate, such as: colors, bloody content",
|
||||
},
|
||||
},
|
||||
imageToVideoGenerate: {
|
||||
|
|
@ -280,12 +283,15 @@ export default {
|
|||
},
|
||||
prompt: {
|
||||
label: 'Prompt (Positive)',
|
||||
tooltip: 'Positive prompt, used to describe elements and visual features expected in the generated video',
|
||||
tooltip:
|
||||
'Positive prompt, used to describe elements and visual features expected in the generated video',
|
||||
},
|
||||
negative_prompt: {
|
||||
label: 'Prompt (Negative)',
|
||||
tooltip: 'Negative prompt, used to describe content you don\'t want to see in the video, which can restrict the video generation',
|
||||
placeholder: 'Please describe video content you don\'t want to generate, such as: colors, bloody content',
|
||||
tooltip:
|
||||
"Negative prompt, used to describe content you don't want to see in the video, which can restrict the video generation",
|
||||
placeholder:
|
||||
"Please describe video content you don't want to generate, such as: colors, bloody content",
|
||||
},
|
||||
first_frame: {
|
||||
label: 'First Frame Image',
|
||||
|
|
@ -336,6 +342,42 @@ export default {
|
|||
applicationNode: {
|
||||
label: 'APP Node',
|
||||
},
|
||||
loopNode: {
|
||||
label: 'Loop Node',
|
||||
text: 'Repeat a series of tasks by setting the number of loops and logic',
|
||||
loopType: {
|
||||
label: 'Loop Type',
|
||||
requiredMessage: 'Please select a loop type',
|
||||
arrayLoop: 'Array Loop',
|
||||
numberLoop: 'Loop for Specified Times',
|
||||
infiniteLoop: 'Infinite Loop',
|
||||
},
|
||||
loopArray: {
|
||||
label: 'Circular Array',
|
||||
requiredMessage: 'Circular Array is required',
|
||||
placeholder: 'Please select a circular array',
|
||||
},
|
||||
loopSetting: 'Loop Settings',
|
||||
loopDetail: 'Loop Details',
|
||||
},
|
||||
loopStartNode: {
|
||||
label: 'Loop Start',
|
||||
loopIndex: 'Index',
|
||||
loopItem: 'Loop Element',
|
||||
loopVariable: 'Loop Variable',
|
||||
},
|
||||
loopBodyNode: {
|
||||
label: 'Loop Body',
|
||||
text: 'Loop Body',
|
||||
},
|
||||
loopContinueNode: {
|
||||
label: 'Continue',
|
||||
text: 'Used to terminate the current loop and proceed to the next one.',
|
||||
},
|
||||
loopBreakNode: {
|
||||
label: 'Exit Loop',
|
||||
text: 'Terminate the current loop and exit the loop body',
|
||||
},
|
||||
},
|
||||
compare: {
|
||||
is_null: 'Is null',
|
||||
|
|
|
|||
|
|
@ -342,6 +342,42 @@ export default {
|
|||
applicationNode: {
|
||||
label: '应用节点',
|
||||
},
|
||||
loopNode: {
|
||||
label: '循环节点',
|
||||
text: '通过设置循环次数和逻辑,重复执行一系列任务',
|
||||
loopType: {
|
||||
label: '循环类型',
|
||||
requiredMessage: '请选择循环类型',
|
||||
arrayLoop: '数组循环',
|
||||
numberLoop: '指定次数循环',
|
||||
infiniteLoop: '无限循环',
|
||||
},
|
||||
loopArray: {
|
||||
label: '循环数组',
|
||||
requiredMessage: '循环数组必填',
|
||||
placeholder: '请选择循环数组',
|
||||
},
|
||||
loopSetting: '循环设置',
|
||||
loopDetail: '循环详情',
|
||||
},
|
||||
loopStartNode: {
|
||||
label: '循环开始',
|
||||
loopIndex: '下标',
|
||||
loopItem: '循环元素',
|
||||
loopVariable: '循环变量',
|
||||
},
|
||||
loopBodyNode: {
|
||||
label: '循环体',
|
||||
text: '循环体',
|
||||
},
|
||||
loopContinueNode: {
|
||||
label: '跳过',
|
||||
text: '用于终止当前循环,执行下次循环',
|
||||
},
|
||||
loopBreakNode: {
|
||||
label: '退出循环',
|
||||
text: '终止当前循环,跳出循环体',
|
||||
},
|
||||
},
|
||||
compare: {
|
||||
is_null: '为空',
|
||||
|
|
|
|||
|
|
@ -335,6 +335,33 @@ export default {
|
|||
applicationNode: {
|
||||
label: '應用節點',
|
||||
},
|
||||
loopNode: {
|
||||
label: '循環節點',
|
||||
text: '通過設置循環次數和邏輯,重複執行一系列任務',
|
||||
loopType: {
|
||||
label: '循環類型',
|
||||
requiredMessage: '請選擇循環類型',
|
||||
arrayLoop: '數組循環',
|
||||
numberLoop: '指定次數循環',
|
||||
infiniteLoop: '無限循環',
|
||||
},
|
||||
loopArray: {
|
||||
label: '循環數組',
|
||||
requiredMessage: '循環數組必填',
|
||||
placeholder: '請選擇循環數組',
|
||||
},
|
||||
loopSetting: '循環設置',
|
||||
loopDetail: '循環詳情',
|
||||
},
|
||||
loopStartNode: {
|
||||
label: '循環開始',
|
||||
loopIndex: '下標',
|
||||
loopItem: '循環元素',
|
||||
loopVariable: '循環變量',
|
||||
},
|
||||
loopBodyNode: { label: '循環體', text: '循環體' },
|
||||
loopContinueNode: { label: '跳過', text: '用於終止當前循環,執行下次循環' },
|
||||
loopBreakNode: { label: '退出循環', text: '終止當前循環,跳出循環體' },
|
||||
},
|
||||
compare: {
|
||||
is_null: '為空',
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ export const baseNode = {
|
|||
node_data: {
|
||||
name: '',
|
||||
desc: '',
|
||||
// @ts-ignore
|
||||
prologue: t('views.application.form.defaultPrologue'),
|
||||
tts_type: 'BROWSER',
|
||||
},
|
||||
|
|
@ -390,15 +389,15 @@ export const loopStartNode = {
|
|||
y: 3340,
|
||||
properties: {
|
||||
height: 364,
|
||||
stepName: t('views.applicationWorkflow.nodes.loopStartNode.label', '循环开始'),
|
||||
stepName: t('views.applicationWorkflow.nodes.loopStartNode.label'),
|
||||
config: {
|
||||
fields: [
|
||||
{
|
||||
label: t('views.applicationWorkflow.nodes.startNode.index', '下标'),
|
||||
label: t('views.applicationWorkflow.nodes.loopStartNode.loopIndex'),
|
||||
value: 'index',
|
||||
},
|
||||
{
|
||||
label: t('views.applicationWorkflow.nodes.startNode.item', '循环元素'),
|
||||
label: t('views.applicationWorkflow.nodes.loopStartNode.loopItem'),
|
||||
value: 'item',
|
||||
},
|
||||
],
|
||||
|
|
@ -411,11 +410,11 @@ export const loopStartNode = {
|
|||
export const loopNode = {
|
||||
type: WorkflowType.LoopNode,
|
||||
visible: false,
|
||||
text: t('views.applicationWorkflow.nodes.loopNode.text', '循环节点'),
|
||||
label: t('views.applicationWorkflow.nodes.loopNode.label', '循环节点'),
|
||||
text: t('views.applicationWorkflow.nodes.loopNode.text'),
|
||||
label: t('views.applicationWorkflow.nodes.loopNode.label'),
|
||||
height: 252,
|
||||
properties: {
|
||||
stepName: t('views.applicationWorkflow.nodes.loopNode.label', '循环节点'),
|
||||
stepName: t('views.applicationWorkflow.nodes.loopNode.label'),
|
||||
workflow: {
|
||||
edges: [],
|
||||
nodes: [
|
||||
|
|
@ -464,12 +463,12 @@ export const imageToVideoNode = {
|
|||
|
||||
export const loopBodyNode = {
|
||||
type: WorkflowType.LoopBodyNode,
|
||||
text: t('views.applicationWorkflow.nodes.loopBodyNode.text', '循环体'),
|
||||
label: t('views.applicationWorkflow.nodes.loopBodyNode.label', '循环体'),
|
||||
text: t('views.applicationWorkflow.nodes.loopBodyNode.text'),
|
||||
label: t('views.applicationWorkflow.nodes.loopBodyNode.label'),
|
||||
height: 1080,
|
||||
properties: {
|
||||
width: 1920,
|
||||
stepName: t('views.applicationWorkflow.nodes.loopBodyNode.label', '循环体'),
|
||||
stepName: t('views.applicationWorkflow.nodes.loopBodyNode.label'),
|
||||
config: {
|
||||
fields: [],
|
||||
},
|
||||
|
|
@ -477,12 +476,12 @@ export const loopBodyNode = {
|
|||
}
|
||||
export const loopContinueNode = {
|
||||
type: WorkflowType.LoopContinueNode,
|
||||
text: t('views.applicationWorkflow.nodes.continueNode.text', '跳过'),
|
||||
label: t('views.applicationWorkflow.nodes.continueNode.label', '跳过'),
|
||||
text: t('views.applicationWorkflow.nodes.loopContinueNode.text'),
|
||||
label: t('views.applicationWorkflow.nodes.loopContinueNode.label'),
|
||||
height: 600,
|
||||
properties: {
|
||||
width: 500,
|
||||
stepName: t('views.applicationWorkflow.nodes.continueNode.label', '跳过'),
|
||||
width: 600,
|
||||
stepName: t('views.applicationWorkflow.nodes.loopContinueNode.label'),
|
||||
config: {
|
||||
fields: [],
|
||||
},
|
||||
|
|
@ -509,11 +508,12 @@ export const textToVideoNode = {
|
|||
|
||||
export const loopBreakNode = {
|
||||
type: WorkflowType.LoopBreakNode,
|
||||
text: t('views.applicationWorkflow.nodes.breakNode.text', '退出循环'),
|
||||
label: t('views.applicationWorkflow.nodes.breakNode.label', '退出循环'),
|
||||
text: t('views.applicationWorkflow.nodes.loopBreakNode.text'),
|
||||
label: t('views.applicationWorkflow.nodes.loopBreakNode.label'),
|
||||
height: 600,
|
||||
properties: {
|
||||
stepName: t('views.applicationWorkflow.nodes.breakNode.label', '退出循环'),
|
||||
width: 600,
|
||||
stepName: t('views.applicationWorkflow.nodes.loopBreakNode.label'),
|
||||
config: {
|
||||
fields: [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<el-avatar class="avatar-gradient" shape="square">
|
||||
<img src="@/assets/workflow/icon_loop_break.svg" style="width: 100%" alt="" />
|
||||
<el-avatar class="avatar-green" shape="square">
|
||||
<img src="@/assets/workflow/icon_loop_break.svg" style="width: 75%" alt="" />
|
||||
</el-avatar>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<el-avatar class="avatar-gradient" shape="square">
|
||||
<img src="@/assets/workflow/icon_loop_break.svg" style="width: 100%" alt="" />
|
||||
<el-avatar class="avatar-green" shape="square">
|
||||
<img src="@/assets/workflow/icon_loop_break.svg" style="width: 75%" alt="" />
|
||||
</el-avatar>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<el-avatar class="avatar-gradient" shape="square">
|
||||
<img src="@/assets/workflow/icon_loop.svg" style="width: 75%" alt="" />
|
||||
<el-avatar class="avatar-green" shape="square">
|
||||
<img src="@/assets/workflow/icon_loop.svg" style="width: 65%" alt="" />
|
||||
</el-avatar>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
|
|
|
|||
|
|
@ -1,105 +1,107 @@
|
|||
<template>
|
||||
<NodeContainer :nodeModel="nodeModel">
|
||||
<el-form
|
||||
:model="form_data"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
label-width="auto"
|
||||
ref="ContinueFromRef"
|
||||
@submit.prevent
|
||||
>
|
||||
<div class="handle flex-between lighter">
|
||||
<div class="info" v-if="form_data.condition_list.length > 1">
|
||||
<span>{{ $t('views.applicationWorkflow.nodes.conditionNode.conditions.info') }}</span>
|
||||
<el-select
|
||||
:teleported="false"
|
||||
v-model="form_data.condition"
|
||||
size="small"
|
||||
style="width: 60px; margin: 0 8px"
|
||||
>
|
||||
<el-option :label="$t('views.applicationWorkflow.condition.AND')" value="and" />
|
||||
<el-option :label="$t('views.applicationWorkflow.condition.OR')" value="or" />
|
||||
</el-select>
|
||||
<span>{{ $t('views.applicationWorkflow.nodes.conditionNode.conditions.label') }}</span>
|
||||
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
|
||||
<el-form
|
||||
:model="form_data"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
label-width="auto"
|
||||
ref="ContinueFromRef"
|
||||
@submit.prevent
|
||||
>
|
||||
<div class="handle flex-between lighter mb-8">
|
||||
<div class="info" v-if="form_data.condition_list.length > 1">
|
||||
<span>{{ $t('views.applicationWorkflow.nodes.conditionNode.conditions.info') }}</span>
|
||||
<el-select
|
||||
:teleported="false"
|
||||
v-model="form_data.condition"
|
||||
size="small"
|
||||
style="width: 60px; margin: 0 8px"
|
||||
>
|
||||
<el-option :label="$t('views.applicationWorkflow.condition.AND')" value="and" />
|
||||
<el-option :label="$t('views.applicationWorkflow.condition.OR')" value="or" />
|
||||
</el-select>
|
||||
<span>{{ $t('views.applicationWorkflow.nodes.conditionNode.conditions.label') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template v-for="(condition, index) in form_data.condition_list" :key="index">
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="11">
|
||||
<el-form-item
|
||||
:prop="'condition_list.' + index + '.field'"
|
||||
: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="condition.field"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item
|
||||
:prop="'condition_list.' + index + '.compare'"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: $t(
|
||||
'views.applicationWorkflow.nodes.conditionNode.conditions.requiredMessage',
|
||||
),
|
||||
trigger: 'change',
|
||||
}"
|
||||
>
|
||||
<el-select
|
||||
@wheel="wheel"
|
||||
:teleported="false"
|
||||
v-model="condition.compare"
|
||||
:placeholder="
|
||||
$t('views.applicationWorkflow.nodes.conditionNode.conditions.requiredMessage')
|
||||
"
|
||||
clearable
|
||||
<template v-for="(condition, index) in form_data.condition_list" :key="index">
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="11">
|
||||
<el-form-item
|
||||
:prop="'condition_list.' + index + '.field'"
|
||||
:rules="{
|
||||
type: 'array',
|
||||
required: true,
|
||||
message: $t('views.applicationWorkflow.variable.placeholder'),
|
||||
trigger: 'change',
|
||||
}"
|
||||
>
|
||||
<template v-for="(item, index) in compareList" :key="index">
|
||||
<el-option :label="item.label" :value="item.value" />
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item
|
||||
v-if="
|
||||
!['is_null', 'is_not_null', 'is_true', 'is_not_true'].includes(condition.compare)
|
||||
"
|
||||
:prop="'condition_list.' + index + '.value'"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: $t('views.applicationWorkflow.nodes.conditionNode.valueMessage'),
|
||||
trigger: 'blur',
|
||||
}"
|
||||
>
|
||||
<el-input
|
||||
v-model="condition.value"
|
||||
:placeholder="$t('views.applicationWorkflow.nodes.conditionNode.valueMessage')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-button link type="info" class="mt-4" @click="deleteCondition(index)">
|
||||
<AppIcon iconName="app-delete"></AppIcon>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row> </template
|
||||
></el-form>
|
||||
<NodeCascader
|
||||
ref="nodeCascaderRef"
|
||||
:nodeModel="nodeModel"
|
||||
class="w-full"
|
||||
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
|
||||
v-model="condition.field"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item
|
||||
:prop="'condition_list.' + index + '.compare'"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: $t(
|
||||
'views.applicationWorkflow.nodes.conditionNode.conditions.requiredMessage',
|
||||
),
|
||||
trigger: 'change',
|
||||
}"
|
||||
>
|
||||
<el-select
|
||||
@wheel="wheel"
|
||||
:teleported="false"
|
||||
v-model="condition.compare"
|
||||
:placeholder="
|
||||
$t('views.applicationWorkflow.nodes.conditionNode.conditions.requiredMessage')
|
||||
"
|
||||
clearable
|
||||
>
|
||||
<template v-for="(item, index) in compareList" :key="index">
|
||||
<el-option :label="item.label" :value="item.value" />
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item
|
||||
v-if="
|
||||
!['is_null', 'is_not_null', 'is_true', 'is_not_true'].includes(condition.compare)
|
||||
"
|
||||
:prop="'condition_list.' + index + '.value'"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: $t('views.applicationWorkflow.nodes.conditionNode.valueMessage'),
|
||||
trigger: 'blur',
|
||||
}"
|
||||
>
|
||||
<el-input
|
||||
v-model="condition.value"
|
||||
:placeholder="$t('views.applicationWorkflow.nodes.conditionNode.valueMessage')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-button link type="info" class="mt-4" @click="deleteCondition(index)">
|
||||
<AppIcon iconName="app-delete"></AppIcon>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row> </template
|
||||
></el-form>
|
||||
|
||||
<el-button link type="primary" @click="addCondition()">
|
||||
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
|
||||
{{ $t('views.applicationWorkflow.nodes.conditionNode.addCondition') }}
|
||||
</el-button>
|
||||
<el-button link type="primary" @click="addCondition()">
|
||||
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
|
||||
{{ $t('views.applicationWorkflow.nodes.conditionNode.addCondition') }}
|
||||
</el-button>
|
||||
</el-card>
|
||||
</NodeContainer>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,105 +1,107 @@
|
|||
<template>
|
||||
<NodeContainer :nodeModel="nodeModel">
|
||||
<el-form
|
||||
:model="form_data"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
label-width="auto"
|
||||
ref="ContinueFromRef"
|
||||
@submit.prevent
|
||||
>
|
||||
<div class="handle flex-between lighter">
|
||||
<div class="info" v-if="form_data.condition_list.length > 1">
|
||||
<span>{{ $t('views.applicationWorkflow.nodes.conditionNode.conditions.info') }}</span>
|
||||
<el-select
|
||||
:teleported="false"
|
||||
v-model="form_data.condition"
|
||||
size="small"
|
||||
style="width: 60px; margin: 0 8px"
|
||||
>
|
||||
<el-option :label="$t('views.applicationWorkflow.condition.AND')" value="and" />
|
||||
<el-option :label="$t('views.applicationWorkflow.condition.OR')" value="or" />
|
||||
</el-select>
|
||||
<span>{{ $t('views.applicationWorkflow.nodes.conditionNode.conditions.label') }}</span>
|
||||
<el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
|
||||
<el-form
|
||||
:model="form_data"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
label-width="auto"
|
||||
ref="ContinueFromRef"
|
||||
@submit.prevent
|
||||
>
|
||||
<div class="handle flex-between lighter mb-8">
|
||||
<div class="info" v-if="form_data.condition_list.length > 1">
|
||||
<span>{{ $t('views.applicationWorkflow.nodes.conditionNode.conditions.info') }}</span>
|
||||
<el-select
|
||||
:teleported="false"
|
||||
v-model="form_data.condition"
|
||||
size="small"
|
||||
style="width: 60px; margin: 0 8px"
|
||||
>
|
||||
<el-option :label="$t('views.applicationWorkflow.condition.AND')" value="and" />
|
||||
<el-option :label="$t('views.applicationWorkflow.condition.OR')" value="or" />
|
||||
</el-select>
|
||||
<span>{{ $t('views.applicationWorkflow.nodes.conditionNode.conditions.label') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template v-for="(condition, index) in form_data.condition_list" :key="index">
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="11">
|
||||
<el-form-item
|
||||
:prop="'condition_list.' + index + '.field'"
|
||||
: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="condition.field"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item
|
||||
:prop="'condition_list.' + index + '.compare'"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: $t(
|
||||
'views.applicationWorkflow.nodes.conditionNode.conditions.requiredMessage',
|
||||
),
|
||||
trigger: 'change',
|
||||
}"
|
||||
>
|
||||
<el-select
|
||||
@wheel="wheel"
|
||||
:teleported="false"
|
||||
v-model="condition.compare"
|
||||
:placeholder="
|
||||
$t('views.applicationWorkflow.nodes.conditionNode.conditions.requiredMessage')
|
||||
"
|
||||
clearable
|
||||
<template v-for="(condition, index) in form_data.condition_list" :key="index">
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="11">
|
||||
<el-form-item
|
||||
:prop="'condition_list.' + index + '.field'"
|
||||
:rules="{
|
||||
type: 'array',
|
||||
required: true,
|
||||
message: $t('views.applicationWorkflow.variable.placeholder'),
|
||||
trigger: 'change',
|
||||
}"
|
||||
>
|
||||
<template v-for="(item, index) in compareList" :key="index">
|
||||
<el-option :label="item.label" :value="item.value" />
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item
|
||||
v-if="
|
||||
!['is_null', 'is_not_null', 'is_true', 'is_not_true'].includes(condition.compare)
|
||||
"
|
||||
:prop="'condition_list.' + index + '.value'"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: $t('views.applicationWorkflow.nodes.conditionNode.valueMessage'),
|
||||
trigger: 'blur',
|
||||
}"
|
||||
>
|
||||
<el-input
|
||||
v-model="condition.value"
|
||||
:placeholder="$t('views.applicationWorkflow.nodes.conditionNode.valueMessage')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-button link type="info" class="mt-4" @click="deleteCondition(index)">
|
||||
<AppIcon iconName="app-delete"></AppIcon>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row> </template
|
||||
></el-form>
|
||||
<NodeCascader
|
||||
ref="nodeCascaderRef"
|
||||
:nodeModel="nodeModel"
|
||||
class="w-full"
|
||||
:placeholder="$t('views.applicationWorkflow.variable.placeholder')"
|
||||
v-model="condition.field"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item
|
||||
:prop="'condition_list.' + index + '.compare'"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: $t(
|
||||
'views.applicationWorkflow.nodes.conditionNode.conditions.requiredMessage',
|
||||
),
|
||||
trigger: 'change',
|
||||
}"
|
||||
>
|
||||
<el-select
|
||||
@wheel="wheel"
|
||||
:teleported="false"
|
||||
v-model="condition.compare"
|
||||
:placeholder="
|
||||
$t('views.applicationWorkflow.nodes.conditionNode.conditions.requiredMessage')
|
||||
"
|
||||
clearable
|
||||
>
|
||||
<template v-for="(item, index) in compareList" :key="index">
|
||||
<el-option :label="item.label" :value="item.value" />
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item
|
||||
v-if="
|
||||
!['is_null', 'is_not_null', 'is_true', 'is_not_true'].includes(condition.compare)
|
||||
"
|
||||
:prop="'condition_list.' + index + '.value'"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: $t('views.applicationWorkflow.nodes.conditionNode.valueMessage'),
|
||||
trigger: 'blur',
|
||||
}"
|
||||
>
|
||||
<el-input
|
||||
v-model="condition.value"
|
||||
:placeholder="$t('views.applicationWorkflow.nodes.conditionNode.valueMessage')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<el-button link type="info" class="mt-4" @click="deleteCondition(index)">
|
||||
<AppIcon iconName="app-delete"></AppIcon>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row> </template
|
||||
></el-form>
|
||||
|
||||
<el-button link type="primary" @click="addCondition()">
|
||||
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
|
||||
{{ $t('views.applicationWorkflow.nodes.conditionNode.addCondition') }}
|
||||
</el-button>
|
||||
<el-button link type="primary" @click="addCondition()">
|
||||
<AppIcon iconName="app-add-outlined" class="mr-4"></AppIcon>
|
||||
{{ $t('views.applicationWorkflow.nodes.conditionNode.addCondition') }}
|
||||
</el-button>
|
||||
</el-card>
|
||||
</NodeContainer>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,44 +10,37 @@
|
|||
ref="replyNodeFormRef"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.label', '循环类型')"
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.label')"
|
||||
@click.prevent
|
||||
prop="loop_type"
|
||||
:rules="{
|
||||
message: $t('views.applicationWorkflow.nodes.loopNode.loopType.requiredMessage'),
|
||||
trigger: 'change',
|
||||
required: true,
|
||||
}"
|
||||
>
|
||||
<template #label>
|
||||
<div class="flex align-center">
|
||||
<div class="mr-4">
|
||||
<span
|
||||
>{{ $t('views.applicationWorkflow.nodes.loopNode.loopType.label', '循环类型')
|
||||
}}<span class="danger">*</span></span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-select v-model="form_data.loop_type" type="small">
|
||||
<el-option
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.array', '数组循环')"
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.arrayLoop')"
|
||||
value="ARRAY"
|
||||
/>
|
||||
<el-option
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.number', '指定次数循环')"
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.numberLoop')"
|
||||
value="NUMBER"
|
||||
/>
|
||||
<el-option
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loop', '无限循环')"
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.infiniteLoop')"
|
||||
value="LOOP"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form_data.loop_type == 'ARRAY'"
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.label', '循环数组')"
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopArray.label')"
|
||||
@click.prevent
|
||||
prop="array"
|
||||
:rules="{
|
||||
message: $t(
|
||||
'views.applicationWorkflow.nodes.loopNode.array.requiredMessage',
|
||||
'循环数组必填',
|
||||
),
|
||||
message: $t('views.applicationWorkflow.nodes.loopNode.loopArray.requiredMessage'),
|
||||
trigger: 'blur',
|
||||
required: true,
|
||||
}"
|
||||
|
|
@ -56,22 +49,17 @@
|
|||
ref="nodeCascaderRef"
|
||||
:nodeModel="nodeModel"
|
||||
class="w-full"
|
||||
:placeholder="
|
||||
$t('views.applicationWorkflow.nodes.loopNode.array.placeholder', '请选择循环数组')
|
||||
"
|
||||
:placeholder="$t('views.applicationWorkflow.nodes.loopNode.loopArray.placeholder')"
|
||||
v-model="form_data.array"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-else-if="form_data.loop_type == 'NUMBER'"
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopType.label', '循环数组')"
|
||||
:label="$t('views.applicationWorkflow.nodes.loopNode.loopArray.label')"
|
||||
@click.prevent
|
||||
prop="number"
|
||||
:rules="{
|
||||
message: $t(
|
||||
'views.applicationWorkflow.nodes.loopNode.array.requiredMessage',
|
||||
'循环数组必填',
|
||||
),
|
||||
message: $t('views.applicationWorkflow.nodes.loopNode.loopArray.requiredMessage'),
|
||||
trigger: 'blur',
|
||||
required: true,
|
||||
}"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<LoopFieldTable :nodeModel="nodeModel"></LoopFieldTable>
|
||||
<template v-if="loop_input_fields?.length">
|
||||
<h5 class="title-decoration-1 mb-8">
|
||||
{{ $t('views.applicationWorkflow.variable.loop', '循环变量') }}
|
||||
{{ $t('views.applicationWorkflow.nodes.loopStartNode.loopVariable') }}
|
||||
</h5>
|
||||
<div
|
||||
v-for="(item, index) in loop_input_fields || []"
|
||||
|
|
|
|||
Loading…
Reference in New Issue