cnhis-design-vue 3.0.5 → 3.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,326 @@
1
+ <template>
2
+ <div v-show="visible" class="search-tree-wrap">
3
+ <n-tree
4
+ v-bind="$attrs"
5
+ ref="searchTree"
6
+ v-model:checked-keys="state.checkedKeys"
7
+ @update:expanded-keys="onExpand"
8
+ @update:checked-keys="onCheck"
9
+ checkable
10
+ cascade
11
+ allow-checking-not-loaded
12
+ check-strategy="all"
13
+ :selectable="false"
14
+ :expanded-keys="state.expandedKeys"
15
+ :data="formatTreeData"
16
+ :render-label="renderLabel"
17
+ >
18
+ </n-tree>
19
+ <div v-show="!searchNoMore" style="text-align: center;">
20
+ <!-- loadMorenLoadinng -->
21
+ <n-spin v-if="loadMorenLoadinng" />
22
+ <div v-else class="load-more-btn-wrap">
23
+ <n-icon :component="Search" class="search-input-icon" />
24
+ <div class="load-more-btn" @click="searchOnloadMore">
25
+ 加载更多
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </template>
31
+
32
+ <script lang="tsx" setup>
33
+ import { ref, reactive, watch, computed } from 'vue'
34
+ import { NSpin, NTree, NTooltip, NIcon } from "naive-ui"
35
+ import type { TreeOption } from 'naive-ui'
36
+ import { Search } from '@vicons/ionicons5'
37
+
38
+ const props = withDefaults(defineProps<{
39
+ visible: boolean
40
+ searchNoMore?: boolean
41
+ loadMorenLoadinng?: boolean
42
+ formatTreeData?: any[]
43
+ searchValue?: string
44
+ defaultExpandedKeys: Array<string | number>
45
+ allCheckedKeys?: any
46
+ dataListKeys?: any
47
+ }>(), {
48
+ visible: false,
49
+ searchNoMore: false,
50
+ loadMorenLoadinng: false,
51
+ formatTreeData: () => ([])
52
+ })
53
+ const state = reactive({
54
+ expandedKeys: [] as Array<string | number>,
55
+ autoExpandParent: true,
56
+ // 初始化时,根据formatTreeData和父组件的checkedKeys,动态计算
57
+ checkedKeys: [],
58
+ defaultCheckedKeys: {
59
+ main: [],
60
+ other: []
61
+ }
62
+ })
63
+
64
+ const emit = defineEmits(['addCheckedkeysMain', 'removeCheckedkeysMain', 'addCheckedkeysOther', 'removeCheckedkeysOther', 'searchOnloadMore'])
65
+
66
+ const dataLen = computed(() => props.formatTreeData?.length || 0)
67
+
68
+ const resetData = () => {
69
+ state.checkedKeys = [];
70
+ state.expandedKeys = [];
71
+ state.autoExpandParent = true;
72
+ state.defaultCheckedKeys.main = [];
73
+ state.defaultCheckedKeys.other = [];
74
+ }
75
+ const emitCheckedkeys = () => {
76
+ emitCheckedkeysMain();
77
+ emitCheckedkeysOther();
78
+ setDefaultCheckedKeys();
79
+ }
80
+ const emitCheckedkeysMain = () => {
81
+ let searchCheckedKeysMain = state.checkedKeys.filter(key => {
82
+ return props.dataListKeys.main.includes(key);
83
+ });
84
+ let defaultCheckedKeysMain = state.defaultCheckedKeys.main;
85
+ // let defaultCheckedKeysMain = this.defaultCheckedKeys.main.filter(key => {
86
+ // return this.dataListKeys.main.includes(key);
87
+ // });
88
+ let { add, remove } = calcChangeKeys(defaultCheckedKeysMain, searchCheckedKeysMain);
89
+ emit("addCheckedkeysMain", add);
90
+ emit("removeCheckedkeysMain", remove);
91
+ }
92
+ const emitCheckedkeysOther = () => {
93
+ let searchCheckedKeysOther = state.checkedKeys.filter(key => {
94
+ return props.dataListKeys.other.includes(key);
95
+ });
96
+ let defaultCheckedKeysOther = state.defaultCheckedKeys.other;
97
+ // let defaultCheckedKeysOther = this.defaultCheckedKeys.other.filter(key => {
98
+ // return this.dataListKeys.other.includes(key);
99
+ // });
100
+ let { add, remove } = calcChangeKeys(defaultCheckedKeysOther, searchCheckedKeysOther);
101
+ emit("addCheckedkeysOther", add);
102
+ emit("removeCheckedkeysOther", remove);
103
+ }
104
+ const calcChangeKeys = (defaultCheckedKeys: Array<string | number>, currentCheckedKeys: Array<string | number>) => {
105
+ let add = [] as Array<string | number>;
106
+ let remove = [] as Array<string | number>;
107
+
108
+ currentCheckedKeys.forEach(key => {
109
+ if (!defaultCheckedKeys.includes(key)) {
110
+ add.push(key);
111
+ }
112
+ });
113
+
114
+ defaultCheckedKeys.forEach(key => {
115
+ if (!currentCheckedKeys.includes(key)) {
116
+ remove.push(key);
117
+ }
118
+ });
119
+
120
+ return {
121
+ add,
122
+ remove
123
+ };
124
+ }
125
+ const emptyCheckedKeys = () => {
126
+ state.checkedKeys = [];
127
+ emitCheckedkeys();
128
+ }
129
+ /* setCheckedKeys */
130
+ const setDefaultCheckedKeys = () => {
131
+ setDefaultCheckedKeysMain();
132
+ setDefaultCheckedKeysOther();
133
+ setCurrentCheckedKeys();
134
+ }
135
+ const setDefaultCheckedKeysMain = () => {
136
+ state.defaultCheckedKeys.main = props.dataListKeys.main.filter((key: any) => {
137
+ return props.allCheckedKeys.main.includes(key);
138
+ });
139
+ }
140
+ const setDefaultCheckedKeysOther = () => {
141
+ state.defaultCheckedKeys.other = props.dataListKeys.other.filter((key: any) => {
142
+ return props.allCheckedKeys.other.includes(key);
143
+ });
144
+ }
145
+ const setCurrentCheckedKeys = () => {
146
+ let { main, other } = state.defaultCheckedKeys;
147
+ let res = [...new Set([...main, ...other])];
148
+ state.checkedKeys = res;
149
+ }
150
+ // 选中事件
151
+ const onCheck = () => {
152
+ emitCheckedkeys();
153
+ // this.$emit('check',...arg)
154
+ }
155
+ // 展开数节点
156
+ const onExpand = (expandedKeys: Array<string | number>) => {
157
+ state.expandedKeys = expandedKeys;
158
+ state.autoExpandParent = false;
159
+ // this.$emit('expand', expandedKeys, ...arg)
160
+ }
161
+ const treeCount = (count: any) => {
162
+ if (!count) return "";
163
+ return `(${count})`;
164
+ }
165
+ const searchOnloadMore = () => {
166
+ emit("searchOnloadMore");
167
+ }
168
+ const formatName = (name: string) => {
169
+ let len = name.length;
170
+ return name.substring(len - 2, len);
171
+ }
172
+ const renderLabel = ({option}: {option: TreeOption}) => {
173
+ return (
174
+ <div class="search-tree-item">
175
+ <div class="info-wrap">
176
+ <NTooltip trigger="hover">
177
+ {{
178
+ default: () => `${option.title} ${option.sub_title || ''}`,
179
+ trigger: () => (
180
+ <p class="info-wrap-top" style="margin: 0">
181
+ <span class="info-wrap-title">
182
+ <span class="c-title">{ option.title }</span>&thinsp;<span class="c-sub-title">{ option.sub_title }</span>
183
+ </span>
184
+ </p>
185
+ )
186
+ }}
187
+ </NTooltip>
188
+ </div>
189
+ </div>
190
+ )
191
+ }
192
+
193
+ watch(
194
+ () => props.defaultExpandedKeys,
195
+ (val) => {
196
+ state.expandedKeys = val
197
+ },
198
+ { immediate: true, deep: true }
199
+ )
200
+ watch(
201
+ () => props.visible,
202
+ (val) => {
203
+ if (!val) {
204
+ resetData()
205
+ return
206
+ }
207
+ setDefaultCheckedKeys();
208
+ }
209
+ )
210
+ watch(
211
+ () => dataLen,
212
+ (val) => {
213
+ if (val.value > 0) {
214
+ setDefaultCheckedKeys()
215
+ }
216
+ }
217
+ )
218
+
219
+ defineExpose({
220
+ setDefaultCheckedKeys,
221
+ checkedKeys: state.checkedKeys,
222
+ emptyCheckedKeys
223
+ })
224
+
225
+ </script>
226
+
227
+ <style lang="less" scoped>
228
+ .df {
229
+ display: flex;
230
+ }
231
+
232
+ .search-tree-wrap {
233
+ .search-tree-item {
234
+ display: flex;
235
+ align-items: center;
236
+ }
237
+ .name-wrap {
238
+ width: 48px;
239
+ height: 48px;
240
+ background: #7d88b5;
241
+ display: flex;
242
+ align-items: center;
243
+ justify-content: center;
244
+ border-radius: 50%;
245
+ margin-right: 13px;
246
+
247
+ .name {
248
+ font-size: 16px;
249
+ color: #ffffff;
250
+ margin-bottom: 0;
251
+ line-height: 16px;
252
+ }
253
+ }
254
+ .info-wrap {
255
+ overflow: hidden;
256
+ text-overflow: ellipsis;
257
+ overflow: hidden;
258
+ white-space: nowrap;
259
+ display: flex;
260
+ flex-direction: column;
261
+ }
262
+ .info-wrap-top {
263
+ align-items: flex-end;
264
+ margin: 0;
265
+ margin-bottom: 1px;
266
+ overflow: hidden;
267
+ text-overflow: ellipsis;
268
+ overflow: hidden;
269
+ white-space: nowrap;
270
+ }
271
+ .info-wrap-title {
272
+ margin-bottom: 0;
273
+ font-size: 16px;
274
+ font-family: PingFangSC-Regular, PingFang SC;
275
+ font-weight: 400;
276
+ color: #4e4e4e;
277
+ line-height: 16px;
278
+
279
+ .c-title {
280
+ font-size: 14px;
281
+ font-family: PingFangSC-Regular, PingFang SC;
282
+ font-weight: 400;
283
+ color: #212121;
284
+ }
285
+ .c-sub-title {
286
+ font-size: 12px;
287
+ font-family: PingFangSC-Regular, PingFang SC;
288
+ color: #4e4e4e;
289
+ }
290
+ }
291
+ .info-wrap-desc {
292
+ margin-left: 10px;
293
+ margin-bottom: 0;
294
+ font-size: 12px;
295
+ line-height: 17px;
296
+ color: #aeaeae;
297
+ }
298
+ .info-wrap-position {
299
+ margin-bottom: 0;
300
+ font-size: 12px;
301
+ color: #7d88b5;
302
+ line-height: 17px;
303
+ }
304
+ }
305
+
306
+ .load-more-btn-wrap {
307
+ display: flex;
308
+ justify-content: center;
309
+ height: 35px;
310
+ line-height: 35px;
311
+ cursor: pointer;
312
+ padding-top: 10px;
313
+ box-sizing: border-box;
314
+
315
+ .search-input-icon {
316
+ font-size: 16px;
317
+ color: rgba(0, 0, 0, 0.4);
318
+ margin-right: 14px;
319
+ }
320
+ .load-more-btn {
321
+ font-size: 12px;
322
+ color: #747c8e;
323
+ line-height: 12px;
324
+ }
325
+ }
326
+ </style>
@@ -0,0 +1,66 @@
1
+ // 过滤树形数据
2
+ export const filterTree = ({ value, data, prop, filter, filterXor, children, visible, filterChildren = true, callback }) => {
3
+ // 默认赋值
4
+ visible = visible || 'visible';
5
+ children = children || 'children';
6
+ prop = prop || 'text';
7
+
8
+ const filterNodeMethod = function(value, data) {
9
+ if (!value) {
10
+ return true;
11
+ }
12
+ let flag = (data[prop] || '').indexOf(value) !== -1;
13
+ return filterXor ? !flag : flag;
14
+ };
15
+
16
+ const traverse = function(node) {
17
+ const childNodes = node[children] || [];
18
+
19
+ childNodes.forEach(child => {
20
+ callback && callback(child);
21
+ child[visible] = (!node.root && !filterChildren && node[visible]) || filterNodeMethod.call(child, value, child, prop);
22
+
23
+ traverse(child);
24
+ });
25
+
26
+ if (!node[visible] && childNodes.length) {
27
+ let allHidden = true;
28
+ allHidden = !childNodes.some(child => child[visible]);
29
+
30
+ node[visible] = allHidden === false;
31
+ }
32
+ };
33
+ let totalData = {
34
+ root: true
35
+ };
36
+ totalData[children] = data;
37
+ traverse(totalData);
38
+
39
+ if (filter) {
40
+ let copyData = data.slice();
41
+ let filterHandle = filterData => {
42
+ return filterData.filter((item, index) => {
43
+ if (item[visible]) {
44
+ if (item[children]) {
45
+ item[children] = filterHandle(item[children]);
46
+ }
47
+ return true;
48
+ }
49
+ return false;
50
+ });
51
+ };
52
+ return filterHandle(copyData);
53
+ }
54
+ };
55
+
56
+ // 查找每一层数据的第一条
57
+ export const deepTraversalFirst = (node, nodeList = []) => {
58
+ if (node !== null) {
59
+ nodeList.push(node);
60
+ if (node.children && node.children.length > 0) {
61
+ let children = node.children;
62
+ deepTraversalFirst(children[0], nodeList);
63
+ }
64
+ }
65
+ return nodeList;
66
+ };