feat: Form nodes support file upload and multi-line text (#3879)
This commit is contained in:
parent
31d71d137a
commit
d26883581c
@ -69,9 +69,11 @@ class BaseFormNode(IFormNode):
|
|||||||
reset_field = ['field', 'label', 'default_value']
|
reset_field = ['field', 'label', 'default_value']
|
||||||
for f in reset_field:
|
for f in reset_field:
|
||||||
_value = field[f]
|
_value = field[f]
|
||||||
|
if _value is None:
|
||||||
|
continue
|
||||||
if isinstance(_value, str):
|
if isinstance(_value, str):
|
||||||
field[f] = self.workflow_manage.generate_prompt(_value)
|
field[f] = self.workflow_manage.generate_prompt(_value)
|
||||||
else:
|
elif f == 'label':
|
||||||
_label_value = _value.get('label')
|
_label_value = _value.get('label')
|
||||||
_value['label'] = self.workflow_manage.generate_prompt(_label_value)
|
_value['label'] = self.workflow_manage.generate_prompt(_label_value)
|
||||||
tooltip = _value.get('attrs').get('tooltip')
|
tooltip = _value.get('attrs').get('tooltip')
|
||||||
|
|||||||
@ -1,44 +1,92 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="aiChatRef" class="ai-chat" :class="type" :style="{
|
<div
|
||||||
|
ref="aiChatRef"
|
||||||
|
class="ai-chat"
|
||||||
|
:class="type"
|
||||||
|
:style="{
|
||||||
height: firsUserInput ? '100%' : undefined,
|
height: firsUserInput ? '100%' : undefined,
|
||||||
paddingBottom: applicationDetails.disclaimer ? '20px' : 0,
|
paddingBottom: applicationDetails.disclaimer ? '20px' : 0,
|
||||||
}">
|
}"
|
||||||
<div v-show="showUserInputContent" :class="firsUserInput ? 'firstUserInput' : 'popperUserInput'">
|
>
|
||||||
<UserForm v-model:api_form_data="api_form_data" v-model:form_data="form_data" :application="applicationDetails"
|
<div
|
||||||
:type="type" :first="firsUserInput" @confirm="UserFormConfirm" @cancel="UserFormCancel" ref="userFormRef">
|
v-show="showUserInputContent"
|
||||||
|
:class="firsUserInput ? 'firstUserInput' : 'popperUserInput'"
|
||||||
|
>
|
||||||
|
<UserForm
|
||||||
|
v-model:api_form_data="api_form_data"
|
||||||
|
v-model:form_data="form_data"
|
||||||
|
:application="applicationDetails"
|
||||||
|
:type="type"
|
||||||
|
:first="firsUserInput"
|
||||||
|
@confirm="UserFormConfirm"
|
||||||
|
@cancel="UserFormCancel"
|
||||||
|
ref="userFormRef"
|
||||||
|
>
|
||||||
</UserForm>
|
</UserForm>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="!(isUserInput || isAPIInput) || !firsUserInput || type === 'log'">
|
<template v-if="!(isUserInput || isAPIInput) || !firsUserInput || type === 'log'">
|
||||||
<el-scrollbar ref="scrollDiv" @scroll="handleScrollTop">
|
<el-scrollbar ref="scrollDiv" @scroll="handleScrollTop">
|
||||||
<div ref="dialogScrollbar" class="ai-chat__content p-16">
|
<div ref="dialogScrollbar" class="ai-chat__content p-16">
|
||||||
<PrologueContent :type="type" :application="applicationDetails" :available="available"
|
<PrologueContent
|
||||||
:send-message="sendMessage"></PrologueContent>
|
:type="type"
|
||||||
|
:application="applicationDetails"
|
||||||
|
:available="available"
|
||||||
|
:send-message="sendMessage"
|
||||||
|
></PrologueContent>
|
||||||
|
|
||||||
<template v-for="(item, index) in chatList" :key="index">
|
<template v-for="(item, index) in chatList" :key="index">
|
||||||
<!-- 问题 -->
|
<!-- 问题 -->
|
||||||
<QuestionContent :type="type" :application="applicationDetails" :chat-record="item"></QuestionContent>
|
<QuestionContent
|
||||||
|
:type="type"
|
||||||
|
:application="applicationDetails"
|
||||||
|
:chat-record="item"
|
||||||
|
></QuestionContent>
|
||||||
<!-- 回答 -->
|
<!-- 回答 -->
|
||||||
<AnswerContent :application="applicationDetails" :loading="loading" v-model:chat-record="chatList[index]"
|
<AnswerContent
|
||||||
:type="type" :send-message="sendMessage" :chat-management="ChatManagement"
|
:application="applicationDetails"
|
||||||
|
:loading="loading"
|
||||||
|
v-model:chat-record="chatList[index]"
|
||||||
|
:type="type"
|
||||||
|
:send-message="sendMessage"
|
||||||
|
:chat-management="ChatManagement"
|
||||||
:executionIsRightPanel="props.executionIsRightPanel"
|
:executionIsRightPanel="props.executionIsRightPanel"
|
||||||
@open-execution-detail="emit('openExecutionDetail', chatList[index])"
|
@open-execution-detail="emit('openExecutionDetail', chatList[index])"
|
||||||
@openParagraph="emit('openParagraph', chatList[index])"
|
@openParagraph="emit('openParagraph', chatList[index])"
|
||||||
@openParagraphDocument="
|
@openParagraphDocument="
|
||||||
(val: any) => emit('openParagraphDocument', chatList[index], val)
|
(val: any) => emit('openParagraphDocument', chatList[index], val)
|
||||||
"></AnswerContent>
|
"
|
||||||
|
></AnswerContent>
|
||||||
</template>
|
</template>
|
||||||
<TransitionContent v-if="transcribing" :text="t('chat.transcribing')" :type="type"
|
<TransitionContent
|
||||||
:application="applicationDetails">
|
v-if="transcribing"
|
||||||
|
:text="t('chat.transcribing')"
|
||||||
|
:type="type"
|
||||||
|
:application="applicationDetails"
|
||||||
|
>
|
||||||
</TransitionContent>
|
</TransitionContent>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
|
||||||
<ChatInputOperate :app-id="appId" :application-details="applicationDetails" :is-mobile="isMobile" :type="type"
|
<ChatInputOperate
|
||||||
:send-message="sendMessage" :open-chat-id="openChatId" :validate="validate" :chat-management="ChatManagement"
|
:app-id="appId"
|
||||||
v-model:chat-id="chartOpenId" v-model:loading="loading" v-model:show-user-input="showUserInput"
|
:application-details="applicationDetails"
|
||||||
v-if="type !== 'log'">
|
:is-mobile="isMobile"
|
||||||
|
:type="type"
|
||||||
|
:send-message="sendMessage"
|
||||||
|
:open-chat-id="openChatId"
|
||||||
|
:validate="validate"
|
||||||
|
:chat-management="ChatManagement"
|
||||||
|
v-model:chat-id="chartOpenId"
|
||||||
|
v-model:loading="loading"
|
||||||
|
v-model:show-user-input="showUserInput"
|
||||||
|
v-if="type !== 'log'"
|
||||||
|
>
|
||||||
<template #userInput>
|
<template #userInput>
|
||||||
<el-button v-if="isUserInput || isAPIInput" class="user-input-button mb-8" @click="toggleUserInput">
|
<el-button
|
||||||
|
v-if="isUserInput || isAPIInput"
|
||||||
|
class="user-input-button mb-8"
|
||||||
|
@click="toggleUserInput"
|
||||||
|
>
|
||||||
<AppIcon iconName="app-edit" :size="16" class="mr-4"></AppIcon>
|
<AppIcon iconName="app-edit" :size="16" class="mr-4"></AppIcon>
|
||||||
<span class="ellipsis">
|
<span class="ellipsis">
|
||||||
{{ userInputTitle || $t('chat.userInput') }}
|
{{ userInputTitle || $t('chat.userInput') }}
|
||||||
@ -52,11 +100,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type Ref, ref, nextTick, computed, watch, reactive, onMounted, onBeforeUnmount } from 'vue'
|
import {
|
||||||
|
type Ref,
|
||||||
|
ref,
|
||||||
|
nextTick,
|
||||||
|
computed,
|
||||||
|
watch,
|
||||||
|
reactive,
|
||||||
|
onMounted,
|
||||||
|
onBeforeUnmount,
|
||||||
|
provide,
|
||||||
|
} from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import applicationApi from '@/api/application/application'
|
import applicationApi from '@/api/application/application'
|
||||||
import chatAPI from '@/api/chat/chat'
|
import chatAPI from '@/api/chat/chat'
|
||||||
import SystemResourceManagementApplicationAPI from "@/api/system-resource-management/application.ts"
|
import SystemResourceManagementApplicationAPI from '@/api/system-resource-management/application.ts'
|
||||||
import syetrmResourceManagementChatLogApi from '@/api/system-resource-management/chat-log'
|
import syetrmResourceManagementChatLogApi from '@/api/system-resource-management/chat-log'
|
||||||
import chatLogApi from '@/api/application/chat-log'
|
import chatLogApi from '@/api/application/chat-log'
|
||||||
import { ChatManagement, type chatType } from '@/api/type/application'
|
import { ChatManagement, type chatType } from '@/api/type/application'
|
||||||
@ -72,6 +130,11 @@ import UserForm from '@/components/ai-chat/component/user-form/index.vue'
|
|||||||
import Control from '@/components/ai-chat/component/control/index.vue'
|
import Control from '@/components/ai-chat/component/control/index.vue'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
import bus from '@/bus'
|
import bus from '@/bus'
|
||||||
|
provide('upload', (file: any, loading?: Ref<boolean>) => {
|
||||||
|
return props.type === 'debug-ai-chat'
|
||||||
|
? applicationApi.postUploadFile(file, 'TEMPORARY_120_MINUTE', 'TEMPORARY_120_MINUTE', loading)
|
||||||
|
: chatAPI.postUploadFile(file, chartOpenId.value, 'CHAT', loading)
|
||||||
|
})
|
||||||
const transcribing = ref<boolean>(false)
|
const transcribing = ref<boolean>(false)
|
||||||
defineOptions({ name: 'AiChat' })
|
defineOptions({ name: 'AiChat' })
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@ -301,17 +364,25 @@ const getChatRecordDetailsAPI = (row: any) => {
|
|||||||
if (row.record_id) {
|
if (row.record_id) {
|
||||||
if (props.type === 'debug-ai-chat') {
|
if (props.type === 'debug-ai-chat') {
|
||||||
if (route.path.includes('resource-management')) {
|
if (route.path.includes('resource-management')) {
|
||||||
return syetrmResourceManagementChatLogApi
|
return syetrmResourceManagementChatLogApi.getChatRecordDetails(
|
||||||
.getChatRecordDetails(id || props.appId, row.chat_id, row.record_id, loading)
|
id || props.appId,
|
||||||
|
row.chat_id,
|
||||||
|
row.record_id,
|
||||||
|
loading,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return chatLogApi
|
return chatLogApi.getChatRecordDetails(
|
||||||
.getChatRecordDetails(id || props.appId, row.chat_id, row.record_id, loading)
|
id || props.appId,
|
||||||
|
row.chat_id,
|
||||||
|
row.record_id,
|
||||||
|
loading,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return chatAPI.getChatRecord(row.chat_id, row.record_id, loading)
|
return chatAPI.getChatRecord(row.chat_id, row.record_id, loading)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.reject("404")
|
return Promise.reject('404')
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 获取对话详情
|
* 获取对话详情
|
||||||
@ -326,7 +397,6 @@ function getSourceDetail(row: any) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 对话
|
* 对话
|
||||||
|
|||||||
@ -2,43 +2,51 @@ import { t } from '@/locales'
|
|||||||
const input_type_list = [
|
const input_type_list = [
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.TextInput'),
|
label: t('dynamicsForm.input_type_list.TextInput'),
|
||||||
value: 'TextInput'
|
value: 'TextInput',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.PasswordInput'),
|
label: t('dynamicsForm.input_type_list.PasswordInput'),
|
||||||
value: 'PasswordInput'
|
value: 'PasswordInput',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.Slider'),
|
label: t('dynamicsForm.input_type_list.Slider'),
|
||||||
value: 'Slider'
|
value: 'Slider',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.SwitchInput'),
|
label: t('dynamicsForm.input_type_list.SwitchInput'),
|
||||||
value: 'SwitchInput'
|
value: 'SwitchInput',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.SingleSelect'),
|
label: t('dynamicsForm.input_type_list.SingleSelect'),
|
||||||
value: 'SingleSelect'
|
value: 'SingleSelect',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.MultiSelect'),
|
label: t('dynamicsForm.input_type_list.MultiSelect'),
|
||||||
value: 'MultiSelect'
|
value: 'MultiSelect',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.DatePicker'),
|
label: t('dynamicsForm.input_type_list.DatePicker'),
|
||||||
value: 'DatePicker'
|
value: 'DatePicker',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.JsonInput'),
|
label: t('dynamicsForm.input_type_list.JsonInput'),
|
||||||
value: 'JsonInput'
|
value: 'JsonInput',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.RadioCard'),
|
label: t('dynamicsForm.input_type_list.RadioCard'),
|
||||||
value: 'RadioCard'
|
value: 'RadioCard',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('dynamicsForm.input_type_list.RadioRow'),
|
label: t('dynamicsForm.input_type_list.RadioRow'),
|
||||||
value: 'RadioRow'
|
value: 'RadioRow',
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
label: t('dynamicsForm.input_type_list.UploadInput'),
|
||||||
|
value: 'UploadInput',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('dynamicsForm.input_type_list.TextareaInput'),
|
||||||
|
value: 'TextareaInput',
|
||||||
|
},
|
||||||
]
|
]
|
||||||
export { input_type_list }
|
export { input_type_list }
|
||||||
|
|||||||
@ -8,9 +8,32 @@
|
|||||||
|
|
||||||
<el-row style="width: 100%" :gutter="10">
|
<el-row style="width: 100%" :gutter="10">
|
||||||
<el-radio-group v-model="formValue.assignment_method">
|
<el-radio-group v-model="formValue.assignment_method">
|
||||||
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list">{{
|
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list"
|
||||||
item.label
|
>{{ item.label }}
|
||||||
}}</el-radio>
|
<el-popover
|
||||||
|
width="300px"
|
||||||
|
v-if="item.value == 'ref_variables'"
|
||||||
|
class="box-item"
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
{{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover') }}:<br />
|
||||||
|
[<br />
|
||||||
|
{<br />
|
||||||
|
"label": "xx",<br />
|
||||||
|
"value": "xx",<br />
|
||||||
|
"default": false<br />
|
||||||
|
}<br />
|
||||||
|
]<br />
|
||||||
|
label: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_label') }}
|
||||||
|
{{ $t('common.required') }}<br />
|
||||||
|
value: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_value') }}
|
||||||
|
{{ $t('common.required') }}<br />
|
||||||
|
default: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_default') }}
|
||||||
|
<template #reference>
|
||||||
|
<el-icon><InfoFilled /></el-icon>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@ -8,9 +8,32 @@
|
|||||||
|
|
||||||
<el-row style="width: 100%" :gutter="10">
|
<el-row style="width: 100%" :gutter="10">
|
||||||
<el-radio-group v-model="formValue.assignment_method">
|
<el-radio-group v-model="formValue.assignment_method">
|
||||||
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list">{{
|
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list"
|
||||||
item.label
|
>{{ item.label }}
|
||||||
}}</el-radio>
|
<el-popover
|
||||||
|
width="300px"
|
||||||
|
v-if="item.value == 'ref_variables'"
|
||||||
|
class="box-item"
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
{{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover') }}:<br />
|
||||||
|
[<br />
|
||||||
|
{<br />
|
||||||
|
"label": "xx",<br />
|
||||||
|
"value": "xx",<br />
|
||||||
|
"default": false<br />
|
||||||
|
}<br />
|
||||||
|
]<br />
|
||||||
|
label: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_label') }}
|
||||||
|
{{ $t('common.required') }}<br />
|
||||||
|
value: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_value') }}
|
||||||
|
{{ $t('common.required') }}<br />
|
||||||
|
default:{{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_default') }}
|
||||||
|
<template #reference>
|
||||||
|
<el-icon><InfoFilled /></el-icon>
|
||||||
|
</template>
|
||||||
|
</el-popover>
|
||||||
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@ -8,9 +8,31 @@
|
|||||||
|
|
||||||
<el-row style="width: 100%" :gutter="10">
|
<el-row style="width: 100%" :gutter="10">
|
||||||
<el-radio-group v-model="formValue.assignment_method">
|
<el-radio-group v-model="formValue.assignment_method">
|
||||||
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list">{{
|
<el-radio :value="item.value" size="large" v-for="item in assignment_method_option_list"
|
||||||
item.label
|
>{{ item.label }}
|
||||||
}}</el-radio>
|
<el-popover
|
||||||
|
width="300px"
|
||||||
|
v-if="item.value == 'ref_variables'"
|
||||||
|
class="box-item"
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
{{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover') }}:<br />
|
||||||
|
[<br />
|
||||||
|
{<br />
|
||||||
|
"label": "xx",<br />
|
||||||
|
"value": "xx",<br />
|
||||||
|
"default": false<br />
|
||||||
|
}<br />
|
||||||
|
]<br />
|
||||||
|
label: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_label') }}
|
||||||
|
{{ $t('common.required') }}<br />
|
||||||
|
value: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_value') }}
|
||||||
|
{{ $t('common.required') }}<br />
|
||||||
|
default: {{ $t('dynamicsForm.AssignmentMethod.ref_variables.popover_default') }}
|
||||||
|
<template #reference>
|
||||||
|
<el-icon><InfoFilled /></el-icon>
|
||||||
|
</template> </el-popover
|
||||||
|
></el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@ -0,0 +1,195 @@
|
|||||||
|
<template>
|
||||||
|
<el-form-item :label="$t('dynamicsForm.TextInput.length.label')" required>
|
||||||
|
<el-row class="w-full">
|
||||||
|
<el-col :span="11">
|
||||||
|
<el-form-item
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: $t('dynamicsForm.TextInput.length.minRequired'),
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
prop="minlength"
|
||||||
|
>
|
||||||
|
<el-input-number
|
||||||
|
style="width: 100%"
|
||||||
|
:min="1"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
v-model="formValue.minlength"
|
||||||
|
controls-position="right"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2" class="text-center">
|
||||||
|
<span>-</span>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="11">
|
||||||
|
<el-form-item
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: $t('dynamicsForm.TextInput.length.maxRequired'),
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
prop="maxlength"
|
||||||
|
>
|
||||||
|
<el-input-number
|
||||||
|
style="width: 100%"
|
||||||
|
:min="formValue.minlength > formValue.maxlength ? formValue.minlength : 1"
|
||||||
|
step-strictly
|
||||||
|
:step="1"
|
||||||
|
v-model="formValue.maxlength"
|
||||||
|
controls-position="right"
|
||||||
|
/></el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item
|
||||||
|
class="defaultValueItem"
|
||||||
|
:required="formValue.required"
|
||||||
|
prop="default_value"
|
||||||
|
:label="$t('dynamicsForm.default.label')"
|
||||||
|
:rules="
|
||||||
|
formValue.required
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: `${$t('dynamicsForm.default.label')}${$t('dynamicsForm.default.requiredMessage')}`,
|
||||||
|
},
|
||||||
|
...rules,
|
||||||
|
]
|
||||||
|
: rules
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="defaultValueCheckbox">
|
||||||
|
<el-checkbox
|
||||||
|
v-model="formValue.show_default_value"
|
||||||
|
:label="$t('dynamicsForm.default.show')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-input
|
||||||
|
v-model="formValue.default_value"
|
||||||
|
:maxlength="formValue.maxlength"
|
||||||
|
:minlength="formValue.minlength"
|
||||||
|
:placeholder="$t('dynamicsForm.default.placeholder')"
|
||||||
|
show-word-limit
|
||||||
|
:autosize="{ minRows: 3, maxRows: 3 }"
|
||||||
|
type="textarea"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, onMounted, watch } from 'vue'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: any
|
||||||
|
}>()
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const formValue = computed({
|
||||||
|
set: (item) => {
|
||||||
|
emit('update:modelValue', item)
|
||||||
|
},
|
||||||
|
get: () => {
|
||||||
|
return props.modelValue
|
||||||
|
},
|
||||||
|
})
|
||||||
|
watch(
|
||||||
|
() => formValue.value.minlength,
|
||||||
|
() => {
|
||||||
|
if (formValue.value.minlength > formValue.value.maxlength) {
|
||||||
|
formValue.value.maxlength = formValue.value.minlength
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
const getData = () => {
|
||||||
|
return {
|
||||||
|
input_type: 'TextareaInput',
|
||||||
|
attrs: {
|
||||||
|
maxlength: formValue.value.maxlength,
|
||||||
|
minlength: formValue.value.minlength,
|
||||||
|
'show-word-limit': true,
|
||||||
|
autosize: { minRows: 3, maxRows: 3 },
|
||||||
|
},
|
||||||
|
default_value: formValue.value.default_value,
|
||||||
|
show_default_value: formValue.value.show_default_value,
|
||||||
|
props_info: {
|
||||||
|
rules: formValue.value.required
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: `${formValue.value.label} ${t('dynamicsForm.default.requiredMessage')}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
min: formValue.value.minlength,
|
||||||
|
max: formValue.value.maxlength,
|
||||||
|
message: `${formValue.value.label}${t('dynamicsForm.TextInput.length.requiredMessage1')} ${formValue.value.minlength} ${t('dynamicsForm.TextInput.length.requiredMessage2')} ${formValue.value.maxlength} ${t('dynamicsForm.TextInput.length.requiredMessage3')}`,
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
min: formValue.value.minlength,
|
||||||
|
max: formValue.value.maxlength,
|
||||||
|
message: `${formValue.value.label}${t('dynamicsForm.TextInput.length.requiredMessage1')} ${formValue.value.minlength} ${t('dynamicsForm.TextInput.length.requiredMessage2')} ${formValue.value.maxlength} ${t('dynamicsForm.TextInput.length.requiredMessage3')}`,
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const rander = (form_data: any) => {
|
||||||
|
const attrs = form_data.attrs || {}
|
||||||
|
formValue.value.minlength = attrs.minlength
|
||||||
|
formValue.value.maxlength = attrs.maxlength
|
||||||
|
formValue.value.default_value = form_data.default_value
|
||||||
|
formValue.value.show_default_value = form_data.show_default_value
|
||||||
|
}
|
||||||
|
const rangeRules = [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!formValue.value.minlength) {
|
||||||
|
callback(new Error(t('dynamicsForm.TextInput.length.requiredMessage4')))
|
||||||
|
}
|
||||||
|
if (!formValue.value.maxlength) {
|
||||||
|
callback(new Error(t('dynamicsForm.TextInput.length.requiredMessage4')))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
message: `${formValue.value.label} ${t('dynamicsForm.default.requiredMessage')}`,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
const rules = computed(() => [
|
||||||
|
{
|
||||||
|
min: formValue.value.minlength,
|
||||||
|
max: formValue.value.maxlength,
|
||||||
|
message: `${t('dynamicsForm.TextInput.length.requiredMessage1')} ${formValue.value.minlength} ${t('dynamicsForm.TextInput.length.requiredMessage2')} ${formValue.value.maxlength} ${t('dynamicsForm.TextInput.length.requiredMessage3')}`,
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
defineExpose({ getData, rander })
|
||||||
|
onMounted(() => {
|
||||||
|
formValue.value.minlength = 0
|
||||||
|
formValue.value.maxlength = 200
|
||||||
|
formValue.value.default_value = ''
|
||||||
|
if (formValue.value.show_default_value === undefined) {
|
||||||
|
formValue.value.show_default_value = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.defaultValueItem {
|
||||||
|
position: relative;
|
||||||
|
.defaultValueCheckbox {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: -35px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,153 @@
|
|||||||
|
<template>
|
||||||
|
<el-form-item :label="$t('dynamicsForm.UploadInput.limit.label')" required prop="limit">
|
||||||
|
<el-input-number
|
||||||
|
style="width: 100%"
|
||||||
|
v-model="formValue.limit"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: $t('dynamicsForm.UploadInput.limit.required'),
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:min="0"
|
||||||
|
controls-position="right"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('dynamicsForm.UploadInput.max_file_size.label')"
|
||||||
|
required
|
||||||
|
prop="max_file_size"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: $t('dynamicsForm.UploadInput.max_file_size.required'),
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<el-input-number
|
||||||
|
style="width: 100%"
|
||||||
|
v-model="formValue.max_file_size"
|
||||||
|
:min="0"
|
||||||
|
controls-position="right"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('dynamicsForm.UploadInput.accept.label')"
|
||||||
|
required
|
||||||
|
prop="accept"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: $t('dynamicsForm.UploadInput.accept.required'),
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<div class="gap-2" style="display: flex">
|
||||||
|
<el-tag
|
||||||
|
v-for="tag in formValue.accept"
|
||||||
|
:key="tag"
|
||||||
|
closable
|
||||||
|
:disable-transitions="false"
|
||||||
|
@close="handleClose(tag)"
|
||||||
|
>
|
||||||
|
{{ tag }}
|
||||||
|
</el-tag>
|
||||||
|
<el-input
|
||||||
|
v-if="inputVisible"
|
||||||
|
ref="InputRef"
|
||||||
|
v-model="inputValue"
|
||||||
|
class="w-20"
|
||||||
|
size="small"
|
||||||
|
@keyup.enter="handleInputConfirm"
|
||||||
|
@blur="handleInputConfirm"
|
||||||
|
/>
|
||||||
|
<el-button v-else class="button-new-tag" size="small" @click="showInput">
|
||||||
|
+ {{ $t('common.fileUpload.addExtensions') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, onMounted, ref, nextTick } from 'vue'
|
||||||
|
import { ElMessage, type InputInstance } from 'element-plus'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const inputValue = ref('')
|
||||||
|
|
||||||
|
const inputVisible = ref(false)
|
||||||
|
const InputRef = ref<InputInstance>()
|
||||||
|
const handleClose = (tag: string) => {
|
||||||
|
formValue.value.accept.splice(formValue.value.accept.indexOf(tag), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const showInput = () => {
|
||||||
|
inputVisible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
InputRef.value!.input!.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleInputConfirm = () => {
|
||||||
|
if (formValue.value.accept.find((item: string) => item === inputValue.value)) {
|
||||||
|
ElMessage.warning(t('common.fileUpload.existingExtensionsTip'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (inputValue.value) {
|
||||||
|
formValue.value.accept.push(inputValue.value)
|
||||||
|
}
|
||||||
|
inputVisible.value = false
|
||||||
|
inputValue.value = ''
|
||||||
|
}
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
const formValue = computed({
|
||||||
|
set: (item) => {
|
||||||
|
emit('update:modelValue', item)
|
||||||
|
},
|
||||||
|
get: () => {
|
||||||
|
return props.modelValue
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const rander = (form_data: any) => {
|
||||||
|
formValue.value.default_value = []
|
||||||
|
formValue.value.limit = form_data.attrs.limit || 3
|
||||||
|
formValue.value.max_file_size = form_data.max_file_size || 10
|
||||||
|
formValue.value.accept = form_data.attrs.accept
|
||||||
|
? form_data.attrs.accept.split(',').map((item: string) => item.substring(1))
|
||||||
|
: ['jpg']
|
||||||
|
}
|
||||||
|
const getData = () => {
|
||||||
|
return {
|
||||||
|
input_type: 'UploadInput',
|
||||||
|
attrs: {
|
||||||
|
accept: formValue.value.accept.map((item: any) => '.' + item).join(','),
|
||||||
|
limit: formValue.value.limit,
|
||||||
|
},
|
||||||
|
max_file_size: formValue.value.max_file_size,
|
||||||
|
default_value: [],
|
||||||
|
show_default_value: formValue.value.show_default_value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ getData, rander })
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
formValue.value.default_value = []
|
||||||
|
formValue.value.limit = 3
|
||||||
|
formValue.value.max_file_size = 10
|
||||||
|
formValue.value.accept = ['jpg']
|
||||||
|
if (formValue.value.show_default_value === undefined) {
|
||||||
|
formValue.value.show_default_value = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.gap-2 {
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
5
ui/src/components/dynamics-form/items/TextareaInput.vue
Normal file
5
ui/src/components/dynamics-form/items/TextareaInput.vue
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<el-input v-bind="$attrs" type="textarea"></el-input>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts"></script>
|
||||||
|
<style lang="scss"></style>
|
||||||
123
ui/src/components/dynamics-form/items/upload/UploadInput.vue
Normal file
123
ui/src/components/dynamics-form/items/upload/UploadInput.vue
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<el-upload
|
||||||
|
style="width: 80%"
|
||||||
|
v-loading="loading"
|
||||||
|
action="#"
|
||||||
|
v-bind="$attrs"
|
||||||
|
:auto-upload="false"
|
||||||
|
:on-change="(file: any, fileList: any) => uploadFile(file, fileList)"
|
||||||
|
v-model:file-list="model_value"
|
||||||
|
multiple
|
||||||
|
>
|
||||||
|
<el-button type="primary">{{ $t('chat.uploadFile.label') }}</el-button>
|
||||||
|
<template #file="{ file, index }"
|
||||||
|
><el-card style="--el-card-padding: 0" shadow="never">
|
||||||
|
<div
|
||||||
|
:class="[inputDisabled ? 'is-disabled' : '']"
|
||||||
|
style="
|
||||||
|
padding: 0 8px 0 8px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<el-tooltip class="box-item" effect="dark" :content="file.name" placement="top-start">
|
||||||
|
<div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 40%">
|
||||||
|
{{ file.name }}
|
||||||
|
</div></el-tooltip
|
||||||
|
>
|
||||||
|
|
||||||
|
<div>{{ formatSize(file.size) }}</div>
|
||||||
|
<el-icon @click="deleteFile(file)" style="cursor: pointer"><DeleteFilled /></el-icon>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, inject, ref, useAttrs } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import type { FormField } from '@/components/dynamics-form/type'
|
||||||
|
import { t } from '@/locales'
|
||||||
|
import { useFormDisabled } from 'element-plus'
|
||||||
|
const inputDisabled = useFormDisabled()
|
||||||
|
const attrs = useAttrs() as any
|
||||||
|
const upload = inject('upload') as any
|
||||||
|
const props = withDefaults(defineProps<{ modelValue?: any; formField: FormField }>(), {
|
||||||
|
modelValue: () => [],
|
||||||
|
})
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
function formatSize(sizeInBytes: number) {
|
||||||
|
const units = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||||
|
let size = sizeInBytes
|
||||||
|
let unitIndex = 0
|
||||||
|
|
||||||
|
while (size >= 1024 && unitIndex < units.length - 1) {
|
||||||
|
size /= 1024
|
||||||
|
unitIndex++
|
||||||
|
}
|
||||||
|
|
||||||
|
return size.toFixed(2) + ' ' + units[unitIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteFile = (file: any) => {
|
||||||
|
if (inputDisabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileArray.value = fileArray.value.filter((f: any) => f.uid != file.uid)
|
||||||
|
emit('update:modelValue', fileArray.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const model_value = computed({
|
||||||
|
get: () => {
|
||||||
|
if (!model_value) {
|
||||||
|
emit('update:modelValue', [])
|
||||||
|
}
|
||||||
|
return props.modelValue
|
||||||
|
},
|
||||||
|
set: (v: Array<any>) => {
|
||||||
|
emit('update:modelValue', v)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const fileArray = ref<any>([])
|
||||||
|
|
||||||
|
const loading = ref<boolean>(false)
|
||||||
|
|
||||||
|
const uploadFile = async (file: any, fileList: Array<any>) => {
|
||||||
|
fileList.splice(fileList.indexOf(file), 1)
|
||||||
|
if (fileArray.value.find((f: any) => f.name === file.name)) {
|
||||||
|
ElMessage.warning(t('chat.uploadFile.fileRepeat'))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const max_file_size = (props.formField as any).max_file_size
|
||||||
|
if (file.size / 1024 / 1024 > max_file_size) {
|
||||||
|
ElMessage.warning(t('chat.uploadFile.sizeLimit') + max_file_size + 'MB')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileList.length > attrs.limit) {
|
||||||
|
ElMessage.warning(
|
||||||
|
t('chat.uploadFile.limitMessage1') + attrs.limit + t('chat.uploadFile.limitMessage2'),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
upload(file.raw, loading).then((ok: any) => {
|
||||||
|
const split_path = ok.data.split('/')
|
||||||
|
const file_id = split_path[split_path.length - 1]
|
||||||
|
fileArray.value?.push({ name: file.name, file_id, size: file.size })
|
||||||
|
emit('update:modelValue', fileArray.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.is-disabled {
|
||||||
|
background-color: var(--el-fill-color-light);
|
||||||
|
color: var(--el-text-color-placeholder);
|
||||||
|
cursor: not-allowed;
|
||||||
|
&:hover {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -10,6 +10,8 @@ export default {
|
|||||||
JsonInput: 'JSON',
|
JsonInput: 'JSON',
|
||||||
RadioCard: 'Radio Card',
|
RadioCard: 'Radio Card',
|
||||||
RadioRow: 'Radio Row',
|
RadioRow: 'Radio Row',
|
||||||
|
UploadInput: 'File upload',
|
||||||
|
TextareaInput: 'Multiline Input',
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
label: 'Default',
|
label: 'Default',
|
||||||
@ -99,6 +101,20 @@ export default {
|
|||||||
requiredMessage4: 'Text length is a required parameter',
|
requiredMessage4: 'Text length is a required parameter',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
UploadInput: {
|
||||||
|
limit: {
|
||||||
|
label: 'Maximum number of files per upload',
|
||||||
|
required: 'Maximum number of files is required',
|
||||||
|
},
|
||||||
|
max_file_size: {
|
||||||
|
label: 'Maximum file size (MB)',
|
||||||
|
required: 'Maximum file size is required',
|
||||||
|
},
|
||||||
|
accept: {
|
||||||
|
label: 'File type',
|
||||||
|
required: 'File type is required',
|
||||||
|
},
|
||||||
|
},
|
||||||
AssignmentMethod: {
|
AssignmentMethod: {
|
||||||
label: 'Assignment Method',
|
label: 'Assignment Method',
|
||||||
custom: {
|
custom: {
|
||||||
@ -106,6 +122,10 @@ export default {
|
|||||||
},
|
},
|
||||||
ref_variables: {
|
ref_variables: {
|
||||||
label: 'Reference Variables',
|
label: 'Reference Variables',
|
||||||
|
popover: 'Variable values must comply with',
|
||||||
|
popover_label: 'Label',
|
||||||
|
popover_value: 'Value',
|
||||||
|
popover_default: 'Is Default',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,6 +71,7 @@ export default {
|
|||||||
imageMessage: '请解析图片内容',
|
imageMessage: '请解析图片内容',
|
||||||
fileMessage: '请解析文件内容',
|
fileMessage: '请解析文件内容',
|
||||||
errorMessage: '上传失败',
|
errorMessage: '上传失败',
|
||||||
|
fileRepeat: '文件已存在',
|
||||||
},
|
},
|
||||||
executionDetails: {
|
executionDetails: {
|
||||||
title: '执行详情',
|
title: '执行详情',
|
||||||
|
|||||||
@ -10,6 +10,8 @@ export default {
|
|||||||
JsonInput: 'JSON文本框',
|
JsonInput: 'JSON文本框',
|
||||||
RadioCard: '选项卡',
|
RadioCard: '选项卡',
|
||||||
RadioRow: '单行选项卡',
|
RadioRow: '单行选项卡',
|
||||||
|
UploadInput: '文件上传',
|
||||||
|
TextareaInput: '多行文本框',
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
label: '默认值',
|
label: '默认值',
|
||||||
@ -99,13 +101,32 @@ export default {
|
|||||||
requiredMessage4: '文本长度为必填参数',
|
requiredMessage4: '文本长度为必填参数',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
UploadInput: {
|
||||||
|
limit: {
|
||||||
|
label: '单次上传最多文件数',
|
||||||
|
required: '单次上传最多文件数必填',
|
||||||
|
},
|
||||||
|
max_file_size: {
|
||||||
|
label: '每个文件最大(MB)',
|
||||||
|
required: '每个文件最大(MB)必填',
|
||||||
|
},
|
||||||
|
accept: {
|
||||||
|
label: '文件类型',
|
||||||
|
required: '文件类型必填',
|
||||||
|
},
|
||||||
|
},
|
||||||
AssignmentMethod: {
|
AssignmentMethod: {
|
||||||
label: '赋值方式',
|
label: '赋值方式',
|
||||||
|
|
||||||
custom: {
|
custom: {
|
||||||
label: '自定义',
|
label: '自定义',
|
||||||
},
|
},
|
||||||
ref_variables: {
|
ref_variables: {
|
||||||
label: '引用变量 ',
|
label: '引用变量 ',
|
||||||
|
popover: '变量的值必须符合',
|
||||||
|
popover_label: '标签',
|
||||||
|
popover_value: '值',
|
||||||
|
popover_default: '是否为默认值',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,8 @@ export default {
|
|||||||
JsonInput: 'JSON文字框',
|
JsonInput: 'JSON文字框',
|
||||||
RadioCard: '選項卡',
|
RadioCard: '選項卡',
|
||||||
RadioRow: '單行選項卡',
|
RadioRow: '單行選項卡',
|
||||||
|
UploadInput: '文件上傳',
|
||||||
|
TextareaInput: '多行文字方塊',
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
label: '預設值',
|
label: '預設值',
|
||||||
@ -99,13 +101,31 @@ export default {
|
|||||||
requiredMessage4: '文字長度為必填參數',
|
requiredMessage4: '文字長度為必填參數',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
UploadInput: {
|
||||||
|
limit: {
|
||||||
|
label: '單次上傳最多文件數',
|
||||||
|
required: '單次上傳最多文件數必填',
|
||||||
|
},
|
||||||
|
max_file_size: {
|
||||||
|
label: '每個文件最大(MB)',
|
||||||
|
required: '每個文件最大必填',
|
||||||
|
},
|
||||||
|
accept: {
|
||||||
|
label: '文件類型',
|
||||||
|
required: '文件類型必填',
|
||||||
|
},
|
||||||
|
},
|
||||||
AssignmentMethod: {
|
AssignmentMethod: {
|
||||||
label: '賦值方式',
|
label: '賦值方式',
|
||||||
custom: {
|
custom: {
|
||||||
label: '自定義',
|
label: '自定義',
|
||||||
},
|
},
|
||||||
ref_variables: {
|
ref_variables: {
|
||||||
label: '引用變量',
|
label: '參考變量',
|
||||||
|
popover: '變量的值必須符合',
|
||||||
|
popover_label: '標籤',
|
||||||
|
popover_value: '值',
|
||||||
|
popover_default: '是否為預設值',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user