Jelajahi Sumber

条件网关的条件字段接入字段选择器

kagg886 1 bulan lalu
induk
melakukan
0f49519d0e

+ 5 - 182
src/components/gFlow/propertySetting/DynamicJudgeInput.vue

@@ -11,42 +11,11 @@
 				@focus="onInputFocus"
 				@blur="onInputBlur"
 			/>
-			<el-popover placement="bottom" :width="600" trigger="click" @hide="handlePopoverHide">
-				<template #reference>
+			<FieldSelector @select="insertField">
+				<template #trigger>
 					<el-button type="primary" size="small" :disabled="readonly" class="template-btn"> 插入字段 </el-button>
 				</template>
-				<div class="popover-content">
-					<div class="two-column-layout">
-						<!-- 第一列:表单类别 -->
-						<div class="left-column">
-							<div class="column-title">表单类别</div>
-							<div class="category-list">
-								<div
-									v-for="item in flowForms"
-									:key="item.value"
-									class="category-item"
-									:class="{ active: currentSelectCate === item }"
-									@click="selectCategory(item)"
-								>
-									{{ item.label }}
-								</div>
-							</div>
-						</div>
-
-						<!-- 第二列:字段列表 -->
-						<div class="right-column">
-							<div class="column-title">字段列表</div>
-							<div class="field-list">
-								<div v-for="field in currentListSelectCate" :key="field.key" class="field-item" @click="insertField(field.key)">
-									<div class="field-name">{{ field.key }}</div>
-									<div class="field-type">{{ field.type }}</div>
-									<div class="field-desc">{{ field.dc }}</div>
-								</div>
-							</div>
-						</div>
-					</div>
-				</div>
-			</el-popover>
+			</FieldSelector>
 		</div>
 
 		<div class="help-text">
@@ -56,22 +25,8 @@
 </template>
 
 <script lang="ts" setup>
-import { computed, getCurrentInstance, Ref, ref, watch } from 'vue'
-import { asyncComputed, useAsyncState } from '@vueuse/core'
-import { getFlowFields, getFlowForm, listFlowForm } from '/@/api/flow/flowForm'
-
-const { proxy } = getCurrentInstance() as any
-const {
-	flow_model_cate,
-}: {
-	[key: string]: Ref<
-		Array<{
-			label: string
-			value: string
-			meta?: FlowFieldsInSql['infos']
-		}>
-	>
-} = proxy.useDict('flow_model_cate')
+import { computed, ref } from 'vue'
+import FieldSelector from './FieldSelector.vue'
 
 // 定义组件的 Props
 interface Props {
@@ -79,14 +34,6 @@ interface Props {
 	readonly?: boolean
 }
 
-type FlowFieldsInSql = {
-	infos: Array<{
-		key: string
-		type: string
-		dc: string
-	}>
-}
-
 const props = withDefaults(defineProps<Props>(), {
 	readonly: false,
 })
@@ -123,13 +70,6 @@ const onInputBlur = () => {
 	}
 }
 
-const currentSelectCate = ref<any | undefined>(undefined)
-
-// 选择表单类别
-const selectCategory = (categoryValue: any) => {
-	currentSelectCate.value = categoryValue
-}
-
 // 插入字段到表达式中
 const insertField = (fieldKey: string) => {
 	const fieldTemplate = `{{.${fieldKey}}}`
@@ -153,58 +93,6 @@ const insertField = (fieldKey: string) => {
 		}
 	}, 0)
 }
-
-const flowForms = asyncComputed<{ label: string; value: string; meta?: FlowFieldsInSql['infos'] }[]>(async () => {
-	const form = await Promise.all(
-		((await listFlowForm({ pageNum: 1, pageSize: 10 })) as unknown as { list: { name: string; id: number }[] }).list.map(async (detail) => {
-			const form_fields_resp = (await getFlowForm(detail.id)) as unknown as { fields: string[]; name: string }
-
-			const fields = form_fields_resp.fields.map((it) => JSON.parse(it)) as unknown as {
-				field: string
-				type: string
-				title: string
-			}[]
-			return {
-				label: form_fields_resp.name,
-				value: form_fields_resp.name,
-				meta: fields.map((it) => {
-					return {
-						key: it.field,
-						type: it.type,
-						dc: it.title,
-					}
-				}),
-			}
-		})
-	)
-
-	return [...flow_model_cate.value, ...form]
-})
-
-watch(currentSelectCate, (newListSelectCate: string) => {
-	if (newListSelectCate === undefined || newListSelectCate === '') return
-	selectCate(100, newListSelectCate)
-})
-
-const { state: currentListSelectCate, execute: selectCate } = useAsyncState(
-	async (data) => {
-		if (data.meta !== undefined) {
-			return data.meta
-		}
-		return await getFlowFields(data.value)
-			.then((res: any) => (res as FlowFieldsInSql).infos)
-			.then((res) => res.filter((it) => it.key !== ''))
-			.catch(() => [] as FlowFieldsInSql['infos'])
-	},
-	[] as FlowFieldsInSql['infos'],
-	{ immediate: false }
-)
-
-// 监听popover关闭,重置组件状态
-const handlePopoverHide = () => {
-	currentSelectCate.value = ''
-	currentListSelectCate.value = []
-}
 </script>
 
 <style scoped lang="scss">
@@ -227,70 +115,5 @@ const handlePopoverHide = () => {
 	}
 }
 
-.popover-content {
-	.two-column-layout {
-		display: flex;
-		gap: 16px;
-		height: 300px;
-
-		.left-column,
-		.right-column {
-			flex: 1;
-			display: flex;
-			flex-direction: column;
-			border: 1px solid #e4e7ed;
-			border-radius: 4px;
-			overflow: hidden;
-
-			.column-title {
-				padding: 8px 12px;
-				background-color: #f5f7fa;
-				border-bottom: 1px solid #e4e7ed;
-				font-weight: 500;
-				font-size: 14px;
-			}
-
-			.category-list,
-			.field-list {
-				flex: 1;
-				overflow-y: auto;
-				padding: 4px 0;
-
-				.category-item,
-				.field-item {
-					padding: 8px 12px;
-					cursor: pointer;
-					transition: background-color 0.2s;
 
-					&:hover {
-						background-color: #f5f7fa;
-					}
-
-					&.active {
-						background-color: #409eff;
-						color: white;
-					}
-				}
-
-				.field-item {
-					.field-name {
-						font-weight: 500;
-						margin-bottom: 2px;
-					}
-
-					.field-type {
-						font-size: 12px;
-						color: #909399;
-						margin-bottom: 2px;
-					}
-
-					.field-desc {
-						font-size: 12px;
-						color: #606266;
-					}
-				}
-			}
-		}
-	}
-}
 </style>

+ 200 - 0
src/components/gFlow/propertySetting/FieldSelector.vue

@@ -0,0 +1,200 @@
+<template>
+	<el-popover placement="bottom" :width="600" trigger="click" @hide="handlePopoverHide">
+		<template #reference>
+			<slot name="trigger" />
+		</template>
+		<div class="popover-content">
+			<div class="two-column-layout">
+				<!-- 第一列:表单类别 -->
+				<div class="left-column">
+					<div class="column-title">表单类别</div>
+					<div class="category-list">
+						<div
+							v-for="item in flowForms"
+							:key="item.value"
+							class="category-item"
+							:class="{ active: currentSelectCate === item }"
+							@click="selectCategory(item)"
+						>
+							{{ item.label }}
+						</div>
+					</div>
+				</div>
+
+				<!-- 第二列:字段列表 -->
+				<div class="right-column">
+					<div class="column-title">字段列表</div>
+					<div class="field-list">
+						<div v-for="field in currentListSelectCate" :key="field.key" class="field-item" @click="handleFieldSelect(field.key)">
+							<div class="field-name">{{ field.key }}</div>
+							<div class="field-type">{{ field.type }}</div>
+							<div class="field-desc">{{ field.dc }}</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</el-popover>
+</template>
+
+<script lang="ts" setup>
+import { getCurrentInstance, Ref, ref, watch } from 'vue'
+import { asyncComputed, useAsyncState } from '@vueuse/core'
+import { getFlowFields, getFlowForm, listFlowForm } from '/@/api/flow/flowForm'
+
+const { proxy } = getCurrentInstance() as any
+const {
+	flow_model_cate,
+}: {
+	[key: string]: Ref<
+		Array<{
+			label: string
+			value: string
+			meta?: FlowFieldsInSql['infos']
+		}>
+	>
+} = proxy.useDict('flow_model_cate')
+
+type FlowFieldsInSql = {
+	infos: Array<{
+		key: string
+		type: string
+		dc: string
+	}>
+}
+
+const emit = defineEmits(['select'])
+
+const currentSelectCate = ref<any | undefined>(undefined)
+
+// 选择表单类别
+const selectCategory = (categoryValue: any) => {
+	currentSelectCate.value = categoryValue
+}
+
+// 处理字段选择
+const handleFieldSelect = (fieldKey: string) => {
+	emit('select', fieldKey)
+}
+
+const flowForms = asyncComputed<{ label: string; value: string; meta?: FlowFieldsInSql['infos'] }[]>(async () => {
+	const form = await Promise.all(
+		((await listFlowForm({ pageNum: 1, pageSize: 10 })) as unknown as { list: { name: string; id: number }[] }).list.map(async (detail) => {
+			const form_fields_resp = (await getFlowForm(detail.id)) as unknown as { fields: string[]; name: string }
+
+			const fields = form_fields_resp.fields.map((it) => JSON.parse(it)) as unknown as {
+				field: string
+				type: string
+				title: string
+			}[]
+			return {
+				label: form_fields_resp.name,
+				value: form_fields_resp.name,
+				meta: fields.map((it) => {
+					return {
+						key: it.field,
+						type: it.type,
+						dc: it.title,
+					}
+				}),
+			}
+		})
+	)
+
+	return [...flow_model_cate.value, ...form]
+})
+
+watch(currentSelectCate, (newListSelectCate: string) => {
+	if (newListSelectCate === undefined || newListSelectCate === '') return
+	selectCate(100, newListSelectCate)
+})
+
+const { state: currentListSelectCate, execute: selectCate } = useAsyncState(
+	async (data) => {
+		if (data.meta !== undefined) {
+			return data.meta
+		}
+		return await getFlowFields(data.value)
+			.then((res: any) => (res as FlowFieldsInSql).infos)
+			.then((res) => res.filter((it) => it.key !== ''))
+			.catch(() => [] as FlowFieldsInSql['infos'])
+	},
+	[] as FlowFieldsInSql['infos'],
+	{ immediate: false }
+)
+
+// 监听popover关闭,重置组件状态
+const handlePopoverHide = () => {
+	currentSelectCate.value = ''
+	currentListSelectCate.value = []
+}
+</script>
+
+<style scoped lang="scss">
+.popover-content {
+	.two-column-layout {
+		display: flex;
+		gap: 16px;
+		height: 300px;
+
+		.left-column,
+		.right-column {
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			border: 1px solid #e4e7ed;
+			border-radius: 4px;
+			overflow: hidden;
+
+			.column-title {
+				padding: 8px 12px;
+				background-color: #f5f7fa;
+				border-bottom: 1px solid #e4e7ed;
+				font-weight: 500;
+				font-size: 14px;
+			}
+
+			.category-list,
+			.field-list {
+				flex: 1;
+				overflow-y: auto;
+				padding: 4px 0;
+
+				.category-item,
+				.field-item {
+					padding: 8px 12px;
+					cursor: pointer;
+					transition: background-color 0.2s;
+
+					&:hover {
+						background-color: #f5f7fa;
+					}
+
+					&.active {
+						background-color: #409eff;
+						color: white;
+					}
+				}
+
+				.field-item {
+					.field-name {
+						font-weight: 500;
+						margin-bottom: 2px;
+					}
+
+					.field-type {
+						font-size: 12px;
+						color: #909399;
+						margin-bottom: 2px;
+					}
+
+					.field-desc {
+						font-size: 12px;
+						color: #606266;
+					}
+				}
+			}
+		}
+	}
+}
+</style>

+ 11 - 3
src/components/gFlow/propertySetting/branch.vue

@@ -38,9 +38,13 @@
                   <el-input
                       v-model="condition.label"
                       placeholder="描述" />
-                  <el-input
-                      v-model="condition.field"
-                      placeholder="条件字段" />
+                  <FieldSelector @select="(fieldKey) => selectField(fieldKey, condition)">
+                    <template #trigger>
+                      <el-input
+                          v-model="condition.field"
+                          placeholder="条件字段" />
+                    </template>
+                  </FieldSelector>
                   <el-select
                       v-model="condition.operator"
                       placeholder="请选择">
@@ -102,6 +106,7 @@
 <script lang="ts" setup>
 import {NodeConditionData} from "/@/components/gFlow/propertySetting/model";
 import {onMounted, ref, watch} from "vue";
+import FieldSelector from './FieldSelector.vue';
 
 const emit = defineEmits(['setNodeExt'])
 const conditionList = ref<Array<NodeConditionData[]>>([])
@@ -125,6 +130,9 @@ const deleteConditionGroup = (idx:number) => {
 const deleteConditionList = (conditionList:NodeConditionData[],idx:number) => {
   conditionList.splice(idx,1)
 }
+const selectField = (fieldKey: string, condition: NodeConditionData) => {
+  condition.field = fieldKey
+}
 const setNodeExt = ()=>{
   emit('setNodeExt',conditionList.value)
 }

+ 5 - 203
src/components/gFlow/propertySetting/webhookParams.vue

@@ -13,42 +13,11 @@
 					</div>
 
 					<div class="param-value">
-						<el-popover placement="bottom" :width="600" trigger="click" @hide="handlePopoverHide">
-							<template #reference>
+						<FieldSelector @select="(fieldKey) => selectField(fieldKey, key)">
+							<template #trigger>
 								<el-input v-model="origin[key]" placeholder="参数值" :disabled="readonly" @input="updateOrigin" />
 							</template>
-							<div class="popover-content">
-								<div class="two-column-layout">
-									<!-- 第一列:flow_model_cate字典数据 -->
-									<div class="left-column">
-										<div class="column-title">表单类别</div>
-										<div class="category-list">
-											<div
-												v-for="item in flowForms"
-												:key="item.value"
-												class="category-item"
-												:class="{ active: currentSelectCate === item }"
-												@click="selectCategory(item)"
-											>
-												{{ item.label }}
-											</div>
-										</div>
-									</div>
-
-									<!-- 第二列:currentListSelectCate数据 -->
-									<div class="right-column">
-										<div class="column-title">字段列表</div>
-										<div class="field-list">
-											<div v-for="field in currentListSelectCate" :key="field.key" class="field-item" @click="selectField(field.key, key)">
-												<div class="field-name">{{ field.key }}</div>
-												<div class="field-type">{{ field.type }}</div>
-												<div class="field-desc">{{ field.dc }}</div>
-											</div>
-										</div>
-									</div>
-								</div>
-							</div>
-						</el-popover>
+						</FieldSelector>
 					</div>
 
 					<div class="param-actions">
@@ -61,25 +30,10 @@
 </template>
 
 <script lang="ts" setup>
-import { computed, getCurrentInstance, Ref, ref, watch } from 'vue'
+import { computed, ref, watch } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Delete } from '@element-plus/icons-vue'
-import { asyncComputed, useAsyncState } from '@vueuse/core'
-import { getFlowFields, getFlowForm, listFlowForm } from '/@/api/flow/flowForm'
-
-const { proxy } = getCurrentInstance() as any
-const {
-	flow_model_cate,
-}: {
-	[key: string]: Ref<
-		Array<{
-			label: string
-			value: string
-
-			meta?: FlowFieldsInSql['infos']
-		}>
-	>
-} = proxy.useDict('flow_model_cate')
+import FieldSelector from './FieldSelector.vue'
 
 // 定义组件的 Props
 interface Props {
@@ -88,15 +42,6 @@ interface Props {
 	readonly?: boolean
 }
 
-type FlowFieldsInSql = {
-	infos: Array<{
-		key: string
-		type: string
-		dc: string
-	}>
-}
-// getFlowFields('表单名').then((res:FlowFieldsInSql)=>xxx)
-
 const props = withDefaults(defineProps<Props>(), {
 	title: '参数配置',
 	readonly: false,
@@ -175,89 +120,11 @@ const updateOrigin = () => {
 	origin.value = { ...origin.value }
 }
 
-const currentSelectCate = ref<any | undefined>(undefined)
-
-// 选择表单类别
-const selectCategory = (categoryValue: any) => {
-	currentSelectCate.value = categoryValue
-}
-
 // 选择字段
 const selectField = (fieldKey: string, paramKey: string) => {
 	origin.value[paramKey] = `{{.${fieldKey}}}`
 	updateOrigin()
 }
-
-const flowForms = asyncComputed<{ label: string; value: string; meta?: FlowFieldsInSql['infos'] }[]>(async () => {
-	const form = await Promise.all(
-		((await listFlowForm({ pageNum: 1, pageSize: 10 })) as unknown as { list: { name: string; id: number }[] }).list.map(async (detail) => {
-			//label: string,
-			//value: string,
-			//meta: any
-			const form_fields_resp = (await getFlowForm(detail.id)) as unknown as { fields: string[]; name: string }
-
-			/**
-			 * {
-			 * 	"type": "input",
-			 * 	"field": "title",
-			 * 	"title": "标题",
-			 * 	"info": "",
-			 * 	"$required": false,
-			 * 	"_fc_drag_tag": "input",
-			 * 	"hidden": false,
-			 * 	"display": true,
-			 * 	"_fc_id": "id_Fhoum1kfoi93abc",
-			 * 	"name": "ref_Fkwqm1kfoi93acc"
-			 * }
-			 */
-			const fields = form_fields_resp.fields.map((it) => JSON.parse(it)) as unknown as {
-				field: string
-				type: string
-				title: string
-			}[]
-			return {
-				label: form_fields_resp.name,
-				value: form_fields_resp.name,
-				meta: fields.map((it) => {
-					return {
-						key: it.field,
-						type: it.type,
-						dc: it.title,
-					}
-				}),
-			}
-		})
-	)
-
-	return [...flow_model_cate.value, ...form]
-})
-
-watch(currentSelectCate, (newListSelectCate: string) => {
-	if (newListSelectCate === undefined || newListSelectCate === '') return
-	selectCate(100, newListSelectCate)
-})
-
-const { state: currentListSelectCate, execute: selectCate } = useAsyncState(
-	async (data) => {
-		if (data.meta !== undefined) {
-			return data.meta
-		}
-		return await getFlowFields(data.value)
-			.then((res: any) => (res as FlowFieldsInSql).infos)
-			.then((res) => res.filter((it) => it.key !== ''))
-			.catch(() => [] as FlowFieldsInSql['infos'])
-	},
-	[] as FlowFieldsInSql['infos'],
-	{ immediate: false }
-)
-
-// 监听popover关闭,重置组件状态
-const handlePopoverHide = () => {
-	// 当popover关闭时,重置所有相关状态
-	currentSelectCate.value = ''
-	// 清空字段列表数据
-	currentListSelectCate.value = []
-}
 </script>
 
 <style scoped lang="scss">
@@ -307,70 +174,5 @@ const handlePopoverHide = () => {
 	}
 }
 
-.popover-content {
-	.two-column-layout {
-		display: flex;
-		gap: 16px;
-		height: 300px;
-
-		.left-column,
-		.right-column {
-			flex: 1;
-			display: flex;
-			flex-direction: column;
-			border: 1px solid #e4e7ed;
-			border-radius: 4px;
-			overflow: hidden;
-
-			.column-title {
-				padding: 8px 12px;
-				background-color: #f5f7fa;
-				border-bottom: 1px solid #e4e7ed;
-				font-weight: 500;
-				font-size: 14px;
-			}
-
-			.category-list,
-			.field-list {
-				flex: 1;
-				overflow-y: auto;
-				padding: 4px 0;
-
-				.category-item,
-				.field-item {
-					padding: 8px 12px;
-					cursor: pointer;
-					transition: background-color 0.2s;
-
-					&:hover {
-						background-color: #f5f7fa;
-					}
 
-					&.active {
-						background-color: #409eff;
-						color: white;
-					}
-				}
-
-				.field-item {
-					.field-name {
-						font-weight: 500;
-						margin-bottom: 2px;
-					}
-
-					.field-type {
-						font-size: 12px;
-						color: #909399;
-						margin-bottom: 2px;
-					}
-
-					.field-desc {
-						font-size: 12px;
-						color: #606266;
-					}
-				}
-			}
-		}
-	}
-}
 </style>