This commit is contained in:
liqiang-fit2cloud 2025-02-28 12:28:40 +08:00
commit 2abf05f11a
37 changed files with 422 additions and 170 deletions

View File

@ -40,7 +40,6 @@ splitter = '\n`-----------------------------------`\n'
class BaseDocumentExtractNode(IDocumentExtractNode): class BaseDocumentExtractNode(IDocumentExtractNode):
def save_context(self, details, workflow_manage): def save_context(self, details, workflow_manage):
self.context['content'] = details.get('content') self.context['content'] = details.get('content')
self.answer_text = details.get('content')
def execute(self, document, chat_id, **kwargs): def execute(self, document, chat_id, **kwargs):

View File

@ -66,7 +66,7 @@ class ISearchDatasetStepNode(INode):
if self.flow_params_serializer.data.get('re_chat', False): if self.flow_params_serializer.data.get('re_chat', False):
history_chat_record = self.flow_params_serializer.data.get('history_chat_record', []) history_chat_record = self.flow_params_serializer.data.get('history_chat_record', [])
paragraph_id_list = [p.get('id') for p in flat_map( paragraph_id_list = [p.get('id') for p in flat_map(
[get_paragraph_list(chat_record, self.node.id) for chat_record in history_chat_record if [get_paragraph_list(chat_record, self.runtime_node_id) for chat_record in history_chat_record if
chat_record.problem_text == question])] chat_record.problem_text == question])]
exclude_paragraph_id_list = list(set(paragraph_id_list)) exclude_paragraph_id_list = list(set(paragraph_id_list))

View File

@ -6761,3 +6761,6 @@ msgstr ""
msgid "AI reply: " msgid "AI reply: "
msgstr "" msgstr ""
msgid "The network is busy, try again later."
msgstr ""

View File

@ -6900,3 +6900,6 @@ msgstr "思考过程: "
msgid "AI reply: " msgid "AI reply: "
msgstr "AI 回复: " msgstr "AI 回复: "
msgid "The network is busy, try again later."
msgstr "网络繁忙,请稍后再试。"

View File

@ -6911,4 +6911,7 @@ msgid "Think: "
msgstr "思考過程: " msgstr "思考過程: "
msgid "AI reply: " msgid "AI reply: "
msgstr "AI 回覆: " msgstr "AI 回覆: "
msgid "The network is busy, try again later."
msgstr "網絡繁忙,請稍後再試。"

View File

@ -122,7 +122,7 @@ function showSource(row: any) {
return false return false
} }
const regenerationChart = (chat: chatType) => { const regenerationChart = (chat: chatType) => {
props.sendMessage(chat.problem_text, { rechat: true }) props.sendMessage(chat.problem_text, { re_chat: true })
} }
const stopChat = (chat: chatType) => { const stopChat = (chat: chatType) => {
props.chatManagement.stop(chat.id) props.chatManagement.stop(chat.id)

View File

@ -86,6 +86,7 @@ import applicationApi from '@/api/application'
import { datetimeFormat } from '@/utils/time' import { datetimeFormat } from '@/utils/time'
import { MsgError } from '@/utils/message' import { MsgError } from '@/utils/message'
import { t } from '@/locales' import { t } from '@/locales'
import bus from '@/bus'
const route = useRoute() const route = useRoute()
const { const {
params: { id } params: { id }
@ -277,6 +278,11 @@ const pausePlayAnswerText = () => {
} }
onMounted(() => { onMounted(() => {
bus.on('pause-autoplay', () => {
pausePlayAnswerText()
// console.log(1234)
})
bus.emit('pause-autoplay')
// //
if (props.tts && props.tts_autoplay && buttonData.value.write_ed && !buttonData.value.update_time) { if (props.tts && props.tts_autoplay && buttonData.value.write_ed && !buttonData.value.update_time) {
playAnswerText(buttonData.value.answer_text) playAnswerText(buttonData.value.answer_text)

View File

@ -16,7 +16,9 @@
<el-icon class="mr-8 arrow-icon" :class="showUserInput ? 'rotate-90' : ''" <el-icon class="mr-8 arrow-icon" :class="showUserInput ? 'rotate-90' : ''"
><CaretRight ><CaretRight
/></el-icon> /></el-icon>
<span class="break-all ellipsis-1 mr-16" :title="inputFieldConfig.title">
{{ inputFieldConfig.title }} {{ inputFieldConfig.title }}
</span>
</div> </div>
<el-scrollbar max-height="160"> <el-scrollbar max-height="160">
<el-collapse-transition> <el-collapse-transition>

View File

@ -4,6 +4,10 @@ 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'),
value: 'PasswordInput'
},
{ {
label: t('dynamicsForm.input_type_list.Slider'), label: t('dynamicsForm.input_type_list.Slider'),
value: 'Slider' value: 'Slider'

View File

@ -0,0 +1,194 @@
<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
type="password"
show-password
/>
</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: 'PasswordInput',
attrs: {
maxlength: formValue.value.maxlength,
minlength: formValue.value.minlength,
'show-word-limit': true,
type: 'password',
'show-password': true
},
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
formValue.value.show_password = attrs['show-password']
}
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 = 20
formValue.value.default_value = ''
formValue.value.show_password = true
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>

View File

@ -1,11 +1,4 @@
<template> <template>
<el-form-item
class="defaultValueItem"
prop="show_password"
:label="$t('dynamicsForm.TextInput.showPassword')"
>
<el-switch v-model="formValue.show_password" />
</el-form-item>
<el-form-item :label="$t('dynamicsForm.TextInput.length.label')" required> <el-form-item :label="$t('dynamicsForm.TextInput.length.label')" required>
<el-row class="w-full"> <el-row class="w-full">
<el-col :span="11"> <el-col :span="11">
@ -77,8 +70,7 @@
:minlength="formValue.minlength" :minlength="formValue.minlength"
:placeholder="$t('dynamicsForm.default.placeholder')" :placeholder="$t('dynamicsForm.default.placeholder')"
show-word-limit show-word-limit
:type="formValue.show_password ? 'password' : 'text'" type="text"
:show-password="formValue.show_password"
/> />
</el-form-item> </el-form-item>
</template> </template>
@ -111,9 +103,7 @@ const getData = () => {
attrs: { attrs: {
maxlength: formValue.value.maxlength, maxlength: formValue.value.maxlength,
minlength: formValue.value.minlength, minlength: formValue.value.minlength,
'show-word-limit': true, 'show-word-limit': true
type: formValue.value.show_password ? 'password' : 'text',
'show-password': formValue.value.show_password
}, },
default_value: formValue.value.default_value, default_value: formValue.value.default_value,
show_default_value: formValue.value.show_default_value, show_default_value: formValue.value.show_default_value,
@ -145,7 +135,6 @@ const rander = (form_data: any) => {
formValue.value.maxlength = attrs.maxlength formValue.value.maxlength = attrs.maxlength
formValue.value.default_value = form_data.default_value formValue.value.default_value = form_data.default_value
formValue.value.show_default_value = form_data.show_default_value formValue.value.show_default_value = form_data.show_default_value
formValue.value.show_password = attrs['show-password']
} }
const rangeRules = [ const rangeRules = [
{ {
@ -176,8 +165,7 @@ onMounted(() => {
formValue.value.minlength = 0 formValue.value.minlength = 0
formValue.value.maxlength = 20 formValue.value.maxlength = 20
formValue.value.default_value = '' formValue.value.default_value = ''
formValue.value.show_password = false // console.log(formValue.value.show_default_value)
if (formValue.value.show_default_value === undefined) { if (formValue.value.show_default_value === undefined) {
formValue.value.show_default_value = true formValue.value.show_default_value = true
} }

View File

@ -48,13 +48,13 @@
type="textarea" type="textarea"
/> />
</el-form-item> </el-form-item>
<el-form-item :label="$t('views.problem.relateParagraph.selectParagraph')" prop="state"> <el-form-item v-if="apiType === 'document'" :label="$t('components.selectParagraph.title')" prop="state">
<el-radio-group v-model="state" class="radio-block"> <el-radio-group v-model="state" class="radio-block">
<el-radio value="error" size="large" class="mb-16">{{ <el-radio value="error" size="large">{{
$t('views.document.form.selectVectorization.error') $t('components.selectParagraph.error')
}}</el-radio> }}</el-radio>
<el-radio value="all" size="large">{{ <el-radio value="all" size="large">{{
$t('views.document.form.selectVectorization.all') $t('components.selectParagraph.all')
}}</el-radio> }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
@ -148,7 +148,6 @@ const submitHandle = async (formEl: FormInstance) => {
const data = { const data = {
...form.value, ...form.value,
paragraph_id_list: idList.value, paragraph_id_list: idList.value,
state_list: stateMap[state.value]
} }
paragraphApi.batchGenerateRelated(id, documentId, data, loading).then(() => { paragraphApi.batchGenerateRelated(id, documentId, data, loading).then(() => {
MsgSuccess(t('views.document.generateQuestion.successMessage')) MsgSuccess(t('views.document.generateQuestion.successMessage'))

View File

@ -57,5 +57,6 @@ export default {
inputPlaceholder: 'Please input', inputPlaceholder: 'Please input',
title: 'Title', title: 'Title',
content: 'Content' content: 'Content',
rename: 'Rename'
} }

View File

@ -3,5 +3,10 @@ export default {
quickCreateName: 'document name', quickCreateName: 'document name',
noData: 'No Data', noData: 'No Data',
loading: 'Loading', loading: 'Loading',
noMore: 'No more' noMore: 'No more! ',
selectParagraph: {
title: 'Select Paragraph',
error: 'Process only the failed segments',
all: 'All Segments'
}
} }

View File

@ -1,6 +1,7 @@
export default { export default {
input_type_list: { input_type_list: {
TextInput: 'Input', TextInput: 'Input',
PasswordInput: 'Password',
Slider: 'Slider', Slider: 'Slider',
SwitchInput: 'Switch', SwitchInput: 'Switch',
SingleSelect: 'Single Select', SingleSelect: 'Single Select',
@ -96,7 +97,6 @@ export default {
requiredMessage2: 'and', requiredMessage2: 'and',
requiredMessage3: 'characters', requiredMessage3: 'characters',
requiredMessage4: 'Text length is a required parameter' requiredMessage4: 'Text length is a required parameter'
}, }
showPassword: 'Show Password'
} }
} }

View File

@ -1,5 +1,6 @@
export default { export default {
node: 'Node', node: 'Node',
nodeName: 'Node Name',
baseComponent: 'Basic', baseComponent: 'Basic',
nodeSetting: 'Node Settings', nodeSetting: 'Node Settings',
workflow: 'Workflow', workflow: 'Workflow',

View File

@ -12,7 +12,7 @@ export default {
cancelGenerateQuestion: 'Cancel Generating Questions', cancelGenerateQuestion: 'Cancel Generating Questions',
cancelVectorization: 'Cancel Vectorization', cancelVectorization: 'Cancel Vectorization',
cancelGenerate: 'Cancel Generation', cancelGenerate: 'Cancel Generation',
export: 'Export to', export: 'Export to'
}, },
tip: { tip: {
saveMessage: 'Current changes have not been saved. Confirm exit?', saveMessage: 'Current changes have not been saved. Confirm exit?',
@ -84,8 +84,7 @@ export default {
text: 'Remove duplicate extra symbols, spaces, blank lines, and tab words.' text: 'Remove duplicate extra symbols, spaces, blank lines, and tab words.'
}, },
checkedConnect: { checkedConnect: {
label: label: 'Add "Related Questions" section for question-based QA pairs during import.'
'Add "Related Questions" section for question-based QA pairs during import.'
} }
}, },
buttons: { buttons: {
@ -153,11 +152,6 @@ export default {
label: 'Similarity Higher Than', label: 'Similarity Higher Than',
placeholder: 'Directly return segment content', placeholder: 'Directly return segment content',
requiredMessage: 'Please enter similarity value' requiredMessage: 'Please enter similarity value'
},
selectVectorization: {
label: 'Select Vectorization Content',
error: 'Segments that failed vectorization',
all: 'All Segments'
} }
}, },
hitHandlingMethod: { hitHandlingMethod: {
@ -173,7 +167,6 @@ export default {
tip4: 'The generation effect depends on the selected model and prompt. Users can adjust to achieve the best effect.', tip4: 'The generation effect depends on the selected model and prompt. Users can adjust to achieve the best effect.',
prompt1: prompt1:
'Content: {data}\n \n Please summarize the above and generate 5 questions based on the summary. \nAnswer requirements: \n - Please output only questions; \n - Please place each question in', 'Content: {data}\n \n Please summarize the above and generate 5 questions based on the summary. \nAnswer requirements: \n - Please output only questions; \n - Please place each question in',
prompt2: 'tag.', prompt2: 'tag.'
error: 'Segments only failed',
} }
} }

View File

@ -31,7 +31,6 @@ export default {
title: 'Relate to Segment', title: 'Relate to Segment',
selectDocument: 'Select a Document', selectDocument: 'Select a Document',
placeholder: 'Search document by name', placeholder: 'Search document by name',
selectParagraph: 'Select Segments',
selectedParagraph: 'Selected Segments', selectedParagraph: 'Selected Segments',
count: 'Count' count: 'Count'
} }

View File

@ -56,5 +56,6 @@ export default {
param: { param: {
outputParam: '输出参数', outputParam: '输出参数',
inputParam:'输入参数' inputParam:'输入参数'
} },
rename:'重命名'
} }

View File

@ -4,4 +4,9 @@ export default {
noData: '无匹配数据', noData: '无匹配数据',
loading: '加载中', loading: '加载中',
noMore: '到底啦!', noMore: '到底啦!',
selectParagraph: {
title: '选择分段',
error: '仅执行未成功分段',
all: '全部分段'
}
} }

View File

@ -1,6 +1,7 @@
export default { export default {
input_type_list: { input_type_list: {
TextInput: '文本框', TextInput: '文本框',
PasswordInput: '密码框',
Slider: '滑块', Slider: '滑块',
SwitchInput: '开关', SwitchInput: '开关',
SingleSelect: '单选框', SingleSelect: '单选框',
@ -96,7 +97,6 @@ export default {
requiredMessage2: '到', requiredMessage2: '到',
requiredMessage3: '个字符', requiredMessage3: '个字符',
requiredMessage4: '文本长度为必填参数' requiredMessage4: '文本长度为必填参数'
}, }
showPassword: '密文显示'
} }
} }

View File

@ -1,5 +1,6 @@
export default { export default {
node: '节点', node: '节点',
nodeName: '节点名称',
baseComponent: '基础组件', baseComponent: '基础组件',
nodeSetting: '节点设置', nodeSetting: '节点设置',
workflow: '工作流', workflow: '工作流',

View File

@ -150,11 +150,6 @@ export default {
placeholder: '直接返回分段内容', placeholder: '直接返回分段内容',
requiredMessage: '请输入相似度' requiredMessage: '请输入相似度'
}, },
selectVectorization: {
label: '选择向量化内容',
error: '向量化未成功的分段',
all: '全部分段'
}
}, },
hitHandlingMethod: { hitHandlingMethod: {
optimization: '模型优化', optimization: '模型优化',
@ -169,6 +164,5 @@ export default {
tip4: '生成效果依赖于所选模型和提示词,用户可自行调整至最佳效果。', tip4: '生成效果依赖于所选模型和提示词,用户可自行调整至最佳效果。',
prompt1: `内容:{data}\n\n请总结上面的内容并根据内容总结生成 5 个问题。\n回答要求\n- 请只输出问题;\n- 请将每个问题放置`, prompt1: `内容:{data}\n\n请总结上面的内容并根据内容总结生成 5 个问题。\n回答要求\n- 请只输出问题;\n- 请将每个问题放置`,
prompt2: `标签中。`, prompt2: `标签中。`,
error: '仅执行未成功的分段',
} }
} }

View File

@ -31,7 +31,6 @@ export default {
title: '关联分段', title: '关联分段',
selectDocument: '选择文档', selectDocument: '选择文档',
placeholder: '按 文档名称 搜索', placeholder: '按 文档名称 搜索',
selectParagraph: '选择分段',
selectedParagraph: '已选分段', selectedParagraph: '已选分段',
count: '个' count: '个'
}, },

View File

@ -55,6 +55,7 @@ export default {
content: '内容', content: '内容',
param: { param: {
outputParam: '輸出參數', outputParam: '輸出參數',
inputParam:'輸入參數' inputParam: '輸入參數'
} },
rename: '重命名'
} }

View File

@ -4,4 +4,9 @@ export default {
noData: '無匹配数据', noData: '無匹配数据',
loading: '加載中', loading: '加載中',
noMore: '到底啦!', noMore: '到底啦!',
selectParagraph: {
title: '選擇分段',
error: '僅執行未成功分段',
all: '全部分段'
}
} }

View File

@ -1,6 +1,7 @@
export default { export default {
input_type_list: { input_type_list: {
TextInput: '文字框', TextInput: '文字框',
PasswordInput: '密文框',
Slider: '滑桿', Slider: '滑桿',
SwitchInput: '開關', SwitchInput: '開關',
SingleSelect: '單選框', SingleSelect: '單選框',
@ -96,7 +97,6 @@ export default {
requiredMessage2: '到', requiredMessage2: '到',
requiredMessage3: '個字元', requiredMessage3: '個字元',
requiredMessage4: '文字長度為必填參數' requiredMessage4: '文字長度為必填參數'
}, }
showPassword: '密文顯示'
} }
} }

View File

@ -1,5 +1,6 @@
export default { export default {
node: '節點', node: '節點',
nodeName: '節點名稱',
baseComponent: '基礎組件', baseComponent: '基礎組件',
nodeSetting: '節點設置', nodeSetting: '節點設置',
workflow: '工作流', workflow: '工作流',

View File

@ -150,11 +150,6 @@ export default {
placeholder: '直接返回分段内容', placeholder: '直接返回分段内容',
requiredMessage: '请输入相似度' requiredMessage: '请输入相似度'
}, },
selectVectorization: {
label: '選擇向量化',
error: '向量化未成功的分段',
all: '全部分段'
}
}, },
hitHandlingMethod: { hitHandlingMethod: {
optimization: '模型優化', optimization: '模型優化',
@ -169,6 +164,5 @@ export default {
tip4: '生成效果取決於所選模型和提示詞,用戶可自行調整至最佳效果。', tip4: '生成效果取決於所選模型和提示詞,用戶可自行調整至最佳效果。',
prompt1: `內容:{data}\n\n請總結上面的內容並根據內容總結生成 5 個問題。\n回答要求\n - 請只輸出問題;\n - 請將每個問題放置在`, prompt1: `內容:{data}\n\n請總結上面的內容並根據內容總結生成 5 個問題。\n回答要求\n - 請只輸出問題;\n - 請將每個問題放置在`,
prompt2: `標籤中。`, prompt2: `標籤中。`,
error: '只執行未成功的分段',
} }
} }

View File

@ -31,7 +31,6 @@ export default {
title: '關聯分段', title: '關聯分段',
selectDocument: '選擇文件', selectDocument: '選擇文件',
placeholder: '按 文件名稱 搜尋', placeholder: '按 文件名稱 搜尋',
selectParagraph: '選擇分段',
selectedParagraph: '已選分段', selectedParagraph: '已選分段',
count: '個' count: '個'
}, },

View File

@ -1,15 +1,15 @@
<template> <template>
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="$t('views.document.form.selectVectorization.label')" :title="$t('components.selectParagraph.title')"
:before-close="close" :before-close="close"
> >
<el-radio-group v-model="state" class="radio-block"> <el-radio-group v-model="state" class="radio-block">
<el-radio value="error" size="large" class="mb-16">{{ <el-radio value="error" size="large" class="mb-16">{{
$t('views.document.form.selectVectorization.error') $t('components.selectParagraph.error')
}}</el-radio> }}</el-radio>
<el-radio value="all" size="large">{{ <el-radio value="all" size="large">{{
$t('views.document.form.selectVectorization.all') $t('components.selectParagraph.all')
}}</el-radio> }}</el-radio>
</el-radio-group> </el-radio-group>
<template #footer> <template #footer>

View File

@ -49,7 +49,7 @@
<div class="p-24" style="padding-bottom: 8px; padding-top: 16px"> <div class="p-24" style="padding-bottom: 8px; padding-top: 16px">
<div class="flex-between mb-16"> <div class="flex-between mb-16">
<div class="bold title align-center"> <div class="bold title align-center">
{{ $t('views.problem.relateParagraph.selectParagraph') }} {{ $t('components.selectParagraph.title') }}
<el-text> <el-text>
{{ $t('views.problem.relateParagraph.selectedParagraph') }}{{ {{ $t('views.problem.relateParagraph.selectedParagraph') }}{{
associationCount(currentDocument) associationCount(currentDocument)

View File

@ -7,28 +7,14 @@
> >
<div v-resize="resizeStepContainer"> <div v-resize="resizeStepContainer">
<div class="flex-between"> <div class="flex-between">
<div <div class="flex align-center" style="width: 70%;">
class="flex align-center"
:style="{ maxWidth: node_status == 200 ? 'calc(100% - 85px)' : 'calc(100% - 85px)' }"
>
<component <component
:is="iconComponent(`${nodeModel.type}-icon`)" :is="iconComponent(`${nodeModel.type}-icon`)"
class="mr-8" class="mr-8"
:size="24" :size="24"
:item="nodeModel?.properties.node_data" :item="nodeModel?.properties.node_data"
/> />
<h4 v-if="showOperate(nodeModel.type)" style="max-width: 90%"> <h4 class="ellipsis-1 break-all">{{ nodeModel.properties.stepName }}</h4>
<ReadWrite
@mousemove.stop
@mousedown.stop
@keydown.stop
@click.stop
@change="editName"
:data="nodeModel.properties.stepName"
trigger="dblclick"
/>
</h4>
<h4 v-else>{{ nodeModel.properties.stepName }}</h4>
</div> </div>
<div @mousemove.stop @mousedown.stop @keydown.stop @click.stop> <div @mousemove.stop @mousedown.stop @keydown.stop @click.stop>
@ -70,6 +56,9 @@
</el-button> </el-button>
<template #dropdown> <template #dropdown>
<el-dropdown-menu style="min-width: 80px"> <el-dropdown-menu style="min-width: 80px">
<el-dropdown-item @click="renameNode" class="p-8">{{
$t('common.rename')
}}</el-dropdown-item>
<el-dropdown-item @click="copyNode" class="p-8">{{ <el-dropdown-item @click="copyNode" class="p-8">{{
$t('common.copy') $t('common.copy')
}}</el-dropdown-item> }}</el-dropdown-item>
@ -138,6 +127,40 @@
@clickNodes="clickNodes" @clickNodes="clickNodes"
/> />
</el-collapse-transition> </el-collapse-transition>
<el-dialog
:title="$t('views.applicationWorkflow.nodeName')"
v-model="nodeNameDialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
:destroy-on-close="true"
append-to-body
>
<el-form label-position="top" ref="titleFormRef" :model="form">
<el-form-item
prop="title"
:rules="[
{
required: true,
message: $t('common.inputPlaceholder'),
trigger: 'blur'
}
]"
>
<el-input v-model="form.title" @blur="form.title = form.title.trim()" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click.prevent="nodeNameDialogVisible = false">
{{ $t('common.cancel') }}
</el-button>
<el-button type="primary" @click="editName(titleFormRef)">
{{ $t('common.save') }}
</el-button>
</span>
</template>
</el-dialog>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -149,6 +172,7 @@ import { iconComponent } from '../icons/utils'
import { copyClick } from '@/utils/clipboard' import { copyClick } from '@/utils/clipboard'
import { WorkflowType } from '@/enums/workflow' import { WorkflowType } from '@/enums/workflow'
import { MsgError, MsgConfirm } from '@/utils/message' import { MsgError, MsgConfirm } from '@/utils/message'
import type { FormInstance } from 'element-plus'
import { t } from '@/locales' import { t } from '@/locales'
const { const {
params: { id } params: { id }
@ -165,6 +189,11 @@ const height = ref<{
}) })
const showAnchor = ref<boolean>(false) const showAnchor = ref<boolean>(false)
const anchorData = ref<any>() const anchorData = ref<any>()
const titleFormRef = ref()
const nodeNameDialogVisible = ref<boolean>(false)
const form = ref<any>({
title: ''
})
const condition = computed({ const condition = computed({
set: (v) => { set: (v) => {
@ -190,6 +219,7 @@ const showNode = computed({
return true return true
} }
}) })
const handleWheel = (event: any) => { const handleWheel = (event: any) => {
const isCombinationKeyPressed = event.ctrlKey || event.metaKey const isCombinationKeyPressed = event.ctrlKey || event.metaKey
if (!isCombinationKeyPressed) { if (!isCombinationKeyPressed) {
@ -202,19 +232,30 @@ const node_status = computed(() => {
} }
return 200 return 200
}) })
function editName(val: string) {
if (val.trim() && val.trim() !== props.nodeModel.properties.stepName) { function renameNode() {
if ( form.value.title = props.nodeModel.properties.stepName
!props.nodeModel.graphModel.nodes?.some( nodeNameDialogVisible.value = true
(node: any) => node.properties.stepName === val.trim()
)
) {
set(props.nodeModel.properties, 'stepName', val.trim())
} else {
MsgError(t('views.applicationWorkflow.tip.repeatedNodeError'))
}
}
} }
const editName = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid) => {
if (valid) {
if (
!props.nodeModel.graphModel.nodes?.some(
(node: any) => node.properties.stepName === form.value.title
)
) {
set(props.nodeModel.properties, 'stepName', form.value.title)
nodeNameDialogVisible.value = false
formEl.resetFields()
} else {
MsgError(t('views.applicationWorkflow.tip.repeatedNodeError'))
}
}
})
}
const mousedown = () => { const mousedown = () => {
props.nodeModel.graphModel.clearSelectElements() props.nodeModel.graphModel.clearSelectElements()
set(props.nodeModel, 'isSelected', true) set(props.nodeModel, 'isSelected', true)

View File

@ -123,6 +123,7 @@ const currentRow = computed(() => {
const currentIndex = ref(null) const currentIndex = ref(null)
const inputTypeList = ref([ const inputTypeList = ref([
{ label: t('dynamicsForm.input_type_list.TextInput'), value: 'TextInputConstructor' }, { label: t('dynamicsForm.input_type_list.TextInput'), value: 'TextInputConstructor' },
{ label: t('dynamicsForm.input_type_list.PasswordInput'), value: 'PasswordInputConstructor' },
{ label: t('dynamicsForm.input_type_list.SingleSelect'), value: 'SingleSelectConstructor' }, { label: t('dynamicsForm.input_type_list.SingleSelect'), value: 'SingleSelectConstructor' },
{ label: t('dynamicsForm.input_type_list.MultiSelect'), value: 'MultiSelectConstructor' }, { label: t('dynamicsForm.input_type_list.MultiSelect'), value: 'MultiSelectConstructor' },
{ label: t('dynamicsForm.input_type_list.RadioCard'), value: 'RadioCardConstructor' }, { label: t('dynamicsForm.input_type_list.RadioCard'), value: 'RadioCardConstructor' },

View File

@ -49,6 +49,9 @@
<el-tag type="info" class="info-tag" v-if="row.input_type === 'TextInput'">{{ <el-tag type="info" class="info-tag" v-if="row.input_type === 'TextInput'">{{
$t('dynamicsForm.input_type_list.TextInput') $t('dynamicsForm.input_type_list.TextInput')
}}</el-tag> }}</el-tag>
<el-tag type="info" class="info-tag" v-if="row.input_type === 'PasswordInput'">{{
$t('dynamicsForm.input_type_list.PasswordInput')
}}</el-tag>
<el-tag type="info" class="info-tag" v-if="row.input_type === 'Slider'">{{ <el-tag type="info" class="info-tag" v-if="row.input_type === 'Slider'">{{
$t('dynamicsForm.input_type_list.Slider') $t('dynamicsForm.input_type_list.Slider')
}}</el-tag> }}</el-tag>
@ -169,6 +172,9 @@ function refreshFieldTitle(data: any) {
} }
const getDefaultValue = (row: any) => { const getDefaultValue = (row: any) => {
if(row.input_type === 'PasswordInput') {
return '******'
}
if (row.default_value) { if (row.default_value) {
const default_value = row.option_list const default_value = row.option_list
?.filter((v: any) => row.default_value.indexOf(v.value) > -1) ?.filter((v: any) => row.default_value.indexOf(v.value) > -1)

View File

@ -28,7 +28,7 @@
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button> <el-button @click.prevent="dialogVisible = false"> {{ $t('common.cancel') }} </el-button>
<el-button type="primary" @click="submit(fieldFormRef)" :loading="loading"> <el-button type="primary" @click="submit(fieldFormRef)" :loading="loading">
{{ isEdit ? $t('common.save') : $t('common.add') }} {{ $t('common.save') }}
</el-button> </el-button>
</span> </span>
</template> </template>
@ -43,14 +43,15 @@ const emit = defineEmits(['refresh'])
const fieldFormRef = ref() const fieldFormRef = ref()
const loading = ref<boolean>(false) const loading = ref<boolean>(false)
const isEdit = ref(false)
const form = ref<any>({ const form = ref<any>({
title: t('chat.userInput') , title: t('chat.userInput')
}) })
const rules = reactive({ const rules = reactive({
title: [{ required: true, message: t('dynamicsForm.paramForm.name.requiredMessage'), trigger: 'blur' }], title: [
{ required: true, message: t('dynamicsForm.paramForm.name.requiredMessage'), trigger: 'blur' }
]
}) })
const dialogVisible = ref<boolean>(false) const dialogVisible = ref<boolean>(false)
@ -58,7 +59,6 @@ const dialogVisible = ref<boolean>(false)
const open = (row: any) => { const open = (row: any) => {
if (row) { if (row) {
form.value = cloneDeep(row) form.value = cloneDeep(row)
isEdit.value = true
} }
dialogVisible.value = true dialogVisible.value = true
@ -66,7 +66,6 @@ const open = (row: any) => {
const close = () => { const close = () => {
dialogVisible.value = false dialogVisible.value = false
isEdit.value = false
} }
const submit = async (formEl: FormInstance | undefined) => { const submit = async (formEl: FormInstance | undefined) => {

View File

@ -39,7 +39,7 @@
<div class="flex-between"> <div class="flex-between">
<div> <div>
<span <span
>{{ $t('views.applicationWorkflow.nodes.variableAssignNode.assign') >{{ $t('views.applicationWorkflow.nodes.variableAssignNode.assign')
}}<span class="danger">*</span></span }}<span class="danger">*</span></span
> >
</div> </div>
@ -60,77 +60,83 @@
</el-select> </el-select>
</div> </div>
</template> </template>
</el-form-item> <div v-if="item.source === 'custom'" class="flex">
<div v-if="item.source === 'custom'" class="flex"> <el-row :gutter="8">
<el-row :gutter="8"> <el-col :span="8">
<el-col :span="8"> <el-select v-model="item.type" style="width: 85px">
<el-select v-model="item.type" style="width: 130px;"> <el-option
<el-option v-for="item in typeOptions" :key="item" :label="item" v-for="item in typeOptions"
:value="item" /> :key="item"
</el-select> :label="item"
</el-col> :value="item"
<el-col :span="16"> />
<el-form-item v-if="item.type === 'string'" </el-select>
:prop="'variable_list.' + index + '.value'" </el-col>
:rules="{ <el-col :span="16">
message: t('dynamicsForm.tip.requiredMessage'), <el-form-item
trigger: 'blur', v-if="item.type === 'string'"
required: true :prop="'variable_list.' + index + '.value'"
}" :rules="{
> message: t('dynamicsForm.tip.requiredMessage'),
<el-input trigger: 'blur',
class="ml-4" required: true
v-model="item.value" }"
:placeholder="$t('common.inputPlaceholder')" >
show-word-limit <el-input
clearable class="ml-4"
@wheel="wheel" v-model="item.value"
></el-input> :placeholder="$t('common.inputPlaceholder')"
</el-form-item> show-word-limit
<el-form-item v-else-if="item.type ==='num'" clearable
:prop="'variable_list.' + index + '.value'" @wheel="wheel"
:rules="{ ></el-input>
message: t('dynamicsForm.tip.requiredMessage'), </el-form-item>
trigger: 'blur', <el-form-item
required: true v-else-if="item.type === 'num'"
}" :prop="'variable_list.' + index + '.value'"
> :rules="{
<el-input-number message: $t('common.inputPlaceholder'),
class="ml-4" trigger: 'blur',
v-model="item.value" required: true
></el-input-number> }"
</el-form-item> >
<el-form-item v-else-if="item.type === 'json'" <el-input-number class="ml-4" v-model="item.value"></el-input-number>
:prop="'variable_list.' + index + '.value'" </el-form-item>
:rules="[{ <el-form-item
message: t('dynamicsForm.tip.requiredMessage'), v-else-if="item.type === 'json'"
trigger: 'blur', :prop="'variable_list.' + index + '.value'"
required: true :rules="[
}, {
{ message: $t('common.inputPlaceholder'),
validator: (rule:any, value:any, callback:any) => { trigger: 'blur',
try { required: true
JSON.parse(value); },
callback(); // Valid JSON {
} catch (e) { validator: (rule: any, value: any, callback: any) => {
callback(new Error('Invalid JSON format')); try {
} JSON.parse(value)
}, callback() // Valid JSON
trigger: 'blur', } catch (e) {
}]" callback(new Error('Invalid JSON format'))
> }
<el-input },
class="ml-4" trigger: 'blur'
v-model="item.value" }
:placeholder="$t('common.inputPlaceholder')" ]"
type="textarea" >
></el-input> <el-input
</el-form-item> class="ml-4"
</el-col> v-model="item.value"
</el-row> :placeholder="$t('common.inputPlaceholder')"
</div> type="textarea"
<el-form-item v-else> autosize
></el-input>
</el-form-item>
</el-col>
</el-row>
</div>
<NodeCascader <NodeCascader
v-else
ref="nodeCascaderRef2" ref="nodeCascaderRef2"
:nodeModel="nodeModel" :nodeModel="nodeModel"
class="w-full" class="w-full"
@ -138,7 +144,6 @@
v-model="item.reference" v-model="item.reference"
/> />
</el-form-item> </el-form-item>
</el-card> </el-card>
</template> </template>
<el-button link type="primary" @click="addVariable"> <el-button link type="primary" @click="addVariable">