mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
Merge branch 'main' of https://github.com/maxkb-dev/maxkb
This commit is contained in:
commit
ba2223c944
|
|
@ -12,6 +12,8 @@ class ApplicationNodeSerializer(serializers.Serializer):
|
|||
question_reference_address = serializers.ListField(required=True, error_messages=ErrMessage.list("用户问题"))
|
||||
api_input_field_list = serializers.ListField(required=False, error_messages=ErrMessage.list("api输入字段"))
|
||||
user_input_field_list = serializers.ListField(required=False, error_messages=ErrMessage.uuid("用户输入字段"))
|
||||
image_list = serializers.ListField(required=False, error_messages=ErrMessage.list("图片"))
|
||||
document_list = serializers.ListField(required=False, error_messages=ErrMessage.list("文档"))
|
||||
|
||||
|
||||
class IApplicationNode(INode):
|
||||
|
|
@ -31,10 +33,27 @@ class IApplicationNode(INode):
|
|||
for user_input_field in self.node_params_serializer.data.get('user_input_field_list', []):
|
||||
kwargs[user_input_field['field']] = self.workflow_manage.get_reference_field(user_input_field['value'][0],
|
||||
user_input_field['value'][1:])
|
||||
|
||||
# 判断是否包含这个属性
|
||||
app_document_list = self.node_params_serializer.data.get('document_list', [])
|
||||
if app_document_list and len(app_document_list) > 0:
|
||||
app_document_list = self.workflow_manage.get_reference_field(
|
||||
app_document_list[0],
|
||||
app_document_list[1:])
|
||||
for document in app_document_list:
|
||||
if 'file_id' not in document:
|
||||
raise ValueError("参数值错误: 上传的文档中缺少file_id")
|
||||
app_image_list = self.node_params_serializer.data.get('image_list', [])
|
||||
if app_image_list and len(app_image_list) > 0:
|
||||
app_image_list = self.workflow_manage.get_reference_field(
|
||||
app_image_list[0],
|
||||
app_image_list[1:])
|
||||
for image in app_image_list:
|
||||
if 'file_id' not in image:
|
||||
raise ValueError("参数值错误: 上传的图片中缺少file_id")
|
||||
return self.execute(**self.node_params_serializer.data, **self.flow_params_serializer.data,
|
||||
app_document_list=app_document_list, app_image_list=app_image_list,
|
||||
message=str(question), **kwargs)
|
||||
|
||||
def execute(self, application_id, message, chat_id, chat_record_id, stream, re_chat, client_id, client_type,
|
||||
**kwargs) -> NodeResult:
|
||||
app_document_list=None, app_image_list=None, **kwargs) -> NodeResult:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class BaseApplicationNode(IApplicationNode):
|
|||
self.answer_text = details.get('answer')
|
||||
|
||||
def execute(self, application_id, message, chat_id, chat_record_id, stream, re_chat, client_id, client_type,
|
||||
app_document_list=None, app_image_list=None,
|
||||
**kwargs) -> NodeResult:
|
||||
from application.serializers.chat_message_serializers import ChatMessageSerializer
|
||||
# 生成嵌入应用的chat_id
|
||||
|
|
@ -79,13 +80,20 @@ class BaseApplicationNode(IApplicationNode):
|
|||
'application_id': application_id,
|
||||
'abstract': message
|
||||
})
|
||||
if app_document_list is None:
|
||||
app_document_list = []
|
||||
if app_image_list is None:
|
||||
app_image_list = []
|
||||
response = ChatMessageSerializer(
|
||||
data={'chat_id': current_chat_id, 'message': message,
|
||||
're_chat': re_chat,
|
||||
'stream': stream,
|
||||
'application_id': application_id,
|
||||
'client_id': client_id,
|
||||
'client_type': client_type, 'form_data': kwargs}).chat(base_to_response=OpenaiToResponse())
|
||||
'client_type': client_type,
|
||||
'document_list': app_document_list,
|
||||
'image_list': app_image_list,
|
||||
'form_data': kwargs}).chat(base_to_response=OpenaiToResponse())
|
||||
if response.status_code == 200:
|
||||
if stream:
|
||||
content_generator = response.streaming_content
|
||||
|
|
|
|||
|
|
@ -116,13 +116,17 @@ class BaseImageUnderstandNode(IImageUnderstandNode):
|
|||
|
||||
def generate_message_list(self, image_model, system: str, prompt: str, history_message, image):
|
||||
if image is not None and len(image) > 0:
|
||||
file_id = image[0]['file_id']
|
||||
file = QuerySet(File).filter(id=file_id).first()
|
||||
base64_image = base64.b64encode(file.get_byte()).decode("utf-8")
|
||||
# 处理多张图片
|
||||
images = []
|
||||
for img in image:
|
||||
file_id = img['file_id']
|
||||
file = QuerySet(File).filter(id=file_id).first()
|
||||
base64_image = base64.b64encode(file.get_byte()).decode("utf-8")
|
||||
images.append({'type': 'image_url', 'image_url': {'url': f'data:image/jpeg;base64,{base64_image}'}})
|
||||
messages = [HumanMessage(
|
||||
content=[
|
||||
{'type': 'text', 'text': self.workflow_manage.generate_prompt(prompt)},
|
||||
{'type': 'image_url', 'image_url': {'url': f'data:image/jpeg;base64,{base64_image}'}},
|
||||
*images
|
||||
])]
|
||||
else:
|
||||
messages = [HumanMessage(self.workflow_manage.generate_prompt(prompt))]
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class Node:
|
|||
self.__setattr__(keyword, kwargs.get(keyword))
|
||||
|
||||
|
||||
end_nodes = ['ai-chat-node', 'reply-node', 'function-node', 'function-lib-node', 'application-node']
|
||||
end_nodes = ['ai-chat-node', 'reply-node', 'function-node', 'function-lib-node', 'application-node', 'image-understand-node']
|
||||
|
||||
|
||||
class Flow:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ class OpenAIImageModelCredential(BaseForm, BaseModelCredential):
|
|||
return False
|
||||
try:
|
||||
model = provider.get_model(model_type, model_name, model_credential)
|
||||
model.stream([HumanMessage(content=[{"type": "text", "text": "你好"}])])
|
||||
res = model.stream([HumanMessage(content=[{"type": "text", "text": "你好"}])])
|
||||
for chunk in res:
|
||||
print(chunk)
|
||||
except Exception as e:
|
||||
if isinstance(e, AppApiException):
|
||||
raise e
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ class QwenVLModelCredential(BaseForm, BaseModelCredential):
|
|||
return False
|
||||
try:
|
||||
model = provider.get_model(model_type, model_name, model_credential)
|
||||
model.stream([HumanMessage(content=[{"type": "text", "text": "你好"}])])
|
||||
res = model.stream([HumanMessage(content=[{"type": "text", "text": "你好"}])])
|
||||
for chunk in res:
|
||||
print(chunk)
|
||||
except Exception as e:
|
||||
if isinstance(e, AppApiException):
|
||||
raise e
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ class TencentVisionModelCredential(BaseForm, BaseModelCredential):
|
|||
return False
|
||||
try:
|
||||
model = provider.get_model(model_type, model_name, model_credential)
|
||||
model.stream([HumanMessage(content=[{"type": "text", "text": "你好"}])])
|
||||
res = model.stream([HumanMessage(content=[{"type": "text", "text": "你好"}])])
|
||||
for chunk in res:
|
||||
print(chunk)
|
||||
except Exception as e:
|
||||
if isinstance(e, AppApiException):
|
||||
raise e
|
||||
|
|
|
|||
|
|
@ -39,9 +39,12 @@ interface chatType {
|
|||
record_id: string
|
||||
chat_id: string
|
||||
vote_status: string
|
||||
status?: number,
|
||||
status?: number
|
||||
execution_details: any[]
|
||||
upload_meta?: any[]
|
||||
upload_meta?: {
|
||||
document_list: Array<any>
|
||||
image_list: Array<any>
|
||||
}
|
||||
}
|
||||
|
||||
export class ChatRecordManage {
|
||||
|
|
|
|||
|
|
@ -80,9 +80,7 @@
|
|||
action="#"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:accept="
|
||||
[...imageExtensions, ...documentExtensions].map((ext) => '.' + ext).join(',')
|
||||
"
|
||||
:accept="getAcceptList()"
|
||||
:on-change="(file: any, fileList: any) => uploadFile(file, fileList)"
|
||||
>
|
||||
<el-button text>
|
||||
|
|
@ -191,6 +189,24 @@ const documentExtensions = ['pdf', 'docx', 'txt', 'xls', 'xlsx', 'md', 'html', '
|
|||
const videoExtensions = ['mp4', 'avi', 'mov', 'mkv', 'flv']
|
||||
const audioExtensions = ['mp3', 'wav', 'aac', 'flac']
|
||||
|
||||
const getAcceptList = () => {
|
||||
const { image, document, audio, video } = props.applicationDetails.file_upload_setting
|
||||
let accepts = ''
|
||||
if (image) {
|
||||
accepts += imageExtensions.map((ext) => '.' + ext).join(',')
|
||||
}
|
||||
if (document) {
|
||||
accepts += documentExtensions.map((ext) => '.' + ext).join(',')
|
||||
}
|
||||
if (audio) {
|
||||
accepts += audioExtensions.map((ext) => '.' + ext).join(',')
|
||||
}
|
||||
if (video) {
|
||||
accepts += videoExtensions.map((ext) => '.' + ext).join(',')
|
||||
}
|
||||
return accepts
|
||||
}
|
||||
|
||||
const uploadFile = async (file: any, fileList: any) => {
|
||||
const { maxFiles, fileLimit } = props.applicationDetails.file_upload_setting
|
||||
if (fileList.length > maxFiles) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ const input_type_list = [
|
|||
label: '单选框',
|
||||
value: 'SingleSelect'
|
||||
},
|
||||
{
|
||||
label: '多选框',
|
||||
value: 'MultiSelect'
|
||||
},
|
||||
{
|
||||
label: '日期',
|
||||
value: 'DatePicker'
|
||||
|
|
@ -22,6 +26,14 @@ const input_type_list = [
|
|||
{
|
||||
label: 'JSON文本框',
|
||||
value: 'JsonInput'
|
||||
},
|
||||
{
|
||||
label: '选项卡',
|
||||
value: 'RadioCard'
|
||||
},
|
||||
{
|
||||
label: '单行选项卡',
|
||||
value: 'RadioRow'
|
||||
}
|
||||
]
|
||||
export { input_type_list }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
<template>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex-between">
|
||||
选项值
|
||||
<el-button link type="primary" @click.stop="addOption()">
|
||||
<el-icon class="mr-4">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-row style="width: 100%" :gutter="10">
|
||||
<el-col :span="10"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
标签</el-col
|
||||
>
|
||||
<el-col :span="12"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
选项值</el-col
|
||||
>
|
||||
</el-row>
|
||||
<el-row
|
||||
style="width: 100%"
|
||||
v-for="(option, $index) in formValue.option_list"
|
||||
:key="$index"
|
||||
:gutter="10"
|
||||
>
|
||||
<el-col :span="10"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-input v-model="formValue.option_list[$index].label" placeholder="请输入选项标签"
|
||||
/></el-col>
|
||||
<el-col :span="12"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值"
|
||||
/></el-col>
|
||||
<el-col :span="1"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-button link class="ml-8" @click.stop="delOption($index)">
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon> </el-button
|
||||
></el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="默认值"
|
||||
:required="formValue.required"
|
||||
prop="default_value"
|
||||
:rules="formValue.required ? [{ required: true, message: '默认值 为必填属性' }] : []"
|
||||
>
|
||||
<el-select
|
||||
class="m-2"
|
||||
multiple
|
||||
collapse-tags
|
||||
filterable
|
||||
clearable
|
||||
v-model="formValue.default_value"
|
||||
:teleported="false"
|
||||
popper-class="default-select"
|
||||
>
|
||||
<el-option
|
||||
v-for="(option, index) in formValue.option_list"
|
||||
:key="index"
|
||||
:label="option.value"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: any
|
||||
}>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const formValue = computed({
|
||||
set: (item) => {
|
||||
emit('update:modelValue', item)
|
||||
},
|
||||
get: () => {
|
||||
return props.modelValue
|
||||
}
|
||||
})
|
||||
|
||||
const addOption = () => {
|
||||
formValue.value.option_list.push({ value: '', label: '' })
|
||||
}
|
||||
|
||||
const delOption = (index: number) => {
|
||||
const option = formValue.value.option_list[index]
|
||||
if (option.value && formValue.value.default_value == option.value) {
|
||||
formValue.value.default_value = ''
|
||||
}
|
||||
formValue.value.option_list.splice(index, 1)
|
||||
}
|
||||
|
||||
const getData = () => {
|
||||
return {
|
||||
input_type: 'MultiSelect',
|
||||
attrs: {},
|
||||
default_value: formValue.value.default_value,
|
||||
textField: 'label',
|
||||
valueField: 'value',
|
||||
option_list: formValue.value.option_list
|
||||
}
|
||||
}
|
||||
const rander = (form_data: any) => {
|
||||
formValue.value.option_list = form_data.option_list || []
|
||||
formValue.value.default_value = form_data.default_value
|
||||
}
|
||||
|
||||
defineExpose({ getData, rander })
|
||||
onMounted(() => {
|
||||
formValue.value.option_list = []
|
||||
formValue.value.default_value = ''
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item__label) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:deep(.el-select-dropdown) {
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
<template>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex-between">
|
||||
选项值
|
||||
<el-button link type="primary" @click.stop="addOption()">
|
||||
<el-icon class="mr-4">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-row style="width: 100%" :gutter="10">
|
||||
<el-col :span="10"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
标签</el-col
|
||||
>
|
||||
<el-col :span="12"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
选项值</el-col
|
||||
>
|
||||
</el-row>
|
||||
<el-row
|
||||
style="width: 100%"
|
||||
v-for="(option, $index) in formValue.option_list"
|
||||
:key="$index"
|
||||
:gutter="10"
|
||||
>
|
||||
<el-col :span="10"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-input v-model="formValue.option_list[$index].label" placeholder="请输入选项标签"
|
||||
/></el-col>
|
||||
<el-col :span="12"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值"
|
||||
/></el-col>
|
||||
<el-col :span="1"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-button link class="ml-8" @click.stop="delOption($index)">
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon> </el-button
|
||||
></el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="默认值"
|
||||
:required="formValue.required"
|
||||
prop="default_value"
|
||||
:rules="formValue.required ? [{ required: true, message: '默认值 为必填属性' }] : []"
|
||||
>
|
||||
<RadioCard
|
||||
:form-field="formField"
|
||||
v-model="formValue.default_value"
|
||||
:other-params="{}"
|
||||
field="default_value"
|
||||
>
|
||||
</RadioCard>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted } from 'vue'
|
||||
import RadioCard from '@/components/dynamics-form/items/radio/RadioCard.vue'
|
||||
const props = defineProps<{
|
||||
modelValue: any
|
||||
}>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const formValue = computed({
|
||||
set: (item) => {
|
||||
emit('update:modelValue', item)
|
||||
},
|
||||
get: () => {
|
||||
return props.modelValue
|
||||
}
|
||||
})
|
||||
|
||||
const addOption = () => {
|
||||
formValue.value.option_list.push({ value: '', label: '' })
|
||||
}
|
||||
|
||||
const delOption = (index: number) => {
|
||||
const option = formValue.value.option_list[index]
|
||||
if (option.value && formValue.value.default_value == option.value) {
|
||||
formValue.value.default_value = ''
|
||||
}
|
||||
formValue.value.option_list.splice(index, 1)
|
||||
}
|
||||
const formField = computed(() => {
|
||||
return { field: '', ...getData() }
|
||||
})
|
||||
const getData = () => {
|
||||
return {
|
||||
input_type: 'RadioCard',
|
||||
attrs: {},
|
||||
default_value: formValue.value.default_value,
|
||||
text_field: 'label',
|
||||
value_field: 'value',
|
||||
option_list: formValue.value.option_list
|
||||
}
|
||||
}
|
||||
const rander = (form_data: any) => {
|
||||
formValue.value.option_list = form_data.option_list || []
|
||||
formValue.value.default_value = form_data.default_value
|
||||
}
|
||||
|
||||
defineExpose({ getData, rander })
|
||||
onMounted(() => {
|
||||
formValue.value.option_list = []
|
||||
formValue.value.default_value = ''
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item__label) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:deep(.el-select-dropdown) {
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
<template>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex-between">
|
||||
选项值
|
||||
<el-button link type="primary" @click.stop="addOption()">
|
||||
<el-icon class="mr-4">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-row style="width: 100%" :gutter="10">
|
||||
<el-col :span="10"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
标签</el-col
|
||||
>
|
||||
<el-col :span="12"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
选项值</el-col
|
||||
>
|
||||
</el-row>
|
||||
<el-row
|
||||
style="width: 100%"
|
||||
v-for="(option, $index) in formValue.option_list"
|
||||
:key="$index"
|
||||
:gutter="10"
|
||||
>
|
||||
<el-col :span="10"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-input v-model="formValue.option_list[$index].label" placeholder="请输入选项标签"
|
||||
/></el-col>
|
||||
<el-col :span="12"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值"
|
||||
/></el-col>
|
||||
<el-col :span="1"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-button link class="ml-8" @click.stop="delOption($index)">
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon> </el-button
|
||||
></el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="默认值"
|
||||
:required="formValue.required"
|
||||
prop="default_value"
|
||||
:rules="formValue.required ? [{ required: true, message: '默认值 为必填属性' }] : []"
|
||||
>
|
||||
<RadioRow
|
||||
:form-field="formField"
|
||||
v-model="formValue.default_value"
|
||||
:other-params="{}"
|
||||
field="default_value"
|
||||
>
|
||||
</RadioRow>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted } from 'vue'
|
||||
import RadioRow from '@/components/dynamics-form/items/radio/RadioRow.vue'
|
||||
import type { FormField } from '@/components/dynamics-form/type'
|
||||
const props = defineProps<{
|
||||
modelValue: any
|
||||
}>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const formValue = computed({
|
||||
set: (item) => {
|
||||
emit('update:modelValue', item)
|
||||
},
|
||||
get: () => {
|
||||
return props.modelValue
|
||||
}
|
||||
})
|
||||
|
||||
const addOption = () => {
|
||||
formValue.value.option_list.push({ value: '', label: '' })
|
||||
}
|
||||
|
||||
const delOption = (index: number) => {
|
||||
const option = formValue.value.option_list[index]
|
||||
if (option.value && formValue.value.default_value == option.value) {
|
||||
formValue.value.default_value = ''
|
||||
}
|
||||
formValue.value.option_list.splice(index, 1)
|
||||
}
|
||||
const formField = computed<FormField>(() => {
|
||||
return { field: '', ...getData() }
|
||||
})
|
||||
const getData = () => {
|
||||
return {
|
||||
input_type: 'RadioCard',
|
||||
attrs: {},
|
||||
default_value: formValue.value.default_value,
|
||||
text_field: 'label',
|
||||
value_field: 'value',
|
||||
option_list: formValue.value.option_list
|
||||
}
|
||||
}
|
||||
const rander = (form_data: any) => {
|
||||
formValue.value.option_list = form_data.option_list || []
|
||||
formValue.value.default_value = form_data.default_value
|
||||
}
|
||||
|
||||
defineExpose({ getData, rander })
|
||||
onMounted(() => {
|
||||
formValue.value.option_list = []
|
||||
formValue.value.default_value = ''
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item__label) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:deep(.el-select-dropdown) {
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -12,18 +12,38 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<div
|
||||
class="w-full flex-between mb-8"
|
||||
<el-row style="width: 100%" :gutter="10">
|
||||
<el-col :span="10"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
标签</el-col
|
||||
>
|
||||
<el-col :span="12"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
选项值</el-col
|
||||
>
|
||||
</el-row>
|
||||
<el-row
|
||||
style="width: 100%"
|
||||
v-for="(option, $index) in formValue.option_list"
|
||||
:key="$index"
|
||||
:gutter="10"
|
||||
>
|
||||
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值" />
|
||||
<el-button link class="ml-8" @click.stop="delOption($index)">
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<el-col :span="10"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-input v-model="formValue.option_list[$index].label" placeholder="请输入选项标签"
|
||||
/></el-col>
|
||||
<el-col :span="12"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值"
|
||||
/></el-col>
|
||||
<el-col :span="1"
|
||||
><div class="grid-content ep-bg-purple" />
|
||||
<el-button link class="ml-8" @click.stop="delOption($index)">
|
||||
<el-icon>
|
||||
<Delete />
|
||||
</el-icon> </el-button
|
||||
></el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="默认值"
|
||||
|
|
@ -58,7 +78,7 @@ const formValue = computed({
|
|||
})
|
||||
|
||||
const addOption = () => {
|
||||
formValue.value.option_list.push({ value: '' })
|
||||
formValue.value.option_list.push({ value: '', label: '' })
|
||||
}
|
||||
|
||||
const delOption = (index: number) => {
|
||||
|
|
@ -74,8 +94,8 @@ const getData = () => {
|
|||
input_type: 'SingleSelect',
|
||||
attrs: {},
|
||||
default_value: formValue.value.default_value,
|
||||
text_field: 'value',
|
||||
value_field: 'value',
|
||||
textField: 'label',
|
||||
valueField: 'value',
|
||||
option_list: formValue.value.option_list
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
<template>
|
||||
<div class="radio_content">
|
||||
<div
|
||||
<div class="radio_content" v-resize="resize" :style="radioContentStyle">
|
||||
<el-card
|
||||
v-for="item in option_list"
|
||||
:key="item.value"
|
||||
class="item"
|
||||
shadow="never"
|
||||
:class="[modelValue == item[valueField] ? 'active' : '']"
|
||||
@click="selected(item[valueField])"
|
||||
>
|
||||
{{ item[textField] }}
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { watch, computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import type { FormField } from '@/components/dynamics-form/type'
|
||||
const props = defineProps<{
|
||||
formValue?: any
|
||||
|
|
@ -29,7 +30,24 @@ const selected = (activeValue: string | number) => {
|
|||
emit('update:modelValue', activeValue)
|
||||
}
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const width = ref<number>()
|
||||
const radioContentStyle = computed(() => {
|
||||
if (width.value) {
|
||||
if (width.value < 350) {
|
||||
return { '--maxkb-radio-card-width': '316px' }
|
||||
} else if (width.value > 770) {
|
||||
return { '--maxkb-radio-card-width': '378px' }
|
||||
} else {
|
||||
return { '--maxkb-radio-card-width': '100%' }
|
||||
}
|
||||
}
|
||||
return {}
|
||||
})
|
||||
const resize = (wh: any) => {
|
||||
if (wh.height) {
|
||||
width.value = wh.width
|
||||
}
|
||||
}
|
||||
const textField = computed(() => {
|
||||
return props.formField.text_field ? props.formField.text_field : 'key'
|
||||
})
|
||||
|
|
@ -41,52 +59,24 @@ const valueField = computed(() => {
|
|||
const option_list = computed(() => {
|
||||
return props.formField.option_list ? props.formField.option_list : []
|
||||
})
|
||||
watch(
|
||||
option_list,
|
||||
() => {
|
||||
if (
|
||||
(option_list.value &&
|
||||
option_list.value.length > 0 &&
|
||||
!option_list.value.some((item) => item.value === props.modelValue)) ||
|
||||
!props.modelValue
|
||||
) {
|
||||
emit('update:modelValue', option_list.value[0][valueField.value])
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.radio_content {
|
||||
height: 32px;
|
||||
display: inline-flex;
|
||||
border: 1px solid #bbbfc4;
|
||||
border-radius: 4px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #1f2329;
|
||||
padding: 3px 4px;
|
||||
box-sizing: border-box;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
.active {
|
||||
border-radius: 4px;
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
border: 1px solid var(--el-color-primary);
|
||||
}
|
||||
.item {
|
||||
cursor: pointer;
|
||||
margin: 0px 2px;
|
||||
padding: 2px 8px;
|
||||
height: 20px;
|
||||
height: 38px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
&:last-child {
|
||||
margin: 0 4px 0 2px;
|
||||
}
|
||||
&:first-child {
|
||||
margin: 0 2px 0 4px;
|
||||
}
|
||||
width: var(--maxkb-radio-card-width, 100%);
|
||||
margin: 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<div class="radio_content">
|
||||
<div
|
||||
v-for="item in option_list"
|
||||
:key="item.value"
|
||||
class="item"
|
||||
:class="[modelValue == item[valueField] ? 'active' : '']"
|
||||
@click="selected(item[valueField])"
|
||||
>
|
||||
{{ item[textField] }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import type { FormField } from '@/components/dynamics-form/type'
|
||||
const props = defineProps<{
|
||||
formValue?: any
|
||||
formfieldList?: Array<FormField>
|
||||
field: string
|
||||
otherParams: any
|
||||
formField: FormField
|
||||
view?: boolean
|
||||
// 选中的值
|
||||
modelValue?: any
|
||||
}>()
|
||||
|
||||
const selected = (activeValue: string | number) => {
|
||||
emit('update:modelValue', activeValue)
|
||||
}
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const textField = computed(() => {
|
||||
return props.formField.text_field ? props.formField.text_field : 'key'
|
||||
})
|
||||
|
||||
const valueField = computed(() => {
|
||||
return props.formField.value_field ? props.formField.value_field : 'value'
|
||||
})
|
||||
|
||||
const option_list = computed(() => {
|
||||
return props.formField.option_list ? props.formField.option_list : []
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.radio_content {
|
||||
height: 32px;
|
||||
display: inline-flex;
|
||||
border: 1px solid #bbbfc4;
|
||||
border-radius: 4px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #1f2329;
|
||||
padding: 3px 4px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
|
||||
.active {
|
||||
border-radius: 4px;
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.item {
|
||||
cursor: pointer;
|
||||
margin: 0px 2px;
|
||||
padding: 2px 8px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
&:last-child {
|
||||
margin: 0 4px 0 2px;
|
||||
}
|
||||
&:first-child {
|
||||
margin: 0 2px 0 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -149,13 +149,20 @@ function clickNodes(item: any, data?: any, type?: string) {
|
|||
}
|
||||
if (type == 'application') {
|
||||
if (isWorkFlow(data.type)) {
|
||||
console.log(data.work_flow.nodes[0].properties.api_input_field_list)
|
||||
const nodeData = data.work_flow.nodes[0].properties.node_data
|
||||
const fileUploadSetting = nodeData.file_upload_setting
|
||||
item['properties']['node_data'] = {
|
||||
name: data.name,
|
||||
icon: data.icon,
|
||||
application_id: data.id,
|
||||
api_input_field_list: data.work_flow.nodes[0].properties.api_input_field_list,
|
||||
user_input_field_list: data.work_flow.nodes[0].properties.user_input_field_list
|
||||
user_input_field_list: data.work_flow.nodes[0].properties.user_input_field_list,
|
||||
...(!fileUploadSetting
|
||||
? {}
|
||||
: {
|
||||
...(fileUploadSetting.document ? { document_list: [] } : {}),
|
||||
...(fileUploadSetting.image ? { image_list: [] } : {})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
item['properties']['node_data'] = {
|
||||
|
|
@ -186,12 +193,20 @@ function onmousedown(item: any, data?: any, type?: string) {
|
|||
}
|
||||
if (type == 'application') {
|
||||
if (isWorkFlow(data.type)) {
|
||||
const nodeData = data.work_flow.nodes[0].properties.node_data
|
||||
const fileUploadSetting = nodeData.file_upload_setting
|
||||
item['properties']['node_data'] = {
|
||||
name: data.name,
|
||||
icon: data.icon,
|
||||
application_id: data.id,
|
||||
api_input_field_list: data.work_flow.nodes[0].properties.api_input_field_list,
|
||||
user_input_field_list: data.work_flow.nodes[0].properties.user_input_field_list
|
||||
user_input_field_list: data.work_flow.nodes[0].properties.user_input_field_list,
|
||||
...(!fileUploadSetting
|
||||
? {}
|
||||
: {
|
||||
...(fileUploadSetting.document ? { document_list: [] } : {}),
|
||||
...(fileUploadSetting.image ? { image_list: [] } : {})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
item['properties']['node_data'] = {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,12 @@
|
|||
<div class="flex-between mb-16">
|
||||
<h4>{{ $t('views.application.applicationList.title') }}</h4>
|
||||
<div class="flex-between">
|
||||
<el-select v-model="selectUserId" class="mr-12 w-120" @change="searchHandle">
|
||||
<el-select
|
||||
v-model="selectUserId"
|
||||
class="mr-12"
|
||||
@change="searchHandle"
|
||||
style="max-width: 240px; width: 150px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.value"
|
||||
|
|
@ -17,6 +22,7 @@
|
|||
:placeholder="$t('views.application.applicationList.searchBar.placeholder')"
|
||||
prefix-icon="Search"
|
||||
class="w-240"
|
||||
style="min-width: 240px"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,12 @@
|
|||
<div class="flex-between mb-16">
|
||||
<h4>知识库</h4>
|
||||
<div class="flex-between">
|
||||
<el-select v-model="selectUserId" class="mr-12 w-120" @change="searchHandle">
|
||||
<el-select
|
||||
v-model="selectUserId"
|
||||
class="mr-12"
|
||||
@change="searchHandle"
|
||||
style="max-width: 240px; width: 150px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.value"
|
||||
|
|
@ -17,6 +22,7 @@
|
|||
:placeholder="$t('views.application.applicationList.searchBar.placeholder')"
|
||||
prefix-icon="Search"
|
||||
class="w-240"
|
||||
style="max-width: 240px"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,12 @@
|
|||
<div class="flex-between mb-16">
|
||||
<h4>函数库</h4>
|
||||
<div class="flex-between">
|
||||
<el-select v-model="selectUserId" class="mr-12 w-120" @change="searchHandle">
|
||||
<el-select
|
||||
v-model="selectUserId"
|
||||
class="mr-12"
|
||||
style="max-width: 240px; width: 150px"
|
||||
@change="searchHandle"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.value"
|
||||
|
|
@ -17,6 +22,7 @@
|
|||
placeholder="按函数名称搜索"
|
||||
prefix-icon="Search"
|
||||
class="w-240"
|
||||
style="max-width: 240px"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -216,33 +216,36 @@ const onUploadImg = async (files: any, callback: any) => {
|
|||
callback(res.map((item) => item.data))
|
||||
}
|
||||
|
||||
function changeDataset(id: string) {
|
||||
if (user.userInfo) {
|
||||
localStorage.setItem(user.userInfo.id + 'chat_dataset_id', id)
|
||||
}
|
||||
function changeDataset(dataset_id: string) {
|
||||
localStorage.setItem(id + 'chat_dataset_id', dataset_id)
|
||||
form.value.document_id = ''
|
||||
getDocument(id)
|
||||
getDocument(dataset_id)
|
||||
}
|
||||
|
||||
function changeDocument(id: string) {
|
||||
if (user.userInfo) {
|
||||
localStorage.setItem(user.userInfo.id + 'chat_document_id', id)
|
||||
}
|
||||
function changeDocument(document_id: string) {
|
||||
localStorage.setItem(id + 'chat_document_id', document_id)
|
||||
}
|
||||
|
||||
function getDocument(id: string) {
|
||||
document.asyncGetAllDocument(id, loading).then((res: any) => {
|
||||
function getDocument(dataset_id: string) {
|
||||
document.asyncGetAllDocument(dataset_id, loading).then((res: any) => {
|
||||
documentList.value = res.data
|
||||
if (localStorage.getItem(id + 'chat_document_id')) {
|
||||
form.value.document_id = localStorage.getItem(id + 'chat_document_id') as string
|
||||
}
|
||||
if (!documentList.value.find((v) => v.id === form.value.document_id)) {
|
||||
form.value.document_id = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getDataset() {
|
||||
application.asyncGetApplicationDataset(id, loading).then((res: any) => {
|
||||
datasetList.value = res.data
|
||||
if (localStorage.getItem(user.userInfo?.id + 'chat_dataset_id')) {
|
||||
form.value.dataset_id = localStorage.getItem(user.userInfo?.id + 'chat_dataset_id') as string
|
||||
if (localStorage.getItem(id + 'chat_dataset_id')) {
|
||||
form.value.dataset_id = localStorage.getItem(id + 'chat_dataset_id') as string
|
||||
if (!datasetList.value.find((v) => v.id === form.value.dataset_id)) {
|
||||
form.value.dataset_id = ''
|
||||
form.value.document_id = ''
|
||||
} else {
|
||||
getDocument(form.value.dataset_id)
|
||||
}
|
||||
|
|
@ -252,9 +255,6 @@ function getDataset() {
|
|||
|
||||
const open = (data: any) => {
|
||||
getDataset()
|
||||
if (localStorage.getItem(user.userInfo?.id + 'chat_document_id')) {
|
||||
form.value.document_id = localStorage.getItem(user.userInfo?.id + 'chat_document_id') as string
|
||||
}
|
||||
form.value.chat_id = data.chat_id
|
||||
form.value.record_id = data.id
|
||||
form.value.problem_text = data.problem_text ? data.problem_text.substring(0, 256) : ''
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@
|
|||
<el-button @click="dialogVisible = true">清除策略</el-button>
|
||||
<el-button @click="exportLog">导出</el-button>
|
||||
<el-button @click="openDocumentDialog" :disabled="multipleSelection.length === 0"
|
||||
>添加至知识库</el-button
|
||||
>
|
||||
>添加至知识库
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -171,9 +171,9 @@
|
|||
<span>天之前的对话记录</span>
|
||||
<template #footer>
|
||||
<div class="dialog-footer" style="margin-top: 16px">
|
||||
<el-button @click="dialogVisible = false">{{
|
||||
$t('layout.topbar.avatar.dialog.cancel')
|
||||
}}</el-button>
|
||||
<el-button @click="dialogVisible = false"
|
||||
>{{ $t('layout.topbar.avatar.dialog.cancel') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="saveCleanTime">
|
||||
{{ $t('layout.topbar.avatar.dialog.save') }}
|
||||
</el-button>
|
||||
|
|
@ -253,7 +253,7 @@
|
|||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click.prevent="dialogVisible = false"> 取消 </el-button>
|
||||
<el-button @click.prevent="documentDialogVisible = false"> 取消 </el-button>
|
||||
<el-button type="primary" @click="submitForm(formRef)" :loading="documentLoading">
|
||||
保存
|
||||
</el-button>
|
||||
|
|
@ -365,6 +365,7 @@ const rules = reactive<FormRules>({
|
|||
|
||||
const optionLoading = ref(false)
|
||||
const documentList = ref<any[]>([])
|
||||
|
||||
function filterChange(val: string) {
|
||||
if (val === 'clear') {
|
||||
filter.value = cloneDeep(defaultFilter)
|
||||
|
|
@ -487,6 +488,7 @@ function getDetail() {
|
|||
days.value = res.data.clean_time
|
||||
})
|
||||
}
|
||||
|
||||
const exportLog = () => {
|
||||
const arr: string[] = []
|
||||
multipleSelection.value.map((v) => {
|
||||
|
|
@ -542,28 +544,26 @@ function saveCleanTime() {
|
|||
})
|
||||
}
|
||||
|
||||
function changeDataset(id: string) {
|
||||
if (user.userInfo) {
|
||||
localStorage.setItem(user.userInfo.id + 'chat_dataset_id', id)
|
||||
}
|
||||
function changeDataset(dataset_id: string) {
|
||||
localStorage.setItem(id + 'chat_dataset_id', dataset_id)
|
||||
form.value.document_id = ''
|
||||
getDocument(id)
|
||||
getDocument(dataset_id)
|
||||
}
|
||||
|
||||
function changeDocument(id: string) {
|
||||
if (user.userInfo) {
|
||||
localStorage.setItem(user.userInfo.id + 'chat_document_id', id)
|
||||
}
|
||||
function changeDocument(document_id: string) {
|
||||
localStorage.setItem(id + 'chat_document_id', document_id)
|
||||
}
|
||||
|
||||
const datasetList = ref<any[]>([])
|
||||
|
||||
function getDataset() {
|
||||
application.asyncGetApplicationDataset(id, documentLoading).then((res: any) => {
|
||||
datasetList.value = res.data
|
||||
if (localStorage.getItem(user.userInfo?.id + 'chat_dataset_id')) {
|
||||
form.value.dataset_id = localStorage.getItem(user.userInfo?.id + 'chat_dataset_id') as string
|
||||
if (localStorage.getItem(id + 'chat_dataset_id')) {
|
||||
form.value.dataset_id = localStorage.getItem(id + 'chat_dataset_id') as string
|
||||
if (!datasetList.value.find((v) => v.id === form.value.dataset_id)) {
|
||||
form.value.dataset_id = ''
|
||||
form.value.document_id = ''
|
||||
} else {
|
||||
getDocument(form.value.dataset_id)
|
||||
}
|
||||
|
|
@ -594,20 +594,24 @@ const submitForm = async (formEl: FormInstance | undefined) => {
|
|||
})
|
||||
}
|
||||
|
||||
function getDocument(id: string) {
|
||||
document.asyncGetAllDocument(id, documentLoading).then((res: any) => {
|
||||
function getDocument(dataset_id: string) {
|
||||
document.asyncGetAllDocument(dataset_id, documentLoading).then((res: any) => {
|
||||
documentList.value = res.data
|
||||
if (localStorage.getItem(id + 'chat_document_id')) {
|
||||
form.value.document_id = localStorage.getItem(id + 'chat_document_id') as string
|
||||
}
|
||||
if (!documentList.value.find((v) => v.id === form.value.document_id)) {
|
||||
form.value.document_id = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function openDocumentDialog() {
|
||||
getDataset()
|
||||
if (localStorage.getItem(user.userInfo?.id + 'chat_document_id')) {
|
||||
form.value.document_id = localStorage.getItem(user.userInfo?.id + 'chat_document_id') as string
|
||||
}
|
||||
formRef.value?.clearValidate()
|
||||
documentDialogVisible.value = true
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
changeDayHandle(history_day.value)
|
||||
getDetail()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const end_nodes: Array<string> = [
|
|||
WorkflowType.Reply,
|
||||
WorkflowType.FunctionLib,
|
||||
WorkflowType.FunctionLibCustom,
|
||||
WorkflowType.ImageUnderstandNode,
|
||||
WorkflowType.Application
|
||||
]
|
||||
export class WorkFlowInstance {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,44 @@
|
|||
v-model="form_data.question_reference_address"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="form_data.hasOwnProperty('document_list') || 'document_list' in form_data"
|
||||
label="选择文档"
|
||||
prop="document_list"
|
||||
:rules="{
|
||||
message: '请选择检索问题',
|
||||
trigger: 'blur',
|
||||
required: false
|
||||
}"
|
||||
>
|
||||
<NodeCascader
|
||||
ref="nodeCascaderRef"
|
||||
:nodeModel="nodeModel"
|
||||
class="w-full"
|
||||
placeholder="请选择检索问题"
|
||||
v-model="form_data.document_list"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="form_data.hasOwnProperty('image_list') || 'image_list' in form_data"
|
||||
label="选择图片"
|
||||
prop="image_list"
|
||||
:rules="{
|
||||
message: '请选择检索问题',
|
||||
trigger: 'blur',
|
||||
required: false
|
||||
}"
|
||||
>
|
||||
<NodeCascader
|
||||
ref="nodeCascaderRef"
|
||||
:nodeModel="nodeModel"
|
||||
class="w-full"
|
||||
placeholder="请选择检索问题"
|
||||
v-model="form_data.image_list"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div v-for="(field, index) in form_data.api_input_field_list" :key="'api-input-' + index">
|
||||
<el-form-item
|
||||
:label="field.variable"
|
||||
|
|
@ -45,7 +83,6 @@
|
|||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- Loop through dynamic fields for user_input_field_list -->
|
||||
<div v-for="(field, index) in form_data.user_input_field_list" :key="'user-input-' + index">
|
||||
<el-form-item
|
||||
:label="field.label"
|
||||
|
|
@ -94,9 +131,11 @@ import NodeCascader from '@/workflow/common/NodeCascader.vue'
|
|||
import type { FormInstance } from 'element-plus'
|
||||
|
||||
const form = {
|
||||
question_reference_address: [],
|
||||
question_reference_address: ['start-node', 'question'],
|
||||
api_input_field_list: [],
|
||||
user_input_field_list: []
|
||||
user_input_field_list: [],
|
||||
document_list: ['start-node', 'document'],
|
||||
image_list: ['start-node', 'image']
|
||||
}
|
||||
|
||||
const applicationNodeFormRef = ref<FormInstance>()
|
||||
|
|
@ -124,7 +163,6 @@ const validate = () => {
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.log(applicationNodeFormRef.value)
|
||||
set(props.nodeModel, 'validate', validate)
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
<Setting />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-switch size="small" v-model="form_data.file_upload_enable"/>
|
||||
<el-switch size="small" v-model="form_data.file_upload_enable" @change="switchFileUpload"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -382,6 +382,22 @@ const refreshTTSForm = (data: any) => {
|
|||
form_data.value.tts_model_params_setting = data
|
||||
}
|
||||
|
||||
|
||||
const switchFileUpload = () => {
|
||||
const default_upload_setting = {
|
||||
maxFiles: 3,
|
||||
fileLimit: 50,
|
||||
document: true,
|
||||
image: false,
|
||||
audio: false,
|
||||
video: false
|
||||
}
|
||||
|
||||
if (form_data.value.file_upload_enable) {
|
||||
form_data.value.file_upload_setting = form_data.value.file_upload_setting || default_upload_setting
|
||||
props.nodeModel.graphModel.eventCenter.emit('refreshFileUploadConfig')
|
||||
}
|
||||
}
|
||||
const openFileUploadSettingDialog = () => {
|
||||
FileUploadSettingDialogRef.value?.open(form_data.value.file_upload_setting)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
<el-table-column label="必填">
|
||||
<template #default="{ row }">
|
||||
<div @click.stop>
|
||||
<el-switch disabled size="small" v-model="row.is_required" />
|
||||
<el-switch disabled size="small" v-model="row.required" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
|
|||
Loading…
Reference in New Issue