@@ -115,49 +115,73 @@ export const getPluginOption =
115
115
*/
116
116
export const getCheckedData =
117
117
( { props, state } ) =>
118
- ( ) => {
118
+ ( selected ) => {
119
119
const checkedKey = [ ]
120
120
121
- if ( ! Array . isArray ( state . selected ) ) {
122
- return props . modelValue ? [ props . modelValue ] : [ state . selected [ props . valueField ] ]
121
+ if ( ! Array . isArray ( selected ) ) {
122
+ return props . modelValue ? [ props . modelValue ] : [ selected [ props . valueField ] ]
123
123
} else {
124
- state . selected . length > 0 &&
125
- state . selected . forEach ( ( item ) => {
124
+ selected . length > 0 &&
125
+ selected . forEach ( ( item ) => {
126
126
checkedKey . push ( item [ props . valueField ] )
127
127
} )
128
128
129
129
return checkedKey
130
130
}
131
131
}
132
132
133
+ /**
134
+ * 递归获取树节点的所有子节点 id 数组
135
+ * @params childNodes 树节点的子节点
136
+ * @params key value 映射字段(valueField)
137
+ * @return 示例:[{ value: 4, children: [{ value: 6 }, { value: 9 }] }] => [4, 6, 9](其中 childNodes 的结构做了简化处理)
138
+ */
139
+ export const getChildValue = ( ) => ( childNodes , key ) => {
140
+ const ids = [ ]
141
+
142
+ const getChild = ( nodes ) => {
143
+ nodes . forEach ( ( node ) => {
144
+ ids . push ( node . data [ key ] )
145
+
146
+ if ( node . childNodes . length > 0 ) {
147
+ getChild ( node . childNodes )
148
+ }
149
+ } )
150
+ }
151
+
152
+ getChild ( childNodes )
153
+
154
+ return ids
155
+ }
156
+
133
157
export const mounted =
134
158
( { api, state, props, vm } ) =>
135
159
( ) => {
136
- if ( ! state . value || state . value . length === 0 ) return
160
+ if ( ! state . modelValue || state . modelValue . length === 0 ) return
137
161
138
162
if ( props . multiple ) {
139
163
let initialNodes = [ ]
140
- if ( Array . isArray ( state . value ) ) {
141
- state . value . forEach ( ( value ) => {
164
+ if ( Array . isArray ( state . modelValue ) ) {
165
+ state . modelValue . forEach ( ( value ) => {
142
166
const option = api . getPluginOption ( value )
143
167
initialNodes = initialNodes . concat ( option )
144
168
} )
145
169
}
146
170
147
- vm . $refs . baseSelectRef . updateSelectedData (
148
- initialNodes . map ( ( node ) => {
149
- return {
150
- ...node ,
151
- currentLabel : node [ props . textField ] ,
152
- value : node [ props . valueField ] ,
153
- isTree : true
154
- }
155
- } )
156
- )
171
+ const selected = initialNodes . map ( ( node ) => {
172
+ return {
173
+ ...node ,
174
+ currentLabel : node [ props . textField ] ,
175
+ value : node [ props . valueField ] ,
176
+ isTree : true
177
+ }
178
+ } )
157
179
158
- state . defaultCheckedKeys = api . getCheckedData ( ) [ 0 ]
180
+ vm . $refs . baseSelectRef . updateSelectedData ( selected )
181
+
182
+ state . defaultCheckedKeys = api . getCheckedData ( selected )
159
183
} else {
160
- const data = api . getPluginOption ( state . value ) [ 0 ]
184
+ const data = api . getPluginOption ( state . modelValue ) [ 0 ]
161
185
vm . $refs . baseSelectRef . updateSelectedData ( {
162
186
...data ,
163
187
currentLabel : data [ props . textField ] ,
@@ -170,3 +194,55 @@ export const mounted =
170
194
state . currentKey = data [ props . valueField ]
171
195
}
172
196
}
197
+
198
+ export const watchValue =
199
+ ( { api, props, vm, state } ) =>
200
+ ( newValue , oldValue ) => {
201
+ if ( props . multiple ) {
202
+ // 取新旧值的差集,用来判断是否是删除标签的操作,如果差值只有一个值,说明是删除操作
203
+ // 如果是删除操作,且不是父子严格模式,则需要将父节点的值也删除(严格模式下父子节点勾选相互独立,不会相互影响)
204
+ const xorResult = oldValue . filter ( ( item ) => ! newValue . includes ( item ) )
205
+ const tagId = xorResult [ 0 ]
206
+ const treeIds = [ tagId ]
207
+ let checkedKeys = newValue
208
+
209
+ // 处理输入框中删除选中标签时,联动下拉面板的逻辑
210
+ if ( xorResult . length === 1 && ! props . treeOp . checkStrictly ) {
211
+ let node = vm . $refs . treeRef . getNode ( tagId )
212
+
213
+ if ( ! node . isLeaf ) {
214
+ treeIds . push ( ...api . getChildValue ( node . childNodes , props . valueField ) )
215
+ }
216
+
217
+ while ( node . parent && ! Array . isArray ( node . parent . data ) ) {
218
+ node . parent . data && treeIds . push ( node . parent . data [ props . valueField ] )
219
+ node = node . parent
220
+ }
221
+
222
+ checkedKeys = newValue . filter ( ( item ) => ! treeIds . includes ( item ) )
223
+ }
224
+
225
+ let initialNodes = [ ]
226
+ if ( Array . isArray ( checkedKeys ) ) {
227
+ checkedKeys . forEach ( ( value ) => {
228
+ const option = api . getPluginOption ( value )
229
+ initialNodes = initialNodes . concat ( option )
230
+ } )
231
+ }
232
+
233
+ const selected = initialNodes . map ( ( node ) => {
234
+ return {
235
+ ...node ,
236
+ currentLabel : node [ props . textField ] ,
237
+ value : node [ props . valueField ] ,
238
+ isTree : true
239
+ }
240
+ } )
241
+
242
+ // 更新输入框中选中的标签
243
+ vm . $refs . baseSelectRef . updateSelectedData ( selected )
244
+
245
+ // 更新下拉面板中选中的树节点
246
+ vm . $refs . treeRef . setCheckedKeys ( checkedKeys )
247
+ }
248
+ }
0 commit comments