1
+ <template >
2
+ <view class =" multi-picker" >
3
+ <view class =" form" >
4
+ <view class =" item" >
5
+ <!-- 下拉框多选 -->
6
+ <view :class =" ['select', selectedValues.length > 0 ? 'selected' : '']"
7
+ @tap.stop =" openMultiple(); isShow = true" >
8
+ {{ selectedTexts || '请选择' }}
9
+ </view >
10
+ </view >
11
+ </view >
12
+
13
+ <view class =" cover" v-show =" !disabled && isShow" >
14
+ <view class =" panel" >
15
+ <view class =" button" >
16
+ <text @tap.stop =" cancel" >取消</text >
17
+ <text >{{ title }}</text >
18
+ <text @tap.stop =" confrim" >确定</text >
19
+ </view >
20
+ <div class =" option" >
21
+ <view class =" checked-all item" v-show =" checkedAll" @tap.stop =" onCheckedAll"
22
+ :class =" [isCheckedAll ? 'checked' : '']" >
23
+ 全选
24
+ <icon v-show =" isCheckedAll" type =" success_no_circle" class =" icon" size =" 16" />
25
+ </view >
26
+ <checkbox-group >
27
+ <view class =" item" v-for =" (item, index) in list" :class =" [item.selected ? 'checked' : '']"
28
+ @tap.stop =" onChange(item, index)" :disabled =" item.disabled" >
29
+ {{ item.text }}
30
+ <icon v-show =" item.selected" class =" icon" type =" success_no_circle" size =" 16"
31
+ :color =" item.disabled ? 'grey' : '#2D8DFF'" />
32
+ </view >
33
+ </checkbox-group >
34
+ </div >
35
+ </view >
36
+ </view >
37
+ </view >
38
+ </template >
39
+
40
+ <script >
41
+ export default {
42
+ props: {
43
+ items: { // 多选列表初始值
44
+ type: Array ,
45
+ default : () => []
46
+ },
47
+ show: { // 多选列表是否显示
48
+ type: Boolean ,
49
+ default: false
50
+ },
51
+ disabled: { // 组件是否可用
52
+ type: Boolean ,
53
+ default: false
54
+ },
55
+ values: { // 组件默认选中code集合
56
+ type: String ,
57
+ default: " "
58
+ },
59
+ text: { // 组件默认选中显示文本
60
+ type: String ,
61
+ default: " "
62
+ },
63
+ title: { // 组件选择器标题
64
+ type: String ,
65
+ default: " "
66
+ },
67
+ checkedAll: {// 是否启用全选功能
68
+ type: Boolean ,
69
+ default: true
70
+ }
71
+ },
72
+ data () {
73
+ return {
74
+ selectedTexts: " " , // 已选集合文本
75
+ selectedValues: [], // 已选集合code
76
+ selectedIndex: [], // 已选集合下标
77
+ list: [], // 全量选项集合
78
+ isShow: this .show , // 组件是否显示
79
+ isCheckedAll: false // 是否已全选
80
+ }
81
+ },
82
+ watch: {
83
+ show: {
84
+ handler (val , old ) {
85
+ this .isShow = this .show ;
86
+ },
87
+ immediate: true
88
+ },
89
+ checkedAll (val ) {
90
+ if (! val)
91
+ val = false ;
92
+ this .onCheckedAll ();
93
+ },
94
+ values (val ) {
95
+ if (! val)
96
+ return ;
97
+ let codes = val .split (" ," );
98
+ this .selectedValues = Object .assign ([], codes);
99
+ this .openMultiple ();
100
+ }
101
+ },
102
+ methods: {
103
+ /**
104
+ * 初始化弹出框数据列表显示
105
+ */
106
+ openMultiple () {
107
+ this .selectedTexts = " " ;
108
+ this .selectedIndex = [];
109
+ this .isCheckedAll = true ;
110
+ this .items .forEach ((item , i ) => {
111
+ if (this .selectedValues && this .selectedValues .indexOf (item .code ) > - 1 ) {
112
+ this .$set (item, " selected" , true );
113
+ this .selectedTexts += (this .selectedTexts ? " 、" : " " ) + item .text ;
114
+ this .selectedIndex .push (i);
115
+ } else {
116
+ this .$set (item, " selected" , false );
117
+ this .isCheckedAll = false ;
118
+ }
119
+ });
120
+ this .list = Object .assign ([], this .items );
121
+ },
122
+ /**
123
+ * 改变选项选中状态事件
124
+ * @param {Object} item
125
+ * @param {Number} i
126
+ */
127
+ onChange (item , i ) {
128
+ if (item .disabled )
129
+ return ;
130
+ this .list [i].selected = ! this .list [i].selected ;
131
+ if (this .isCheckedAll && ! this .list [i].selected ) {
132
+ this .isCheckedAll = false ;
133
+ } else {
134
+ let isCheckedAll = this .isCheckedAll ;
135
+ try {
136
+ this .isCheckedAll = true ;
137
+ for (let j = 0 ; j < this .list .length ; j++ ) {
138
+ if (! this .list [j].selected ) {
139
+ this .isCheckedAll = false ;
140
+ break ;
141
+ }
142
+ }
143
+ } catch (e) {
144
+ this .isCheckedAll = isCheckedAll;
145
+ console .error (e);
146
+ }
147
+
148
+ }
149
+ this .$emit (" onChange" , { item: item, i: i });
150
+ },
151
+ /**
152
+ * 取消事件
153
+ * @param {Object} event
154
+ */
155
+ cancel (event ) {
156
+ if (! this .list || this .list .length == 0 )
157
+ return ;
158
+ this .list .forEach ((item , i ) => {
159
+ if (this .selectedIndex .indexOf (i) > - 1 ) {
160
+ this .$set (item, " selected" , true );
161
+ } else {
162
+ this .$set (item, " selected" , false );
163
+ }
164
+ })
165
+ this .isShow = false ;
166
+ this .$emit (" cancel" , event );
167
+ },
168
+ /**
169
+ * 确定事件
170
+ * @param {Object} event
171
+ */
172
+ confrim (event ) {
173
+ if (! this .list && this .list .length > 0 )
174
+ return ;
175
+ this .selectedValues = [];
176
+ this .selectedTexts = " " ;
177
+ this .selectedIndex = [];
178
+ let selected = [];
179
+ for (let i = 0 ; i < this .list .length ; i++ ) {
180
+ let item = this .list [i];
181
+ if (item .selected ) {
182
+ selected .push (item);
183
+ if (this .selectedValues .indexOf (item .code ) == - 1 )
184
+ this .selectedValues .push (item .code );
185
+ if (this .selectedTexts .indexOf (item .text ) == - 1 ) {
186
+ if (! this .selectedTexts )
187
+ this .selectedTexts += item .text ;
188
+ else
189
+ this .selectedTexts += " 、" + item .text ;
190
+ }
191
+ if (this .selectedIndex .indexOf (i) == - 1 )
192
+ this .selectedIndex .push (i);
193
+ }
194
+ }
195
+ event .currentTarget .dataset .multiPicker = {
196
+ values: this .selectedValues ,
197
+ texts: this .selectedTexts ,
198
+ indnexs: this .selectedIndex ,
199
+ selected: selected
200
+ };
201
+ this .isShow = false ;
202
+ this .$emit (" confrim" , event );
203
+ },
204
+ /**
205
+ * 全选事件
206
+ */
207
+ onCheckedAll () {
208
+ for (let i = 0 ; i < this .list .length ; i++ ) {
209
+ if (this .list [i].disabled )
210
+ continue ;
211
+ this .list [i].selected = ! this .isCheckedAll ;
212
+ }
213
+ this .isCheckedAll = ! this .isCheckedAll ;
214
+ }
215
+ }
216
+ }
217
+ </script >
218
+
219
+ <style scoped lang="scss">
220
+ .multi-picker {
221
+ position : relative ;
222
+
223
+ .form {
224
+ width : 100% ;
225
+ box-sizing : border-box ;
226
+
227
+ .item {
228
+ width : 100% ;
229
+
230
+ .select {
231
+ width : 100% ;
232
+ padding-left : 9px ;
233
+ padding-right : 9px ;
234
+ box-sizing : border-box ;
235
+ color : #CCCCCC ;
236
+
237
+ & .selected {
238
+ color : black ;
239
+ }
240
+ }
241
+ }
242
+ }
243
+
244
+ .cover {
245
+ z-index : 2 ;
246
+ width : 100% ;
247
+ height : 100% ;
248
+ position : fixed ;
249
+ top : 0 ;
250
+ left : 0 ;
251
+ right : 0 ;
252
+ bottom : 0 ;
253
+ background-color : rgba (10 , 10 , 10 , 0.4 );
254
+
255
+ .panel {
256
+ width : 100% ;
257
+ height : 600 rpx;
258
+ position : fixed ;
259
+ background-color : rgba (255 , 255 , 255 , 1 );
260
+ bottom : 0 ;
261
+ left : 0 ;
262
+ right : 0 ;
263
+
264
+ .button {
265
+ width : 100% ;
266
+ height : 80 rpx;
267
+ border-bottom : #aaaaaa solid 1 rpx;
268
+ padding-left : 20 rpx;
269
+ padding-right : 20 rpx;
270
+ box-sizing : border-box ;
271
+ line-height : 80 rpx;
272
+ text-align : center ;
273
+ color : #888888 ;
274
+
275
+ text :first-child {
276
+ color : #888888 ;
277
+ float : left ;
278
+ }
279
+
280
+ text :last-child {
281
+ color : rgb (77 , 157 , 254 );
282
+ float : right ;
283
+ }
284
+ }
285
+
286
+ .option {
287
+ width : 100% ;
288
+ height : 500 rpx;
289
+ overflow-y : scroll ;
290
+ padding-left : 20 rpx;
291
+ padding-right : 20 rpx;
292
+ margin-bottom : auto ;
293
+ margin-top : auto ;
294
+ box-sizing : border-box ;
295
+
296
+ .item {
297
+ position : relative ;
298
+ border-bottom : 1 rpx solid #CCCCCC ;
299
+ width : 100% ;
300
+ height : 60 rpx;
301
+ line-height : 60 rpx;
302
+ text-align : center ;
303
+
304
+ .icon {
305
+ position : absolute ;
306
+ top : 50% ;
307
+ right : 10 rpx;
308
+ transform : translateY (-50% );
309
+ }
310
+
311
+ & .checked {
312
+ color : #2D8DFF ;
313
+ }
314
+
315
+ }
316
+ }
317
+ }
318
+ }
319
+ }
320
+ </style >
0 commit comments