feat: i18n
Some checks failed
sync2gitee / repo-sync (push) Has been cancelled
Typos Check / Spell Check with Typos (push) Has been cancelled

This commit is contained in:
王丹 2025-01-18 17:15:31 +08:00
parent 5c4d61c45c
commit ff3f51179b
18 changed files with 333 additions and 130 deletions

View File

@ -1,7 +1,7 @@
<template>
<el-dialog
class="execution-details-dialog"
title="执行详情"
:title="$t('components.chat.executionDetails.title')"
v-model="dialogVisible"
destroy-on-close
append-to-body
@ -56,7 +56,9 @@
"
>
<div class="card-never border-r-4">
<h5 class="p-8-12">参数输入</h5>
<h5 class="p-8-12">
{{ $t('components.chat.executionDetails.paramInput') }}
</h5>
<div class="p-8-12 border-t-dashed lighter">
<div class="mb-8">
<span class="color-secondary">用户问题:</span>

View File

@ -65,6 +65,7 @@ import ChatInputOperate from '@/components/ai-chat/component/chat-input-operate/
import PrologueContent from '@/components/ai-chat/component/prologue-content/index.vue'
import UserForm from '@/components/ai-chat/component/user-form/index.vue'
import Control from '@/components/ai-chat/component/control/index.vue'
import { t } from '@/locales'
defineOptions({ name: 'AiChat' })
const route = useRoute()
const {
@ -270,7 +271,7 @@ const getWrite = (chat: any, reader: any, stream: boolean) => {
const errorWrite = (chat: any, message?: string) => {
ChatManagement.addChatRecord(chat, 50, loading)
ChatManagement.write(chat.id)
ChatManagement.append(chat.id, message || '抱歉,当前正在维护,无法提供服务,请稍后再试!')
ChatManagement.append(chat.id, message || t('components.chat.tip.error500Message'))
ChatManagement.updateStatus(chat.id, 500)
ChatManagement.close(chat.id)
}
@ -343,9 +344,9 @@ function chatMessage(chat?: any, problem?: string, re_chat?: boolean, other_para
errorWrite(chat)
})
} else if (response.status === 460) {
return Promise.reject('无法识别用户身份')
return Promise.reject(t('components.chat.tip.errorIdentifyMessage'))
} else if (response.status === 461) {
return Promise.reject('抱歉,您的提问已达到最大限制,请明天再来吧!')
return Promise.reject('components.chat.tip.errorLimitMessage')
} else {
nextTick(() => {
//

View File

@ -39,6 +39,7 @@ export default {
debug: 'Debug',
required: 'Required',
noData: 'No data',
result: 'Result',
status: {
label: 'Status',
enableSuccess: 'Enable Successful',

View File

@ -67,7 +67,6 @@ export default {
paramInfo1: 'Displayed when using the function',
paramInfo2: 'Not displayed when using the function',
code: 'Code',
result: 'Result'
},
debug: {
run: 'Run',

View File

@ -39,6 +39,7 @@ export default {
debug: '调试',
required: '必填',
noData: '暂无数据',
result: '结果',
status: {
label: '状态',
enableSuccess: '启用成功',

View File

@ -11,6 +11,13 @@ export default {
errorMessage2: '密码错误'
},
executionDetails: {
title: '执行详情',
paramInput: '参数输入',
paramOutput: '参数输出',
},
tip: {
error500Message: '抱歉,当前正在维护,无法提供服务,请稍后再试!',
errorIdentifyMessage: '无法识别用户身份',
errorLimitMessage:'抱歉,您的提问已达到最大限制,请明天再来吧!'
}
}

View File

@ -1,6 +1,8 @@
import type { result } from 'lodash'
export default {
node: '节点',
baseNodes: '基础组件',
baseComponent: '基础组件',
searchBar: {
placeholder: '按名称搜索'
},
@ -27,10 +29,21 @@ export default {
onlylest: '只允许连接左边的锚点',
applicationNodeError: '该应用不可用',
functionNodeError: '该函数不可用',
repeatedNodeError: '节点名称已存在!'
repeatedNodeError: '节点名称已存在!',
cannotCopy: '不能被复制',
copyError: '已复制节点'
},
delete: {
confirmTitle: '确定删除该节点?'
confirmTitle: '确定删除该节点?',
deleteMessage: '节点不允许删除'
},
control: {
zoomOut: '缩小',
zoomIn: '放大',
fitView: '适应',
retract: '收起全部节点',
extend: '展开全部节点',
beautify: '一键美化'
},
variable: {
global: '全局变量',
@ -45,5 +58,116 @@ export default {
AND: '所有',
OR: '任一',
text: '连线节点执行完,执行当前节点'
},
validate: {
startNodeRequired: '开始节点必填',
startNodeOnly: '开始节点只能有一个',
baseNodeRequired: '基本信息节点必填',
baseNodeOnly: '基本信息节点只能有一个',
notInWorkFlowNode: '未在流程中的节点',
noNextNode: '不存在的下一个节点',
nodeUnavailable: '节点不可用',
needConnect1: '节点的',
needConnect2: '分支需要连接',
cannotEndNode: '节点不能当做结束节点'
},
nodes: {
startNode: {
label: '开始',
question: '用户问题',
currentTime: '当前时间'
},
baseNode: {
label: '基本信息'
},
aiChatNode: {
label: 'AI 对话',
text: '与 AI 大模型进行对话',
answer: 'AI 回答内容'
},
searchDatasetNode: {
label: '知识库检索',
text: '关联知识库,查找与问题相关的分段',
paragraph_list: '检索结果的分段列表',
is_hit_handling_method_list: '满足直接回答的分段列表',
result: '检索结果',
directly_return: '满足直接回答的分段内容'
},
questionNode: {
label: '问题优化',
text: '根据历史聊天记录优化完善当前问题,更利于匹配知识库分段',
result: '问题优化结果'
},
conditionNode: {
label: '判断器',
text: '根据不同条件执行不同的节点',
branch_name: '分支名称'
},
replyNode: {
label: '指定回复',
text: '指定回复内容,引用变量会转换为字符串进行输出',
content: '内容'
},
rerankerNode: {
label: '多路召回',
text: '使用重排模型对多个知识库的检索结果进行二次召回',
result_list: '重排结果列表',
result: '重排结果'
},
formNode: {
label: '表单收集',
text: '在问答过程中用于收集用户信息,可以根据收集到表单数据执行后续流程',
form_content_format: `你好,请先填写下面表单内容:
{{form}}
`,
form_data: '表单全部内容'
},
documentExtractNode: {
label: '文档内容提取',
text: '提取文档中的内容',
content: '文档内容'
},
imageUnderstandNode: {
label: '图片理解',
text: '识别出图片中的对象、场景等信息回答用户问题',
answer: 'AI 回答内容'
},
imageGenerateNode: {
label: '图片生成',
text: '根据提供的文本内容生成图片',
answer: 'AI 回答内容',
image: '图片'
},
speechToTextNode: {
label: '语音转文本',
text: '将音频通过语音识别模型转换为文本'
},
textToSpeechNode: {
label: '文本转语音',
text: '将文本通过语音合成模型转换为音频'
},
functionNode: {
label: '自定义函数',
text: '通过执行自定义脚本,实现数据处理'
},
applicationNode: {
label: '应用节点'
}
},
compare: {
is_null: '为空',
is_not_null: '不为空',
contain: '包含',
not_contain: '不包含',
eq: '等于',
ge: '大于等于',
gt: '大于',
le: '小于等于',
lt: '小于',
len_eq: '长度等于',
len_ge: '长度大于等于',
len_gt: '长度大于',
len_le: '长度小于等于',
len_lt: '长度小于'
}
}

View File

@ -65,7 +65,6 @@ export default {
paramInfo1: '使用函数时显示',
paramInfo2: '使用函数时不显示',
code: '代码',
result: '结果'
},
debug: {
run: '运行',

View File

@ -39,6 +39,7 @@ export default {
debug: '調試',
required: '必填',
noData: '暂无数据',
result: '結果',
status: {
label: '狀態',
enableSuccess: '啟用成功',

View File

@ -65,7 +65,6 @@ export default {
paramInfo1: '使用函數時顯示',
paramInfo2: '使用函數時不顯示',
code: '代碼',
result: '結果'
},
debug: {
run: '運行',

View File

@ -13,7 +13,7 @@
</el-input>
</div>
<el-tab-pane :label="$t('views.applicationWorkflow.baseNodes')" name="base">
<el-tab-pane :label="$t('views.applicationWorkflow.baseComponent')" name="base">
<el-scrollbar height="400">
<div v-if="filter_menu_nodes.length > 0">
<template v-for="(item, index) in filter_menu_nodes" :key="index">

View File

@ -147,7 +147,7 @@
</el-text>
</h4>
<div class="flex-between border-r-4 p-8-12 mb-8 layout-bg lighter">
<span>{{ $t('views.functionLib.functionForm.form.param.result') }} {result}</span>
<span>{{ $t('common.result') }} {result}</span>
</div>
</div>

View File

@ -1,34 +1,83 @@
<template>
<el-card shadow="always" style="--el-card-padding: 8px 12px; --el-card-border-radius: 8px">
<el-button link @click="zoomOut">
<el-tooltip class="box-item" effect="dark" content="缩小" placement="top">
<el-icon :size="16" title="缩小"><ZoomOut /></el-icon>
<el-tooltip
class="box-item"
effect="dark"
:content="$t('views.applicationWorkflow.control.zoomOut')"
placement="top"
>
<el-icon :size="16" :title="$t('views.applicationWorkflow.control.zoomOut')"
><ZoomOut
/></el-icon>
</el-tooltip>
</el-button>
<el-button link @click="zoomIn">
<el-tooltip class="box-item" effect="dark" content="放大" placement="top">
<el-icon :size="16" title="放大"><ZoomIn /></el-icon>
<el-tooltip
class="box-item"
effect="dark"
:content="$t('views.applicationWorkflow.control.zoomIn')"
placement="top"
>
<el-icon :size="16" :title="$t('views.applicationWorkflow.control.zoomIn')"
><ZoomIn
/></el-icon>
</el-tooltip>
</el-button>
<el-button link @click="fitView">
<el-tooltip class="box-item" effect="dark" content="适应" placement="top">
<AppIcon iconName="app-fitview" title="适应"></AppIcon>
<el-tooltip
class="box-item"
effect="dark"
:content="$t('views.applicationWorkflow.control.fitView')"
placement="top"
>
<AppIcon
iconName="app-fitview"
:title="$t('views.applicationWorkflow.control.fitView')"
></AppIcon>
</el-tooltip>
</el-button>
<el-divider direction="vertical" />
<el-button link @click="retract">
<el-tooltip class="box-item" effect="dark" content="收起全部节点" placement="top">
<AppIcon style="font-size: 16px" iconName="app-retract" title="收起全部节点"></AppIcon>
<el-tooltip
class="box-item"
effect="dark"
:content="$t('views.applicationWorkflow.control.retract')"
placement="top"
>
<AppIcon
style="font-size: 16px"
iconName="app-retract"
:title="$t('views.applicationWorkflow.control.retract')"
></AppIcon>
</el-tooltip>
</el-button>
<el-button link @click="extend">
<el-tooltip class="box-item" effect="dark" content="展开全部节点" placement="top">
<AppIcon style="font-size: 16px" iconName="app-extend" title="展开全部节点"></AppIcon>
<el-tooltip
class="box-item"
effect="dark"
:content="$t('views.applicationWorkflow.control.extend')"
placement="top"
>
<AppIcon
style="font-size: 16px"
iconName="app-extend"
:title="$t('views.applicationWorkflow.control.extend')"
></AppIcon>
</el-tooltip>
</el-button>
<el-button link @click="layout">
<el-tooltip class="box-item" effect="dark" content="一键美化" placement="top">
<AppIcon style="font-size: 16px" iconName="app-beautify" title="一键美化"></AppIcon>
<el-tooltip
class="box-item"
effect="dark"
:content="$t('views.applicationWorkflow.control.beautify')"
placement="top"
>
<AppIcon
style="font-size: 16px"
iconName="app-beautify"
:title="$t('views.applicationWorkflow.control.beautify')"
></AppIcon>
</el-tooltip>
</el-button>
</el-card>

View File

@ -8,18 +8,18 @@ export const startNode = {
y: 720,
properties: {
height: 200,
stepName: '开始',
stepName: t('views.applicationWorkflow.nodes.startNode.label'),
config: {
fields: [
{
label: '用户问题',
label: t('views.applicationWorkflow.nodes.startNode.question'),
value: 'question'
}
],
globalFields: [
{
value: 'time',
label: '当前时间'
label: t('views.applicationWorkflow.nodes.startNode.currentTime')
}
]
}
@ -34,7 +34,7 @@ export const baseNode = {
properties: {
width: 420,
height: 200,
stepName: '基本信息',
stepName: t('views.applicationWorkflow.nodes.baseNode.label'),
input_field_list: [],
node_data: {
name: '',
@ -55,15 +55,15 @@ export const baseNodes = [baseNode, startNode]
*/
export const aiChatNode = {
type: WorkflowType.AiChat,
text: '与 AI 大模型进行对话',
label: 'AI 对话',
text: t('views.applicationWorkflow.nodes.aiChatNode.text'),
label: t('views.applicationWorkflow.nodes.aiChatNode.label'),
height: 340,
properties: {
stepName: 'AI 对话',
stepName: t('views.applicationWorkflow.nodes.aiChatNode.label'),
config: {
fields: [
{
label: 'AI 回答内容',
label: t('views.applicationWorkflow.nodes.aiChatNode.answer'),
value: 'answer'
}
]
@ -75,21 +75,27 @@ export const aiChatNode = {
*/
export const searchDatasetNode = {
type: WorkflowType.SearchDataset,
text: '关联知识库,查找与问题相关的分段',
label: '知识库检索',
text: t('views.applicationWorkflow.nodes.searchDatasetNode.text'),
label: t('views.applicationWorkflow.nodes.searchDatasetNode.label'),
height: 355,
properties: {
stepName: '知识库检索',
stepName: t('views.applicationWorkflow.nodes.searchDatasetNode.label'),
config: {
fields: [
{ label: '检索结果的分段列表', value: 'paragraph_list' },
{ label: '满足直接回答的分段列表', value: 'is_hit_handling_method_list' },
{
label: '检索结果',
label: t('views.applicationWorkflow.nodes.searchDatasetNode.paragraph_list'),
value: 'paragraph_list'
},
{
label: t('views.applicationWorkflow.nodes.searchDatasetNode.is_hit_handling_method_list'),
value: 'is_hit_handling_method_list'
},
{
label: t('views.applicationWorkflow.nodes.searchDatasetNode.result'),
value: 'data'
},
{
label: '满足直接回答的分段内容',
label: t('views.applicationWorkflow.nodes.searchDatasetNode.directly_return'),
value: 'directly_return'
}
]
@ -98,15 +104,15 @@ export const searchDatasetNode = {
}
export const questionNode = {
type: WorkflowType.Question,
text: '根据历史聊天记录优化完善当前问题,更利于匹配知识库分段',
label: '问题优化',
text: t('views.applicationWorkflow.nodes.searchDatasetNode.text'),
label: t('views.applicationWorkflow.nodes.searchDatasetNode.label'),
height: 345,
properties: {
stepName: '问题优化',
stepName: t('views.applicationWorkflow.nodes.searchDatasetNode.label'),
config: {
fields: [
{
label: '问题优化结果',
label: t('views.applicationWorkflow.nodes.searchDatasetNode.result'),
value: 'answer'
}
]
@ -115,16 +121,16 @@ export const questionNode = {
}
export const conditionNode = {
type: WorkflowType.Condition,
text: '根据不同条件执行不同的节点',
label: '判断器',
text: t('views.applicationWorkflow.nodes.conditionNode.text'),
label: t('views.applicationWorkflow.nodes.conditionNode.label'),
height: 175,
properties: {
width: 600,
stepName: '判断器',
stepName: t('views.applicationWorkflow.nodes.conditionNode.label'),
config: {
fields: [
{
label: '分支名称',
label: t('views.applicationWorkflow.nodes.conditionNode.branch_name'),
value: 'branch_name'
}
]
@ -133,15 +139,15 @@ export const conditionNode = {
}
export const replyNode = {
type: WorkflowType.Reply,
text: '指定回复内容,引用变量会转换为字符串进行输出',
label: '指定回复',
text: t('views.applicationWorkflow.nodes.replyNode.text'),
label: t('views.applicationWorkflow.nodes.replyNode.label'),
height: 210,
properties: {
stepName: '指定回复',
stepName: t('views.applicationWorkflow.nodes.replyNode.label'),
config: {
fields: [
{
label: '内容',
label: t('views.applicationWorkflow.nodes.replyNode.content'),
value: 'answer'
}
]
@ -150,19 +156,19 @@ export const replyNode = {
}
export const rerankerNode = {
type: WorkflowType.RrerankerNode,
text: '使用重排模型对多个知识库的检索结果进行二次召回',
label: '多路召回',
text: t('views.applicationWorkflow.nodes.rerankerNode.text'),
label: t('views.applicationWorkflow.nodes.rerankerNode.label'),
height: 252,
properties: {
stepName: '多路召回',
stepName: t('views.applicationWorkflow.nodes.rerankerNode.label'),
config: {
fields: [
{
label: '重排结果列表',
label: t('views.applicationWorkflow.nodes.rerankerNode.result_list'),
value: 'result_list'
},
{
label: '重排结果',
label: t('views.applicationWorkflow.nodes.rerankerNode.result'),
value: 'result'
}
]
@ -171,23 +177,21 @@ export const rerankerNode = {
}
export const formNode = {
type: WorkflowType.FormNode,
text: '在问答过程中用于收集用户信息,可以根据收集到表单数据执行后续流程',
label: '表单收集',
text: t('views.applicationWorkflow.nodes.formNode.text'),
label: t('views.applicationWorkflow.nodes.formNode.label'),
height: 252,
properties: {
width: 600,
stepName: '表单收集',
stepName: t('views.applicationWorkflow.nodes.formNode.label'),
node_data: {
is_result: true,
form_field_list: [],
form_content_format: `你好,请先填写下面表单内容:
{{form}}
`
form_content_format: t('views.applicationWorkflow.nodes.formNode.form_content_format')
},
config: {
fields: [
{
label: '表单全部内容',
label: t('views.applicationWorkflow.nodes.formNode.form_data'),
value: 'form_data'
}
]
@ -196,15 +200,15 @@ export const formNode = {
}
export const documentExtractNode = {
type: WorkflowType.DocumentExtractNode,
text: '提取文档中的内容',
label: '文档内容提取',
text: t('views.applicationWorkflow.nodes.documentExtractNode.text'),
label: t('views.applicationWorkflow.nodes.documentExtractNode.label'),
height: 252,
properties: {
stepName: '文档内容提取',
stepName: t('views.applicationWorkflow.nodes.documentExtractNode.label'),
config: {
fields: [
{
label: '文档内容',
label: t('views.applicationWorkflow.nodes.documentExtractNode.content'),
value: 'content'
}
]
@ -213,15 +217,15 @@ export const documentExtractNode = {
}
export const imageUnderstandNode = {
type: WorkflowType.ImageUnderstandNode,
text: '识别出图片中的对象、场景等信息回答用户问题',
label: '图片理解',
text: t('views.applicationWorkflow.nodes.imageUnderstandNode.text'),
label: t('views.applicationWorkflow.nodes.imageUnderstandNode.label'),
height: 252,
properties: {
stepName: '图片理解',
stepName: t('views.applicationWorkflow.nodes.imageUnderstandNode.label'),
config: {
fields: [
{
label: 'AI 回答内容',
label: t('views.applicationWorkflow.nodes.imageUnderstandNode.answer'),
value: 'answer'
}
]
@ -231,19 +235,19 @@ export const imageUnderstandNode = {
export const imageGenerateNode = {
type: WorkflowType.ImageGenerateNode,
text: '根据提供的文本内容生成图片',
label: '图片生成',
text: t('views.applicationWorkflow.nodes.imageGenerateNode.text'),
label: t('views.applicationWorkflow.nodes.imageGenerateNode.label'),
height: 252,
properties: {
stepName: '图片生成',
stepName: t('views.applicationWorkflow.nodes.imageGenerateNode.label'),
config: {
fields: [
{
label: 'AI 回答内容',
label: t('views.applicationWorkflow.nodes.imageGenerateNode.answer'),
value: 'answer'
},
{
label: '图片',
label: t('views.applicationWorkflow.nodes.imageGenerateNode.image'),
value: 'image'
}
]
@ -253,15 +257,15 @@ export const imageGenerateNode = {
export const speechToTextNode = {
type: WorkflowType.SpeechToTextNode,
text: '将音频通过语音识别模型转换为文本',
label: '语音转文本',
text: t('views.applicationWorkflow.nodes.speechToTextNode.text'),
label: t('views.applicationWorkflow.nodes.speechToTextNode.label'),
height: 252,
properties: {
stepName: '语音转文本',
stepName: t('views.applicationWorkflow.nodes.speechToTextNode.label'),
config: {
fields: [
{
label: '结果',
label: t('common.result'),
value: 'result'
}
]
@ -270,15 +274,15 @@ export const speechToTextNode = {
}
export const textToSpeechNode = {
type: WorkflowType.TextToSpeechNode,
text: '将文本通过语音合成模型转换为音频',
label: '文本转语音',
text: t('views.applicationWorkflow.nodes.textToSpeechNode.text'),
label: t('views.applicationWorkflow.nodes.textToSpeechNode.label'),
height: 252,
properties: {
stepName: '文本转语音',
stepName: t('views.applicationWorkflow.nodes.textToSpeechNode.label'),
config: {
fields: [
{
label: '结果',
label: t('common.result'),
value: 'result'
}
]
@ -305,15 +309,15 @@ export const menuNodes = [
*/
export const functionNode = {
type: WorkflowType.FunctionLibCustom,
text: '通过执行自定义脚本,实现数据处理',
label: '自定义函数',
text: t('views.applicationWorkflow.nodes.functionNode.text'),
label: t('views.applicationWorkflow.nodes.functionNode.label'),
height: 260,
properties: {
stepName: '自定义函数',
stepName: t('views.applicationWorkflow.nodes.functionNode.label'),
config: {
fields: [
{
label: '结果',
label: t('common.result'),
value: 'result'
}
]
@ -322,15 +326,15 @@ export const functionNode = {
}
export const functionLibNode = {
type: WorkflowType.FunctionLib,
text: '通过执行自定义脚本,实现数据处理',
label: '自定义函数',
text: t('views.applicationWorkflow.nodes.functionNode.text'),
label: t('views.applicationWorkflow.nodes.functionNode.label'),
height: 170,
properties: {
stepName: '自定义函数',
stepName: t('views.applicationWorkflow.nodes.functionNode.label'),
config: {
fields: [
{
label: '结果',
label: t('common.result'),
value: 'result'
}
]
@ -340,15 +344,15 @@ export const functionLibNode = {
export const applicationNode = {
type: WorkflowType.Application,
text: '应用节点',
label: '应用节点',
text: t('views.applicationWorkflow.nodes.applicationNode.label'),
label: t('views.applicationWorkflow.nodes.applicationNode.label'),
height: 260,
properties: {
stepName: '应用节点',
stepName: t('views.applicationWorkflow.nodes.applicationNode.label'),
config: {
fields: [
{
label: '结果',
label: t('common.result'),
value: 'result'
}
]
@ -357,20 +361,20 @@ export const applicationNode = {
}
export const compareList = [
{ value: 'is_null', label: '为空' },
{ value: 'is_not_null', label: '不为空' },
{ value: 'contain', label: '包含' },
{ value: 'not_contain', label: '不包含' },
{ value: 'eq', label: '等于' },
{ value: 'ge', label: '大于等于' },
{ value: 'gt', label: '大于' },
{ value: 'le', label: '小于等于' },
{ value: 'lt', label: '小于' },
{ value: 'len_eq', label: '长度等于' },
{ value: 'len_ge', label: '长度大于等于' },
{ value: 'len_gt', label: '长度大于' },
{ value: 'len_le', label: '长度小于等于' },
{ value: 'len_lt', label: '长度小于' }
{ value: 'is_null', label: t('views.applicationWorkflow.compare.is_null') },
{ value: 'is_not_null', label: t('views.applicationWorkflow.compare.is_not_null') },
{ value: 'contain', label: t('views.applicationWorkflow.compare.contain') },
{ value: 'not_contain', label: t('views.applicationWorkflow.compare.not_contain') },
{ value: 'eq', label: t('views.applicationWorkflow.compare.eq') },
{ value: 'ge', label: t('views.applicationWorkflow.compare.ge') },
{ value: 'gt', label:t('views.applicationWorkflow.compare.gt') },
{ value: 'le', label: t('views.applicationWorkflow.compare.le') },
{ value: 'lt', label: t('views.applicationWorkflow.compare.lt') },
{ value: 'len_eq', label: t('views.applicationWorkflow.compare.len_eq')},
{ value: 'len_ge', label: t('views.applicationWorkflow.compare.len_ge') },
{ value: 'len_gt', label:t('views.applicationWorkflow.compare.len_gt') },
{ value: 'len_le', label: t('views.applicationWorkflow.compare.len_le') },
{ value: 'len_lt', label: t('views.applicationWorkflow.compare.len_lt') }
]
export const nodeDict: any = {

View File

@ -60,13 +60,13 @@ export function initDefaultShortcut(lf: LogicFlow, graph: GraphModel) {
(node: any) => node.type === WorkflowType.Start || node.type === WorkflowType.Base
)
if (base_nodes.length > 0) {
MsgError(base_nodes[0]?.properties?.stepName + '不能被复制')
MsgError(base_nodes[0]?.properties?.stepName + t('views.applicationWorkflow.tip.cannotCopy'))
return
}
selected = elements
selected.nodes.forEach((node: any) => translationNodeData(node, TRANSLATION_DISTANCE))
selected.edges.forEach((edge: any) => translationEdgeData(edge, TRANSLATION_DISTANCE))
MsgSuccess('已复制节点')
MsgSuccess(t('views.applicationWorkflow.tip.copyError'))
return false
}
const paste_node = () => {
@ -96,7 +96,7 @@ export function initDefaultShortcut(lf: LogicFlow, graph: GraphModel) {
}
const nodes = elements.nodes.filter((node) => ['start-node', 'base-node'].includes(node.type))
if (nodes.length > 0) {
MsgError(`${nodes[0].properties?.stepName}节点不允许删除`)
MsgError(`${nodes[0].properties?.stepName}${t('views.applicationWorkflow.delete.deleteMessage')}`)
return
}
MsgConfirm(t('common.tip'), t('views.applicationWorkflow.delete.confirmTitle'), {

View File

@ -1,4 +1,5 @@
import { WorkflowType } from '@/enums/workflow'
import { t } from '@/locales'
const end_nodes: Array<string> = [
WorkflowType.AiChat,
@ -26,9 +27,9 @@ export class WorkFlowInstance {
private is_valid_start_node() {
const start_node_list = this.nodes.filter((item) => item.id === WorkflowType.Start)
if (start_node_list.length == 0) {
throw '开始节点必填'
throw t('views.applicationWorkflow.validate.startNodeRequired')
} else if (start_node_list.length > 1) {
throw '开始节点只能有一个'
throw t('views.applicationWorkflow.validate.startNodeOnly')
}
}
/**
@ -37,9 +38,9 @@ export class WorkFlowInstance {
private is_valid_base_node() {
const start_node_list = this.nodes.filter((item) => item.id === WorkflowType.Base)
if (start_node_list.length == 0) {
throw '基本信息节点必填'
throw t('views.applicationWorkflow.validate.baseNodeRequired')
} else if (start_node_list.length > 1) {
throw '基本信息节点只能有一个'
throw t('views.applicationWorkflow.validate.baseNodeOnly')
}
}
/**
@ -91,7 +92,7 @@ export class WorkFlowInstance {
.filter((node: any) => node.id !== WorkflowType.Start && node.id !== WorkflowType.Base)
.filter((node) => !this.workFlowNodes.includes(node))
if (notInWorkFlowNodes.length > 0) {
throw `未在流程中的节点:${notInWorkFlowNodes.map((node) => node.properties.stepName).join('')}`
throw `${t('views.applicationWorkflow.validate.notInWorkFlowNode')}:${notInWorkFlowNodes.map((node) => node.properties.stepName).join('')}`
}
this.workFlowNodes = []
}
@ -106,7 +107,7 @@ export class WorkFlowInstance {
.map((edge) => this.nodes.filter((node) => node.id == edge.targetNodeId))
.reduce((x, y) => [...x, ...y], [])
if (node_list.length == 0 && !end_nodes.includes(node.type)) {
throw '不存在的下一个节点'
throw t('views.applicationWorkflow.validate.noNextNode')
}
return node_list
}
@ -114,7 +115,7 @@ export class WorkFlowInstance {
for (const node of this.nodes) {
if (node.type !== WorkflowType.Base && node.type !== WorkflowType.Start) {
if (!this.edges.some((edge) => edge.targetNodeId === node.id)) {
throw `未在流程中的节点:${node.properties.stepName}`
throw `${t('views.applicationWorkflow.validate.notInWorkFlowNode')}:${node.properties.stepName}`
}
}
}
@ -125,7 +126,7 @@ export class WorkFlowInstance {
*/
private is_valid_node(node: any) {
if (node.properties.status && node.properties.status === 500) {
throw `${node.properties.stepName} 节点不可用`
throw `${node.properties.stepName} ${t('views.applicationWorkflow.validate.nodeUnavailable')}`
}
if (node.type === WorkflowType.Condition) {
const branch_list = node.properties.node_data.branch
@ -133,17 +134,17 @@ export class WorkFlowInstance {
const source_anchor_id = `${node.id}_${branch.id}_right`
const edge_list = this.edges.filter((edge) => edge.sourceAnchorId == source_anchor_id)
if (edge_list.length == 0) {
throw `${node.properties.stepName} 节点的${branch.type}分支需要连接`
throw `${node.properties.stepName} ${t('views.applicationWorkflow.validate.needConnect1')}${branch.type}${t('views.applicationWorkflow.validate.needConnect2')}`
}
}
} else {
const edge_list = this.edges.filter((edge) => edge.sourceNodeId == node.id)
if (edge_list.length == 0 && !end_nodes.includes(node.type)) {
throw `${node.properties.stepName} 节点不能当做结束节点`
throw `${node.properties.stepName} ${t('views.applicationWorkflow.validate.cannotEndNode')}`
}
}
if (node.properties.status && node.properties.status !== 200) {
throw `${node.properties.stepName} 节点不可用`
throw `${node.properties.stepName} ${t('views.applicationWorkflow.validate.nodeUnavailable')}`
}
}
}

View File

@ -93,7 +93,7 @@
<div class="flex-between">
<div>历史聊天记录</div>
<el-select v-model="chat_data.dialogue_type" type="small" style="width: 100px">
<el-option label="节点" value="NODE" />
<el-option :label="$t('views.applicationWorkflow.node')" value="NODE" />
<el-option label="工作流" value="WORKFLOW" />
</el-select>
</div>

View File

@ -1,6 +1,6 @@
<template>
<NodeContainer :nodeModel="nodeModel">
<h5 class="title-decoration-1 mb-8">全局变量</h5>
<h5 class="title-decoration-1 mb-8">{{ $t('views.applicationWorkflow.variable.global') }}</h5>
<div
v-for="(item, index) in nodeModel.properties.config.globalFields"
:key="index"
@ -9,10 +9,19 @@
@mouseleave="showicon = false"
>
<span>{{ item.label }} {{ '{' + item.value + '}' }}</span>
<el-tooltip effect="dark" :content="$t('views.applicationWorkflow.setting.copyParam')" placement="top" v-if="showicon === true">
<el-tooltip
effect="dark"
content="$t('views.applicationWorkflow.setting.copyParam')"
placement="top"
v-if="showicon === true"
>
<el-button
link
@click="copyClick('{{' + '全局变量.' + item.value + '}}')"
@click="
copyClick(
`{{${$t('views.applicationWorkflow.variable.global')}.${item.value}}}`
)
"
style="padding: 0"
>
<AppIcon iconName="app-copy"></AppIcon>
@ -69,7 +78,13 @@ const refreshFileUploadConfig = () => {
.map((v: any) => cloneDeep(v.properties.node_data.file_upload_setting))
.filter((v: any) => v)
fields = fields.filter((item: any) => item.value !== 'image' && item.value !== 'document' && item.value !== 'audio' && item.value !== 'video')
fields = fields.filter(
(item: any) =>
item.value !== 'image' &&
item.value !== 'document' &&
item.value !== 'audio' &&
item.value !== 'video'
)
if (form_data.length === 0) {
set(props.nodeModel.properties.config, 'fields', fields)