Commit fb748734ca33c189fdde516d9af1e32f7a851337

Authored by mullins
1 parent 058f060df9
Exists in master

首页部分逻辑修改

src/components/HMFilterDropdown/HMFilterDropdown.vue
1 1 <template>
2   - <view class="HMfilterDropdown" @touchmove.stop.prevent="discard" @tap.stop="discard">
3   - <view class="nav">
4   - <block v-for="(item,index) in menu" :key="index">
5   - <view
6   - class="first-menu"
7   - :class="{'on':showPage==index || on[index] === 1}"
8   - @tap="togglePage(index)"
9   - v-if="!item.isNoPull"
10   - >
11   - <text class="name">{{item.name}}</text>
12   - <text
13   - class="iconfont triangle"
14   - :style="'transform:rotate('+triangleDeg[index]+'deg);'"
15   - ></text>
16   - </view>
17   - <view
18   - class="first-menu"
19   - :class="{'on':showPage==index || on[index] === 1}"
20   - @tap="showAll()"
21   - v-else
22   - >
23   - <text class="name">{{item.name}}</text>
24   - </view>
25   - </block>
26   - </view>
27   - <view class="mask" :class="{'show':isShowMask,'hide':maskVisibility!=true}" @tap="togglePage(showPage)"></view>
28   - <block v-for="(page,page_index) in subData" :key="page_index">
29   - <view class="sub-menu-class" :class="{'show':showPage==page_index,'hide':pageState[page_index]!=true}">
30   - <block v-if="page.type=='hierarchy'&& page.submenu.length>0">
31   - <scroll-view class="sub-menu-list" :class="[activeMenuArr[page_index].length>1?'first':'alone']"
32   - :scroll-y="true" :scroll-into-view="'first_id'+firstScrollInto">
33   - <block v-for="(sub,index) in page.submenu" :key="index">
34   - <view class="sub-menu" :id="'first_id'+index" :class="{'on':activeMenuArr[page_index][0]==index}" @tap="selectHierarchyMenu(page_index,index,null,null)">
35   - <view class="menu-name">
36   - <text>{{sub.name}}</text>
37   - <text class="iconfont selected"></text>
38   - </view>
39   - </view>
40   - </block>
41   - </scroll-view>
42   - <block v-for="(sub,index) in page.submenu" :key="index">
43   - <scroll-view class="sub-menu-list not-first" :scroll-y="true" v-if="activeMenuArr[page_index][0]==index&&sub.submenu.length>0"
44   - :scroll-into-view="'second_id'+secondScrollInto">
45   - <block v-for="(sub_second,second_index) in sub.submenu" :key="second_index">
46   - <view class="sub-menu" :id="'second_id'+second_index" :class="{'on':activeMenuArr[page_index][1]==second_index}">
47   - <view class="menu-name" @tap="selectHierarchyMenu(page_index,activeMenuArr[page_index][0],second_index,null)">
48   - <text>{{sub_second.name}}</text>
49   - <text class="iconfont selected"></text>
50   - </view>
51   - <view class="more-sub-menu" v-if="sub_second.submenu&&sub.submenu.length>0&&sub_second.submenu.length>0">
52   - <block v-for="(sub2,sub2_index) in sub_second.submenu" :key="sub2_index">
53   - <text v-if="sub_second.showAllSub || (sub2_index<8)" :class="{'on':activeMenuArr[page_index][1]==second_index&&activeMenuArr[page_index][2]==sub2_index}"
54   - @tap="selectHierarchyMenu(page_index,activeMenuArr[page_index][0],second_index,sub2_index)">{{sub2.name}}</text>
55   - <text v-if="sub_second.showAllSub!=true && sub2_index==8 && sub_second.submenu.length>9" @tap="showMoreSub(second_index)">更多<text
56   - class="iconfont triangle"></text></text>
57   - </block>
58   - </view>
59   - </view>
60   - </block>
61   - </scroll-view>
62   - </block>
63   - </block>
64   - <block v-if="page.type=='filter'||page.type=='checkbox'">
65   - <view class="filter">
66   - <scroll-view class="menu-box" :scroll-y="true">
67   - <view class="box" v-for="(box,box_index) in page.submenu" :key="box_index">
68   - <view class="title">{{box.name}}</view>
69   - <view class="labels">
70   - <view v-for="(label,label_index) in box.submenu" :key="label_index" @tap="selectFilterLabel(page_index,box_index,label_index)"
71   - :class="{'on':label.selected}">{{label.name}}</view>
72   - </view>
73   - </view>
74   - </scroll-view>
75   - <view class="btn-box">
76   - <view class="reset" @tap="resetFilterData(page_index)">重置</view>
77   - <view class="submit" @tap="setFilterData(page_index)">确定</view>
78   - </view>
79   - </view>
80   - </block>
81   - <block v-if="page.type=='radio'">
82   - <view class="filter">
83   - <scroll-view class="menu-box" :scroll-y="true">
84   - <view class="box" v-for="(box,box_index) in page.submenu" :key="box_index">
85   - <view class="title">{{box.name}}</view>
86   - <view class="labels">
87   - <view v-for="(label,label_index) in box.submenu" :key="label_index" @tap="selectRadioLabel(page_index,box_index,label_index)"
88   - :class="{'on':label.selected}">{{label.name}}</view>
89   - </view>
90   - </view>
91   - </scroll-view>
92   - <view class="btn-box">
93   - <view class="reset" @tap="resetFilterData(page_index)">重置</view>
94   - <view class="submit" @tap="setFilterData(page_index)">确定</view>
95   - </view>
96   - </view>
97   - </block>
98   - </view>
99   - </block>
100   - </view>
  2 + <view
  3 + class="HMfilterDropdown"
  4 + @touchmove.stop.prevent="discard"
  5 + @tap.stop="discard"
  6 + >
  7 + <view class="nav">
  8 + <block
  9 + v-for="(item,index) in menu"
  10 + :key="index"
  11 + >
  12 + <view
  13 + class="first-menu"
  14 + :class="{'on':showPage==index || on[index] === 1}"
  15 + @tap="togglePage(index)"
  16 + v-if="!item.isNoPull"
  17 + >
  18 + <text class="name">{{item.name}}</text>
  19 + <text
  20 + class="iconfont triangle"
  21 + :style="'transform:rotate('+triangleDeg[index]+'deg);'"
  22 + ></text>
  23 + </view>
  24 + <view
  25 + class="first-menu"
  26 + :class="{'on':showPage==index || on[index] === 1}"
  27 + @tap="showAll()"
  28 + v-else
  29 + >
  30 + <text class="name">{{item.name}}</text>
  31 + </view>
  32 + </block>
  33 + </view>
  34 + <view
  35 + class="mask"
  36 + :class="{'show':isShowMask,'hide':maskVisibility!=true}"
  37 + @tap="togglePage(showPage)"
  38 + ></view>
  39 + <block
  40 + v-for="(page,page_index) in subData"
  41 + :key="page_index"
  42 + >
  43 + <view
  44 + class="sub-menu-class"
  45 + :class="{'show':showPage==page_index,'hide':pageState[page_index]!=true}"
  46 + >
  47 + <block v-if="page.type=='hierarchy'&& page.submenu.length>0">
  48 + <scroll-view
  49 + class="sub-menu-list"
  50 + :class="[activeMenuArr[page_index].length>1?'first':'alone']"
  51 + :scroll-y="true"
  52 + :scroll-into-view="'first_id'+firstScrollInto"
  53 + >
  54 + <block
  55 + v-for="(sub,index) in page.submenu"
  56 + :key="index"
  57 + >
  58 + <view
  59 + class="sub-menu"
  60 + :id="'first_id'+index"
  61 + :class="{'on':activeMenuArr[page_index][0]==index}"
  62 + @tap="selectHierarchyMenu(page_index,index,null,null)"
  63 + >
  64 + <view class="menu-name">
  65 + <text>{{sub.name}}</text>
  66 + <text class="iconfont selected"></text>
  67 + </view>
  68 + </view>
  69 + </block>
  70 + </scroll-view>
  71 + <block
  72 + v-for="(sub,index) in page.submenu"
  73 + :key="index"
  74 + >
  75 + <scroll-view
  76 + class="sub-menu-list not-first"
  77 + :scroll-y="true"
  78 + v-if="activeMenuArr[page_index][0]==index&&sub.submenu.length>0"
  79 + :scroll-into-view="'second_id'+secondScrollInto"
  80 + >
  81 + <block
  82 + v-for="(sub_second,second_index) in sub.submenu"
  83 + :key="second_index"
  84 + >
  85 + <view
  86 + class="sub-menu"
  87 + :id="'second_id'+second_index"
  88 + :class="{'on':activeMenuArr[page_index][1]==second_index}"
  89 + >
  90 + <view
  91 + class="menu-name"
  92 + @tap="selectHierarchyMenu(page_index,activeMenuArr[page_index][0],second_index,null)"
  93 + >
  94 + <text>{{sub_second.name}}</text>
  95 + <text class="iconfont selected"></text>
  96 + </view>
  97 + <view
  98 + class="more-sub-menu"
  99 + v-if="sub_second.submenu&&sub.submenu.length>0&&sub_second.submenu.length>0"
  100 + >
  101 + <block
  102 + v-for="(sub2,sub2_index) in sub_second.submenu"
  103 + :key="sub2_index"
  104 + >
  105 + <text
  106 + v-if="sub_second.showAllSub || (sub2_index<8)"
  107 + :class="{'on':activeMenuArr[page_index][1]==second_index&&activeMenuArr[page_index][2]==sub2_index}"
  108 + @tap="selectHierarchyMenu(page_index,activeMenuArr[page_index][0],second_index,sub2_index)"
  109 + >{{sub2.name}}</text>
  110 + <text
  111 + v-if="sub_second.showAllSub!=true && sub2_index==8 && sub_second.submenu.length>9"
  112 + @tap="showMoreSub(second_index)"
  113 + >更多<text class="iconfont triangle"></text></text>
  114 + </block>
  115 + </view>
  116 + </view>
  117 + </block>
  118 + </scroll-view>
  119 + </block>
  120 + </block>
  121 + <block v-if="page.type=='filter' || page.type=='checkbox'">
  122 + <view class="filter">
  123 + <scroll-view
  124 + class="menu-box"
  125 + :scroll-y="true"
  126 + >
  127 + <view
  128 + class="box"
  129 + v-for="(box,box_index) in page.submenu"
  130 + :key="box_index"
  131 + >
  132 + <view class="title">{{box.name}}</view>
  133 + <view class="labels">
  134 + <view
  135 + v-for="(label,label_index) in box.submenu"
  136 + :key="label_index"
  137 + @tap="selectFilterLabel(page_index, box_index, label_index)"
  138 + :class="{'on': label.selected}"
  139 + >{{label.name}}</view>
  140 + </view>
  141 + </view>
  142 + </scroll-view>
  143 + <view class="btn-box">
  144 + <view
  145 + class="reset"
  146 + @tap="resetFilterData(page_index)"
  147 + >重置</view>
  148 + <view
  149 + class="submit"
  150 + @tap="setFilterData(page_index)"
  151 + >确定</view>
  152 + </view>
  153 + </view>
  154 + </block>
  155 + <block v-if="page.type=='radio'">
  156 + <view class="filter">
  157 + <scroll-view
  158 + class="menu-box"
  159 + :scroll-y="true"
  160 + >
  161 + <view
  162 + class="box"
  163 + v-for="(box,box_index) in page.submenu"
  164 + :key="box_index"
  165 + >
  166 + <view class="title">{{box.name}}</view>
  167 + <view class="labels">
  168 + <view
  169 + v-for="(label,label_index) in box.submenu"
  170 + :key="label_index"
  171 + @tap="selectRadioLabel(page_index,box_index,label_index)"
  172 + :class="{'on':label.selected}"
  173 + >{{label.name}}</view>
  174 + </view>
  175 + </view>
  176 + </scroll-view>
  177 + <view class="btn-box">
  178 + <view
  179 + class="reset"
  180 + @tap="resetFilterData(page_index)"
  181 + >重置</view>
  182 + <view
  183 + class="submit"
  184 + @tap="setFilterData(page_index)"
  185 + >确定</view>
  186 + </view>
  187 + </view>
  188 + </block>
  189 + </view>
  190 + </block>
  191 + </view>
101 192 </template>
102 193 <script>
103   - export default {
104   - data() {
105   - return {
106   - subData: [], //菜单数据
107   - menu: [], //顶部横条数据
108   - showPage: -1, //菜单页面显示/隐藏动画控制
109   - pageState: [], //页面的状态
110   - activeMenuArr: [], //UI状态
111   - shadowActiveMenuArr: [], //记录选中
112   - defaultActive:[],
113   - triangleDeg: [], //小三角形的翻转动画控制
114   - isShowMask: false, //遮罩层显示/隐藏动画控制
115   - maskVisibility: false, //遮罩层显示/隐藏状态
116   - //滚动区域定位
117   - firstScrollInto: 0,
118   - secondScrollInto: 0,
119   - componentTop:0 ,//组件top
120   - isReadNewSelect:false,
121   - on: [1,0,0,0,0],
122   - }
123   - },
124   - props: {
125   - filterData: {
126   - value: Array,
127   - default: []
128   - },
129   - defaultSelected:{
130   - value: Array,
131   - default: []
132   - },
133   - updateMenuName:{
134   - value: Boolean,
135   - default: true
136   - },
137   - dataFormat:{
138   - value: String,
139   - default: 'Array'
140   - }
141   - },
142   - watch: {
143   - filterData: {
144   - handler() {
145   - this.initMenu(); //filterData重新赋值初始化菜单
146   - },
147   - immediate: true
148   - },
149   - defaultSelected(newVal) {
150   - if(newVal.length==0){
151   - return;
152   - }
153   - this.defaultActive = JSON.parse(JSON.stringify(newVal));
154   - this.activeMenuArr = JSON.parse(JSON.stringify(newVal));
155   - this.shadowActiveMenuArr = JSON.parse(JSON.stringify(newVal));
156   - // if(this.updateMenuName){
157   - // this.setMenuName();
158   - // }
159   - }
160   - },
161   - methods: {
162   - initMenu() {
163   - let tmpMenuActiveArr=[];
164   - let tmpMenu=[];
165   - for (let i = 0; i < this.filterData.length; i++) {
166   - let tmpitem = this.filterData[i];
167   - tmpMenu.push({
168   - //如果没有设置name,则取第一个菜单作为menu.name,filter类型则将"筛选"作为menu.name
169   - name: tmpitem.name || (tmpitem.type == "filter" ? "筛选" : tmpitem.submenu[0].name),
170   - type: tmpitem.type,
171   - isNoPull: tmpitem.isNoPull,
172   - });
173   - // 初始化选中项数组-ui状态
174   - tmpMenuActiveArr.push(this.processActive(tmpitem));
175   - // 初始化角度数组
176   - this.triangleDeg.push(0);
177   - // 初始化控制显示状态数组
178   - this.pageState.push(false);
179   - // 递归处理子菜单数据
180   - tmpitem = this.processSubMenu(tmpitem);
181   - this.filterData[i] = tmpitem;
182   - }
183   - this.menu = tmpMenu;
184   - // 初始化选中项数组
185   - tmpMenuActiveArr = this.defaultActive.length>0?this.defaultActive:this.activeMenuArr.length>0?this.activeMenuArr:tmpMenuActiveArr;
186   - this.defaultActive = [];
187   - this.activeMenuArr = JSON.parse(JSON.stringify(tmpMenuActiveArr));
188   - this.shadowActiveMenuArr = JSON.parse(JSON.stringify(tmpMenuActiveArr));
189   - // 加载菜单数据
190   - this.subData = this.filterData;
191   - // 设定顶部菜单名字
192   - // if(this.updateMenuName){
193   - // this.setMenuName();
194   - // }
195   - },
196   - // setMenuName(){
197   - // for(var i=0;i<this.activeMenuArr.length;i++){
198   - // let row = this.activeMenuArr[i];
199   - // if (typeof(row[0]) != 'object'){
200   - // var tmpsub = false;
201   - // if(row.length>0 && row[0]!=null){
202   - // tmpsub = this.subData[i].submenu[row[0]];
203   - // if(row.length>1 && row[1]!=null){
204   - // tmpsub = tmpsub.submenu[row[1]];
205   - // if(row.length>2 && row[2]!=null){
206   - // tmpsub = tmpsub.submenu[row[2]];
207   - // }
208   - // }
209   - // }else{
210   - // tmpsub = false;
211   - // }
212   - // if(tmpsub){
213   - // this.menu[i].name = tmpsub.name;
214   - // }
215   - // }
216   - // }
217   - // },
218   - //展开更多
219   - showMoreSub(index) {
220   - this.subData[this.showPage].submenu[this.activeMenuArr[this.showPage][0]].submenu[index].showAllSub = true;
221   - this.$forceUpdate();
222   - },
223   - //选中
224   - selectHierarchyMenu(page_index, level1_index, level2_index, level3_index) {
225   - //读取记录
226   - if (level1_index != null && level2_index == null && level3_index == null && this.shadowActiveMenuArr[page_index][0] ==
227   - level1_index) {
228   - this.activeMenuArr.splice(page_index, 1, JSON.parse(JSON.stringify(this.shadowActiveMenuArr[page_index])));
229   - } else {
230   - this.activeMenuArr[page_index].splice(0, 1, level1_index);
231   - (level2_index!=null||this.activeMenuArr[page_index].length>=2)&&this.activeMenuArr[page_index].splice(1, 1, level2_index) || this.activeMenuArr[page_index].splice(1, 1);
232   - (level3_index!=null||this.activeMenuArr[page_index].length>=3)&&this.activeMenuArr[page_index].splice(2, 1, level3_index) || this.activeMenuArr[page_index].splice(2, 1);
233   - }
234   - //写入结果
235   - if (level3_index != null || level2_index != null || (level1_index != null && this.subData[page_index].submenu[level1_index].submenu.length == 0)
236   - ) {
237   - let sub = this.subData[page_index].submenu[level1_index].submenu[level2_index];
238   - // if(this.updateMenuName){
239   - // this.menu[page_index].name = (level3_index != null && sub.submenu[level3_index].name) || (level2_index != null && sub.name) || this.subData[page_index].submenu[level1_index].name;
240   - // }
241   - this.shadowActiveMenuArr[page_index] = JSON.parse(JSON.stringify(this.activeMenuArr[page_index]));
242   - this.togglePage(this.showPage);
243   - }
244   - },
245   - //写入结果,筛选
246   - setFilterData(page_index) {
247   - this.shadowActiveMenuArr[page_index] = JSON.parse(JSON.stringify(this.activeMenuArr[page_index]));
248   - this.togglePage(this.showPage);
249   - },
250   - //重置结果和ui,筛选
251   - resetFilterData(page_index) {
252   - let tmpArr = [];
253   - let level = this.shadowActiveMenuArr[page_index].length;
254   - while (level > 0) {
255   - tmpArr.push([]);
256   - let box = this.subData[page_index].submenu[level - 1].submenu;
257   - for (let i = 0; i < box.length; i++) {
258   - this.subData[page_index].submenu[level - 1].submenu[i].selected = false;
259   - }
260   - level--;
261   - }
262   - this.activeMenuArr[page_index] = JSON.parse(JSON.stringify(tmpArr));
263   - this.$forceUpdate();
264   - },
265   - //选中筛选类label-UI状态
266   - selectFilterLabel(page_index, box_index, label_index) {
267   - let find_index = this.activeMenuArr[page_index][box_index].indexOf(label_index);
268   - if (find_index > -1) {
269   - this.activeMenuArr[page_index][box_index].splice(find_index, 1);
270   - this.subData[page_index].submenu[box_index].submenu[label_index].selected = false;
271   - } else {
272   - this.activeMenuArr[page_index][box_index].push(label_index);
273   - this.subData[page_index].submenu[box_index].submenu[label_index].selected = true;
274   - }
275   - this.$forceUpdate();
276   - },
277   - //选中单选类label-UI状态
278   - selectRadioLabel(page_index, box_index, label_index) {
279   -
280   - let activeIndex = this.activeMenuArr[page_index][box_index][0];
281   - if(activeIndex == label_index){
282   - this.subData[page_index].submenu[box_index].submenu[activeIndex].selected = false;
283   - this.activeMenuArr[page_index][box_index][0] = null;
284   - }else{
285   - if(activeIndex!=null && activeIndex<this.subData[page_index].submenu[box_index].submenu.length){
286   - this.subData[page_index].submenu[box_index].submenu[activeIndex].selected = false;
287   - }
288   -
289   - this.subData[page_index].submenu[box_index].submenu[label_index].selected = true;
290   - this.activeMenuArr[page_index][box_index][0] = label_index;
291   - }
292   - this.$forceUpdate();
293   - },
294   - //菜单开关
295   - togglePage(index) {
296   - if (index == this.showPage) {
297   - this.hidePageLayer(true);
298   - this.hideMask();
299   - this.showPage = -1;
300   - } else {
301   - if (this.showPage > -1) {
302   - this.hidePageLayer(false);
303   - }
304   - this.showPageLayer(index);
305   - this.showMask();
306   - }
307   - if(this.on[0] === 1) {
308   - this.on[0] = 0;
309   - }
310   - this.on[index] = 1;
311   - },
312   - showAll() {
313   - this.on = [1,0,0,0,0]
314   - // 输出
315   - this.$emit('search', {
316   - index: {},
317   - value: {},
318   - on: this.on,
319   - });
320   - },
321   - //hide遮罩层
322   - hideMask() {
323   - this.isShowMask = false;
324   - setTimeout(() => {
325   - this.maskVisibility = false;
326   - }, 200);
327   - },
328   - //show遮罩层
329   - showMask() {
330   - this.maskVisibility = true;
331   - this.$nextTick(() => {
332   - setTimeout(() => {
333   - this.isShowMask = true;
334   - }, 0);
335   - })
336   - },
337   - //hide菜单页
338   - hidePageLayer(isAnimation) {
339   - this.triangleDeg[this.showPage] = 0;
340   - let tmpIndex = this.showPage;
341   - if (isAnimation) {
342   - setTimeout(() => {
343   - this.pageState.splice(tmpIndex, 1, false);
344   - }, 200);
345   - this.confirm();
346   - } else {
347   - this.pageState.splice(tmpIndex, 1, false)
348   - }
349   - this.firstScrollInto = null;
350   - this.secondScrollInto = null;
351   - },
352   - confirm() {
353   - let index = JSON.parse(JSON.stringify(this.shadowActiveMenuArr));
354   - let value = JSON.parse(JSON.stringify(this.shadowActiveMenuArr));
355   -
356   - //对结果做一下处理
357   - index.forEach((item, i) => {
358   - if (typeof(item[0]) == 'object') {
359   - //针对筛选结果过一个排序
360   - item.forEach((s, j) => {
361   - if(s!=null){
362   - s.sort((val1, val2) => {
363   - return val1 - val2;
364   - });
365   - item[j] = s;
366   - s.forEach((v, k) => {
367   - value[i][j][k] = (v==null||v>=this.subData[i].submenu[j].submenu.length)?null:this.subData[i].submenu[j].submenu[v].value;
368   - if(this.subData[i].type == 'radio' && value[i][j][k] == null){
369   - value[i][j] = [];
370   - index[i][j] = [];
371   - }
372   - });
373   - }
374   - });
375   - }else{
376   - let submenu = this.subData[i].submenu[item[0]];
377   - value[i][0] = submenu && submenu.value;
378   - if(value[i].length>=2 && item[1]!=null){
379   - if(submenu.submenu.length>0){
380   - submenu = submenu.submenu[item[1]];
381   - value[i][1] = submenu.hasOwnProperty('value')?submenu.value:null;
382   - }else{
383   - value[i][1] = null
384   - }
385   - if(value[i].length>=3 && item[2]!=null){
386   - if(submenu.submenu.length>0){
387   - submenu = submenu.submenu[item[2]];
388   - value[i][2] = submenu.hasOwnProperty('value')?submenu.value:null;
389   - }else{
390   - value[i][2] = null;
391   - }
392   - }
393   - }
394   - }
395   - index[i] = item;
396   -
397   - });
398   - // 输出
399   - this.$emit('search', {
400   - index: index,
401   - value: value,
402   - on: this.on,
403   - });
404   - },
405   - //show菜单页
406   - showPageLayer(index) {
407   - this.processPage(index);
408   - this.pageState.splice(index, 1, true);
409   - this.$nextTick(() => {
410   - setTimeout(() => {
411   - this.showPage = index;
412   - }, 0);
413   - })
414   - this.triangleDeg[index] = 180;
415   - },
416   - reloadActiveMenuArr(){
417   - for (let i = 0; i < this.filterData.length; i++) {
418   - let tmpitem = this.filterData[i];
419   - let tmpArr = this.processActive(tmpitem);
420   - tmpitem = this.processSubMenu(tmpitem);
421   - if(this.activeMenuArr[i].length!=tmpArr.length){
422   - this.filterData[i] = tmpitem;
423   - this.activeMenuArr.splice(i, 1, JSON.parse(JSON.stringify(tmpArr)));
424   - this.shadowActiveMenuArr.splice(i, 1, JSON.parse(JSON.stringify(tmpArr)));
425   - }
426   - }
427   - this.subData = this.filterData;
428   - this.$forceUpdate();
429   - },
430   - processPage(index) {
431   - //check UI控制数组,结果数组,防止传入数据层级和UI控制数组不同步
432   - this.reloadActiveMenuArr();
433   - //重置UI控制数组
434   - this.activeMenuArr.splice(index, 1, JSON.parse(JSON.stringify(this.shadowActiveMenuArr[index])));
435   - if (this.menu[index].type == 'filter') {
436   - //重载筛选页选中状态
437   - let level = this.shadowActiveMenuArr[index].length;
438   - for (let i = 0; i < level; i++) {
439   - let box = this.subData[index].submenu[i].submenu;
440   - for (let j = 0; j < box.length; j++) {
441   - if (this.shadowActiveMenuArr[index][i].indexOf(j) > -1) {
442   - this.subData[index].submenu[i].submenu[j].selected = true;
443   - } else {
444   - this.subData[index].submenu[i].submenu[j].selected = false;
445   - }
446   - }
447   - }
448   - } else if (this.menu[index].type == 'hierarchy') {
449   - this.$nextTick(() => {
450   - setTimeout(() => {
451   - //滚动到选中项
452   - this.firstScrollInto = parseInt(this.activeMenuArr[index][0]);
453   - this.secondScrollInto = parseInt(this.activeMenuArr[index][1]);
454   - }, 0);
455   - })
456   - } else if (this.menu[index].type == 'radio') {
457   - //重载筛选页选中状态
458   - let level = this.shadowActiveMenuArr[index].length;
459   - for (let i = 0; i < level; i++) {
460   - let box = this.subData[index].submenu[i].submenu;
461   - for (let j = 0; j < box.length; j++) {
462   - if (this.shadowActiveMenuArr[index][i].indexOf(j) > -1) {
463   - this.subData[index].submenu[i].submenu[j].selected = true;
464   - } else {
465   - this.subData[index].submenu[i].submenu[j].selected = false;
466   - }
467   - }
468   - }
469   - }
470   - },
471   - processActive(tmpitem) {
472   - let tmpArr = []
473   - if (tmpitem.type == 'hierarchy'&&tmpitem.hasOwnProperty('submenu')&&tmpitem.submenu.length>0) {
474   - let level = this.getMaxFloor(tmpitem.submenu);
475   - while (level > 0) {
476   - tmpArr.push(0);
477   - level--;
478   - }
479   - } else if (tmpitem.type == 'filter') {
480   - let level = tmpitem.submenu.length;
481   - while (level > 0) {
482   - tmpArr.push([]);
483   - level--;
484   - }
485   - } else if (tmpitem.type == 'radio') {
486   - let level = tmpitem.submenu.length;
487   - while (level > 0) {
488   - tmpArr.push([]);
489   - level--;
490   - }
491   - }
492   - return tmpArr;
493   - },
494   - processSubMenu(menu) {
495   - if (menu.hasOwnProperty('submenu') && menu.submenu.length > 0) {
496   - for (let i = 0; i < menu.submenu.length; i++) {
497   - menu.submenu[i] = this.processSubMenu(menu.submenu[i]);
498   - }
499   - } else {
500   - menu.submenu = [];
501   - }
502   - return menu;
503   - },
504   - //计算菜单层级
505   - getMaxFloor(treeData) {
506   - let floor = 0
507   - let max = 0
508   - function each(data, floor) {
509   - data.forEach(e => {
510   - max = floor > max ? floor : max;
511   - if (e.hasOwnProperty('submenu') && e.submenu.length > 0) {
512   - each(e.submenu, floor + 1)
513   - }
514   - })
515   - }
516   - each(treeData, 1)
517   - return max;
518   - },
519   - discard() {
  194 +export default {
  195 + data () {
  196 + return {
  197 + subData: [], // 菜单数据
  198 + menu: [], // 顶部横条数据
  199 + showPage: -1, // 菜单页面显示/隐藏动画控制
  200 + pageState: [], // 页面的状态
  201 + activeMenuArr: [], // UI状态
  202 + shadowActiveMenuArr: [], // 记录选中
  203 + defaultActive: [],
  204 + triangleDeg: [], // 小三角形的翻转动画控制
  205 + isShowMask: false, // 遮罩层显示/隐藏动画控制
  206 + maskVisibility: false, // 遮罩层显示/隐藏状态
  207 + // 滚动区域定位
  208 + firstScrollInto: 0,
  209 + secondScrollInto: 0,
  210 + componentTop: 0, // 组件top
  211 + isReadNewSelect: false,
  212 + on: [1, 0, 0, 0, 0],
  213 + selectedData: {}
  214 + }
  215 + },
  216 + props: {
  217 + filterData: {
  218 + value: Array,
  219 + default: []
  220 + },
  221 + defaultSelected: {
  222 + value: Array,
  223 + default: []
  224 + },
  225 + updateMenuName: {
  226 + value: Boolean,
  227 + default: true
  228 + },
  229 + dataFormat: {
  230 + value: String,
  231 + default: 'Array'
  232 + }
  233 + },
  234 + watch: {
  235 + filterData: {
  236 + handler () {
  237 + this.initMenu() // filterData重新赋值初始化菜单
  238 + },
  239 + immediate: true
  240 + },
  241 + defaultSelected (newVal) {
  242 + if (newVal.length === 0) {
  243 + return
  244 + }
  245 + this.defaultActive = JSON.parse(JSON.stringify(newVal))
  246 + this.activeMenuArr = JSON.parse(JSON.stringify(newVal))
  247 + this.shadowActiveMenuArr = JSON.parse(JSON.stringify(newVal))
  248 + }
  249 + },
  250 + methods: {
  251 + initMenu () {
  252 + let tmpMenuActiveArr = []
  253 + const tmpMenu = []
  254 + for (let i = 0; i < this.filterData.length; i++) {
  255 + let tmpitem = this.filterData[i]
  256 + tmpMenu.push({
  257 + // 如果没有设置name,则取第一个菜单作为menu.name,filter类型则将"筛选"作为menu.name
  258 + name: tmpitem.name || (tmpitem.type === 'filter' ? '筛选' : tmpitem.submenu[0].name),
  259 + type: tmpitem.type,
  260 + isNoPull: tmpitem.isNoPull
  261 + })
  262 + // 初始化选中项数组-ui状态
  263 + tmpMenuActiveArr.push(this.processActive(tmpitem))
  264 + // 初始化角度数组
  265 + this.triangleDeg.push(0)
  266 + // 初始化控制显示状态数组
  267 + this.pageState.push(false)
  268 + // 递归处理子菜单数据
  269 + tmpitem = this.processSubMenu(tmpitem)
  270 + this.filterData[i] = tmpitem
  271 + if (tmpitem.type === 'filter') {
  272 + for (let i = 0; i < tmpitem.length; i++) {
  273 + this.selectedData[`${tmpitem.submenu[i].value}`] = []
  274 + }
  275 + }
  276 + }
  277 + console.log('this.selectedData', this.selectedData)
  278 + this.menu = tmpMenu
  279 + // 初始化选中项数组
  280 + tmpMenuActiveArr = this.defaultActive.length > 0 ? this.defaultActive : this.activeMenuArr.length > 0 ? this.activeMenuArr : tmpMenuActiveArr
  281 + this.defaultActive = []
  282 + this.activeMenuArr = JSON.parse(JSON.stringify(tmpMenuActiveArr))
  283 + this.shadowActiveMenuArr = JSON.parse(JSON.stringify(tmpMenuActiveArr))
  284 + // 加载菜单数据
  285 + this.subData = this.filterData
  286 + },
  287 + // 展开更多
  288 + showMoreSub (index) {
  289 + this.subData[this.showPage].submenu[this.activeMenuArr[this.showPage][0]].submenu[index].showAllSub = true
  290 + this.$forceUpdate()
  291 + },
  292 + // 选中
  293 + selectHierarchyMenu (page_index, level1_index, level2_index, level3_index) {
  294 + // 读取记录
  295 + if (level1_index != null && level2_index == null && level3_index == null && this.shadowActiveMenuArr[page_index][0] === level1_index) {
  296 + this.activeMenuArr.splice(page_index, 1, JSON.parse(JSON.stringify(this.shadowActiveMenuArr[page_index])))
  297 + } else {
  298 + this.activeMenuArr[page_index].splice(0, 1, level1_index);
  299 + (level2_index != null || this.activeMenuArr[page_index].length >= 2) && this.activeMenuArr[page_index].splice(1, 1, level2_index) || this.activeMenuArr[page_index].splice(1, 1);
  300 + (level3_index != null || this.activeMenuArr[page_index].length >= 3) && this.activeMenuArr[page_index].splice(2, 1, level3_index) || this.activeMenuArr[page_index].splice(2, 1)
  301 + }
  302 + // 写入结果
  303 + if (level3_index != null || level2_index != null || (level1_index != null && this.subData[page_index].submenu[level1_index].submenu.length == 0)
  304 + ) {
  305 + const sub = this.subData[page_index].submenu[level1_index].submenu[level2_index]
  306 + this.shadowActiveMenuArr[page_index] = JSON.parse(JSON.stringify(this.activeMenuArr[page_index]))
  307 + this.togglePage(this.showPage)
  308 + }
  309 + },
  310 + // 写入结果,筛选
  311 + setFilterData (page_index) {
  312 + this.shadowActiveMenuArr[page_index] = JSON.parse(JSON.stringify(this.activeMenuArr[page_index]))
  313 + this.togglePage(this.showPage)
  314 + },
  315 + // 重置结果和ui,筛选
  316 + resetFilterData (page_index) {
  317 + const tmpArr = []
  318 + let level = this.shadowActiveMenuArr[page_index].length
  319 + while (level > 0) {
  320 + tmpArr.push([])
  321 + const box = this.subData[page_index].submenu[level - 1].submenu
  322 + for (let i = 0; i < box.length; i++) {
  323 + this.subData[page_index].submenu[level - 1].submenu[i].selected = false
  324 + }
  325 + level--
  326 + }
  327 + this.activeMenuArr[page_index] = JSON.parse(JSON.stringify(tmpArr))
  328 + this.$forceUpdate()
  329 + },
  330 + // 选中筛选类label-UI状态
  331 + selectFilterLabel (page_index, box_index, label_index) {
  332 + const findIndex = this.activeMenuArr[page_index][box_index].indexOf(label_index)
  333 + console.log('select', page_index, box_index, label_index, findIndex)
  334 + const data = this.filterData[page_index].submenu
  335 + const selected = this.selectedData[`${data[box_index].value}`]
  336 + if (findIndex > -1) {
  337 + this.activeMenuArr[page_index][box_index].splice(findIndex, 1)
  338 + this.subData[page_index].submenu[box_index].submenu[label_index].selected = false
  339 + for (let i = 0; i < selected.length; i++) {
  340 + if (selected[i] === data[box_index].submenu[label_index].value) {
  341 + console.log('dd', this.selectedData[`${data[box_index].value}`], selected)
  342 + this.selectedData[`${data[box_index].value}`] = selected.slice(1, 1)
  343 + console.log('dd2', this.selectedData[`${data[box_index].value}`], selected)
  344 + }
  345 + }
  346 + } else {
  347 + this.activeMenuArr[page_index][box_index].push(label_index)
  348 + this.subData[page_index].submenu[box_index].submenu[label_index].selected = true
  349 + if (!selected) {
  350 + this.selectedData[`${data[box_index].value}`] = []
  351 + this.selectedData[`${data[box_index].value}`].push(data[box_index].submenu[label_index].value)
  352 + } else {
  353 + this.selectedData[`${data[box_index].value}`].push(data[box_index].submenu[label_index].value)
  354 + }
  355 + // this.selectedData[`${data[box_index].value}`].push(data[box_index][label_index])
  356 + console.log('---', data, this.filterData, this.selectedData)
  357 + }
  358 + this.$forceUpdate()
  359 + },
  360 + // 选中单选类label-UI状态
  361 + selectRadioLabel (page_index, box_index, label_index) {
  362 + const activeIndex = this.activeMenuArr[page_index][box_index][0]
  363 + if (activeIndex == label_index) {
  364 + this.subData[page_index].submenu[box_index].submenu[activeIndex].selected = false
  365 + this.activeMenuArr[page_index][box_index][0] = null
  366 + } else {
  367 + if (activeIndex != null && activeIndex < this.subData[page_index].submenu[box_index].submenu.length) {
  368 + this.subData[page_index].submenu[box_index].submenu[activeIndex].selected = false
  369 + }
520 370  
521   - }
522   - }
523   - }
  371 + this.subData[page_index].submenu[box_index].submenu[label_index].selected = true
  372 + this.activeMenuArr[page_index][box_index][0] = label_index
  373 + }
  374 + this.$forceUpdate()
  375 + },
  376 + // 菜单开关
  377 + togglePage (index) {
  378 + if (index == this.showPage) {
  379 + this.hidePageLayer(true)
  380 + this.hideMask()
  381 + this.showPage = -1
  382 + } else {
  383 + if (this.showPage > -1) {
  384 + this.hidePageLayer(false)
  385 + }
  386 + this.showPageLayer(index)
  387 + this.showMask()
  388 + }
  389 + if (this.on[0] === 1) {
  390 + this.on[0] = 0
  391 + }
  392 + this.on[index] = 1
  393 + },
  394 + showAll () {
  395 + this.on = [1, 0, 0, 0, 0]
  396 + // 输出
  397 + this.$emit('search', {
  398 + index: {},
  399 + value: {},
  400 + on: this.on,
  401 + selectedData: this.selectedData
  402 + })
  403 + },
  404 + // hide遮罩层
  405 + hideMask () {
  406 + this.isShowMask = false
  407 + setTimeout(() => {
  408 + this.maskVisibility = false
  409 + }, 200)
  410 + },
  411 + // show遮罩层
  412 + showMask () {
  413 + this.maskVisibility = true
  414 + this.$nextTick(() => {
  415 + setTimeout(() => {
  416 + this.isShowMask = true
  417 + }, 0)
  418 + })
  419 + },
  420 + // hide菜单页
  421 + hidePageLayer (isAnimation) {
  422 + this.triangleDeg[this.showPage] = 0
  423 + const tmpIndex = this.showPage
  424 + if (isAnimation) {
  425 + setTimeout(() => {
  426 + this.pageState.splice(tmpIndex, 1, false)
  427 + }, 200)
  428 + this.confirm()
  429 + } else {
  430 + this.pageState.splice(tmpIndex, 1, false)
  431 + }
  432 + this.firstScrollInto = null
  433 + this.secondScrollInto = null
  434 + },
  435 + confirm () {
  436 + const index = JSON.parse(JSON.stringify(this.shadowActiveMenuArr))
  437 + const value = JSON.parse(JSON.stringify(this.shadowActiveMenuArr))
  438 +
  439 + // 对结果做一下处理
  440 + index.forEach((item, i) => {
  441 + if (typeof (item[0]) === 'object') {
  442 + // 针对筛选结果过一个排序
  443 + item.forEach((s, j) => {
  444 + if (s != null) {
  445 + s.sort((val1, val2) => {
  446 + return val1 - val2
  447 + })
  448 + item[j] = s
  449 + s.forEach((v, k) => {
  450 + value[i][j][k] = (v == null || v >= this.subData[i].submenu[j].submenu.length) ? null : this.subData[i].submenu[j].submenu[v].value
  451 + if (this.subData[i].type == 'radio' && value[i][j][k] == null) {
  452 + value[i][j] = []
  453 + index[i][j] = []
  454 + }
  455 + })
  456 + }
  457 + })
  458 + } else {
  459 + let submenu = this.subData[i].submenu[item[0]]
  460 + value[i][0] = submenu && submenu.value
  461 + if (value[i].length >= 2 && item[1] != null) {
  462 + if (submenu.submenu.length > 0) {
  463 + submenu = submenu.submenu[item[1]]
  464 + value[i][1] = submenu.hasOwnProperty('value') ? submenu.value : null
  465 + } else {
  466 + value[i][1] = null
  467 + }
  468 + if (value[i].length >= 3 && item[2] != null) {
  469 + if (submenu.submenu.length > 0) {
  470 + submenu = submenu.submenu[item[2]]
  471 + value[i][2] = submenu.hasOwnProperty('value') ? submenu.value : null
  472 + } else {
  473 + value[i][2] = null
  474 + }
  475 + }
  476 + }
  477 + }
  478 + index[i] = item
  479 + })
  480 + // 输出
  481 + this.$emit('search', {
  482 + index: index,
  483 + value: value,
  484 + on: this.on,
  485 + selectedData: this.selectedData
  486 + })
  487 + },
  488 + // show菜单页
  489 + showPageLayer (index) {
  490 + this.processPage(index)
  491 + this.pageState.splice(index, 1, true)
  492 + this.$nextTick(() => {
  493 + setTimeout(() => {
  494 + this.showPage = index
  495 + }, 0)
  496 + })
  497 + this.triangleDeg[index] = 180
  498 + },
  499 + reloadActiveMenuArr () {
  500 + for (let i = 0; i < this.filterData.length; i++) {
  501 + let tmpitem = this.filterData[i]
  502 + const tmpArr = this.processActive(tmpitem)
  503 + tmpitem = this.processSubMenu(tmpitem)
  504 + if (this.activeMenuArr[i].length != tmpArr.length) {
  505 + this.filterData[i] = tmpitem
  506 + this.activeMenuArr.splice(i, 1, JSON.parse(JSON.stringify(tmpArr)))
  507 + this.shadowActiveMenuArr.splice(i, 1, JSON.parse(JSON.stringify(tmpArr)))
  508 + }
  509 + }
  510 + this.subData = this.filterData
  511 + this.$forceUpdate()
  512 + },
  513 + processPage (index) {
  514 + // check UI控制数组,结果数组,防止传入数据层级和UI控制数组不同步
  515 + this.reloadActiveMenuArr()
  516 + // 重置UI控制数组
  517 + this.activeMenuArr.splice(index, 1, JSON.parse(JSON.stringify(this.shadowActiveMenuArr[index])))
  518 + if (this.menu[index].type === 'filter') {
  519 + // 重载筛选页选中状态
  520 + const level = this.shadowActiveMenuArr[index].length
  521 + for (let i = 0; i < level; i++) {
  522 + const box = this.subData[index].submenu[i].submenu
  523 + for (let j = 0; j < box.length; j++) {
  524 + if (this.shadowActiveMenuArr[index][i].indexOf(j) > -1) {
  525 + this.subData[index].submenu[i].submenu[j].selected = true
  526 + } else {
  527 + this.subData[index].submenu[i].submenu[j].selected = false
  528 + }
  529 + }
  530 + }
  531 + } else if (this.menu[index].type === 'hierarchy') {
  532 + this.$nextTick(() => {
  533 + setTimeout(() => {
  534 + // 滚动到选中项
  535 + this.firstScrollInto = parseInt(this.activeMenuArr[index][0])
  536 + this.secondScrollInto = parseInt(this.activeMenuArr[index][1])
  537 + }, 0)
  538 + })
  539 + } else if (this.menu[index].type === 'radio') {
  540 + // 重载筛选页选中状态
  541 + const level = this.shadowActiveMenuArr[index].length
  542 + for (let i = 0; i < level; i++) {
  543 + const box = this.subData[index].submenu[i].submenu
  544 + for (let j = 0; j < box.length; j++) {
  545 + if (this.shadowActiveMenuArr[index][i].indexOf(j) > -1) {
  546 + this.subData[index].submenu[i].submenu[j].selected = true
  547 + } else {
  548 + this.subData[index].submenu[i].submenu[j].selected = false
  549 + }
  550 + }
  551 + }
  552 + }
  553 + },
  554 + processActive (tmpitem) {
  555 + const tmpArr = []
  556 + if (tmpitem.type === 'hierarchy' && tmpitem.hasOwnProperty('submenu') && tmpitem.submenu.length > 0) {
  557 + let level = this.getMaxFloor(tmpitem.submenu)
  558 + while (level > 0) {
  559 + tmpArr.push(0)
  560 + level--
  561 + }
  562 + } else if (tmpitem.type === 'filter') {
  563 + let level = tmpitem.submenu.length
  564 + while (level > 0) {
  565 + tmpArr.push([])
  566 + level--
  567 + }
  568 + } else if (tmpitem.type === 'radio') {
  569 + let level = tmpitem.submenu.length
  570 + while (level > 0) {
  571 + tmpArr.push([])
  572 + level--
  573 + }
  574 + }
  575 + return tmpArr
  576 + },
  577 + processSubMenu (menu) {
  578 + if (menu.hasOwnProperty('submenu') && menu.submenu.length > 0) {
  579 + for (let i = 0; i < menu.submenu.length; i++) {
  580 + menu.submenu[i] = this.processSubMenu(menu.submenu[i])
  581 + }
  582 + } else {
  583 + menu.submenu = []
  584 + }
  585 + return menu
  586 + },
  587 + // 计算菜单层级
  588 + getMaxFloor (treeData) {
  589 + const floor = 0
  590 + let max = 0
  591 + function each (data, floor) {
  592 + data.forEach(e => {
  593 + max = floor > max ? floor : max
  594 + if (e.hasOwnProperty('submenu') && e.submenu.length > 0) {
  595 + each(e.submenu, floor + 1)
  596 + }
  597 + })
  598 + }
  599 + each(treeData, 1)
  600 +
  601 + return max
  602 + },
  603 + discard () {
  604 +
  605 + }
  606 + }
  607 +}
524 608 </script>
525 609 <style lang="scss">
526   - .HMfilterDropdown {
527   - flex-shrink: 0;
528   - width: 100%;
529   - height: 44px;
530   - position: fixed;
531   - z-index: 997;
532   - flex-wrap: nowrap;
533   - display: flex;
534   - flex-direction: row;
535   - top: var(--window-top);
536   - left:0;
537   - view {
538   - display: flex;
539   - flex-wrap: nowrap;
540   - }
541   - }
542   - .region {
543   - flex: 1;
544   - height: 44px;
545   - }
546   - .nav {
547   - width: 100%;
548   - height: 44px;
549   - z-index: 12;
550   - background-color: #ffffff;
551   - flex-direction: row;