1010 <div class =" workflow-search-container flex-between" >
1111 <el-input
1212 ref =" searchInputRef"
13- v-model =" searchText"
13+ v-bind:modelValue =" searchText"
14+ @update:modelValue =" handleSearch"
1415 :placeholder =" $t('workflow.tip.searchPlaceholder')"
1516 clearable
16- @keyup.enter =" handleSearch "
17+ @keyup.enter =" next "
1718 @keyup.esc =" closeSearch"
1819 >
1920 </el-input >
2021 <span >
2122 <el-space :size =" 4" >
22- <span class =" lighter" > 2/3 </span >
23+ <span class =" lighter" v-if =" selectedCount && selectedCount > 0" >
24+ {{ currentIndex + 1 }}/{{ selectedCount }}
25+ </span >
26+ <span class =" lighter" v-else-if =" searchText.length > 0" > 无结果 </span >
2327 <el-divider direction =" vertical" />
2428
2529 <el-button text >
26- <el-icon ><ArrowUp /></el-icon >
30+ <el-icon @click = " up " ><ArrowUp /></el-icon >
2731 </el-button >
2832 <el-button text >
29- <el-icon ><ArrowDown /></el-icon >
33+ <el-icon @click = " next " ><ArrowDown /></el-icon >
3034 </el-button >
3135 <el-button text @click =" closeSearch()" >
3236 <el-icon ><Close /></el-icon >
4347</template >
4448
4549<script setup lang="ts">
46- import { ref , onMounted , onUnmounted , nextTick } from ' vue'
47-
50+ import { ref , onMounted , onUnmounted , nextTick , computed } from ' vue'
51+ import { MsgSuccess , MsgWarning } from ' @/utils/message '
4852// Props定义
4953interface Props {
50- onSearch ? : ( keyword : string ) => void // 搜索回调
54+ lf ? : any
5155}
52- const props = withDefaults (defineProps <Props >(), {
53- onSearch: undefined ,
54- })
56+ const props = withDefaults (defineProps <Props >(), {})
5557
5658// 状态
5759const showSearch = ref (false )
@@ -72,6 +74,99 @@ const handleKeyDown = (e: KeyboardEvent) => {
7274 }
7375}
7476
77+ const focusOn = (node : any ) => {
78+ console .log (node )
79+ props .lf ?.graphModel .transformModel .focusOn (
80+ node .x ,
81+ node .y ,
82+ props .lf ?.container .clientWidth ,
83+ props .lf ?.container .clientHeight ,
84+ )
85+ }
86+ const selectedNodes = ref <Array <any >>()
87+ const currentIndex = ref <number >(0 )
88+ const selectedCount = computed (() => {
89+ return selectedNodes .value ?.length
90+ })
91+
92+ const getSelectNodes = (kw : string ) => {
93+ const result: Array <any > = []
94+ const graph_data = props .lf ?.getGraphData ()
95+ graph_data .nodes .filter ((node : any ) => {
96+ if (node .properties .stepName .includes (kw )) {
97+ result .push ({
98+ ... node ,
99+ order: 1 ,
100+ focusOn : () => {
101+ focusOn (node )
102+ props .lf ?.graphModel .getNodeModelById (node .id ).focusOn (searchText .value )
103+ },
104+ selectOn : () => {
105+ props .lf ?.graphModel .getNodeModelById (node .id ).selectOn (searchText .value )
106+ },
107+ clearSelectOn : () => {
108+ props .lf ?.graphModel .getNodeModelById (node .id ).clearSelectOn (searchText .value )
109+ },
110+ })
111+ }
112+ if (node .type == ' loop-body-node' ) {
113+ const nodeModel = props .lf ?.graphModel
114+ const childNodeModel = nodeModel .getNodeModelById (node .id )
115+ childNodeModel .getSelectNodes (searchText .value ).map ((childNode : any ) => {
116+ result .push ({
117+ ... childNode ,
118+ order: 2 ,
119+ focusOn : () => {
120+ focusOn (node )
121+ childNodeModel .focusOn ({ node: childNode , kw: searchText .value })
122+ },
123+ selectOn : () => {
124+ childNodeModel .selectOn ({ node: childNode , kw: searchText .value })
125+ },
126+ clearSelectOn : () => {
127+ childNodeModel .clearSelectOn ({ node: childNode , kw: searchText .value })
128+ },
129+ })
130+ })
131+ }
132+ })
133+ result .sort ((a , b ) => a .order - b .order || a .y - b .y || a .x - b .x )
134+ return result
135+ }
136+ const selectNodes = (nodes : Array <any >) => {
137+ nodes .forEach ((node ) => node .selectOn ())
138+ }
139+ const next = () => {
140+ if (selectedNodes .value && selectedNodes .value .length > 0 ) {
141+ if (selectedNodes .value .length - 1 >= currentIndex .value + 1 ) {
142+ currentIndex .value ++
143+ } else {
144+ currentIndex .value = 0
145+ }
146+ selectedNodes .value [currentIndex .value ].focusOn ()
147+ }
148+ }
149+ const up = () => {
150+ if (selectedNodes .value && selectedNodes .value .length > 0 ) {
151+ if (currentIndex .value - 1 <= 0 ) {
152+ currentIndex .value = selectedNodes .value .length - 1
153+ } else {
154+ currentIndex .value --
155+ }
156+ selectedNodes .value [currentIndex .value ].focusOn ()
157+ }
158+ }
159+
160+ const onSearch = (kw : string ) => {
161+ if (selectedNodes .value === undefined ) {
162+ const selected = getSelectNodes (kw )
163+ if (selected && selected .length > 0 ) {
164+ selectedNodes .value = selected
165+ selectNodes (selected )
166+ selected [currentIndex .value ].focusOn ()
167+ }
168+ }
169+ }
75170// 打开搜索
76171const openSearch = () => {
77172 showSearch .value = true
@@ -84,14 +179,31 @@ const openSearch = () => {
84179
85180// 关闭搜索
86181const closeSearch = () => {
182+ clearSelect ()
87183 showSearch .value = false
88184 searchText .value = ' '
89185}
90-
186+ const clearSelect = () => {
187+ if (selectedNodes .value ) {
188+ selectedNodes .value [currentIndex .value ].clearSelectOn ()
189+ }
190+ selectedNodes .value = undefined
191+ currentIndex .value = 0
192+ props .lf ?.graphModel .clearSelectElements ()
193+ const graph_data = props .lf ?.getGraphData ()
194+ graph_data .nodes .forEach ((node : any ) => {
195+ if (node .type == ' loop-body-node' ) {
196+ props .lf ?.graphModel .getNodeModelById (node .id ).clearSelectElements ()
197+ }
198+ })
199+ }
91200// 执行搜索
92- const handleSearch = () => {
201+ const handleSearch = (kw : string ) => {
202+ searchText .value = kw
203+ clearSelect ()
204+
93205 if (searchText .value .trim ()) {
94- props . onSearch ?.(searchText .value )
206+ onSearch ?.(searchText .value )
95207 }
96208}
97209
@@ -123,7 +235,7 @@ onUnmounted(() => {
123235 width : 360px ;
124236 :deep(.el-input__wrapper) {
125237 box-shadow : none ;
126- padding : 0 8px 0 1px !important ;
238+ padding : 0 8px 0 1px !important ;
127239 }
128240}
129241 </style >
0 commit comments