Explorar o código

fix: 修改节点渲染

jiaxing.liao hai 5 días
pai
achega
abc126ce1b

+ 105 - 84
apps/web/src/components/setter/DatabaseSetter.vue

@@ -6,52 +6,78 @@
  * @Describe: 数据设置器
 -->
 <script lang="ts" setup>
-import { computed, ref } from 'vue'
+import { computed, ref, watch } from 'vue'
 import { IconButton, Icon } from '@repo/ui'
 import SelectTableModal from '@/features/selectTableModal/index.vue'
+import { clone, isEqual } from 'lodash-es'
 
 const props = withDefaults(
 	defineProps<{
 		data: any
-		visible: boolean
 	}>(),
 	{
-		visible: false,
 		data: {}
 	}
 )
+
 const emit = defineEmits<{
-	'update:visible': [value: boolean]
+	update: [data: unknown]
 }>()
 
+const DEFAULT_DATA = {
+	tableList: [],
+	fieldList: [],
+	limit: 100,
+	sortList: [],
+	conditionList: [],
+	output: {
+		outputList: []
+	},
+	exception: 'none',
+	exceptionDefaultValue: {
+		body: '',
+		status_code: 0,
+		headers: '{}'
+	}
+}
+
+const formData = ref(clone(DEFAULT_DATA))
+
+watch(
+	() => props.data,
+	(newVal) => {
+		if (!isEqual(newVal, formData.value)) {
+			formData.value = {
+				...clone(DEFAULT_DATA),
+				...(newVal || {})
+			}
+		}
+	},
+	{
+		deep: true,
+		immediate: true
+	}
+)
+
+watch(
+	() => formData.value,
+	(value) => {
+		emit('update', value)
+	},
+	{ deep: true }
+)
+
 const selectTableModalRef = ref<InstanceType<typeof SelectTableModal> | null>(null)
-// 数据表
-const tableList = ref<any[]>([])
-// 查询字段
-const fieldList = ref<any[]>([])
-// 查询条件
-const conditionList = ref<any[]>([])
-// 排序方式
-const sortList = ref<any[]>([])
-// 查询上限
-const limit = ref<number>(100)
-// 输出
-const outputList = ref<any[]>([])
 
-// 异常处理
-const exceptionConfig = ref<{
-	timeout: number
-	retry: number
-	handler: number
-}>({
-	timeout: 60,
-	retry: 3,
-	handler: 0
-})
+const exceptionOptions = [
+	{ label: '无', value: 'none' },
+	{ label: '默认值', value: 'default_value' },
+	{ label: '异常分支', value: 'exception_branch' }
+]
 
 const columns = computed(() => {
-	return (tableList.value?.[0]?.columns || []).filter(
-		(item: any) => !fieldList.value.find((field: any) => field.name === item.name)
+	return (formData.value.tableList?.[0]?.columns || []).filter(
+		(item: any) => !formData.value.fieldList.find((field: any) => field.name === item.name)
 	)
 })
 
@@ -60,7 +86,7 @@ const addDatabase = () => {
 }
 
 const onAddTable = (table: unknown) => {
-	tableList.value = [table]
+	formData.value.tableList = [table]
 }
 </script>
 
@@ -80,7 +106,7 @@ const onAddTable = (table: unknown) => {
 						/>
 					</div>
 				</template>
-				<template v-for="table in tableList" :key="table">
+				<template v-for="table in formData.tableList" :key="table">
 					<div
 						class="px-12px flex items-center justify-between cursor-pointer mb-12px p-12px hover:bg-gray-100 border border-solid border-gray-300 rounded-8px"
 					>
@@ -106,7 +132,11 @@ const onAddTable = (table: unknown) => {
 					</div>
 				</template>
 
-				<el-empty v-if="!tableList.length" description="请添加一个数据表到此处" :image-size="40" />
+				<el-empty
+					v-if="!formData.tableList.length"
+					description="请添加一个数据表到此处"
+					:image-size="40"
+				/>
 			</el-collapse-item>
 
 			<el-collapse-item name="2">
@@ -119,18 +149,18 @@ const onAddTable = (table: unknown) => {
 								<el-dropdown-item
 									v-for="column in columns"
 									:key="column.name"
-									@click="fieldList.push(column)"
+									@click="formData.fieldList.push(column)"
 									>{{ column.name }}</el-dropdown-item
 								>
 							</template>
 						</el-dropdown>
 					</div>
 				</template>
-				<div v-for="field in fieldList" :key="field.name" class="flex gap-4px mb-12px">
+				<div v-for="field in formData.fieldList" :key="field.name" class="flex gap-4px mb-12px">
 					<span>{{ field.name }}</span>
 					<el-tag type="info" effect="light">{{ field.type }}</el-tag>
 				</div>
-				<el-empty v-if="!fieldList.length" description="请添加查询字段" :image-size="40" />
+				<el-empty v-if="!formData.fieldList.length" description="请添加查询字段" :image-size="40" />
 			</el-collapse-item>
 
 			<el-collapse-item title="查询条件" name="3"> </el-collapse-item>
@@ -143,10 +173,10 @@ const onAddTable = (table: unknown) => {
 							<IconButton size="large" v-show="isActive" icon="iconoir:plus" link @click.stop />
 							<template #dropdown>
 								<el-dropdown-item
-									v-for="column in fieldList"
+									v-for="column in formData.fieldList"
 									:key="column.name"
 									@click="
-										sortList.push({
+										formData.sortList.push({
 											name: column.name,
 											type: column.type,
 											sort: 'asc'
@@ -158,7 +188,11 @@ const onAddTable = (table: unknown) => {
 						</el-dropdown>
 					</div>
 				</template>
-				<div v-for="field in sortList" :key="field.name" class="flex items-center gap-4px mb-12px">
+				<div
+					v-for="field in formData.sortList"
+					:key="field.name"
+					class="flex items-center gap-4px mb-12px"
+				>
 					<div class="flex-1 flex justify-between">
 						<span>{{ field.name }}</span>
 						<el-tag type="info" effect="light">{{ field.type }}</el-tag>
@@ -168,12 +202,12 @@ const onAddTable = (table: unknown) => {
 						<el-option label="降序" value="desc"></el-option>
 					</el-select>
 				</div>
-				<el-empty v-if="!sortList.length" description="请添加排序字段" :image-size="40" />
+				<el-empty v-if="!formData.sortList.length" description="请添加排序字段" :image-size="40" />
 			</el-collapse-item>
 
 			<el-collapse-item title="查询上限" name="6">
 				<el-input-number
-					v-model="limit"
+					v-model="formData.limit"
 					:min="1"
 					:max="1000"
 					style="width: 100%"
@@ -191,10 +225,10 @@ const onAddTable = (table: unknown) => {
 								<IconButton size="large" v-show="isActive" icon="iconoir:plus" link @click.stop />
 								<template #dropdown>
 									<el-dropdown-item
-										v-for="column in fieldList"
+										v-for="column in formData.fieldList"
 										:key="column.name"
 										@click="
-											outputList.push({
+											formData.output.outputList.push({
 												name: column.name,
 												type: column.type
 											})
@@ -206,7 +240,7 @@ const onAddTable = (table: unknown) => {
 						</div>
 					</template>
 					<div
-						v-for="field in outputList"
+						v-for="field in formData.output.outputList"
 						:key="field.name"
 						class="flex items-center gap-4px mb-12px"
 					>
@@ -215,49 +249,36 @@ const onAddTable = (table: unknown) => {
 					</div>
 				</el-collapse-item>
 			</el-collapse-item>
-
-			<el-collapse-item title="异常处理" name="8">
-				<el-form label-width="120px">
-					<el-row>
-						<el-col :span="24">
-							<el-form-item label="超时时间">
-								<el-input-number
-									v-model="exceptionConfig.timeout"
-									:min="1"
-									:max="1000"
-									style="width: 100%"
-									controls-position="right"
-									placeholder="请输入"
-									suffix="s"
-								/>
-							</el-form-item>
-						</el-col>
-						<el-col :span="24">
-							<el-form-item label="重试次数">
-								<el-input-number
-									v-model="exceptionConfig.retry"
-									:min="0"
-									:max="5"
-									style="width: 100%"
-									controls-position="right"
-									placeholder="请输入"
-									suffix="s"
-								/>
-							</el-form-item>
-						</el-col>
-						<el-col :span="24">
-							<el-form-item label="异常处理方式">
-								<el-select v-model="exceptionConfig.handler" placeholder="请选择">
-									<el-option label="中断流程" :value="0" />
-									<el-option label="返回设定内容" :value="1" />
-									<el-option label="执行异常流程" :value="2" />
-								</el-select>
-							</el-form-item>
-						</el-col>
-					</el-row>
-				</el-form>
-			</el-collapse-item>
 		</el-collapse>
+		<div class="p-12px">
+			<el-form-item label="异常处理" label-width="90px" label-position="left">
+				<div class="w-full text-right">
+					<el-select
+						v-model="formData.exception"
+						:options="exceptionOptions"
+						style="width: 120px"
+					/>
+				</div>
+			</el-form-item>
+			<div v-if="formData.exception === 'default_value'">
+				<div class="text-12px text-gray-500">当发生异常时,指定默认数据输出</div>
+				<el-form-item label="body" label-position="top">
+					<el-input v-model="formData.exceptionDefaultValue.body" type="textarea" rows="3" />
+				</el-form-item>
+				<el-form-item label="status_code" label-position="top">
+					<el-input-number
+						controls-position="right"
+						v-model="formData.exceptionDefaultValue.status_code"
+					/>
+				</el-form-item>
+				<el-form-item label="headers" label-position="top">
+					<el-input v-model="formData.exceptionDefaultValue.headers" type="textarea" rows="5" />
+				</el-form-item>
+			</div>
+			<div v-if="formData.exception === 'exception_branch'">
+				<div class="text-12px text-gray-500">请在画布定义异常处理逻辑!</div>
+			</div>
+		</div>
 	</el-scrollbar>
 
 	<SelectTableModal ref="selectTableModalRef" @add="onAddTable" />

+ 13 - 34
packages/workflow/src/components/elements/node-temp/DataBaseNode.vue

@@ -11,36 +11,15 @@ import CanvasHandle from '../handles/CanvasHandle.vue'
 import { Icon } from '@repo/ui'
 import { computed } from 'vue'
 
-interface Datasource {
-	type: 'mysql' | 'postgresql' | 'mongodb' | 'redis' | 'api'
-	connectionId: string
-	connectionName?: string
-}
+import type { NodeProps } from '@vue-flow/core'
+import type { IWorkflowNode } from '../../../Interface'
 
-interface Query {
-	type: 'sql' | 'nosql' | 'rest'
-	content: string
-	params?: Record<string, any>
+type Props = NodeProps<IWorkflowNode['data']> & {
+	readOnly?: boolean
+	hovered?: boolean
 }
 
-interface Props {
-	data: {
-		label?: string
-		description?: string
-		datasource?: Datasource
-		query?: Query
-		result?: {
-			limit?: number
-			mapping?: Record<string, string>
-		}
-		[key: string]: any
-	}
-	selected?: boolean
-}
-
-const props = withDefaults(defineProps<Props>(), {
-	selected: false
-})
+const props = defineProps<Props>()
 
 // 数据源类型图标映射
 const datasourceIcons: Record<string, string> = {
@@ -141,11 +120,11 @@ const queryTypeLabel = computed(() => {
 				<div class="flex items-start gap-2">
 					<Icon icon="lucide:code-2" color="#94a3b8" :size="14" class="flex-shrink-0 mt-0.5" />
 					<div class="flex-1 min-w-0">
-						<div class="text-xs text-gray-500 mb-1">查询语句</div>
+						<div class="text-xs text-gray-500 mb-1">数据表</div>
 						<div
 							class="text-xs text-gray-700 font-mono bg-gray-50 px-2 py-2 rounded border border-gray-200 max-h-20 overflow-y-auto"
 						>
-							{{ data.query?.content || 'SELECT * FROM table_name' }}
+							{{ data.tableList?.[0]?.name }}
 						</div>
 					</div>
 				</div>
@@ -225,23 +204,23 @@ const queryTypeLabel = computed(() => {
 
 		<!-- 输出连接点 - 成功 -->
 		<CanvasHandle
-			handle-id="code-node-output1"
+			handle-id="database-node-output1"
 			type="source"
 			:connections-count="2"
 			:position="Position.Right"
-			:style="{ top: '40%' }"
-			label="true"
+			:style="data.exception === 'exception_branch' ? { top: '40%' } : {}"
 		>
 		</CanvasHandle>
 
 		<!-- 输出连接点 - 失败 -->
 		<CanvasHandle
-			handle-id="code-node-output2"
+			v-if="data.exception === 'exception_branch'"
+			handle-id="database-node-output2"
 			type="source"
 			:connections-count="2"
 			:position="Position.Right"
 			:style="{ top: '60%' }"
-			label="false"
+			label="exception"
 		>
 		</CanvasHandle>
 	</div>

+ 16 - 10
packages/workflow/src/components/elements/node-temp/HttpNode1.vue

@@ -120,21 +120,27 @@ const methodColors: Record<string, string> = {
 			</div>
 		</div>
 
-		<!-- 输入连接点 -->
+		<!-- 输出连接点 - 成功 -->
 		<CanvasHandle
-			handle-id="http-node-input"
-			type="target"
-			:connections-count="1"
-			:position="Position.Left"
-		/>
+			handle-id="http-node-output1"
+			type="source"
+			:connections-count="2"
+			:position="Position.Right"
+			:style="data.exception === 'exception_branch' ? { top: '40%' } : {}"
+		>
+		</CanvasHandle>
 
-		<!-- 输出连接点 -->
+		<!-- 输出连接点 - 失败 -->
 		<CanvasHandle
-			handle-id="http-node-output"
+			v-if="data.exception === 'exception_branch'"
+			handle-id="http-node-output2"
 			type="source"
-			:connections-count="1"
+			:connections-count="2"
 			:position="Position.Right"
-		/>
+			:style="{ top: '60%' }"
+			label="exception"
+		>
+		</CanvasHandle>
 	</div>
 </template>