mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 10:12:51 +00:00
Merge branch 'pr@main@application_flow' of github.com:1Panel-dev/MaxKB into pr@main@application_flow
This commit is contained in:
commit
96cfd07576
|
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<el-dialog title="执行详情" v-model="dialogVisible" destroy-on-close align-center @click.stop>
|
||||
<el-scrollbar>
|
||||
<div class="execution-details">
|
||||
<template v-for="(item, index) in arraySort(detail, 'index')" :key="index">
|
||||
<el-card class="mb-8" shadow="never" style="--el-card-padding: 12px 16px">
|
||||
<div class="flex-between cursor" @click="current = index">
|
||||
<div class="flex align-center">
|
||||
<el-icon class="mr-8 arrow-icon" :class="current === index ? 'rotate-90' : ''"
|
||||
><CaretRight
|
||||
/></el-icon>
|
||||
<component :is="iconComponent(`${item.type}-icon`)" class="mr-8" :size="24" />
|
||||
<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?.message_tokens + item?.answer_tokens }} tokens</span
|
||||
>
|
||||
<span class="mr-16 color-secondary">{{ item?.run_time?.toFixed(2) }} s</span>
|
||||
<el-icon class="success" :size="16"><CircleCheck /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<el-collapse-transition>
|
||||
<div class="card-never border-r-4 mt-8" v-if="current === index">
|
||||
<h5 class="p-8-12">参数输入</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">如何快速开始</div>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</el-card>
|
||||
</template>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onBeforeUnmount } from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { arraySort } from '@/utils/utils'
|
||||
import { iconComponent } from '@/workflow/icons/utils'
|
||||
import { WorkflowType } from '@/enums/workflow'
|
||||
import { MdPreview } from 'md-editor-v3'
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const detail = ref<any[]>([])
|
||||
|
||||
const current = ref<number | string>('')
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
if (!bool) {
|
||||
detail.value = []
|
||||
}
|
||||
})
|
||||
|
||||
const open = (data: any) => {
|
||||
detail.value = cloneDeep(data)
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
dialogVisible.value = false
|
||||
})
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.execution-details {
|
||||
max-height: calc(100vh - 260px);
|
||||
.arrow-icon {
|
||||
transition: 0.2s;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="flex align-center mt-16">
|
||||
<div class="flex align-center mt-16" v-if="!isWorkFlow(props.type)">
|
||||
<span class="mr-4 color-secondary">知识来源</span>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button type="primary" class="mr-8" link @click="openParagraph(data)">
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
引用分段 {{ data.paragraph_list?.length || 0 }}</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="mt-8 mb-12">
|
||||
<div class="mt-8" v-if="!isWorkFlow(props.type)">
|
||||
<el-space wrap>
|
||||
<el-button
|
||||
v-for="(dataset, index) in data.dataset_list"
|
||||
|
|
@ -20,28 +20,51 @@
|
|||
</el-space>
|
||||
</div>
|
||||
|
||||
<div class="border-t color-secondary" style="padding-top: 12px">
|
||||
<span class="mr-8"> 消耗 tokens: {{ data?.message_tokens + data?.answer_tokens }} </span>
|
||||
<span> 耗时: {{ data?.run_time?.toFixed(2) }} s</span>
|
||||
<div class="border-t color-secondary flex-between mt-12" style="padding-top: 12px">
|
||||
<div>
|
||||
<span class="mr-8"> 消耗 tokens: {{ data?.message_tokens + data?.answer_tokens }} </span>
|
||||
<span> 耗时: {{ data?.run_time?.toFixed(2) }} s</span>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="isWorkFlow(props.type)"
|
||||
type="primary"
|
||||
link
|
||||
@click="openExecutionDetail(data.execution_details)"
|
||||
>
|
||||
<el-icon class="mr-4"><Document /></el-icon>
|
||||
执行详情</el-button
|
||||
>
|
||||
</div>
|
||||
<!-- 知识库引用 dialog -->
|
||||
<ParagraphSourceDialog ref="ParagraphSourceDialogRef" />
|
||||
<!-- 执行详情 dialog -->
|
||||
<ExecutionDetailDialog ref="ExecutionDetialDialogRef" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import ParagraphSourceDialog from './ParagraphSourceDialog.vue'
|
||||
import ExecutionDetailDialog from './ExecutionDetailDialog.vue'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const ParagraphSourceDialogRef = ref()
|
||||
const ExecutionDetialDialogRef = ref()
|
||||
function openParagraph(row: any, id?: string) {
|
||||
ParagraphSourceDialogRef.value.open(row, id)
|
||||
}
|
||||
function openExecutionDetail(row: any) {
|
||||
ExecutionDetialDialogRef.value.open(row)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.source_dataset-button {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
<MdRenderer :source="item.answer_text"></MdRenderer>
|
||||
<!-- 知识来源 -->
|
||||
<div v-if="showSource(item)">
|
||||
<KnowledgeSource :data="item" />
|
||||
<KnowledgeSource :data="item" :type="props.data.type" />
|
||||
</div>
|
||||
</el-card>
|
||||
<div class="flex-between mt-8" v-if="log">
|
||||
|
|
@ -153,6 +153,7 @@ import { ChatManagement, type chatType } from '@/api/type/application'
|
|||
import { randomId } from '@/utils/utils'
|
||||
import useStore from '@/stores'
|
||||
import MdRenderer from '@/components/markdown-renderer/MdRenderer.vue'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
import { MdPreview } from 'md-editor-v3'
|
||||
import { debounce } from 'lodash'
|
||||
defineOptions({ name: 'AiChat' })
|
||||
|
|
@ -335,7 +336,7 @@ function getChartOpenId(chat?: any) {
|
|||
}
|
||||
})
|
||||
} else {
|
||||
if (obj.type === 'WORK_FLOW') {
|
||||
if (isWorkFlow(obj.type)) {
|
||||
const submitObj = {
|
||||
work_flow: obj.work_flow
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
export enum WorkflowType {
|
||||
Base = 'base-node',
|
||||
Start = 'start-node',
|
||||
AiChat = 'ai-chat-node',
|
||||
SearchDataset = 'search-dataset-node',
|
||||
Question = 'question-node',
|
||||
Condition = 'condition-node',
|
||||
Reply = 'reply-node'
|
||||
}
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { onBeforeRouteLeave, useRouter, useRoute } from 'vue-router'
|
||||
import { isAppIcon } from '@/utils/application'
|
||||
import { isAppIcon, isWorkFlow } from '@/utils/application'
|
||||
import useStore from '@/stores'
|
||||
const { common, dataset, application } = useStore()
|
||||
const route = useRoute()
|
||||
|
|
@ -162,7 +162,7 @@ function changeMenu(id: string) {
|
|||
} else if (isApplication.value) {
|
||||
const type = list.value?.filter((v) => v.id === id)?.[0]?.type
|
||||
if (
|
||||
type === 'WORK_FLOW' &&
|
||||
isWorkFlow(type) &&
|
||||
(lastMatched.name === 'AppSetting' || lastMatched.name === 'AppHitTest')
|
||||
) {
|
||||
router.push({ path: `/application/${id}/${type}/overview` })
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useRouter, useRoute, type RouteRecordRaw } from 'vue-router'
|
||||
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
const props = defineProps<{
|
||||
menu: RouteRecordRaw
|
||||
activeMenu: any
|
||||
|
|
@ -30,7 +30,7 @@ const {
|
|||
} = route as any
|
||||
|
||||
function showMenu() {
|
||||
if (type === 'WORK_FLOW') {
|
||||
if (isWorkFlow(type)) {
|
||||
return props.menu.name !== 'AppHitTest'
|
||||
} else {
|
||||
return true
|
||||
|
|
@ -38,7 +38,7 @@ function showMenu() {
|
|||
}
|
||||
|
||||
function clickHandle(item: any) {
|
||||
if (type === 'WORK_FLOW' && item.name === 'AppSetting') {
|
||||
if (isWorkFlow(type) && item.name === 'AppSetting') {
|
||||
router.push({ path: `/application/${id}/workflow` })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,6 +288,10 @@ h5 {
|
|||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.border-t-dashed {
|
||||
border-top: 1px dashed var(--el-border-color);
|
||||
}
|
||||
|
||||
.cursor {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,3 +4,7 @@ export const defaultIcon = '/ui/favicon.ico'
|
|||
export function isAppIcon(url: string | undefined) {
|
||||
return url === defaultIcon ? '' : url
|
||||
}
|
||||
|
||||
export function isWorkFlow(type: string | undefined) {
|
||||
return type === 'WORK_FLOW'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export function relatedObject(list: any, val: any, attr: string) {
|
|||
}
|
||||
|
||||
// 排序
|
||||
export function arraySort(list: Array<string>, property: any, desc?: boolean) {
|
||||
export function arraySort(list: Array<any>, property: any, desc?: boolean) {
|
||||
return list.sort((a: any, b: any) => {
|
||||
return desc ? b[property] - a[property] : a[property] - b[property]
|
||||
})
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
<h5 class="title">基础组件</h5>
|
||||
<template v-for="(item, index) in menuNodes" :key="index">
|
||||
<div class="workflow-dropdown-item cursor flex p-8-12" @mousedown="onmousedown(item)">
|
||||
<component :is="iconComponent(item.icon)" class="mr-8 mt-4" :size="32" />
|
||||
<component :is="iconComponent(`${item.type}-icon`)" class="mr-8 mt-4" :size="32" />
|
||||
<div class="pre-line">
|
||||
<div class="lighter">{{ item.label }}</div>
|
||||
<el-text type="info" size="small">{{ item.text }}</el-text>
|
||||
|
|
@ -87,6 +87,7 @@ import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message'
|
|||
import { datetimeFormat } from '@/utils/time'
|
||||
import useStore from '@/stores'
|
||||
import { WorkFlowInstanse } from '@/workflow/common/validate'
|
||||
|
||||
const { application } = useStore()
|
||||
const route = useRoute()
|
||||
|
||||
|
|
@ -134,6 +135,7 @@ const clickShowDebug = () => {
|
|||
const workflow = new WorkFlowInstanse(graphData)
|
||||
try {
|
||||
workflow.is_valid()
|
||||
getDetail()
|
||||
showDebug.value = true
|
||||
} catch (e: any) {
|
||||
MsgError(e.toString())
|
||||
|
|
@ -242,7 +244,7 @@ onBeforeUnmount(() => {
|
|||
}
|
||||
|
||||
.workflow-debug-container {
|
||||
z-index: 10000;
|
||||
z-index: 2000;
|
||||
position: relative;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ffffff;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
<el-card
|
||||
shadow="never"
|
||||
class="mb-16"
|
||||
:class="applicationForm.type === 'WORK_FLOW' ? 'active' : ''"
|
||||
:class="isWorkFlow(applicationForm.type) ? 'active' : ''"
|
||||
>
|
||||
<el-radio value="WORK_FLOW" size="large">
|
||||
<p class="mb-4">高级编排</p>
|
||||
|
|
@ -80,6 +80,7 @@ import type { ApplicationFormType } from '@/api/type/application'
|
|||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import applicationApi from '@/api/application'
|
||||
import { MsgSuccess } from '@/utils/message'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
import { t } from '@/locales'
|
||||
const router = useRouter()
|
||||
|
||||
|
|
@ -174,7 +175,7 @@ const submitHandle = async (formEl: FormInstance | undefined) => {
|
|||
applicationApi.postApplication(applicationForm.value, loading).then((res) => {
|
||||
console.log(res)
|
||||
MsgSuccess(t('views.application.applicationForm.buttons.createSuccess'))
|
||||
if (applicationForm.value.type === 'WORK_FLOW') {
|
||||
if (isWorkFlow(applicationForm.value.type)) {
|
||||
router.push({ path: `/application/${res.data.id}/workflow` })
|
||||
} else {
|
||||
router.push({ path: `/application/${res.data.id}/${res.data.type}/setting` })
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ import CreateApplicationDialog from './component/CreateApplicationDialog.vue'
|
|||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import { isAppIcon } from '@/utils/application'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
import useStore from '@/stores'
|
||||
import { t } from '@/locales'
|
||||
const { application } = useStore()
|
||||
|
|
@ -133,10 +134,6 @@ const paginationConfig = reactive({
|
|||
|
||||
const searchValue = ref('')
|
||||
|
||||
function isWorkFlow(type: string) {
|
||||
return type === 'WORK_FLOW'
|
||||
}
|
||||
|
||||
function settingApplication(row: any) {
|
||||
if (isWorkFlow(row.type)) {
|
||||
router.push({ path: `/application/${row.id}/workflow` })
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
import { ref } from 'vue'
|
||||
import { iconComponent } from '../icons/utils'
|
||||
import { copyClick } from '@/utils/clipboard'
|
||||
import { WorkflowType } from '@/enums/workflow'
|
||||
const height = ref<{
|
||||
stepContainerHeight: number
|
||||
inputContainerHeight: number
|
||||
|
|
@ -79,7 +80,7 @@ const props = defineProps<{
|
|||
}>()
|
||||
|
||||
function showOperate(type: string) {
|
||||
return type !== 'base-node' && type !== 'start-node'
|
||||
return type !== WorkflowType.Base && type !== WorkflowType.Start
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { h as lh } from '@logicflow/core'
|
|||
import { createApp, h } from 'vue'
|
||||
import directives from '@/directives'
|
||||
import i18n from '@/locales'
|
||||
import { WorkflowType } from '@/enums/workflow'
|
||||
|
||||
class AppNode extends HtmlResize.view {
|
||||
isMounted
|
||||
|
|
@ -171,8 +172,8 @@ class AppNodeModel extends HtmlResize.model {
|
|||
const { id, x, y, width } = this
|
||||
const anchors: any = []
|
||||
|
||||
if (this.type !== 'base-node') {
|
||||
if (this.type !== 'start-node') {
|
||||
if (this.type !== WorkflowType.Base) {
|
||||
if (this.type !== WorkflowType.Start) {
|
||||
anchors.push({
|
||||
x: x - width / 2 + 10,
|
||||
y: y,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import { WorkflowType } from '@/enums/workflow'
|
||||
|
||||
/**
|
||||
* 说明
|
||||
* type 与 nodes 文件对应
|
||||
*/
|
||||
export const baseNodes = [
|
||||
{
|
||||
id: 'base-node',
|
||||
type: 'base-node',
|
||||
id: WorkflowType.Base,
|
||||
type: WorkflowType.Base,
|
||||
x: 200,
|
||||
y: 270,
|
||||
properties: {
|
||||
|
|
@ -20,8 +22,8 @@ export const baseNodes = [
|
|||
}
|
||||
},
|
||||
{
|
||||
id: 'start-node',
|
||||
type: 'start-node',
|
||||
id: WorkflowType.Start,
|
||||
type: WorkflowType.Start,
|
||||
x: 180,
|
||||
y: 720,
|
||||
properties: {
|
||||
|
|
@ -32,7 +34,7 @@ export const baseNodes = [
|
|||
label: '用户问题',
|
||||
value: 'question',
|
||||
globeLabel: '{{开始.question}}',
|
||||
globeValue: "{{content['start-node'].question}}"
|
||||
globeValue: `{{content['${WorkflowType.Start}'].question}}`
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -41,10 +43,9 @@ export const baseNodes = [
|
|||
|
||||
export const menuNodes = [
|
||||
{
|
||||
type: 'ai-chat-node',
|
||||
type: WorkflowType.AiChat,
|
||||
text: '与 AI 大模型进行对话',
|
||||
label: 'AI 对话',
|
||||
icon: 'ai-chat-node-icon',
|
||||
properties: {
|
||||
stepName: 'AI 对话',
|
||||
fields: [
|
||||
|
|
@ -56,10 +57,9 @@ export const menuNodes = [
|
|||
}
|
||||
},
|
||||
{
|
||||
type: 'search-dataset-node',
|
||||
type: WorkflowType.SearchDataset,
|
||||
text: '关联知识库,查找与问题相关的分段',
|
||||
label: '知识库检索',
|
||||
icon: 'search-dataset-node-icon',
|
||||
properties: {
|
||||
stepName: '知识库检索',
|
||||
fields: [
|
||||
|
|
@ -77,10 +77,9 @@ export const menuNodes = [
|
|||
}
|
||||
},
|
||||
{
|
||||
type: 'question-node',
|
||||
type: WorkflowType.Question,
|
||||
text: '根据历史聊天记录优化完善当前问题,更利于匹配知识库分段',
|
||||
label: '问题优化',
|
||||
icon: 'question-node-icon',
|
||||
properties: {
|
||||
stepName: '问题优化',
|
||||
fields: [
|
||||
|
|
@ -92,20 +91,18 @@ export const menuNodes = [
|
|||
}
|
||||
},
|
||||
{
|
||||
type: 'condition-node',
|
||||
type: WorkflowType.Condition,
|
||||
text: '根据不同条件执行不同的节点',
|
||||
label: '判断器',
|
||||
icon: 'condition-node-icon',
|
||||
properties: {
|
||||
width: 600,
|
||||
stepName: '判断器'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'reply-node',
|
||||
type: WorkflowType.Reply,
|
||||
text: '指定回复内容,引用变量会转换为字符串进行输出',
|
||||
label: '指定回复',
|
||||
icon: 'reply-node-icon',
|
||||
properties: {
|
||||
stepName: '指定回复'
|
||||
}
|
||||
|
|
@ -125,3 +122,7 @@ export const compareList = [
|
|||
{ value: 'len_lt', label: '长度小于' },
|
||||
{ value: 'lt', label: '小于' }
|
||||
]
|
||||
|
||||
export function isWorkFlow(type: string | undefined) {
|
||||
return type === 'WORK_FLOW'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
const end_nodes = ['ai-chat-node', 'reply-node']
|
||||
import { WorkflowType } from '@/enums/workflow'
|
||||
|
||||
const end_nodes = [WorkflowType.AiChat, WorkflowType.Reply]
|
||||
export class WorkFlowInstanse {
|
||||
nodes
|
||||
edges
|
||||
|
|
@ -10,7 +12,7 @@ export class WorkFlowInstanse {
|
|||
* 校验开始节点
|
||||
*/
|
||||
private is_valid_start_node() {
|
||||
const start_node_list = this.nodes.filter((item) => item.id === 'start-node')
|
||||
const start_node_list = this.nodes.filter((item) => item.id === WorkflowType.Start)
|
||||
if (start_node_list.length == 0) {
|
||||
throw '开始节点必填'
|
||||
} else if (start_node_list.length > 1) {
|
||||
|
|
@ -21,7 +23,7 @@ export class WorkFlowInstanse {
|
|||
* 校验基本信息节点
|
||||
*/
|
||||
private is_valid_base_node() {
|
||||
const start_node_list = this.nodes.filter((item) => item.id === 'base-node')
|
||||
const start_node_list = this.nodes.filter((item) => item.id === WorkflowType.Base)
|
||||
if (start_node_list.length == 0) {
|
||||
throw '基本信息节点必填'
|
||||
} else if (start_node_list.length > 1) {
|
||||
|
|
@ -43,7 +45,7 @@ export class WorkFlowInstanse {
|
|||
* @returns
|
||||
*/
|
||||
get_start_node() {
|
||||
const start_node_list = this.nodes.filter((item) => item.id === 'start-node')
|
||||
const start_node_list = this.nodes.filter((item) => item.id === WorkflowType.Start)
|
||||
return start_node_list[0]
|
||||
}
|
||||
/**
|
||||
|
|
@ -51,7 +53,7 @@ export class WorkFlowInstanse {
|
|||
* @returns 基本节点
|
||||
*/
|
||||
get_base_node() {
|
||||
const base_node_list = this.nodes.filter((item) => item.id === 'base-node')
|
||||
const base_node_list = this.nodes.filter((item) => item.id === WorkflowType.Base)
|
||||
return base_node_list[0]
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +88,7 @@ export class WorkFlowInstanse {
|
|||
}
|
||||
private is_valid_nodes() {
|
||||
for (const node of this.nodes) {
|
||||
if (node.type !== 'base-node' && node.type !== 'start-node') {
|
||||
if (node.type !== WorkflowType.Base && node.type !== WorkflowType.Start) {
|
||||
console.log(node.properties.stepName)
|
||||
if (!this.edges.some((edge) => edge.targetNodeId === node.id)) {
|
||||
throw `未在流程中的节点:${node.properties.stepName}`
|
||||
|
|
@ -99,7 +101,7 @@ export class WorkFlowInstanse {
|
|||
* @param node 节点
|
||||
*/
|
||||
private is_valid_node(node: any) {
|
||||
if (node.type === 'condition-node') {
|
||||
if (node.type === WorkflowType.Condition) {
|
||||
const branch_list = node.properties.node_data.branch
|
||||
for (const branch of branch_list) {
|
||||
const source_anchor_id = `${node.id}_${branch.id}_right`
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
@mousedown.stop
|
||||
@keydown.stop
|
||||
@click.stop
|
||||
@wheel.stop
|
||||
:model="chat_data"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
@mousedown.stop
|
||||
@keydown.stop
|
||||
@click.stop
|
||||
@wheel.stop
|
||||
:model="form_data"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
|
|
|
|||
Loading…
Reference in New Issue