Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
813eaacf
authored
Aug 29, 2024
by
Archer
Committed by
GitHub
Aug 29, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
4.8.10 fix (#2572)
* fix: circle workflow response modal * perf: workflow runtime check
parent
322ca757
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
143 additions
and
97 deletions
+143
-97
packages/global/core/chat/type.d.ts
+1
-0
packages/global/core/workflow/runtime/type.d.ts
+3
-0
packages/global/core/workflow/runtime/utils.ts
+48
-40
packages/service/core/workflow/dispatch/index.ts
+2
-1
packages/service/core/workflow/dispatch/tools/runUpdateVar.ts
+7
-4
packages/web/i18n/en/common.json
+1
-0
packages/web/i18n/zh/common.json
+24
-22
projects/app/src/components/core/chat/components/WholeResponseModal.tsx
+35
-16
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx
+4
-4
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx
+15
-9
projects/app/src/pages/app/detail/components/WorkflowComponents/utils.tsx
+3
-1
No files found.
packages/global/core/chat/type.d.ts
View file @
813eaacf
...
@@ -151,6 +151,7 @@ export type ChatHistoryItemType = HistoryItemType & {
...
@@ -151,6 +151,7 @@ export type ChatHistoryItemType = HistoryItemType & {
/* ------- response data ------------ */
/* ------- response data ------------ */
export
type
ChatHistoryItemResType
=
DispatchNodeResponseType
&
{
export
type
ChatHistoryItemResType
=
DispatchNodeResponseType
&
{
nodeId
:
string
;
nodeId
:
string
;
id
:
string
;
moduleType
:
FlowNodeTypeEnum
;
moduleType
:
FlowNodeTypeEnum
;
moduleName
:
string
;
moduleName
:
string
;
};
};
...
...
packages/global/core/workflow/runtime/type.d.ts
View file @
813eaacf
...
@@ -159,6 +159,9 @@ export type DispatchNodeResponseType = {
...
@@ -159,6 +159,9 @@ export type DispatchNodeResponseType = {
// user select
// user select
userSelectResult
?:
string
;
userSelectResult
?:
string
;
// update var
updateVarResult
?:
any
[];
};
};
export
type
DispatchNodeResultType
<
T
>
=
{
export
type
DispatchNodeResultType
<
T
>
=
{
...
...
packages/global/core/workflow/runtime/utils.ts
View file @
813eaacf
...
@@ -118,39 +118,6 @@ export const filterWorkflowEdges = (edges: RuntimeEdgeItemType[]) => {
...
@@ -118,39 +118,6 @@ export const filterWorkflowEdges = (edges: RuntimeEdgeItemType[]) => {
};
};
/*
/*
区分普通连线和递归连线
递归连线:可以通过往上查询 nodes,最终追溯到自身
*/
export
const
splitEdges2WorkflowEdges
=
({
edges
,
allEdges
,
currentNode
}:
{
edges
:
RuntimeEdgeItemType
[];
allEdges
:
RuntimeEdgeItemType
[];
currentNode
:
RuntimeNodeItemType
;
})
=>
{
const
commonEdges
:
RuntimeEdgeItemType
[]
=
[];
const
recursiveEdges
:
RuntimeEdgeItemType
[]
=
[];
edges
.
forEach
((
edge
)
=>
{
const
checkIsCurrentNode
=
(
edge
:
RuntimeEdgeItemType
):
boolean
=>
{
const
sourceEdge
=
allEdges
.
find
((
item
)
=>
item
.
target
===
edge
.
source
);
if
(
!
sourceEdge
)
return
false
;
if
(
sourceEdge
.
source
===
currentNode
.
nodeId
)
return
true
;
return
checkIsCurrentNode
(
sourceEdge
);
};
if
(
checkIsCurrentNode
(
edge
))
{
recursiveEdges
.
push
(
edge
);
}
else
{
commonEdges
.
push
(
edge
);
}
});
return
{
commonEdges
,
recursiveEdges
};
};
/*
1. 输入线分类:普通线和递归线(可以追溯到自身)
1. 输入线分类:普通线和递归线(可以追溯到自身)
2. 起始线全部非 waiting 执行,或递归线全部非 waiting 执行
2. 起始线全部非 waiting 执行,或递归线全部非 waiting 执行
*/
*/
...
@@ -161,31 +128,72 @@ export const checkNodeRunStatus = ({
...
@@ -161,31 +128,72 @@ export const checkNodeRunStatus = ({
node
:
RuntimeNodeItemType
;
node
:
RuntimeNodeItemType
;
runtimeEdges
:
RuntimeEdgeItemType
[];
runtimeEdges
:
RuntimeEdgeItemType
[];
})
=>
{
})
=>
{
const
workflowEdges
=
filterWorkflowEdges
(
runtimeEdges
).
filter
(
/*
区分普通连线和递归连线
递归连线:可以通过往上查询 nodes,最终追溯到自身
*/
const
splitEdges2WorkflowEdges
=
({
sourceEdges
,
allEdges
,
currentNode
}:
{
sourceEdges
:
RuntimeEdgeItemType
[];
allEdges
:
RuntimeEdgeItemType
[];
currentNode
:
RuntimeNodeItemType
;
})
=>
{
const
commonEdges
:
RuntimeEdgeItemType
[]
=
[];
const
recursiveEdges
:
RuntimeEdgeItemType
[]
=
[];
const
checkIsCircular
=
(
edge
:
RuntimeEdgeItemType
,
visited
:
Set
<
string
>
):
boolean
=>
{
if
(
edge
.
source
===
currentNode
.
nodeId
)
{
return
true
;
// 检测到环,并且环中包含当前节点
}
if
(
visited
.
has
(
edge
.
source
))
{
return
false
;
// 检测到环,但不包含当前节点(子节点成环)
}
visited
.
add
(
edge
.
source
);
const
nextEdges
=
allEdges
.
filter
((
item
)
=>
item
.
target
===
edge
.
source
);
return
nextEdges
.
some
((
nextEdge
)
=>
checkIsCircular
(
nextEdge
,
new
Set
(
visited
)));
};
sourceEdges
.
forEach
((
edge
)
=>
{
if
(
checkIsCircular
(
edge
,
new
Set
([
currentNode
.
nodeId
])))
{
recursiveEdges
.
push
(
edge
);
}
else
{
commonEdges
.
push
(
edge
);
}
});
return
{
commonEdges
,
recursiveEdges
};
};
const
runtimeNodeSourceEdge
=
filterWorkflowEdges
(
runtimeEdges
).
filter
(
(
item
)
=>
item
.
target
===
node
.
nodeId
(
item
)
=>
item
.
target
===
node
.
nodeId
);
);
// Entry
// Entry
if
(
workflowEdges
.
length
===
0
)
{
if
(
runtimeNodeSourceEdge
.
length
===
0
)
{
return
'run'
;
return
'run'
;
}
}
// Classify edges
const
{
commonEdges
,
recursiveEdges
}
=
splitEdges2WorkflowEdges
({
const
{
commonEdges
,
recursiveEdges
}
=
splitEdges2WorkflowEdges
({
edges
:
workflowEdges
,
sourceEdges
:
runtimeNodeSourceEdge
,
allEdges
:
runtimeEdges
,
allEdges
:
runtimeEdges
,
currentNode
:
node
currentNode
:
node
});
});
// check skip
// check skip
(其中一组边,全 skip)
if
(
commonEdges
.
every
((
item
)
=>
item
.
status
===
'skipped'
))
{
if
(
commonEdges
.
length
>
0
&&
commonEdges
.
every
((
item
)
=>
item
.
status
===
'skipped'
))
{
return
'skip'
;
return
'skip'
;
}
}
if
(
recursiveEdges
.
length
>
0
&&
recursiveEdges
.
every
((
item
)
=>
item
.
status
===
'skipped'
))
{
if
(
recursiveEdges
.
length
>
0
&&
recursiveEdges
.
every
((
item
)
=>
item
.
status
===
'skipped'
))
{
return
'skip'
;
return
'skip'
;
}
}
// check active
// check active
(有一类边,不全是 wait 即可运行)
if
(
commonEdges
.
every
((
item
)
=>
item
.
status
!==
'waiting'
))
{
if
(
commonEdges
.
length
>
0
&&
commonEdges
.
every
((
item
)
=>
item
.
status
!==
'waiting'
))
{
return
'run'
;
return
'run'
;
}
}
if
(
recursiveEdges
.
length
>
0
&&
recursiveEdges
.
every
((
item
)
=>
item
.
status
!==
'waiting'
))
{
if
(
recursiveEdges
.
length
>
0
&&
recursiveEdges
.
every
((
item
)
=>
item
.
status
!==
'waiting'
))
{
...
...
packages/service/core/workflow/dispatch/index.ts
View file @
813eaacf
...
@@ -19,7 +19,7 @@ import {
...
@@ -19,7 +19,7 @@ import {
FlowNodeInputTypeEnum
,
FlowNodeInputTypeEnum
,
FlowNodeTypeEnum
FlowNodeTypeEnum
}
from
'@fastgpt/global/core/workflow/node/constant'
;
}
from
'@fastgpt/global/core/workflow/node/constant'
;
import
{
replaceVariable
}
from
'@fastgpt/global/common/string/tools'
;
import
{
getNanoid
,
replaceVariable
}
from
'@fastgpt/global/common/string/tools'
;
import
{
getSystemTime
}
from
'@fastgpt/global/common/time/timezone'
;
import
{
getSystemTime
}
from
'@fastgpt/global/common/time/timezone'
;
import
{
replaceEditorVariable
}
from
'@fastgpt/global/core/workflow/utils'
;
import
{
replaceEditorVariable
}
from
'@fastgpt/global/core/workflow/utils'
;
...
@@ -434,6 +434,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
...
@@ -434,6 +434,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
const
formatResponseData
:
ChatHistoryItemResType
=
(()
=>
{
const
formatResponseData
:
ChatHistoryItemResType
=
(()
=>
{
if
(
!
dispatchRes
[
DispatchNodeResponseKeyEnum
.
nodeResponse
])
return
undefined
;
if
(
!
dispatchRes
[
DispatchNodeResponseKeyEnum
.
nodeResponse
])
return
undefined
;
return
{
return
{
id
:
getNanoid
(),
nodeId
:
node
.
nodeId
,
nodeId
:
node
.
nodeId
,
moduleName
:
node
.
name
,
moduleName
:
node
.
name
,
moduleType
:
node
.
flowNodeType
,
moduleType
:
node
.
flowNodeType
,
...
...
packages/service/core/workflow/dispatch/tools/runUpdateVar.ts
View file @
813eaacf
...
@@ -19,12 +19,12 @@ export const dispatchUpdateVariable = async (props: Props): Promise<Response> =>
...
@@ -19,12 +19,12 @@ export const dispatchUpdateVariable = async (props: Props): Promise<Response> =>
const
{
params
,
variables
,
runtimeNodes
,
workflowStreamResponse
,
node
}
=
props
;
const
{
params
,
variables
,
runtimeNodes
,
workflowStreamResponse
,
node
}
=
props
;
const
{
updateList
}
=
params
;
const
{
updateList
}
=
params
;
updateList
.
forEach
((
item
)
=>
{
const
result
=
updateList
.
map
((
item
)
=>
{
const
varNodeId
=
item
.
variable
?.[
0
];
const
varNodeId
=
item
.
variable
?.[
0
];
const
varKey
=
item
.
variable
?.[
1
];
const
varKey
=
item
.
variable
?.[
1
];
if
(
!
varNodeId
||
!
varKey
)
{
if
(
!
varNodeId
||
!
varKey
)
{
return
;
return
null
;
}
}
const
value
=
(()
=>
{
const
value
=
(()
=>
{
...
@@ -48,10 +48,11 @@ export const dispatchUpdateVariable = async (props: Props): Promise<Response> =>
...
@@ -48,10 +48,11 @@ export const dispatchUpdateVariable = async (props: Props): Promise<Response> =>
}
}
})();
})();
// Global variable
if
(
varNodeId
===
VARIABLE_NODE_ID
)
{
if
(
varNodeId
===
VARIABLE_NODE_ID
)
{
// update global variable
variables
[
varKey
]
=
value
;
variables
[
varKey
]
=
value
;
}
else
{
}
else
{
// Other nodes
runtimeNodes
runtimeNodes
.
find
((
node
)
=>
node
.
nodeId
===
varNodeId
)
.
find
((
node
)
=>
node
.
nodeId
===
varNodeId
)
?.
outputs
?.
find
((
output
)
=>
{
?.
outputs
?.
find
((
output
)
=>
{
...
@@ -61,6 +62,8 @@ export const dispatchUpdateVariable = async (props: Props): Promise<Response> =>
...
@@ -61,6 +62,8 @@ export const dispatchUpdateVariable = async (props: Props): Promise<Response> =>
}
}
});
});
}
}
return
value
;
});
});
workflowStreamResponse
?.({
workflowStreamResponse
?.({
...
@@ -70,7 +73,7 @@ export const dispatchUpdateVariable = async (props: Props): Promise<Response> =>
...
@@ -70,7 +73,7 @@ export const dispatchUpdateVariable = async (props: Props): Promise<Response> =>
return
{
return
{
[
DispatchNodeResponseKeyEnum
.
nodeResponse
]:
{
[
DispatchNodeResponseKeyEnum
.
nodeResponse
]:
{
totalPoints
:
0
updateVarResult
:
result
}
}
};
};
};
};
packages/web/i18n/en/common.json
View file @
813eaacf
...
@@ -565,6 +565,7 @@
...
@@ -565,6 +565,7 @@
"plugin output"
:
"Plugin output value"
,
"plugin output"
:
"Plugin output value"
,
"search using reRank"
:
"Result rearrangement"
,
"search using reRank"
:
"Result rearrangement"
,
"text output"
:
"text output"
,
"text output"
:
"text output"
,
"update_var_result"
:
"Variable update results (display multiple variable update results in order)"
,
"user_select_result"
:
"User select result"
"user_select_result"
:
"User select result"
},
},
"retry"
:
"Regenerate"
,
"retry"
:
"Regenerate"
,
...
...
packages/web/i18n/zh/common.json
View file @
813eaacf
...
@@ -10,6 +10,8 @@
...
@@ -10,6 +10,8 @@
"auto_renew_q"
:
"订阅套餐会自动续费么?"
,
"auto_renew_q"
:
"订阅套餐会自动续费么?"
,
"change_package_a"
:
"当前套餐价格大于新套餐时,无法立即切换,将会在当前套餐过期后以“续费”形式进行切换。
\n
当前套餐价格小于新套餐时,系统会自动计算当前套餐剩余余额,您可支付差价进行套餐切换。"
,
"change_package_a"
:
"当前套餐价格大于新套餐时,无法立即切换,将会在当前套餐过期后以“续费”形式进行切换。
\n
当前套餐价格小于新套餐时,系统会自动计算当前套餐剩余余额,您可支付差价进行套餐切换。"
,
"change_package_q"
:
"能否切换订阅套餐?"
,
"change_package_q"
:
"能否切换订阅套餐?"
,
"check_subscription_a"
:
"账号-个人信息-套餐详情-使用情况。您可以查看所拥有套餐的生效和到期时间。当付费套餐到期后将自动切换免费版。"
,
"check_subscription_q"
:
"在哪里查看已订阅的套餐?"
,
"dataset_compute_a"
:
"1条知识库存储等于1条知识库索引。一条知识库数据可以包含1条或多条知识库索引。增强训练中,1条数据会生成5条索引。"
,
"dataset_compute_a"
:
"1条知识库存储等于1条知识库索引。一条知识库数据可以包含1条或多条知识库索引。增强训练中,1条数据会生成5条索引。"
,
"dataset_compute_q"
:
"知识库存储怎么计算?"
,
"dataset_compute_q"
:
"知识库存储怎么计算?"
,
"dataset_index_a"
:
"不会。但知识库索引超出时,无法插入和更新知识库内容。"
,
"dataset_index_a"
:
"不会。但知识库索引超出时,无法插入和更新知识库内容。"
,
...
@@ -18,19 +20,15 @@
...
@@ -18,19 +20,15 @@
"free_user_clean_q"
:
"免费版数据会清除么?"
,
"free_user_clean_q"
:
"免费版数据会清除么?"
,
"package_overlay_a"
:
"可以的。每次购买的资源包都是独立的,在其有效期内将会叠加使用。AI积分会优先扣除最先过期的资源包。"
,
"package_overlay_a"
:
"可以的。每次购买的资源包都是独立的,在其有效期内将会叠加使用。AI积分会优先扣除最先过期的资源包。"
,
"package_overlay_q"
:
"额外资源包可以叠加么?"
,
"package_overlay_q"
:
"额外资源包可以叠加么?"
,
"switch_package_q"
:
"是否切换订阅套餐?"
,
"switch_package_a"
:
"套餐使用规则为优先使用更高级的套餐,因此,购买的新套餐若比当前套餐更高级,则新套餐立即生效:否则将继续使用当前套餐。"
,
"switch_package_a"
:
"套餐使用规则为优先使用更高级的套餐,因此,购买的新套餐若比当前套餐更高级,则新套餐立即生效:否则将继续使用当前套餐。"
,
"check_subscription_q"
:
"在哪里查看已订阅的套餐?"
,
"switch_package_q"
:
"是否切换订阅套餐?"
"check_subscription_a"
:
"账号-个人信息-套餐详情-使用情况。您可以查看所拥有套餐的生效和到期时间。当付费套餐到期后将自动切换免费版。"
},
},
"Folder"
:
"文件夹"
,
"Folder"
:
"文件夹"
,
"Login"
:
"登录"
,
"Login"
:
"登录"
,
"is_using"
:
"正在使用"
,
"Move"
:
"移动"
,
"Move"
:
"移动"
,
"Name"
:
"名称"
,
"Name"
:
"名称"
,
"Rename"
:
"重命名"
,
"Rename"
:
"重命名"
,
"Resume"
:
"恢复"
,
"Resume"
:
"恢复"
,
"free"
:
"免费"
,
"Running"
:
"运行中"
,
"Running"
:
"运行中"
,
"UnKnow"
:
"未知"
,
"UnKnow"
:
"未知"
,
"Warning"
:
"提示"
,
"Warning"
:
"提示"
,
...
@@ -119,7 +117,6 @@
...
@@ -119,7 +117,6 @@
"Cancel"
:
"取消"
,
"Cancel"
:
"取消"
,
"Choose"
:
"选择"
,
"Choose"
:
"选择"
,
"Close"
:
"关闭"
,
"Close"
:
"关闭"
,
"base_config"
:
"基础配置"
,
"Config"
:
"配置"
,
"Config"
:
"配置"
,
"Confirm"
:
"确认"
,
"Confirm"
:
"确认"
,
"Confirm Create"
:
"确认创建"
,
"Confirm Create"
:
"确认创建"
,
...
@@ -224,6 +221,7 @@
...
@@ -224,6 +221,7 @@
"Select Avatar"
:
"点击选择头像"
,
"Select Avatar"
:
"点击选择头像"
,
"Select Failed"
:
"选择头像异常"
"Select Failed"
:
"选择头像异常"
},
},
"base_config"
:
"基础配置"
,
"choosable"
:
"可选"
,
"choosable"
:
"可选"
,
"confirm"
:
{
"confirm"
:
{
"Common Tip"
:
"操作确认"
"Common Tip"
:
"操作确认"
...
@@ -567,6 +565,7 @@
...
@@ -567,6 +565,7 @@
"plugin output"
:
"插件输出值"
,
"plugin output"
:
"插件输出值"
,
"search using reRank"
:
"结果重排"
,
"search using reRank"
:
"结果重排"
,
"text output"
:
"文本输出"
,
"text output"
:
"文本输出"
,
"update_var_result"
:
"变量更新结果(按顺序展示多个变量更新结果)"
,
"user_select_result"
:
"用户选择结果"
"user_select_result"
:
"用户选择结果"
},
},
"retry"
:
"重新生成"
,
"retry"
:
"重新生成"
,
...
@@ -639,7 +638,8 @@
...
@@ -639,7 +638,8 @@
"success"
:
"开始同步"
"success"
:
"开始同步"
}
}
},
},
"training"
:
{}
"training"
:
{
}
},
},
"data"
:
{
"data"
:
{
"Auxiliary Data"
:
"辅助数据"
,
"Auxiliary Data"
:
"辅助数据"
,
...
@@ -775,7 +775,6 @@
...
@@ -775,7 +775,6 @@
"test result tip"
:
"根据知识库内容与测试文本的相似度进行排序,你可以根据测试结果调整对应的文本。
\n
注意:测试记录中的数据可能已经被修改过,点击某条测试数据后将展示最新的数据。"
"test result tip"
:
"根据知识库内容与测试文本的相似度进行排序,你可以根据测试结果调整对应的文本。
\n
注意:测试记录中的数据可能已经被修改过,点击某条测试数据后将展示最新的数据。"
},
},
"training"
:
{
"training"
:
{
"tag"
:
"排队情况"
,
"Agent queue"
:
"QA 训练排队"
,
"Agent queue"
:
"QA 训练排队"
,
"Auto mode"
:
"增强处理(实验)"
,
"Auto mode"
:
"增强处理(实验)"
,
"Auto mode Tip"
:
"通过子索引以及调用模型生成相关问题与摘要,来增加数据块的语义丰富度,更利于检索。需要消耗更多的存储空间和增加 AI 调用次数。"
,
"Auto mode Tip"
:
"通过子索引以及调用模型生成相关问题与摘要,来增加数据块的语义丰富度,更利于检索。需要消耗更多的存储空间和增加 AI 调用次数。"
,
...
@@ -785,7 +784,8 @@
...
@@ -785,7 +784,8 @@
"QA mode"
:
"问答拆分"
,
"QA mode"
:
"问答拆分"
,
"Vector queue"
:
"索引排队"
,
"Vector queue"
:
"索引排队"
,
"Waiting"
:
"预计 5 分钟"
,
"Waiting"
:
"预计 5 分钟"
,
"Website Sync"
:
"Web 站点同步"
"Website Sync"
:
"Web 站点同步"
,
"tag"
:
"排队情况"
},
},
"website"
:
{
"website"
:
{
"Base Url"
:
"根地址"
,
"Base Url"
:
"根地址"
,
...
@@ -1078,6 +1078,7 @@
...
@@ -1078,6 +1078,7 @@
},
},
"extraction_results"
:
"提取结果"
,
"extraction_results"
:
"提取结果"
,
"field_name"
:
"字段名"
,
"field_name"
:
"字段名"
,
"free"
:
"免费"
,
"get_QR_failed"
:
"获取二维码失败"
,
"get_QR_failed"
:
"获取二维码失败"
,
"get_app_failed"
:
"获取应用失败"
,
"get_app_failed"
:
"获取应用失败"
,
"get_laf_failed"
:
"获取Laf函数列表失败"
,
"get_laf_failed"
:
"获取Laf函数列表失败"
,
...
@@ -1097,6 +1098,7 @@
...
@@ -1097,6 +1098,7 @@
},
},
"invalid_variable"
:
"无效变量"
,
"invalid_variable"
:
"无效变量"
,
"is_open"
:
"是否开启"
,
"is_open"
:
"是否开启"
,
"is_using"
:
"正在使用"
,
"item_description"
:
"字段描述"
,
"item_description"
:
"字段描述"
,
"item_name"
:
"字段名"
,
"item_name"
:
"字段名"
,
"key_repetition"
:
"key 重复"
,
"key_repetition"
:
"key 重复"
,
...
@@ -1125,14 +1127,14 @@
...
@@ -1125,14 +1127,14 @@
"notice"
:
"请勿关闭页面"
,
"notice"
:
"请勿关闭页面"
,
"old_package_price"
:
"旧套餐余额"
,
"old_package_price"
:
"旧套餐余额"
,
"other"
:
"其他金额,请取整数"
,
"other"
:
"其他金额,请取整数"
,
"to_recharge"
:
"余额不足,去充值"
,
"wechat"
:
"请微信扫码支付: {{price}}元
\n
请勿关闭页面"
,
"yuan"
:
"{{amount}}元"
,
"package_tip"
:
{
"package_tip"
:
{
"buy"
:
"您购买的套餐等级低于当前套餐,该套餐将在当前套餐过期后生效。您可在账号—个人信息—套餐详情里,查看套餐使用情况。"
,
"buy"
:
"您购买的套餐等级低于当前套餐,该套餐将在当前套餐过期后生效。您可在账号—个人信息—套餐详情里,查看套餐使用情况。"
,
"renewal"
:
"您正在续费套餐。您可在账号—个人信息—套餐详情里,查看套餐使用情况。"
,
"renewal"
:
"您正在续费套餐。您可在账号—个人信息—套餐详情里,查看套餐使用情况。"
,
"upgrade"
:
"您购买的套餐等级高于当前套餐,该套餐将即刻生效,当前套餐将延后生效。您可在账号—个人信息—套餐详情里,查看套餐使用情况。"
"upgrade"
:
"您购买的套餐等级高于当前套餐,该套餐将即刻生效,当前套餐将延后生效。您可在账号—个人信息—套餐详情里,查看套餐使用情况。"
}
},
"to_recharge"
:
"余额不足,去充值"
,
"wechat"
:
"请微信扫码支付: {{price}}元
\n
请勿关闭页面"
,
"yuan"
:
"{{amount}}元"
},
},
"permission"
:
{
"permission"
:
{
"Collaborator"
:
"协作者"
,
"Collaborator"
:
"协作者"
,
...
@@ -1217,8 +1219,8 @@
...
@@ -1217,8 +1219,8 @@
"standard"
:
{
"standard"
:
{
"AI Bonus Points"
:
"AI 积分"
,
"AI Bonus Points"
:
"AI 积分"
,
"Expired Time"
:
"结束时间"
,
"Expired Time"
:
"结束时间"
,
"due_date"
:
"到期时间"
,
"Start Time"
:
"开始时间"
,
"Start Time"
:
"开始时间"
,
"due_date"
:
"到期时间"
,
"storage"
:
"存储量"
,
"storage"
:
"存储量"
,
"type"
:
"类型"
"type"
:
"类型"
},
},
...
@@ -1334,11 +1336,6 @@
...
@@ -1334,11 +1336,6 @@
"noBill"
:
"无账单记录~"
,
"noBill"
:
"无账单记录~"
,
"no_invoice"
:
"暂无开票记录"
,
"no_invoice"
:
"暂无开票记录"
,
"subscription"
:
{
"subscription"
:
{
"status"
:
{
"expired"
:
"已过期"
,
"active"
:
"生效中"
,
"inactive"
:
"待使用"
},
"AI points"
:
"AI 积分"
,
"AI points"
:
"AI 积分"
,
"AI points click to read tip"
:
"每次调用 AI 模型时,都会消耗一定的 AI 积分(类似于 token)。点击可查看详细计算规则。"
,
"AI points click to read tip"
:
"每次调用 AI 模型时,都会消耗一定的 AI 积分(类似于 token)。点击可查看详细计算规则。"
,
"AI points usage"
:
"AI 积分使用量"
,
"AI points usage"
:
"AI 积分使用量"
,
...
@@ -1384,13 +1381,18 @@
...
@@ -1384,13 +1381,18 @@
"standardSubLevel"
:
{
"standardSubLevel"
:
{
"custom"
:
"自定义版"
,
"custom"
:
"自定义版"
,
"enterprise"
:
"企业版"
,
"enterprise"
:
"企业版"
,
"enterprise_desc"
:
"适合中小企业在生产环境构建知识库应用"
,
"experience"
:
"体验版"
,
"experience"
:
"体验版"
,
"experience_desc"
:
"可解锁 FastGPT 完整功能"
,
"free"
:
"免费版"
,
"free"
:
"免费版"
,
"free desc"
:
"每月均可免费使用基础功能,连续 30 天未登录系统,将会自动清除知识库"
,
"free desc"
:
"每月均可免费使用基础功能,连续 30 天未登录系统,将会自动清除知识库"
,
"team"
:
"团队版"
,
"team"
:
"团队版"
,
"experience_desc"
:
"可解锁 FastGPT 完整功能"
,
"team_desc"
:
"适合小团队构建知识库应用并提供对外服务"
"team_desc"
:
"适合小团队构建知识库应用并提供对外服务"
,
},
"enterprise_desc"
:
"适合中小企业在生产环境构建知识库应用"
"status"
:
{
"active"
:
"生效中"
,
"expired"
:
"已过期"
,
"inactive"
:
"待使用"
},
},
"token_compute"
:
"点击查看在线 Tokens 计算器"
,
"token_compute"
:
"点击查看在线 Tokens 计算器"
,
"type"
:
{
"type"
:
{
...
...
projects/app/src/components/core/chat/components/WholeResponseModal.tsx
View file @
813eaacf
...
@@ -24,7 +24,8 @@ type sideTabItemType = {
...
@@ -24,7 +24,8 @@ type sideTabItemType = {
moduleName
:
string
;
moduleName
:
string
;
runningTime
?:
number
;
runningTime
?:
number
;
moduleType
:
string
;
moduleType
:
string
;
nodeId
:
string
;
// nodeId:string; // abandon
id
:
string
;
children
:
sideTabItemType
[];
children
:
sideTabItemType
[];
};
};
...
@@ -149,18 +150,28 @@ export const ResponseBox = React.memo(function ResponseBox({
...
@@ -149,18 +150,28 @@ export const ResponseBox = React.memo(function ResponseBox({
})
{
})
{
const
{
t
}
=
useTranslation
();
const
{
t
}
=
useTranslation
();
const
{
isPc
}
=
useSystem
();
const
{
isPc
}
=
useSystem
();
const
flattedResponse
=
useMemo
(()
=>
flattenArray
(
response
),
[
response
]);
const
flattedResponse
=
useMemo
(
()
=>
flattenArray
(
response
).
map
((
item
)
=>
({
...
item
,
id
:
item
.
id
??
item
.
nodeId
})),
[
response
]
);
const
[
currentNodeId
,
setCurrentNodeId
]
=
useState
(
const
[
currentNodeId
,
setCurrentNodeId
]
=
useState
(
flattedResponse
[
0
]?.
nodeId
?
flattedResponse
[
0
].
nodeId
:
''
flattedResponse
[
0
]?.
id
??
flattedResponse
[
0
]?.
nodeId
??
''
);
);
const
activeModule
=
useMemo
(
const
activeModule
=
useMemo
(
()
=>
flattedResponse
.
find
((
item
)
=>
item
.
nodeI
d
===
currentNodeId
)
as
ChatHistoryItemResType
,
()
=>
flattedResponse
.
find
((
item
)
=>
item
.
i
d
===
currentNodeId
)
as
ChatHistoryItemResType
,
[
currentNodeId
,
flattedResponse
]
[
currentNodeId
,
flattedResponse
]
);
);
const
sideResponse
:
sideTabItemType
[]
=
useMemo
(()
=>
{
const
sliderResponseList
:
sideTabItemType
[]
=
useMemo
(()
=>
{
return
pretreatmentResponse
(
response
);
return
pretreatmentResponse
(
response
);
},
[
response
]);
},
[
response
]);
const
{
const
{
isOpen
:
isOpenMobileModal
,
isOpen
:
isOpenMobileModal
,
onOpen
:
onOpenMobileModal
,
onOpen
:
onOpenMobileModal
,
...
@@ -174,7 +185,7 @@ export const ResponseBox = React.memo(function ResponseBox({
...
@@ -174,7 +185,7 @@ export const ResponseBox = React.memo(function ResponseBox({
<
Box
flex=
{
'2 0 0'
}
borderRight=
{
'sm'
}
p=
{
3
}
>
<
Box
flex=
{
'2 0 0'
}
borderRight=
{
'sm'
}
p=
{
3
}
>
<
Box
overflow=
{
'auto'
}
height=
{
'100%'
}
>
<
Box
overflow=
{
'auto'
}
height=
{
'100%'
}
>
<
WholeResponseSideTab
<
WholeResponseSideTab
response=
{
s
ideResponse
}
response=
{
s
liderResponseList
}
value=
{
currentNodeId
}
value=
{
currentNodeId
}
onChange=
{
setCurrentNodeId
}
onChange=
{
setCurrentNodeId
}
/>
/>
...
@@ -192,7 +203,7 @@ export const ResponseBox = React.memo(function ResponseBox({
...
@@ -192,7 +203,7 @@ export const ResponseBox = React.memo(function ResponseBox({
<
Box
h=
{
'100%'
}
overflow=
{
'auto'
}
>
<
Box
h=
{
'100%'
}
overflow=
{
'auto'
}
>
{
!
isOpenMobileModal
&&
(
{
!
isOpenMobileModal
&&
(
<
WholeResponseSideTab
<
WholeResponseSideTab
response=
{
s
ideResponse
}
response=
{
s
liderResponseList
}
value=
{
currentNodeId
}
value=
{
currentNodeId
}
onChange=
{
(
item
:
string
)
=>
{
onChange=
{
(
item
:
string
)
=>
{
setCurrentNodeId
(
item
);
setCurrentNodeId
(
item
);
...
@@ -442,11 +453,11 @@ export const WholeResponseContent = ({
...
@@ -442,11 +453,11 @@ export const WholeResponseContent = ({
/>
/>
{
/* code */
}
{
/* code */
}
<>
<>
<
Row
label=
{
t
(
'workflow:response.Custom inputs'
)
}
value=
{
activeModule
?.
customInputs
}
/>
<
Row
<
Row
label=
{
t
(
'workflow:response.Custom outputs'
)
}
label=
{
t
(
'workflow:response.Custom outputs'
)
}
value=
{
activeModule
?.
customOutputs
}
value=
{
activeModule
?.
customOutputs
}
/>
/>
<
Row
label=
{
t
(
'workflow:response.Custom inputs'
)
}
value=
{
activeModule
?.
customInputs
}
/>
<
Row
label=
{
t
(
'workflow:response.Code log'
)
}
value=
{
activeModule
?.
codeLog
}
/>
<
Row
label=
{
t
(
'workflow:response.Code log'
)
}
value=
{
activeModule
?.
codeLog
}
/>
</>
</>
...
@@ -491,6 +502,12 @@ export const WholeResponseContent = ({
...
@@ -491,6 +502,12 @@ export const WholeResponseContent = ({
label=
{
t
(
'common:core.chat.response.user_select_result'
)
}
label=
{
t
(
'common:core.chat.response.user_select_result'
)
}
value=
{
activeModule
?.
userSelectResult
}
value=
{
activeModule
?.
userSelectResult
}
/>
/>
{
/* update var */
}
<
Row
label=
{
t
(
'common:core.chat.response.update_var_result'
)
}
value=
{
activeModule
?.
updateVarResult
}
/>
</
Box
>
</
Box
>
)
}
)
}
</>
</>
...
@@ -512,7 +529,7 @@ const WholeResponseSideTab = ({
...
@@ -512,7 +529,7 @@ const WholeResponseSideTab = ({
<>
<>
{
response
.
map
((
item
)
=>
(
{
response
.
map
((
item
)
=>
(
<
Box
<
Box
key=
{
item
.
nodeI
d
}
key=
{
item
.
i
d
}
bg=
{
isMobile
?
'myGray.100'
:
''
}
bg=
{
isMobile
?
'myGray.100'
:
''
}
m=
{
isMobile
?
3
:
0
}
m=
{
isMobile
?
3
:
0
}
borderRadius=
{
'md'
}
borderRadius=
{
'md'
}
...
@@ -532,7 +549,7 @@ const AccordionSideTabItem = ({
...
@@ -532,7 +549,7 @@ const AccordionSideTabItem = ({
index
index
}:
{
}:
{
sideBarItem
:
sideTabItemType
;
sideBarItem
:
sideTabItemType
;
onChange
:
(
nodeI
d
:
string
)
=>
void
;
onChange
:
(
i
d
:
string
)
=>
void
;
value
:
string
;
value
:
string
;
index
:
number
;
index
:
number
;
})
=>
{
})
=>
{
...
@@ -565,7 +582,7 @@ const AccordionSideTabItem = ({
...
@@ -565,7 +582,7 @@ const AccordionSideTabItem = ({
{
sideBarItem
.
children
.
map
((
item
)
=>
(
{
sideBarItem
.
children
.
map
((
item
)
=>
(
<
SideTabItem
<
SideTabItem
value=
{
value
}
value=
{
value
}
key=
{
item
.
nodeI
d
}
key=
{
item
.
i
d
}
sideBarItem=
{
item
}
sideBarItem=
{
item
}
onChange=
{
onChange
}
onChange=
{
onChange
}
index=
{
index
+
1
}
index=
{
index
+
1
}
...
@@ -585,7 +602,7 @@ const NormalSideTabItem = ({
...
@@ -585,7 +602,7 @@ const NormalSideTabItem = ({
children
children
}:
{
}:
{
sideBarItem
:
sideTabItemType
;
sideBarItem
:
sideTabItemType
;
onChange
:
(
nodeI
d
:
string
)
=>
void
;
onChange
:
(
i
d
:
string
)
=>
void
;
value
:
string
;
value
:
string
;
index
:
number
;
index
:
number
;
children
?:
React
.
ReactNode
;
children
?:
React
.
ReactNode
;
...
@@ -596,9 +613,9 @@ const NormalSideTabItem = ({
...
@@ -596,9 +613,9 @@ const NormalSideTabItem = ({
<
Flex
<
Flex
alignItems=
{
'center'
}
alignItems=
{
'center'
}
onClick=
{
()
=>
{
onClick=
{
()
=>
{
onChange
(
sideBarItem
.
nodeI
d
);
onChange
(
sideBarItem
.
i
d
);
}
}
}
}
background=
{
value
===
sideBarItem
.
nodeI
d
?
'myGray.100'
:
''
}
background=
{
value
===
sideBarItem
.
i
d
?
'myGray.100'
:
''
}
_hover=
{
{
background
:
'myGray.100'
}
}
_hover=
{
{
background
:
'myGray.100'
}
}
p=
{
2
}
p=
{
2
}
width=
{
'100%'
}
width=
{
'100%'
}
...
@@ -647,7 +664,7 @@ const SideTabItem = ({
...
@@ -647,7 +664,7 @@ const SideTabItem = ({
index
index
}:
{
}:
{
sideBarItem
:
sideTabItemType
;
sideBarItem
:
sideTabItemType
;
onChange
:
(
nodeI
d
:
string
)
=>
void
;
onChange
:
(
i
d
:
string
)
=>
void
;
value
:
string
;
value
:
string
;
index
:
number
;
index
:
number
;
})
=>
{
})
=>
{
...
@@ -668,6 +685,7 @@ const SideTabItem = ({
...
@@ -668,6 +685,7 @@ const SideTabItem = ({
);
);
};
};
/* Format response data to slider data */
function
pretreatmentResponse
(
res
:
ChatHistoryItemResType
[]):
sideTabItemType
[]
{
function
pretreatmentResponse
(
res
:
ChatHistoryItemResType
[]):
sideTabItemType
[]
{
return
res
.
map
((
item
)
=>
{
return
res
.
map
((
item
)
=>
{
let
children
:
sideTabItemType
[]
=
[];
let
children
:
sideTabItemType
[]
=
[];
...
@@ -681,12 +699,13 @@ function pretreatmentResponse(res: ChatHistoryItemResType[]): sideTabItemType[]
...
@@ -681,12 +699,13 @@ function pretreatmentResponse(res: ChatHistoryItemResType[]): sideTabItemType[]
moduleName
:
item
.
moduleName
,
moduleName
:
item
.
moduleName
,
runningTime
:
item
.
runningTime
,
runningTime
:
item
.
runningTime
,
moduleType
:
item
.
moduleType
,
moduleType
:
item
.
moduleType
,
nodeId
:
item
.
nodeId
,
id
:
item
.
id
??
item
.
nodeId
,
children
children
};
};
});
});
}
}
/* Flat response */
function
flattenArray
(
arr
:
ChatHistoryItemResType
[])
{
function
flattenArray
(
arr
:
ChatHistoryItemResType
[])
{
const
result
:
ChatHistoryItemResType
[]
=
[];
const
result
:
ChatHistoryItemResType
[]
=
[];
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx
View file @
813eaacf
...
@@ -56,9 +56,9 @@ const FlowController = React.memo(function FlowController() {
...
@@ -56,9 +56,9 @@ const FlowController = React.memo(function FlowController() {
<>
<>
<
MiniMap
<
MiniMap
style=
{
{
style=
{
{
height
:
9
8
,
height
:
9
2
,
width
:
1
84
,
width
:
1
50
,
marginBottom
:
7
2
,
marginBottom
:
6
2
,
borderRadius
:
'10px'
,
borderRadius
:
'10px'
,
boxShadow
:
'0px 0px 1px rgba(19, 51, 107, 0.10), 0px 4px 10px rgba(19, 51, 107, 0.10)'
boxShadow
:
'0px 0px 1px rgba(19, 51, 107, 0.10), 0px 4px 10px rgba(19, 51, 107, 0.10)'
}
}
}
}
...
@@ -68,7 +68,7 @@ const FlowController = React.memo(function FlowController() {
...
@@ -68,7 +68,7 @@ const FlowController = React.memo(function FlowController() {
position=
{
'bottom-right'
}
position=
{
'bottom-right'
}
style=
{
{
style=
{
{
display
:
'flex'
,
display
:
'flex'
,
marginBottom
:
24
,
marginBottom
:
16
,
padding
:
'5px 8px'
,
padding
:
'5px 8px'
,
background
:
'white'
,
background
:
'white'
,
borderRadius
:
'6px'
,
borderRadius
:
'6px'
,
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/NodeIfElse/ListItem.tsx
View file @
813eaacf
...
@@ -375,15 +375,21 @@ const ConditionSelect = ({
...
@@ -375,15 +375,21 @@ const ConditionSelect = ({
return
[];
return
[];
},
[
valueType
]);
},
[
valueType
]);
const
filterQuiredConditionList
=
useMemo
(()
=>
{
const
filterQuiredConditionList
=
useMemo
(()
=>
{
if
(
required
)
{
const
list
=
(()
=>
{
return
conditionList
.
filter
(
if
(
required
)
{
(
item
)
=>
return
conditionList
.
filter
(
item
.
value
!==
VariableConditionEnum
.
isEmpty
&&
(
item
)
=>
item
.
value
!==
VariableConditionEnum
.
isNotEmpty
item
.
value
!==
VariableConditionEnum
.
isEmpty
&&
);
item
.
value
!==
VariableConditionEnum
.
isNotEmpty
}
);
return
conditionList
;
}
},
[
conditionList
,
required
]);
return
conditionList
;
})();
return
list
.
map
((
item
)
=>
({
...
item
,
label
:
t
(
item
.
label
)
}));
},
[
conditionList
,
required
,
t
]);
return
(
return
(
<
MySelect
<
MySelect
...
...
projects/app/src/pages/app/detail/components/WorkflowComponents/utils.tsx
View file @
813eaacf
...
@@ -87,7 +87,9 @@ export const getEditorVariables = ({
...
@@ -87,7 +87,9 @@ export const getEditorVariables = ({
appDetail
:
AppDetailType
;
appDetail
:
AppDetailType
;
t
:
TFunction
;
t
:
TFunction
;
})
=>
{
})
=>
{
const
currentNode
=
nodeList
.
find
((
node
)
=>
node
.
nodeId
===
nodeId
)
!
;
const
currentNode
=
nodeList
.
find
((
node
)
=>
node
.
nodeId
===
nodeId
);
if
(
!
currentNode
)
return
[];
const
nodeVariables
=
currentNode
.
inputs
const
nodeVariables
=
currentNode
.
inputs
.
filter
((
input
)
=>
input
.
canEdit
)
.
filter
((
input
)
=>
input
.
canEdit
)
.
map
((
item
)
=>
({
.
map
((
item
)
=>
({
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment