eoss-ui 0.8.37 → 0.8.39

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.
@@ -1,761 +1,764 @@
1
- <template>
2
- <div
3
- v-if="isRender"
4
- class="es-selector"
5
- ref="esSelector"
6
- :class="{ 'es-pointer': !readonly && !filterable }"
7
- v-clickoutside="handleClose"
8
- >
9
- <template v-if="form">
10
- <el-button v-if="button" v-bind="button" @click="openDialog">
11
- <slot>
12
- <es-icon v-if="icon" :contents="icon"></es-icon>
13
- <template v-else>选择</template>
14
- </slot>
15
- </el-button>
16
- <template v-else>
17
- <div
18
- :class="[
19
- selectorSize ? 'el-select--' + selectorSize : 'es-selector-box',
20
- { 'es-selector-search': filterable }
21
- ]"
22
- @click.stop="toggleMenu"
23
- >
24
- <div
25
- v-if="multiple"
26
- ref="tags"
27
- class="el-select__tags"
28
- :class="{ 'es-selector-edit': !readonly }"
29
- >
30
- <div
31
- v-if="collapseTags && selected.length"
32
- class="es-selector-tags"
33
- :class="{ 'es-selector-more': selected.length > 1 }"
34
- >
35
- <el-tag
36
- v-for="(item, index) in selected.slice(
37
- 0,
38
- collapseTags === true ? 1 : collapseTags
39
- )"
40
- :key="getValueKey(item)"
41
- :closable="
42
- !selectorDisabled && !readonly && selected.length > min
43
- "
44
- type="info"
45
- disable-transitions
46
- @close="deleteTag($event, item, index)"
47
- >
48
- <span class="el-select__tags-text">{{ getLabel(item) }}</span>
49
- </el-tag>
50
-
51
- <el-tag
52
- v-if="
53
- selected.length > (collapseTags === true ? 1 : collapseTags)
54
- "
55
- :closable="false"
56
- type="info"
57
- disable-transitions
58
- class="es-tags-more"
59
- >
60
- <span class="el-select__tags-text"
61
- >+
62
- {{
63
- selected.length - (collapseTags === true ? 1 : collapseTags)
64
- }}</span
65
- >
66
- </el-tag>
67
- </div>
68
- <transition-group v-else @after-leave="resetInputHeight">
69
- <el-tag
70
- v-for="(item, index) in selected"
71
- :key="getValueKey(item)"
72
- :closable="
73
- !selectorDisabled && !readonly && selected.length > min
74
- "
75
- type="info"
76
- disable-transitions
77
- @close="deleteTag($event, item, index)"
78
- >
79
- <span class="el-select__tags-text">{{ getLabel(item) }}</span>
80
- </el-tag>
81
- </transition-group>
82
- </div>
83
- <div ref="reference" class="es-input__inner" v-if="readonly">
84
- <template v-if="!multiple">{{ selectedLabel }}</template>
85
- </div>
86
- <template v-else>
87
- <template v-if="multiple">
88
- <el-input
89
- type="text"
90
- ref="reference"
91
- autocomplete="off"
92
- v-model="words"
93
- :readonly="filterable ? false : true"
94
- :id="id"
95
- :placeholder="currentPlaceholder"
96
- :size="selectorSize"
97
- :disabled="selectorDisabled"
98
- :class="{
99
- 'is-focus': visible,
100
- 'es-plain': plain,
101
- 'es-pointer': !filterable,
102
- 'es-zindex-2': focus
103
- }"
104
- :tabindex="tabindex"
105
- v-popover:popover
106
- @dblclick.native="openDialog"
107
- @focus="handleFocus"
108
- @blur="handleBlur"
109
- >
110
- <template slot="append">
111
- <el-button
112
- ref="openDialog"
113
- v-if="filterable || showButton"
114
- @click.stop="openDialog"
115
- >
116
- <slot>
117
- <es-icon v-if="icon" :contents="icon"></es-icon>
118
- <template v-else>选择</template>
119
- </slot>
120
- </el-button>
121
- </template>
122
- </el-input>
123
- <el-input
124
- v-model="selectedLabel"
125
- readonly
126
- :name="name"
127
- type="text"
128
- v-show="false"
129
- ></el-input>
130
- </template>
131
- <el-input
132
- v-else
133
- v-model="selectedLabel"
134
- type="text"
135
- ref="reference"
136
- autocomplete="off"
137
- :clearable="clearable"
138
- showClearIcon
139
- :name="name"
140
- :readonly="filterable ? false : true"
141
- :active="actived"
142
- :id="id"
143
- :placeholder="currentPlaceholder"
144
- :size="selectorSize"
145
- :disabled="selectorDisabled"
146
- :class="{
147
- 'is-focus': visible,
148
- 'es-plain': this.plain,
149
- 'es-pointer': !filterable
150
- }"
151
- :tabindex="tabindex"
152
- @dblclick.native="openDialog"
153
- @clear="handleClear"
154
- >
155
- <template slot="append">
156
- <el-button
157
- ref="openDialog"
158
- v-if="filterable || showButton"
159
- @click.stop="openDialog"
160
- >
161
- <slot>
162
- <es-icon v-if="icon" :contents="icon"></es-icon>
163
- <template v-else>选择</template>
164
- </slot>
165
- </el-button>
166
- </template>
167
- </el-input>
168
- </template>
169
- </div>
170
- <el-popover
171
- v-model="show"
172
- placement="bottom-start"
173
- trigger="manual"
174
- popper-class="es-selector-popover"
175
- :width="minWidth"
176
- :queryParent="true"
177
- :reference="reference"
178
- :arrow-offset="20"
179
- >
180
- <el-scrollbar
181
- tag="ul"
182
- wrap-class="es-selector-dropdown__wrap"
183
- view-class="es-selector-dropdown__list"
184
- ref="scrollbar"
185
- v-show="options.length"
186
- maxHeight="228"
187
- >
188
- <li
189
- v-for="item in options"
190
- :key="item.id"
191
- @click="handleSelect(item)"
192
- class="es-selector-dropdown-item"
193
- :class="{ 'es-selected': item.selected }"
194
- >
195
- <span>
196
- {{ getDep(item) }}
197
- {{ item[labelKey] }}
198
- </span>
199
- </li>
200
- </el-scrollbar>
201
- <p v-if="options.length == 0" class="el-select-dropdown__empty">
202
- {{ noMatchText }}
203
- </p>
204
- </el-popover>
205
- </template>
206
- </template>
207
- <es-dialog
208
- v-if="!readonly"
209
- :title="title"
210
- :visible.sync="visible"
211
- :width="width"
212
- :height="height"
213
- :css="false"
214
- :append-to-body="true"
215
- :close-on-click-modal="false"
216
- class="es-selector-dialog"
217
- >
218
- <es-selector-panel
219
- v-if="isReset"
220
- v-model="selected"
221
- v-bind="$attrs"
222
- :multiple="multiple"
223
- width="100%"
224
- height="100%"
225
- :value-key="valueKey"
226
- :label-key="labelKey"
227
- :host="host"
228
- :type="types"
229
- :mix="mix"
230
- :isShowLevel3="isShowLevel3"
231
- @tabschage="tabschage"
232
- @click.capture="stopd"
233
- @confirm="handleConfirm"
234
- @cancel="handleCancel"
235
- ></es-selector-panel>
236
- </es-dialog>
237
- </div>
238
- </template>
239
- <script>
240
- import util from 'eoss-ui/src/utils/util.js';
241
- import { getSelectorOrgDetail, getSysParam } from 'eoss-ui/src/config/api.js';
242
- import Clickoutside from 'eoss-element/src/utils/clickoutside';
243
- export default {
244
- name: 'EsSelector',
245
- inheritAttrs: false,
246
- inject: {
247
- elForm: {
248
- default: ''
249
- },
250
- elFormItem: {
251
- default: ''
252
- }
253
- },
254
- directives: { Clickoutside },
255
- props: {
256
- form: {
257
- type: Boolean,
258
- default: true
259
- },
260
- isShowLevel3: {
261
- type: Boolean,
262
- default: true
263
- },
264
- value: [Array, Object],
265
- action: {
266
- type: String,
267
- default: getSelectorOrgDetail
268
- },
269
- host: {
270
- type: String,
271
- default: ''
272
- },
273
- title: {
274
- type: String,
275
- default: '公用选择器'
276
- },
277
- width: {
278
- type: String,
279
- default: '900px'
280
- },
281
- height: {
282
- type: String,
283
- default: '560px'
284
- },
285
- multiple: {
286
- type: Boolean,
287
- default: true
288
- },
289
- valueKey: {
290
- type: String,
291
- default: 'showid'
292
- },
293
- labelKey: {
294
- type: String,
295
- default: 'showname'
296
- },
297
- valueType: {
298
- type: String,
299
- default: 'object',
300
- validator: function (value) {
301
- return ['string', 'object'].includes(value);
302
- }
303
- },
304
- size: String,
305
- id: String,
306
- disabled: Boolean,
307
- clearable: {
308
- type: Boolean,
309
- default: true
310
- },
311
- placeholder: {
312
- type: String,
313
- default: '请选择'
314
- },
315
- autocomplete: {
316
- type: String,
317
- default: 'off'
318
- },
319
- name: String,
320
- readonly: Boolean,
321
- collapseTags: [Boolean, Number],
322
- plain: Boolean,
323
- types: {
324
- type: Array,
325
- default() {
326
- return ['enterprise', 'person'];
327
- }
328
- },
329
- tabindex: {
330
- type: [String, Number],
331
- default: -1
332
- },
333
- //是否显示搜索框
334
- filterable: Boolean,
335
- //搜索列表是否显示部门信息
336
- showFilterListDep: {
337
- type: Boolean,
338
- default: true
339
- },
340
- //是否根据搜索值创建新的数据
341
- createable: Boolean,
342
- showButton: Boolean,
343
- button: Object,
344
- icon: String,
345
- active: String,
346
- keywords: {
347
- type: String,
348
- default: 'namelike'
349
- },
350
- //输入框搜索参数
351
- where: {
352
- type: Object,
353
- default() {
354
- return {
355
- mid: '0-0-0-0-0'
356
- };
357
- }
358
- },
359
- //混选
360
- mix: Boolean,
361
- //混选时是否分类显示
362
- classify: {
363
- type: Boolean,
364
- default: true
365
- },
366
- noMatchText: {
367
- type: String,
368
- default: '无匹配数据'
369
- },
370
- emptySerach: Boolean,
371
- reset: Boolean,
372
- useCaseCode: String,
373
- businessData: [String, Array, Object],
374
- inputHeight: {
375
- type: Number,
376
- default: 40
377
- },
378
- min: {
379
- type: Number,
380
- default: 0
381
- },
382
- select: {
383
- type: Boolean,
384
- default: true
385
- }
386
- },
387
- data() {
388
- return {
389
- selected: [],
390
- visible: false,
391
- menuVisibleOnFocus: false,
392
- inputHovering: false,
393
- styles: {},
394
- words: '',
395
- minWidth: '',
396
- options: '',
397
- show: false,
398
- focus: false,
399
- reference: undefined,
400
- timer: null
401
- };
402
- },
403
- computed: {
404
- isRender() {
405
- let useCaseCodes = util.getStorage('useCaseCodes');
406
- if (useCaseCodes && this.useCaseCode) {
407
- return useCaseCodes.indexOf(this.useCaseCode) > -1;
408
- }
409
- return true;
410
- },
411
- isReset() {
412
- return this.reset ? this.visible : true;
413
- },
414
- _elFormItemSize() {
415
- return (this.elFormItem || {}).elFormItemSize;
416
- },
417
- actived() {
418
- if (this.active) {
419
- return this.active;
420
- }
421
- return this.types[0];
422
- },
423
- selectorSize() {
424
- return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
425
- },
426
- selectorDisabled() {
427
- return this.disabled || (this.elForm || {}).disabled;
428
- },
429
- selectedLabel: {
430
- get() {
431
- if (this.selected) {
432
- if (typeof this.selected === 'string') {
433
- return this.selected;
434
- } else if (util.isObject(this.selected)) {
435
- return this.selected[this.labelKey];
436
- } else if (Array.isArray(this.selected)) {
437
- return this.selected
438
- .map((item) => {
439
- return typeof item === 'string' ? item : item[this.labelKey];
440
- })
441
- .join(',');
442
- }
443
- }
444
- return '';
445
- },
446
- set(val) {
447
- this.selected = [val];
448
- this.words = val;
449
- return val;
450
- }
451
- },
452
- currentPlaceholder() {
453
- if (this.selected && this.selected.length) {
454
- return '';
455
- } else if (this.filterable) {
456
- return '输入关键字搜索';
457
- } else {
458
- return this.placeholder;
459
- }
460
- }
461
- },
462
- watch: {
463
- value: {
464
- immediate: true,
465
- deep: true,
466
- handler(val) {
467
- if (util.isExist(val)) {
468
- if (util.isObject(val)) {
469
- this.selected = [val];
470
- } else {
471
- this.selected = val;
472
- }
473
- } else {
474
- this.selected = [];
475
- }
476
- }
477
- },
478
- selected: {
479
- deep: true,
480
- handler(val) {
481
- this.$emit(
482
- 'change',
483
- Array.isArray(val) ? val : [val],
484
- this.businessData
485
- );
486
- if (this.multiple) {
487
- this.resetInputHeight();
488
- }
489
- }
490
- },
491
- words(val) {
492
- if (this.emptySerach || val !== '') {
493
- clearTimeout(this.timer);
494
- this.timer = setTimeout(this.handleSearch, 500);
495
- }
496
- },
497
- mix(val) {
498
- if (val) {
499
- this.getSysParam();
500
- }
501
- }
502
- },
503
- created() {
504
- this.reference = this.$refs.esSelector;
505
- this.mix && this.getSysParam();
506
- },
507
- mounted() {
508
- this.resetInputHeight();
509
- if (this.filterable) {
510
- this.$nextTick(() => {
511
- this.$refs.reference &&
512
- (this.minWidth = this.$refs.reference.$el.children[0].offsetWidth);
513
- });
514
- }
515
- if (this.$refs.openDialog) {
516
- this.$refs.openDialog.$el.parentNode.addEventListener('click', () => {
517
- this.openDialog();
518
- });
519
- }
520
- },
521
- methods: {
522
- getSysParam() {
523
- if (util.getStorage('sysorgname') && util.getStorage('sysdepname')) {
524
- return;
525
- }
526
- util
527
- .ajax({
528
- url: getSysParam,
529
- params: {
530
- paramCode: 'sysorgname,sysdepname'
531
- }
532
- })
533
- .then((res) => {
534
- if (res.rCode === 0) {
535
- let params = res.results.split(',');
536
- sessionStorage.setItem('sysorgname', params[0]);
537
- sessionStorage.setItem('sysdepname', params[1]);
538
- }
539
- });
540
- },
541
- getDep(res) {
542
- if (!this.showFilterListDep) {
543
- return '';
544
- }
545
- const attr = res.attr ? JSON.parse(res.attr) : null;
546
- return attr && attr.depShortName ? `[${attr.depShortName}]` : '';
547
- },
548
- getValueKey(obj) {
549
- return util.isObject(obj) ? obj[this.valueKey] : obj;
550
- },
551
- toggleMenu() {
552
- if (
553
- !this.selectorDisabled &&
554
- !this.readonly &&
555
- !this.filterable &&
556
- this.select
557
- ) {
558
- this.visible = true;
559
- }
560
- },
561
- openDialog() {
562
- if (!this.selectorDisabled && !this.readonly && this.select) {
563
- this.visible = true;
564
- }
565
- },
566
- handleSearch() {
567
- let options = [];
568
- if (this.createable) {
569
- options = [
570
- {
571
- [this.labelKey]: this.words,
572
- [this.valueKey]: this.words
573
- }
574
- ];
575
- }
576
- if (this.filterable) {
577
- let params = {
578
- type: this.actived
579
- };
580
- params[this.keywords] = this.words;
581
- params = util.extend({}, params, this.where);
582
- util
583
- .ajax({
584
- url: this.action,
585
- params: params
586
- })
587
- .then((res) => {
588
- if (res.rCode === 0) {
589
- this.options = [...options, ...res.results];
590
- if (this.selected.length && this.multiple) {
591
- this.selected.forEach((item) => {
592
- let i = util.indexOfObj(this.options, item, this.valueKey);
593
- if (i > -1) {
594
- this.options[i].selected = true;
595
- }
596
- });
597
- }
598
- this.show = true;
599
- }
600
- })
601
- .catch((err) => {
602
- if (err.message && err.message !== 'canceled') {
603
- this.$message.error(err.message);
604
- }
605
- });
606
- } else if (this.createable) {
607
- this.options = options;
608
- this.show = true;
609
- }
610
- },
611
- handleFocus() {
612
- if (this.filterable) {
613
- this.focus = true;
614
- }
615
- },
616
- handleBlur() {
617
- this.focus = false;
618
- },
619
- tabschage(trees, active) {
620
- this.$emit('tabs-change', trees, active);
621
- },
622
- handleClose(res) {
623
- if (!this.multiple && this.selected[0] === this.words) {
624
- this.selected = [];
625
- }
626
- this.show = false;
627
- },
628
- handleSelect(res) {
629
- this.words = '';
630
- if (!res.selected) {
631
- if (this.multiple) {
632
- if (this.selected.length) {
633
- if (!res.selected) {
634
- res.selected = true;
635
- this.selected.push(res);
636
- this.selected = util.arrUnique(this.selected, this.valueKey);
637
- }
638
- } else {
639
- res.selected = true;
640
- this.selected = [res];
641
- }
642
- } else {
643
- res.selected = true;
644
- if (Array.isArray(this.selected)) {
645
- if (
646
- this.selected[0] &&
647
- typeof this.selected[0] !== 'string' &&
648
- this.selected[0][this.valueKey] !== res[this.valueKey]
649
- ) {
650
- this.selected[0].selected = false;
651
- }
652
- this.selected = [res];
653
- } else {
654
- if (
655
- this.selected &&
656
- typeof this.selected !== 'string' &&
657
- this.selected[this.valueKey] !== res[this.valueKey]
658
- ) {
659
- this.selected.selected = false;
660
- }
661
- this.selected = [res];
662
- }
663
- }
664
- }
665
- this.$emit('input', this.selected);
666
- this.$emit('confirm', this.selected);
667
- },
668
- handleConfirm(res) {
669
- this.visible = false;
670
- let val = util.isObject(res) ? [res] : res;
671
- if (this.mix) {
672
- val.forEach((item, index) => {
673
- val[index]._typeName = util.getTypeName(item.stype);
674
- });
675
- }
676
- this.$emit('input', val);
677
- this.$emit('confirm', val, this.businessData);
678
- let inputChildNodes = this.$refs.reference
679
- ? this.$refs.reference.$el.childNodes
680
- : null;
681
- let input = inputChildNodes
682
- ? [].filter.call(inputChildNodes, (item) => item.tagName === 'INPUT')[0]
683
- : null;
684
- if (input) {
685
- input.focus();
686
- input.blur();
687
- }
688
- if (this.reset) {
689
- this.selected = [];
690
- }
691
- },
692
- handleClear() {
693
- this.$emit('input', []);
694
- this.$emit('clear');
695
- },
696
- handleCancel() {
697
- this.visible = false;
698
- this.$emit('cancel');
699
- },
700
- deleteTag(event, item, index) {
701
- event;
702
- item;
703
- index = index === undefined ? 0 : index;
704
- this.selected.length > this.min && this.selected.splice(index, 1);
705
- },
706
- resetInputHeight() {
707
- if (this.collapseTags) return;
708
- this.$nextTick(() => {
709
- if (!this.$refs.reference) return;
710
- const sizeInMap = this.inputHeight;
711
- let height = '';
712
- if (this.selected !== undefined && this.selected.length === 0) {
713
- height = sizeInMap + 'px';
714
- } else if (this.$refs.tags) {
715
- if (this.$refs.tags.clientHeight > sizeInMap) {
716
- height += this.$refs.tags.clientHeight + 2 + 'px';
717
- } else {
718
- height = sizeInMap + 'px';
719
- }
720
- }
721
- if (height) {
722
- if (this.readonly) {
723
- this.$refs.reference.style.height = height;
724
- } else {
725
- let inputChildNodes = this.$refs.reference.$el.childNodes;
726
- let input = [].filter.call(
727
- inputChildNodes,
728
- (item) => item.tagName === 'INPUT'
729
- )[0];
730
- input.style.height = height;
731
- }
732
- }
733
- });
734
- },
735
- getLabel(res) {
736
- let tag = '';
737
- if (this.mix) {
738
- tag = this.classify?util.getTypeName(res.stype) : '';
739
- } else if (this.showFilterListDep) {
740
- tag = this.getDep(res);
741
- }
742
- return (
743
- tag +
744
- (typeof res == 'string'
745
- ? res
746
- : res[this.labelKey]
747
- ? res[this.labelKey]
748
- : res.label || res[this.valueKey])
749
- );
750
- }
751
- },
752
- beforeDestroy() {
753
- this.$el.removeEventListener('keyup', this.doSearch);
754
- if (this.$refs.openDialog) {
755
- this.$refs.openDialog.$el.parentNode.removeEventListener('click', () => {
756
- this.openDialog();
757
- });
758
- }
759
- }
760
- };
761
- </script>
1
+ <template>
2
+ <div
3
+ v-if="isRender"
4
+ class="es-selector"
5
+ ref="esSelector"
6
+ :class="{ 'es-pointer': !readonly && !filterable }"
7
+ v-clickoutside="handleClose"
8
+ >
9
+ <template v-if="form">
10
+ <el-button v-if="button" v-bind="button" @click="openDialog">
11
+ <slot>
12
+ <es-icon v-if="icon" :contents="icon"></es-icon>
13
+ <template v-else>选择</template>
14
+ </slot>
15
+ </el-button>
16
+ <template v-else>
17
+ <div
18
+ :class="[
19
+ selectorSize ? 'el-select--' + selectorSize : 'es-selector-box',
20
+ { 'es-selector-search': filterable }
21
+ ]"
22
+ @click.stop="toggleMenu"
23
+ >
24
+ <div
25
+ v-if="multiple"
26
+ ref="tags"
27
+ class="el-select__tags"
28
+ :class="{ 'es-selector-edit': !readonly }"
29
+ >
30
+ <div
31
+ v-if="collapseTags && selected.length"
32
+ class="es-selector-tags"
33
+ :class="{ 'es-selector-more': selected.length > 1 }"
34
+ >
35
+ <el-tag
36
+ v-for="(item, index) in selected.slice(
37
+ 0,
38
+ collapseTags === true ? 1 : collapseTags
39
+ )"
40
+ :key="getValueKey(item)"
41
+ :closable="
42
+ !selectorDisabled && !readonly && selected.length > min
43
+ "
44
+ type="info"
45
+ disable-transitions
46
+ @close="deleteTag($event, item, index)"
47
+ >
48
+ <span class="el-select__tags-text">{{ getLabel(item) }}</span>
49
+ </el-tag>
50
+
51
+ <el-tag
52
+ v-if="
53
+ selected.length > (collapseTags === true ? 1 : collapseTags)
54
+ "
55
+ :closable="false"
56
+ type="info"
57
+ disable-transitions
58
+ class="es-tags-more"
59
+ >
60
+ <span class="el-select__tags-text"
61
+ >+
62
+ {{
63
+ selected.length - (collapseTags === true ? 1 : collapseTags)
64
+ }}</span
65
+ >
66
+ </el-tag>
67
+ </div>
68
+ <transition-group v-else @after-leave="resetInputHeight">
69
+ <el-tag
70
+ v-for="(item, index) in selected"
71
+ :key="getValueKey(item)"
72
+ :closable="
73
+ !selectorDisabled && !readonly && selected.length > min
74
+ "
75
+ type="info"
76
+ disable-transitions
77
+ @close="deleteTag($event, item, index)"
78
+ >
79
+ <span class="el-select__tags-text">{{ getLabel(item) }}</span>
80
+ </el-tag>
81
+ </transition-group>
82
+ </div>
83
+ <div ref="reference" class="es-input__inner" v-if="readonly">
84
+ <template v-if="!multiple">{{ selectedLabel }}</template>
85
+ </div>
86
+ <template v-else>
87
+ <template v-if="multiple">
88
+ <el-input
89
+ type="text"
90
+ ref="reference"
91
+ autocomplete="off"
92
+ v-model="words"
93
+ :readonly="filterable ? false : true"
94
+ :id="id"
95
+ :placeholder="currentPlaceholder"
96
+ :size="selectorSize"
97
+ :disabled="selectorDisabled"
98
+ :class="{
99
+ 'is-focus': visible,
100
+ 'es-plain': plain,
101
+ 'es-pointer': !filterable,
102
+ 'es-zindex-2': focus
103
+ }"
104
+ :tabindex="tabindex"
105
+ v-popover:popover
106
+ @dblclick.native="openDialog"
107
+ @focus="handleFocus"
108
+ @blur="handleBlur"
109
+ >
110
+ <template slot="append">
111
+ <el-button
112
+ ref="openDialog"
113
+ v-if="filterable || showButton"
114
+ @click.stop="openDialog"
115
+ >
116
+ <slot>
117
+ <es-icon v-if="icon" :contents="icon"></es-icon>
118
+ <template v-else>选择</template>
119
+ </slot>
120
+ </el-button>
121
+ </template>
122
+ </el-input>
123
+ <el-input
124
+ v-model="selectedLabel"
125
+ readonly
126
+ :name="name"
127
+ type="text"
128
+ v-show="false"
129
+ ></el-input>
130
+ </template>
131
+ <el-input
132
+ v-else
133
+ v-model="selectedLabel"
134
+ type="text"
135
+ ref="reference"
136
+ autocomplete="off"
137
+ :clearable="clearable"
138
+ showClearIcon
139
+ :name="name"
140
+ :readonly="filterable ? false : true"
141
+ :active="actived"
142
+ :id="id"
143
+ :placeholder="currentPlaceholder"
144
+ :size="selectorSize"
145
+ :disabled="selectorDisabled"
146
+ :class="{
147
+ 'is-focus': visible,
148
+ 'es-plain': this.plain,
149
+ 'es-pointer': !filterable
150
+ }"
151
+ :tabindex="tabindex"
152
+ @dblclick.native="openDialog"
153
+ @clear="handleClear"
154
+ >
155
+ <template slot="append">
156
+ <el-button
157
+ ref="openDialog"
158
+ v-if="filterable || showButton"
159
+ @click.stop="openDialog"
160
+ >
161
+ <slot>
162
+ <es-icon v-if="icon" :contents="icon"></es-icon>
163
+ <template v-else>选择</template>
164
+ </slot>
165
+ </el-button>
166
+ </template>
167
+ </el-input>
168
+ </template>
169
+ </div>
170
+ <el-popover
171
+ v-model="show"
172
+ placement="bottom-start"
173
+ trigger="manual"
174
+ popper-class="es-selector-popover"
175
+ :width="minWidth"
176
+ :queryParent="true"
177
+ :reference="reference"
178
+ :arrow-offset="20"
179
+ >
180
+ <el-scrollbar
181
+ tag="ul"
182
+ wrap-class="es-selector-dropdown__wrap"
183
+ view-class="es-selector-dropdown__list"
184
+ ref="scrollbar"
185
+ v-show="options.length"
186
+ maxHeight="228"
187
+ >
188
+ <li
189
+ v-for="item in options"
190
+ :key="item.id"
191
+ @click="handleSelect(item)"
192
+ class="es-selector-dropdown-item"
193
+ :class="{ 'es-selected': item.selected }"
194
+ >
195
+ <span>
196
+ {{ getDep(item) }}
197
+ {{ item[labelKey] }}
198
+ </span>
199
+ </li>
200
+ </el-scrollbar>
201
+ <p v-if="options.length == 0" class="el-select-dropdown__empty">
202
+ {{ noMatchText }}
203
+ </p>
204
+ </el-popover>
205
+ </template>
206
+ </template>
207
+ <es-dialog
208
+ v-if="!readonly"
209
+ :title="title"
210
+ :visible.sync="visible"
211
+ :width="width"
212
+ :height="height"
213
+ :css="false"
214
+ :append-to-body="true"
215
+ :close-on-click-modal="false"
216
+ :destroy-on-close="destroyOnClose"
217
+ class="es-selector-dialog"
218
+ >
219
+ <es-selector-panel
220
+ v-if="isReset"
221
+ v-model="selected"
222
+ v-bind="$attrs"
223
+ :multiple="multiple"
224
+ width="100%"
225
+ height="100%"
226
+ :value-key="valueKey"
227
+ :label-key="labelKey"
228
+ :host="host"
229
+ :type="types"
230
+ :mix="mix"
231
+ :isShowLevel3="isShowLevel3"
232
+ @tabschage="tabschage"
233
+ @click.capture="stopd"
234
+ @confirm="handleConfirm"
235
+ @cancel="handleCancel"
236
+ ></es-selector-panel>
237
+ </es-dialog>
238
+ </div>
239
+ </template>
240
+ <script>
241
+ import util from 'eoss-ui/src/utils/util.js';
242
+ import { getSelectorOrgDetail, getSysParam } from 'eoss-ui/src/config/api.js';
243
+ import Clickoutside from 'eoss-element/src/utils/clickoutside';
244
+ export default {
245
+ name: 'EsSelector',
246
+ inheritAttrs: false,
247
+ inject: {
248
+ elForm: {
249
+ default: ''
250
+ },
251
+ elFormItem: {
252
+ default: ''
253
+ }
254
+ },
255
+ directives: { Clickoutside },
256
+ props: {
257
+ form: {
258
+ type: Boolean,
259
+ default: true
260
+ },
261
+ isShowLevel3: {
262
+ type: Boolean,
263
+ default: true
264
+ },
265
+ value: [Array, Object],
266
+ action: {
267
+ type: String,
268
+ default: getSelectorOrgDetail
269
+ },
270
+ host: {
271
+ type: String,
272
+ default: ''
273
+ },
274
+ title: {
275
+ type: String,
276
+ default: '公用选择器'
277
+ },
278
+ width: {
279
+ type: String,
280
+ default: '900px'
281
+ },
282
+ height: {
283
+ type: String,
284
+ default: '560px'
285
+ },
286
+ multiple: {
287
+ type: Boolean,
288
+ default: true
289
+ },
290
+ valueKey: {
291
+ type: String,
292
+ default: 'showid'
293
+ },
294
+ labelKey: {
295
+ type: String,
296
+ default: 'showname'
297
+ },
298
+ valueType: {
299
+ type: String,
300
+ default: 'object',
301
+ validator: function (value) {
302
+ return ['string', 'object'].includes(value);
303
+ }
304
+ },
305
+ size: String,
306
+ id: String,
307
+ disabled: Boolean,
308
+ clearable: {
309
+ type: Boolean,
310
+ default: true
311
+ },
312
+ placeholder: {
313
+ type: String,
314
+ default: '请选择'
315
+ },
316
+ autocomplete: {
317
+ type: String,
318
+ default: 'off'
319
+ },
320
+ name: String,
321
+ readonly: Boolean,
322
+ collapseTags: [Boolean, Number],
323
+ plain: Boolean,
324
+ types: {
325
+ type: Array,
326
+ default() {
327
+ return ['enterprise', 'person'];
328
+ }
329
+ },
330
+ tabindex: {
331
+ type: [String, Number],
332
+ default: -1
333
+ },
334
+ //是否显示搜索框
335
+ filterable: Boolean,
336
+ //搜索列表是否显示部门信息
337
+ showFilterListDep: {
338
+ type: Boolean,
339
+ default: true
340
+ },
341
+ //是否根据搜索值创建新的数据
342
+ createable: Boolean,
343
+ showButton: Boolean,
344
+ button: Object,
345
+ icon: String,
346
+ active: String,
347
+ keywords: {
348
+ type: String,
349
+ default: 'namelike'
350
+ },
351
+ //输入框搜索参数
352
+ where: {
353
+ type: Object,
354
+ default() {
355
+ return {
356
+ mid: '0-0-0-0-0'
357
+ };
358
+ }
359
+ },
360
+ //混选
361
+ mix: Boolean,
362
+ //混选时是否分类显示
363
+ classify: {
364
+ type: Boolean,
365
+ default: true
366
+ },
367
+ noMatchText: {
368
+ type: String,
369
+ default: '无匹配数据'
370
+ },
371
+ emptySerach: Boolean,
372
+ reset: Boolean,
373
+ useCaseCode: String,
374
+ businessData: [String, Array, Object],
375
+ inputHeight: {
376
+ type: Number,
377
+ default: 40
378
+ },
379
+ min: {
380
+ type: Number,
381
+ default: 0
382
+ },
383
+ select: {
384
+ type: Boolean,
385
+ default: true
386
+ },
387
+ //弹窗关闭时是否销毁子组件
388
+ destroyOnClose: Boolean
389
+ },
390
+ data() {
391
+ return {
392
+ selected: [],
393
+ visible: false,
394
+ menuVisibleOnFocus: false,
395
+ inputHovering: false,
396
+ styles: {},
397
+ words: '',
398
+ minWidth: '',
399
+ options: '',
400
+ show: false,
401
+ focus: false,
402
+ reference: undefined,
403
+ timer: null
404
+ };
405
+ },
406
+ computed: {
407
+ isRender() {
408
+ let useCaseCodes = util.getStorage('useCaseCodes');
409
+ if (useCaseCodes && this.useCaseCode) {
410
+ return useCaseCodes.indexOf(this.useCaseCode) > -1;
411
+ }
412
+ return true;
413
+ },
414
+ isReset() {
415
+ return this.reset ? this.visible : true;
416
+ },
417
+ _elFormItemSize() {
418
+ return (this.elFormItem || {}).elFormItemSize;
419
+ },
420
+ actived() {
421
+ if (this.active) {
422
+ return this.active;
423
+ }
424
+ return this.types[0];
425
+ },
426
+ selectorSize() {
427
+ return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
428
+ },
429
+ selectorDisabled() {
430
+ return this.disabled || (this.elForm || {}).disabled;
431
+ },
432
+ selectedLabel: {
433
+ get() {
434
+ if (this.selected) {
435
+ if (typeof this.selected === 'string') {
436
+ return this.selected;
437
+ } else if (util.isObject(this.selected)) {
438
+ return this.selected[this.labelKey];
439
+ } else if (Array.isArray(this.selected)) {
440
+ return this.selected
441
+ .map((item) => {
442
+ return typeof item === 'string' ? item : item[this.labelKey];
443
+ })
444
+ .join(',');
445
+ }
446
+ }
447
+ return '';
448
+ },
449
+ set(val) {
450
+ this.selected = [val];
451
+ this.words = val;
452
+ return val;
453
+ }
454
+ },
455
+ currentPlaceholder() {
456
+ if (this.selected && this.selected.length) {
457
+ return '';
458
+ } else if (this.filterable) {
459
+ return '输入关键字搜索';
460
+ } else {
461
+ return this.placeholder;
462
+ }
463
+ }
464
+ },
465
+ watch: {
466
+ value: {
467
+ immediate: true,
468
+ deep: true,
469
+ handler(val) {
470
+ if (util.isExist(val)) {
471
+ if (util.isObject(val)) {
472
+ this.selected = [val];
473
+ } else {
474
+ this.selected = val;
475
+ }
476
+ } else {
477
+ this.selected = [];
478
+ }
479
+ }
480
+ },
481
+ selected: {
482
+ deep: true,
483
+ handler(val) {
484
+ this.$emit(
485
+ 'change',
486
+ Array.isArray(val) ? val : [val],
487
+ this.businessData
488
+ );
489
+ if (this.multiple) {
490
+ this.resetInputHeight();
491
+ }
492
+ }
493
+ },
494
+ words(val) {
495
+ if (this.emptySerach || val !== '') {
496
+ clearTimeout(this.timer);
497
+ this.timer = setTimeout(this.handleSearch, 500);
498
+ }
499
+ },
500
+ mix(val) {
501
+ if (val) {
502
+ this.getSysParam();
503
+ }
504
+ }
505
+ },
506
+ created() {
507
+ this.reference = this.$refs.esSelector;
508
+ this.mix && this.getSysParam();
509
+ },
510
+ mounted() {
511
+ this.resetInputHeight();
512
+ if (this.filterable) {
513
+ this.$nextTick(() => {
514
+ this.$refs.reference &&
515
+ (this.minWidth = this.$refs.reference.$el.children[0].offsetWidth);
516
+ });
517
+ }
518
+ if (this.$refs.openDialog) {
519
+ this.$refs.openDialog.$el.parentNode.addEventListener('click', () => {
520
+ this.openDialog();
521
+ });
522
+ }
523
+ },
524
+ methods: {
525
+ getSysParam() {
526
+ if (util.getStorage('sysorgname') && util.getStorage('sysdepname')) {
527
+ return;
528
+ }
529
+ util
530
+ .ajax({
531
+ url: getSysParam,
532
+ params: {
533
+ paramCode: 'sysorgname,sysdepname'
534
+ }
535
+ })
536
+ .then((res) => {
537
+ if (res.rCode === 0) {
538
+ let params = res.results.split(',');
539
+ sessionStorage.setItem('sysorgname', params[0]);
540
+ sessionStorage.setItem('sysdepname', params[1]);
541
+ }
542
+ });
543
+ },
544
+ getDep(res) {
545
+ if (!this.showFilterListDep) {
546
+ return '';
547
+ }
548
+ const attr = res.attr ? JSON.parse(res.attr) : null;
549
+ return attr && attr.depShortName ? `[${attr.depShortName}]` : '';
550
+ },
551
+ getValueKey(obj) {
552
+ return util.isObject(obj) ? obj[this.valueKey] : obj;
553
+ },
554
+ toggleMenu() {
555
+ if (
556
+ !this.selectorDisabled &&
557
+ !this.readonly &&
558
+ !this.filterable &&
559
+ this.select
560
+ ) {
561
+ this.visible = true;
562
+ }
563
+ },
564
+ openDialog() {
565
+ if (!this.selectorDisabled && !this.readonly && this.select) {
566
+ this.visible = true;
567
+ }
568
+ },
569
+ handleSearch() {
570
+ let options = [];
571
+ if (this.createable) {
572
+ options = [
573
+ {
574
+ [this.labelKey]: this.words,
575
+ [this.valueKey]: this.words
576
+ }
577
+ ];
578
+ }
579
+ if (this.filterable) {
580
+ let params = {
581
+ type: this.actived
582
+ };
583
+ params[this.keywords] = this.words;
584
+ params = util.extend({}, params, this.where);
585
+ util
586
+ .ajax({
587
+ url: this.action,
588
+ params: params
589
+ })
590
+ .then((res) => {
591
+ if (res.rCode === 0) {
592
+ this.options = [...options, ...res.results];
593
+ if (this.selected.length && this.multiple) {
594
+ this.selected.forEach((item) => {
595
+ let i = util.indexOfObj(this.options, item, this.valueKey);
596
+ if (i > -1) {
597
+ this.options[i].selected = true;
598
+ }
599
+ });
600
+ }
601
+ this.show = true;
602
+ }
603
+ })
604
+ .catch((err) => {
605
+ if (err.message && err.message !== 'canceled') {
606
+ this.$message.error(err.message);
607
+ }
608
+ });
609
+ } else if (this.createable) {
610
+ this.options = options;
611
+ this.show = true;
612
+ }
613
+ },
614
+ handleFocus() {
615
+ if (this.filterable) {
616
+ this.focus = true;
617
+ }
618
+ },
619
+ handleBlur() {
620
+ this.focus = false;
621
+ },
622
+ tabschage(trees, active) {
623
+ this.$emit('tabs-change', trees, active);
624
+ },
625
+ handleClose(res) {
626
+ if (!this.multiple && this.selected[0] === this.words) {
627
+ this.selected = [];
628
+ }
629
+ this.show = false;
630
+ },
631
+ handleSelect(res) {
632
+ this.words = '';
633
+ if (!res.selected) {
634
+ if (this.multiple) {
635
+ if (this.selected.length) {
636
+ if (!res.selected) {
637
+ res.selected = true;
638
+ this.selected.push(res);
639
+ this.selected = util.arrUnique(this.selected, this.valueKey);
640
+ }
641
+ } else {
642
+ res.selected = true;
643
+ this.selected = [res];
644
+ }
645
+ } else {
646
+ res.selected = true;
647
+ if (Array.isArray(this.selected)) {
648
+ if (
649
+ this.selected[0] &&
650
+ typeof this.selected[0] !== 'string' &&
651
+ this.selected[0][this.valueKey] !== res[this.valueKey]
652
+ ) {
653
+ this.selected[0].selected = false;
654
+ }
655
+ this.selected = [res];
656
+ } else {
657
+ if (
658
+ this.selected &&
659
+ typeof this.selected !== 'string' &&
660
+ this.selected[this.valueKey] !== res[this.valueKey]
661
+ ) {
662
+ this.selected.selected = false;
663
+ }
664
+ this.selected = [res];
665
+ }
666
+ }
667
+ }
668
+ this.$emit('input', this.selected);
669
+ this.$emit('confirm', this.selected);
670
+ },
671
+ handleConfirm(res) {
672
+ this.visible = false;
673
+ let val = util.isObject(res) ? [res] : res;
674
+ if (this.mix) {
675
+ val.forEach((item, index) => {
676
+ val[index]._typeName = util.getTypeName(item.stype);
677
+ });
678
+ }
679
+ this.$emit('input', val);
680
+ this.$emit('confirm', val, this.businessData);
681
+ let inputChildNodes = this.$refs.reference
682
+ ? this.$refs.reference.$el.childNodes
683
+ : null;
684
+ let input = inputChildNodes
685
+ ? [].filter.call(inputChildNodes, (item) => item.tagName === 'INPUT')[0]
686
+ : null;
687
+ if (input) {
688
+ input.focus();
689
+ input.blur();
690
+ }
691
+ if (this.reset) {
692
+ this.selected = [];
693
+ }
694
+ },
695
+ handleClear() {
696
+ this.$emit('input', []);
697
+ this.$emit('clear');
698
+ },
699
+ handleCancel() {
700
+ this.visible = false;
701
+ this.$emit('cancel');
702
+ },
703
+ deleteTag(event, item, index) {
704
+ event;
705
+ item;
706
+ index = index === undefined ? 0 : index;
707
+ this.selected.length > this.min && this.selected.splice(index, 1);
708
+ },
709
+ resetInputHeight() {
710
+ if (this.collapseTags) return;
711
+ this.$nextTick(() => {
712
+ if (!this.$refs.reference) return;
713
+ const sizeInMap = this.inputHeight;
714
+ let height = '';
715
+ if (this.selected !== undefined && this.selected.length === 0) {
716
+ height = sizeInMap + 'px';
717
+ } else if (this.$refs.tags) {
718
+ if (this.$refs.tags.clientHeight > sizeInMap) {
719
+ height += this.$refs.tags.clientHeight + 2 + 'px';
720
+ } else {
721
+ height = sizeInMap + 'px';
722
+ }
723
+ }
724
+ if (height) {
725
+ if (this.readonly) {
726
+ this.$refs.reference.style.height = height;
727
+ } else {
728
+ let inputChildNodes = this.$refs.reference.$el.childNodes;
729
+ let input = [].filter.call(
730
+ inputChildNodes,
731
+ (item) => item.tagName === 'INPUT'
732
+ )[0];
733
+ input.style.height = height;
734
+ }
735
+ }
736
+ });
737
+ },
738
+ getLabel(res) {
739
+ let tag = '';
740
+ if (this.mix) {
741
+ tag = this.classify ? util.getTypeName(res.stype) : '';
742
+ } else if (this.showFilterListDep) {
743
+ tag = this.getDep(res);
744
+ }
745
+ return (
746
+ tag +
747
+ (typeof res == 'string'
748
+ ? res
749
+ : res[this.labelKey]
750
+ ? res[this.labelKey]
751
+ : res.label || res[this.valueKey])
752
+ );
753
+ }
754
+ },
755
+ beforeDestroy() {
756
+ this.$el.removeEventListener('keyup', this.doSearch);
757
+ if (this.$refs.openDialog) {
758
+ this.$refs.openDialog.$el.parentNode.removeEventListener('click', () => {
759
+ this.openDialog();
760
+ });
761
+ }
762
+ }
763
+ };
764
+ </script>