mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: Support session variables (#3792)
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
This commit is contained in:
parent
0e78245bfb
commit
83a1ffb891
|
|
@ -23,6 +23,7 @@ def get_default_global_variable(input_field_list: List):
|
|||
if item.get('default_value', None) is not None
|
||||
}
|
||||
|
||||
|
||||
def get_global_variable(node):
|
||||
body = node.workflow_manage.get_body()
|
||||
history_chat_record = node.flow_params_serializer.data.get('history_chat_record', [])
|
||||
|
|
@ -74,6 +75,7 @@ class BaseStartStepNode(IStarNode):
|
|||
'other': self.workflow_manage.other_list,
|
||||
|
||||
}
|
||||
self.workflow_manage.chat_context = self.workflow_manage.get_chat_info().get_chat_variable()
|
||||
return NodeResult(node_variable, workflow_variable)
|
||||
|
||||
def get_details(self, index: int, **kwargs):
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
import json
|
||||
from typing import List
|
||||
|
||||
from django.db.models import QuerySet
|
||||
|
||||
from application.flow.i_step_node import NodeResult
|
||||
from application.flow.step_node.variable_assign_node.i_variable_assign_node import IVariableAssignNode
|
||||
from application.models import Chat
|
||||
|
||||
|
||||
class BaseVariableAssignNode(IVariableAssignNode):
|
||||
|
|
@ -11,40 +14,56 @@ class BaseVariableAssignNode(IVariableAssignNode):
|
|||
self.context['variable_list'] = details.get('variable_list')
|
||||
self.context['result_list'] = details.get('result_list')
|
||||
|
||||
def global_evaluation(self, variable, value):
|
||||
self.workflow_manage.context[variable['fields'][1]] = value
|
||||
|
||||
def chat_evaluation(self, variable, value):
|
||||
self.workflow_manage.chat_context[variable['fields'][1]] = value
|
||||
|
||||
def handle(self, variable, evaluation):
|
||||
result = {
|
||||
'name': variable['name'],
|
||||
'input_value': self.get_reference_content(variable['fields']),
|
||||
}
|
||||
if variable['source'] == 'custom':
|
||||
if variable['type'] == 'json':
|
||||
if isinstance(variable['value'], dict) or isinstance(variable['value'], list):
|
||||
val = variable['value']
|
||||
else:
|
||||
val = json.loads(variable['value'])
|
||||
evaluation(variable, val)
|
||||
result['output_value'] = variable['value'] = val
|
||||
elif variable['type'] == 'string':
|
||||
# 变量解析 例如:{{global.xxx}}
|
||||
val = self.workflow_manage.generate_prompt(variable['value'])
|
||||
evaluation(variable, val)
|
||||
result['output_value'] = val
|
||||
else:
|
||||
val = variable['value']
|
||||
evaluation(variable, val)
|
||||
result['output_value'] = val
|
||||
else:
|
||||
reference = self.get_reference_content(variable['reference'])
|
||||
evaluation(variable, reference)
|
||||
result['output_value'] = reference
|
||||
return result
|
||||
|
||||
def execute(self, variable_list, stream, **kwargs) -> NodeResult:
|
||||
#
|
||||
result_list = []
|
||||
is_chat = False
|
||||
for variable in variable_list:
|
||||
if 'fields' not in variable:
|
||||
continue
|
||||
if 'global' == variable['fields'][0]:
|
||||
result = {
|
||||
'name': variable['name'],
|
||||
'input_value': self.get_reference_content(variable['fields']),
|
||||
}
|
||||
if variable['source'] == 'custom':
|
||||
if variable['type'] == 'json':
|
||||
if isinstance(variable['value'], dict) or isinstance(variable['value'], list):
|
||||
val = variable['value']
|
||||
else:
|
||||
val = json.loads(variable['value'])
|
||||
self.workflow_manage.context[variable['fields'][1]] = val
|
||||
result['output_value'] = variable['value'] = val
|
||||
elif variable['type'] == 'string':
|
||||
# 变量解析 例如:{{global.xxx}}
|
||||
val = self.workflow_manage.generate_prompt(variable['value'])
|
||||
self.workflow_manage.context[variable['fields'][1]] = val
|
||||
result['output_value'] = val
|
||||
else:
|
||||
val = variable['value']
|
||||
self.workflow_manage.context[variable['fields'][1]] = val
|
||||
result['output_value'] = val
|
||||
else:
|
||||
reference = self.get_reference_content(variable['reference'])
|
||||
self.workflow_manage.context[variable['fields'][1]] = reference
|
||||
result['output_value'] = reference
|
||||
result = self.handle(variable, self.global_evaluation)
|
||||
result_list.append(result)
|
||||
|
||||
if 'chat' == variable['fields'][0]:
|
||||
result = self.handle(variable, self.chat_evaluation)
|
||||
result_list.append(result)
|
||||
is_chat = True
|
||||
if is_chat:
|
||||
self.workflow_manage.get_chat_info().set_chat_variable(self.workflow_manage.chat_context)
|
||||
return NodeResult({'variable_list': variable_list, 'result_list': result_list}, {})
|
||||
|
||||
def get_reference_content(self, fields: List[str]):
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ class WorkflowManage:
|
|||
self.params = params
|
||||
self.flow = flow
|
||||
self.context = {}
|
||||
self.chat_context = {}
|
||||
self.node_chunk_manage = NodeChunkManage(self)
|
||||
self.work_flow_post_handler = work_flow_post_handler
|
||||
self.current_node = None
|
||||
|
|
@ -131,6 +132,7 @@ class WorkflowManage:
|
|||
self.lock = threading.Lock()
|
||||
self.field_list = []
|
||||
self.global_field_list = []
|
||||
self.chat_field_list = []
|
||||
self.init_fields()
|
||||
if start_node_id is not None:
|
||||
self.load_node(chat_record, start_node_id, start_node_data)
|
||||
|
|
@ -140,6 +142,7 @@ class WorkflowManage:
|
|||
def init_fields(self):
|
||||
field_list = []
|
||||
global_field_list = []
|
||||
chat_field_list = []
|
||||
for node in self.flow.nodes:
|
||||
properties = node.properties
|
||||
node_name = properties.get('stepName')
|
||||
|
|
@ -154,10 +157,16 @@ class WorkflowManage:
|
|||
if global_fields is not None:
|
||||
for global_field in global_fields:
|
||||
global_field_list.append({**global_field, 'node_id': node_id, 'node_name': node_name})
|
||||
chat_fields = node_config.get('chatFields')
|
||||
if chat_fields is not None:
|
||||
for chat_field in chat_fields:
|
||||
chat_field_list.append({**chat_field, 'node_id': node_id, 'node_name': node_name})
|
||||
field_list.sort(key=lambda f: len(f.get('node_name') + f.get('value')), reverse=True)
|
||||
global_field_list.sort(key=lambda f: len(f.get('node_name') + f.get('value')), reverse=True)
|
||||
chat_field_list.sort(key=lambda f: len(f.get('node_name') + f.get('value')), reverse=True)
|
||||
self.field_list = field_list
|
||||
self.global_field_list = global_field_list
|
||||
self.chat_field_list = chat_field_list
|
||||
|
||||
def append_answer(self, content):
|
||||
self.answer += content
|
||||
|
|
@ -445,6 +454,9 @@ class WorkflowManage:
|
|||
return current_node.node_params.get('is_result', not self._has_next_node(
|
||||
current_node, current_node_result)) if current_node.node_params is not None else False
|
||||
|
||||
def get_chat_info(self):
|
||||
return self.work_flow_post_handler.chat_info
|
||||
|
||||
def get_chunk_content(self, chunk, is_end=False):
|
||||
return 'data: ' + json.dumps(
|
||||
{'chat_id': self.params['chat_id'], 'id': self.params['chat_record_id'], 'operate': True,
|
||||
|
|
@ -587,12 +599,15 @@ class WorkflowManage:
|
|||
"""
|
||||
if node_id == 'global':
|
||||
return INode.get_field(self.context, fields)
|
||||
elif node_id == 'chat':
|
||||
return INode.get_field(self.chat_context, fields)
|
||||
else:
|
||||
return self.get_node_by_id(node_id).get_reference_field(fields)
|
||||
|
||||
def get_workflow_content(self):
|
||||
context = {
|
||||
'global': self.context,
|
||||
'chat': self.chat_context
|
||||
}
|
||||
|
||||
for node in self.node_context:
|
||||
|
|
@ -610,6 +625,10 @@ class WorkflowManage:
|
|||
globeLabelNew = f"global.{field.get('value')}"
|
||||
globeValue = f"context.get('global').get('{field.get('value', '')}','')"
|
||||
prompt = prompt.replace(globeLabel, globeValue).replace(globeLabelNew, globeValue)
|
||||
for field in self.chat_field_list:
|
||||
chatLabel = f"chat.{field.get('value')}"
|
||||
chatValue = f"context.get('chat').get('{field.get('value', '')}','')"
|
||||
prompt = prompt.replace(chatLabel, chatValue)
|
||||
return prompt
|
||||
|
||||
def generate_prompt(self, prompt: str):
|
||||
|
|
|
|||
|
|
@ -166,6 +166,34 @@ class ChatInfo:
|
|||
'exclude_paragraph_id_list': exclude_paragraph_id_list, 'stream': stream, 'chat_user_id': chat_user_id,
|
||||
'chat_user_type': chat_user_type, 'form_data': form_data}
|
||||
|
||||
def set_chat(self, question):
|
||||
if not self.debug:
|
||||
if not QuerySet(Chat).filter(id=self.chat_id).exists():
|
||||
Chat(id=self.chat_id, application_id=self.application_id, abstract=question[0:1024],
|
||||
chat_user_id=self.chat_user_id, chat_user_type=self.chat_user_type,
|
||||
asker=self.get_chat_user()).save()
|
||||
|
||||
def set_chat_variable(self, chat_context):
|
||||
if not self.debug:
|
||||
chat = QuerySet(Chat).filter(id=self.chat_id).first()
|
||||
if chat:
|
||||
chat.meta = {**(chat.meta if isinstance(chat.meta, dict) else {}), **chat_context}
|
||||
chat.save()
|
||||
else:
|
||||
cache.set(Cache_Version.CHAT_VARIABLE.get_key(key=self.chat_id), chat_context,
|
||||
version=Cache_Version.CHAT_VARIABLE.get_version(),
|
||||
timeout=60 * 30)
|
||||
|
||||
def get_chat_variable(self):
|
||||
if not self.debug:
|
||||
chat = QuerySet(Chat).filter(id=self.chat_id).first()
|
||||
if chat:
|
||||
return chat.meta
|
||||
return {}
|
||||
else:
|
||||
return cache.get(Cache_Version.CHAT_VARIABLE.get_key(key=self.chat_id),
|
||||
version=Cache_Version.CHAT_VARIABLE.get_version()) or {}
|
||||
|
||||
def append_chat_record(self, chat_record: ChatRecord):
|
||||
chat_record.problem_text = chat_record.problem_text[0:10240] if chat_record.problem_text is not None else ""
|
||||
chat_record.answer_text = chat_record.answer_text[0:40960] if chat_record.problem_text is not None else ""
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ class ChatSerializers(serializers.Serializer):
|
|||
# 构建运行参数
|
||||
params = chat_info.to_pipeline_manage_params(message, get_post_handler(chat_info), exclude_paragraph_id_list,
|
||||
chat_user_id, chat_user_type, stream, form_data)
|
||||
chat_info.set_chat(message)
|
||||
# 运行流水线作业
|
||||
pipeline_message.run(params)
|
||||
return pipeline_message.context['chat_result']
|
||||
|
|
@ -307,6 +308,7 @@ class ChatSerializers(serializers.Serializer):
|
|||
other_list,
|
||||
instance.get('runtime_node_id'),
|
||||
instance.get('node_data'), chat_record, instance.get('child_node'))
|
||||
chat_info.set_chat(message)
|
||||
r = work_flow_manage.run()
|
||||
return r
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ class Cache_Version(Enum):
|
|||
|
||||
# 对话
|
||||
CHAT = "CHAT", lambda key: key
|
||||
|
||||
CHAT_VARIABLE = "CHAT_VARIABLE", lambda key: key
|
||||
|
||||
# 应用API KEY
|
||||
APPLICATION_API_KEY = "APPLICATION_API_KEY", lambda secret_key, use_get_data: secret_key
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ export default {
|
|||
variable: {
|
||||
label: '变量',
|
||||
global: '全局变量',
|
||||
chat: '会话变量',
|
||||
Referencing: '引用变量',
|
||||
ReferencingRequired: '引用变量必填',
|
||||
ReferencingError: '引用变量错误',
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ const wheel = (e: any) => {
|
|||
function visibleChange(bool: boolean) {
|
||||
if (bool) {
|
||||
options.value = props.global
|
||||
? props.nodeModel.get_up_node_field_list(false, true).filter((v: any) => v.value === 'global')
|
||||
? props.nodeModel
|
||||
.get_up_node_field_list(false, true)
|
||||
.filter((v: any) => ['global', 'chat'].includes(v.value))
|
||||
: props.nodeModel.get_up_node_field_list(false, true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class AppNode extends HtmlResize.view {
|
|||
} else {
|
||||
const filterNodes = props.graphModel.nodes.filter((v: any) => v.type === props.model.type)
|
||||
const filterNameSameNodes = filterNodes.filter(
|
||||
(v: any) => v.properties.stepName === props.model.properties.stepName
|
||||
(v: any) => v.properties.stepName === props.model.properties.stepName,
|
||||
)
|
||||
if (filterNameSameNodes.length - 1 > 0) {
|
||||
getNodesName(filterNameSameNodes.length - 1)
|
||||
|
|
@ -61,14 +61,20 @@ class AppNode extends HtmlResize.view {
|
|||
value: 'global',
|
||||
label: t('views.applicationWorkflow.variable.global'),
|
||||
type: 'global',
|
||||
children: this.props.model.properties?.config?.globalFields || []
|
||||
children: this.props.model.properties?.config?.globalFields || [],
|
||||
})
|
||||
result.push({
|
||||
value: 'chat',
|
||||
label: t('views.applicationWorkflow.variable.chat'),
|
||||
type: 'chat',
|
||||
children: this.props.model.properties?.config?.chatFields || [],
|
||||
})
|
||||
}
|
||||
result.push({
|
||||
value: this.props.model.id,
|
||||
label: this.props.model.properties.stepName,
|
||||
type: this.props.model.type,
|
||||
children: this.props.model.properties?.config?.fields || []
|
||||
children: this.props.model.properties?.config?.fields || [],
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
|
@ -83,7 +89,7 @@ class AppNode extends HtmlResize.view {
|
|||
if (contain_self) {
|
||||
return {
|
||||
...this.up_node_field_dict,
|
||||
[this.props.model.id]: this.get_node_field_list()
|
||||
[this.props.model.id]: this.get_node_field_list(),
|
||||
}
|
||||
}
|
||||
return this.up_node_field_dict ? this.up_node_field_dict : {}
|
||||
|
|
@ -92,7 +98,7 @@ class AppNode extends HtmlResize.view {
|
|||
get_up_node_field_list(contain_self: boolean, use_cache: boolean) {
|
||||
const result = Object.values(this.get_up_node_field_dict(contain_self, use_cache)).reduce(
|
||||
(pre, next) => [...pre, ...next],
|
||||
[]
|
||||
[],
|
||||
)
|
||||
const start_node_field_list = this.props.graphModel
|
||||
.getNodeModelById('start-node')
|
||||
|
|
@ -126,7 +132,7 @@ class AppNode extends HtmlResize.view {
|
|||
x: x - 10,
|
||||
y: y - 12,
|
||||
width: 30,
|
||||
height: 30
|
||||
height: 30,
|
||||
},
|
||||
[
|
||||
lh('div', {
|
||||
|
|
@ -174,10 +180,10 @@ class AppNode extends HtmlResize.view {
|
|||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5199_166905" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>`
|
||||
}
|
||||
})
|
||||
]
|
||||
</svg>`,
|
||||
},
|
||||
}),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +220,7 @@ class AppNode extends HtmlResize.view {
|
|||
} else {
|
||||
this.r = h(this.component, {
|
||||
properties: this.props.model.properties,
|
||||
nodeModel: this.props.model
|
||||
nodeModel: this.props.model,
|
||||
})
|
||||
this.app = createApp({
|
||||
render() {
|
||||
|
|
@ -223,13 +229,13 @@ class AppNode extends HtmlResize.view {
|
|||
provide() {
|
||||
return {
|
||||
getNode: () => model,
|
||||
getGraph: () => graphModel
|
||||
getGraph: () => graphModel,
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
this.app.use(ElementPlus, {
|
||||
locale: zhCn
|
||||
locale: zhCn,
|
||||
})
|
||||
this.app.use(Components)
|
||||
this.app.use(directives)
|
||||
|
|
@ -295,7 +301,7 @@ class AppNodeModel extends HtmlResize.model {
|
|||
}
|
||||
getNodeStyle() {
|
||||
return {
|
||||
overflow: 'visible'
|
||||
overflow: 'visible',
|
||||
}
|
||||
}
|
||||
getOutlineStyle() {
|
||||
|
|
@ -361,13 +367,13 @@ class AppNodeModel extends HtmlResize.model {
|
|||
message: t('views.applicationWorkflow.tip.onlyRight'),
|
||||
validate: (sourceNode: any, targetNode: any, sourceAnchor: any) => {
|
||||
return sourceAnchor.type === 'right'
|
||||
}
|
||||
},
|
||||
}
|
||||
this.sourceRules.push({
|
||||
message: t('views.applicationWorkflow.tip.notRecyclable'),
|
||||
validate: (sourceNode: any, targetNode: any, sourceAnchor: any, targetAnchor: any) => {
|
||||
return !isLoop(sourceNode.id, targetNode.id)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
this.sourceRules.push(circleOnlyAsTarget)
|
||||
|
|
@ -375,7 +381,7 @@ class AppNodeModel extends HtmlResize.model {
|
|||
message: t('views.applicationWorkflow.tip.onlyLeft'),
|
||||
validate: (sourceNode: any, targetNode: any, sourceAnchor: any, targetAnchor: any) => {
|
||||
return targetAnchor.type === 'left'
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
getDefaultAnchor() {
|
||||
|
|
@ -390,14 +396,14 @@ class AppNodeModel extends HtmlResize.model {
|
|||
y: showNode ? y : y - 15,
|
||||
id: `${id}_left`,
|
||||
edgeAddable: false,
|
||||
type: 'left'
|
||||
type: 'left',
|
||||
})
|
||||
}
|
||||
anchors.push({
|
||||
x: x + width / 2 - 10,
|
||||
y: showNode ? y : y - 15,
|
||||
id: `${id}_right`,
|
||||
type: 'right'
|
||||
type: 'right',
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<template>
|
||||
<img src="@/assets/workflow/icon_globe_color.svg" style="width: 18px" alt="" />
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
:title="isEdit ? $t('common.param.editParam') : $t('common.param.addParam')"
|
||||
v-model="dialogVisible"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:destroy-on-close="true"
|
||||
:before-close="close"
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
label-position="top"
|
||||
ref="fieldFormRef"
|
||||
:rules="rules"
|
||||
:model="form"
|
||||
require-asterisk-position="right"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$t('dynamicsForm.paramForm.field.label')"
|
||||
:required="true"
|
||||
prop="field"
|
||||
:rules="rules.field"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.field"
|
||||
:maxlength="64"
|
||||
:placeholder="$t('dynamicsForm.paramForm.field.placeholder')"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('dynamicsForm.paramForm.name.label')"
|
||||
:required="true"
|
||||
prop="label"
|
||||
:rules="rules.label"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.label"
|
||||
:maxlength="64"
|
||||
show-word-limit
|
||||
:placeholder="$t('dynamicsForm.paramForm.name.placeholder')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
|
||||
<el-button type="primary" @click="submit(fieldFormRef)" :loading="loading">
|
||||
{{ isEdit ? $t('common.save') : $t('common.add') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { t } from '@/locales'
|
||||
const emit = defineEmits(['refresh'])
|
||||
|
||||
const fieldFormRef = ref()
|
||||
const loading = ref<boolean>(false)
|
||||
const isEdit = ref(false)
|
||||
const currentIndex = ref(null)
|
||||
const form = ref<any>({
|
||||
field: '',
|
||||
label: '',
|
||||
})
|
||||
|
||||
const rules = reactive({
|
||||
label: [
|
||||
{ required: true, message: t('dynamicsForm.paramForm.name.requiredMessage'), trigger: 'blur' },
|
||||
],
|
||||
field: [
|
||||
{ required: true, message: t('dynamicsForm.paramForm.field.requiredMessage'), trigger: 'blur' },
|
||||
{
|
||||
pattern: /^[a-zA-Z0-9_]+$/,
|
||||
message: t('dynamicsForm.paramForm.field.requiredMessage2'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const dialogVisible = ref<boolean>(false)
|
||||
|
||||
const open = (row: any, index?: any) => {
|
||||
if (row) {
|
||||
form.value = cloneDeep(row)
|
||||
isEdit.value = true
|
||||
currentIndex.value = index
|
||||
}
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
dialogVisible.value = false
|
||||
isEdit.value = false
|
||||
currentIndex.value = null
|
||||
form.value = {
|
||||
field: '',
|
||||
label: '',
|
||||
}
|
||||
}
|
||||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
emit('refresh', form.value, currentIndex.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ open, close })
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
<template>
|
||||
<div class="flex-between mb-16">
|
||||
<h5 class="break-all ellipsis lighter" style="max-width: 80%">
|
||||
{{ $t('views.applicationWorkflow.variable.chat') }}
|
||||
</h5>
|
||||
<div>
|
||||
<span class="ml-4">
|
||||
<el-button link type="primary" @click="openAddDialog()">
|
||||
<el-icon class="mr-4">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
{{ $t('common.add') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-if="props.nodeModel.properties.chat_input_field_list?.length > 0"
|
||||
:data="props.nodeModel.properties.chat_input_field_list"
|
||||
class="mb-16"
|
||||
ref="tableRef"
|
||||
row-key="field"
|
||||
>
|
||||
<el-table-column prop="field" :label="$t('dynamicsForm.paramForm.field.label')" width="95">
|
||||
<template #default="{ row }">
|
||||
<span :title="row.field" class="ellipsis-1">{{ row.field }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="label" :label="$t('dynamicsForm.paramForm.name.label')">
|
||||
<template #default="{ row }">
|
||||
<span>
|
||||
<span :title="row.label" class="ellipsis-1">
|
||||
{{ row.label }}
|
||||
</span></span
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common.operation')" align="left" width="90">
|
||||
<template #default="{ row, $index }">
|
||||
<span class="mr-4">
|
||||
<el-tooltip effect="dark" :content="$t('common.modify')" placement="top">
|
||||
<el-button type="primary" text @click.stop="openAddDialog(row, $index)">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-tooltip effect="dark" :content="$t('common.delete')" placement="top">
|
||||
<el-button type="primary" text @click="deleteField($index)">
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<ChatFieldDialog ref="ChatFieldDialogRef" @refresh="refreshFieldList"></ChatFieldDialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { set, cloneDeep } from 'lodash'
|
||||
import ChatFieldDialog from './ChatFieldDialog.vue'
|
||||
import { MsgError } from '@/utils/message'
|
||||
import { t } from '@/locales'
|
||||
|
||||
const props = defineProps<{ nodeModel: any }>()
|
||||
|
||||
const tableRef = ref()
|
||||
const ChatFieldDialogRef = ref()
|
||||
|
||||
const inputFieldList = ref<any[]>([])
|
||||
|
||||
function openAddDialog(data?: any, index?: any) {
|
||||
ChatFieldDialogRef.value.open(data, index)
|
||||
}
|
||||
|
||||
function deleteField(index: any) {
|
||||
inputFieldList.value.splice(index, 1)
|
||||
props.nodeModel.graphModel.eventCenter.emit('chatFieldList')
|
||||
}
|
||||
|
||||
function refreshFieldList(data: any, index: any) {
|
||||
for (let i = 0; i < inputFieldList.value.length; i++) {
|
||||
if (inputFieldList.value[i].field === data.field && index !== i) {
|
||||
MsgError(t('views.applicationWorkflow.tip.paramErrorMessage') + data.field)
|
||||
return
|
||||
}
|
||||
}
|
||||
console.log(index)
|
||||
if (index) {
|
||||
inputFieldList.value.splice(index, 1, data)
|
||||
} else {
|
||||
inputFieldList.value.push(data)
|
||||
}
|
||||
|
||||
ChatFieldDialogRef.value.close()
|
||||
props.nodeModel.graphModel.eventCenter.emit('chatFieldList')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.nodeModel.properties.chat_input_field_list) {
|
||||
inputFieldList.value = cloneDeep(props.nodeModel.properties.chat_input_field_list)
|
||||
}
|
||||
set(props.nodeModel.properties, 'chat_input_field_list', inputFieldList)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
@ -83,6 +83,7 @@
|
|||
</el-form-item>
|
||||
<UserInputFieldTable ref="UserInputFieldTableFef" :node-model="nodeModel" />
|
||||
<ApiInputFieldTable ref="ApiInputFieldTableFef" :node-model="nodeModel" />
|
||||
<ChatFieldTable ref="ChatFieldTeble" :node-model="nodeModel"></ChatFieldTable>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex-between">
|
||||
|
|
@ -177,6 +178,7 @@ import TTSModeParamSettingDialog from '@/views/application/component/TTSModePara
|
|||
import ApiInputFieldTable from './component/ApiInputFieldTable.vue'
|
||||
import UserInputFieldTable from './component/UserInputFieldTable.vue'
|
||||
import FileUploadSettingDialog from '@/workflow/nodes/base-node/component/FileUploadSettingDialog.vue'
|
||||
import ChatFieldTable from './component/ChatFieldTable.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
||||
const getApplicationDetail = inject('getApplicationDetail') as any
|
||||
|
|
|
|||
|
|
@ -20,6 +20,30 @@
|
|||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<template v-if="nodeModel.properties.config.chatFields">
|
||||
<h5 class="title-decoration-1 mb-8">{{ $t('views.applicationWorkflow.variable.chat') }}</h5>
|
||||
<div
|
||||
v-for="(item, index) in nodeModel.properties.config.chatFields
|
||||
? nodeModel.properties.config.chatFields
|
||||
: []"
|
||||
:key="index"
|
||||
class="flex-between border-r-6 p-8-12 mb-8 layout-bg lighter"
|
||||
@mouseenter="showicon = true"
|
||||
@mouseleave="showicon = false"
|
||||
>
|
||||
<span class="break-all">{{ item.label }} {{ '{' + item.value + '}' }}</span>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('views.applicationWorkflow.setting.copyParam')"
|
||||
placement="top"
|
||||
v-if="showicon === true"
|
||||
>
|
||||
<el-button link @click="copyClick(`{{chat.${item.value}}}`)" style="padding: 0">
|
||||
<AppIcon iconName="app-copy"></AppIcon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
</NodeContainer>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
|
@ -75,8 +99,18 @@ const refreshFieldList = () => {
|
|||
const refreshFieldList = getRefreshFieldList()
|
||||
set(props.nodeModel.properties.config, 'globalFields', [...globalFields, ...refreshFieldList])
|
||||
}
|
||||
props.nodeModel.graphModel.eventCenter.on('refreshFieldList', refreshFieldList)
|
||||
|
||||
const refreshChatFieldList = () => {
|
||||
const chatFieldList = props.nodeModel.graphModel.nodes
|
||||
.filter((v: any) => v.id === 'base-node')
|
||||
.map((v: any) => cloneDeep(v.properties.chat_input_field_list))
|
||||
.reduce((x: any, y: any) => [...x, ...y], [])
|
||||
.map((i: any) => ({ label: i.label, value: i.field }))
|
||||
|
||||
set(props.nodeModel.properties.config, 'chatFields', chatFieldList)
|
||||
}
|
||||
props.nodeModel.graphModel.eventCenter.on('refreshFieldList', refreshFieldList)
|
||||
props.nodeModel.graphModel.eventCenter.on('chatFieldList', refreshChatFieldList)
|
||||
const refreshFileUploadConfig = () => {
|
||||
let fields = cloneDeep(props.nodeModel.properties.config.fields)
|
||||
const form_data = props.nodeModel.graphModel.nodes
|
||||
|
|
@ -120,6 +154,7 @@ const refreshFileUploadConfig = () => {
|
|||
props.nodeModel.graphModel.eventCenter.on('refreshFileUploadConfig', refreshFileUploadConfig)
|
||||
|
||||
onMounted(() => {
|
||||
refreshChatFieldList()
|
||||
refreshFieldList()
|
||||
refreshFileUploadConfig()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -245,6 +245,11 @@ function variableChange(item: any) {
|
|||
item.name = field.label
|
||||
}
|
||||
})
|
||||
node.properties.config.chatFields.forEach((field: any) => {
|
||||
if (field.value === item.fields[1]) {
|
||||
item.name = field.label
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue