您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

use-config.ts 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import { useCallback, useEffect, useState } from 'react'
  2. import produce from 'immer'
  3. import useVarList from '../_base/hooks/use-var-list'
  4. import useOutputVarList from '../_base/hooks/use-output-var-list'
  5. import { BlockEnum, VarType } from '../../types'
  6. import type { Var, Variable } from '../../types'
  7. import { useStore } from '../../store'
  8. import type { CodeNodeType, OutputVar } from './types'
  9. import { CodeLanguage } from './types'
  10. import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
  11. import { fetchNodeDefault } from '@/service/workflow'
  12. import { useStore as useAppStore } from '@/app/components/app/store'
  13. import {
  14. useNodesReadOnly,
  15. } from '@/app/components/workflow/hooks'
  16. const useConfig = (id: string, payload: CodeNodeType) => {
  17. const { nodesReadOnly: readOnly } = useNodesReadOnly()
  18. const appId = useAppStore.getState().appDetail?.id
  19. const [allLanguageDefault, setAllLanguageDefault] = useState<Record<CodeLanguage, CodeNodeType> | null>(null)
  20. useEffect(() => {
  21. if (appId) {
  22. (async () => {
  23. const { config: javaScriptConfig } = await fetchNodeDefault(appId, BlockEnum.Code, { code_language: CodeLanguage.javascript }) as any
  24. const { config: pythonConfig } = await fetchNodeDefault(appId, BlockEnum.Code, { code_language: CodeLanguage.python3 }) as any
  25. setAllLanguageDefault({
  26. [CodeLanguage.javascript]: javaScriptConfig as CodeNodeType,
  27. [CodeLanguage.python3]: pythonConfig as CodeNodeType,
  28. } as any)
  29. })()
  30. }
  31. }, [appId])
  32. const defaultConfig = useStore(s => s.nodesDefaultConfigs)[payload.type]
  33. const { inputs, setInputs } = useNodeCrud<CodeNodeType>(id, payload)
  34. const { handleVarListChange, handleAddVariable } = useVarList<CodeNodeType>({
  35. inputs,
  36. setInputs,
  37. })
  38. const [outputKeyOrders, setOutputKeyOrders] = useState<string[]>([])
  39. const syncOutputKeyOrders = useCallback((outputs: OutputVar) => {
  40. setOutputKeyOrders(Object.keys(outputs))
  41. }, [])
  42. useEffect(() => {
  43. if (inputs.code) {
  44. if (inputs.outputs && Object.keys(inputs.outputs).length > 0)
  45. syncOutputKeyOrders(inputs.outputs)
  46. return
  47. }
  48. const isReady = defaultConfig && Object.keys(defaultConfig).length > 0
  49. if (isReady) {
  50. setInputs({
  51. ...inputs,
  52. ...defaultConfig,
  53. })
  54. syncOutputKeyOrders(defaultConfig.outputs)
  55. }
  56. // eslint-disable-next-line react-hooks/exhaustive-deps
  57. }, [defaultConfig])
  58. const handleCodeChange = useCallback((code: string) => {
  59. const newInputs = produce(inputs, (draft) => {
  60. draft.code = code
  61. })
  62. setInputs(newInputs)
  63. }, [inputs, setInputs])
  64. const handleCodeLanguageChange = useCallback((codeLanguage: CodeLanguage) => {
  65. const currDefaultConfig = allLanguageDefault?.[codeLanguage]
  66. const newInputs = produce(inputs, (draft) => {
  67. draft.code_language = codeLanguage
  68. if (!currDefaultConfig)
  69. return
  70. draft.code = currDefaultConfig.code
  71. draft.variables = currDefaultConfig.variables
  72. draft.outputs = currDefaultConfig.outputs
  73. })
  74. setInputs(newInputs)
  75. }, [allLanguageDefault, inputs, setInputs])
  76. const handleSyncFunctionSignature = useCallback(() => {
  77. const generateSyncSignatureCode = (code: string) => {
  78. let mainDefRe
  79. let newMainDef
  80. if (inputs.code_language === CodeLanguage.javascript) {
  81. mainDefRe = /function\s+main\b\s*\([\s\S]*?\)/g
  82. newMainDef = 'function main({{var_list}})'
  83. let param_list = inputs.variables?.map(item => item.variable).join(', ') || ''
  84. param_list = param_list ? `{${param_list}}` : ''
  85. newMainDef = newMainDef.replace('{{var_list}}', param_list)
  86. }
  87. else if (inputs.code_language === CodeLanguage.python3) {
  88. mainDefRe = /def\s+main\b\s*\([\s\S]*?\)/g
  89. const param_list = []
  90. for (const item of inputs.variables) {
  91. let param = item.variable
  92. let param_type = ''
  93. switch (item.value_type) {
  94. case VarType.string:
  95. param_type = ': str'
  96. break
  97. case VarType.number:
  98. param_type = ': float'
  99. break
  100. case VarType.object:
  101. param_type = ': dict'
  102. break
  103. case VarType.array:
  104. param_type = ': list'
  105. break
  106. case VarType.arrayNumber:
  107. param_type = ': list[float]'
  108. break
  109. case VarType.arrayString:
  110. param_type = ': list[str]'
  111. break
  112. case VarType.arrayObject:
  113. param_type = ': list[dict]'
  114. break
  115. }
  116. param += param_type
  117. param_list.push(`${param}`)
  118. }
  119. newMainDef = `def main(${param_list.join(', ')})`
  120. }
  121. else { return code }
  122. const newCode = code.replace(mainDefRe, newMainDef)
  123. return newCode
  124. }
  125. const newInputs = produce(inputs, (draft) => {
  126. draft.code = generateSyncSignatureCode(draft.code)
  127. })
  128. setInputs(newInputs)
  129. }, [inputs, setInputs])
  130. const {
  131. handleVarsChange,
  132. handleAddVariable: handleAddOutputVariable,
  133. handleRemoveVariable,
  134. isShowRemoveVarConfirm,
  135. hideRemoveVarConfirm,
  136. onRemoveVarConfirm,
  137. } = useOutputVarList<CodeNodeType>({
  138. id,
  139. inputs,
  140. setInputs,
  141. outputKeyOrders,
  142. onOutputKeyOrdersChange: setOutputKeyOrders,
  143. })
  144. const filterVar = useCallback((varPayload: Var) => {
  145. return [VarType.string, VarType.number, VarType.secret, VarType.object, VarType.array, VarType.arrayNumber, VarType.arrayString, VarType.arrayObject, VarType.file, VarType.arrayFile].includes(varPayload.type)
  146. }, [])
  147. const handleCodeAndVarsChange = useCallback((code: string, inputVariables: Variable[], outputVariables: OutputVar) => {
  148. const newInputs = produce(inputs, (draft) => {
  149. draft.code = code
  150. draft.variables = inputVariables
  151. draft.outputs = outputVariables
  152. })
  153. setInputs(newInputs)
  154. syncOutputKeyOrders(outputVariables)
  155. }, [inputs, setInputs, syncOutputKeyOrders])
  156. return {
  157. readOnly,
  158. inputs,
  159. outputKeyOrders,
  160. handleVarListChange,
  161. handleAddVariable,
  162. handleRemoveVariable,
  163. handleSyncFunctionSignature,
  164. handleCodeChange,
  165. handleCodeLanguageChange,
  166. handleVarsChange,
  167. filterVar,
  168. handleAddOutputVariable,
  169. isShowRemoveVarConfirm,
  170. hideRemoveVarConfirm,
  171. onRemoveVarConfirm,
  172. handleCodeAndVarsChange,
  173. }
  174. }
  175. export default useConfig