Blame view

ant-design-vue-jeecg/src/components/menu/index.js 6.08 KB
肖超群 authored
1
2
3
import Menu from 'ant-design-vue/es/menu'
import Icon from 'ant-design-vue/es/icon'
肖超群 authored
4
const {Item, SubMenu} = Menu
肖超群 authored
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

export default {
  name: 'SMenu',
  props: {
    menu: {
      type: Array,
      required: true
    },
    theme: {
      type: String,
      required: false,
      default: 'dark'
    },
    mode: {
      type: String,
      required: false,
      default: 'inline'
    },
    collapsed: {
      type: Boolean,
      required: false,
      default: false
    }
  },
肖超群 authored
29
  data() {
肖超群 authored
30
31
32
33
34
35
36
37
38
39
40
41
42
    return {
      openKeys: [],
      selectedKeys: [],
      cachedOpenKeys: []
    }
  },
  computed: {
    rootSubmenuKeys: vm => {
      const keys = []
      vm.menu.forEach(item => keys.push(item.path))
      return keys
    }
  },
肖超群 authored
43
  mounted() {
肖超群 authored
44
45
46
    this.updateMenu()
  },
  watch: {
肖超群 authored
47
    collapsed(val) {
肖超群 authored
48
49
50
51
52
53
54
55
56
57
58
59
60
      if (val) {
        this.cachedOpenKeys = this.openKeys.concat()
        this.openKeys = []
      } else {
        this.openKeys = this.cachedOpenKeys
      }
    },
    $route: function () {
      this.updateMenu()
    }
  },
  methods: {
    // select menu item
肖超群 authored
61
    onOpenChange(openKeys) {
肖超群 authored
62
63
64
65
66
67
68
69
70
71
72
73
74
75

      // 在水平模式下时执行,并且不再执行后续
      if (this.mode === 'horizontal') {
        this.openKeys = openKeys
        return
      }
      // 非水平模式时
      const latestOpenKey = openKeys.find(key => !this.openKeys.includes(key))
      if (!this.rootSubmenuKeys.includes(latestOpenKey)) {
        this.openKeys = openKeys
      } else {
        this.openKeys = latestOpenKey ? [latestOpenKey] : []
      }
    },
肖超群 authored
76
    updateMenu() {
肖超群 authored
77
      const routes = this.$route.matched.concat()
肖超群 authored
78
      const {hidden} = this.$route.meta
肖超群 authored
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
      if (routes.length >= 3 && hidden) {
        routes.pop()
        this.selectedKeys = [routes[routes.length - 1].path]
      } else {
        this.selectedKeys = [routes.pop().path]
      }
      let openKeys = []
      if (this.mode === 'inline') {
        routes.forEach(item => {
          openKeys.push(item.path)
        })
      }

      // update-begin-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
      // 包含冒号的是动态菜单
      if (this.selectedKeys[0].includes(':')) {
        let selectedKey = this.$route.fullPath
        this.selectedKeys = [selectedKey]
        let newOpenKeys = []
        this.fullOpenKeys(this.menu, selectedKey, newOpenKeys)
        if (newOpenKeys.length > 0) {
          openKeys = newOpenKeys.reverse()
        }
      }
      // update-end-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题

      //update-begin-author:taoyan date:20190510 for:online表单菜单点击展开的一级目录不对
肖超群 authored
106
      if (!this.selectedKeys || this.selectedKeys[0].indexOf(":") < 0) {
肖超群 authored
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
        this.collapsed ? (this.cachedOpenKeys = openKeys) : (this.openKeys = openKeys)
      }
      //update-end-author:taoyan date:20190510 for:online表单菜单点击展开的一级目录不对
    },
    // update-begin-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题
    // 递归查找当前选中的菜单和父级菜单,填充openKeys
    fullOpenKeys(menus, selectedKey, openKeys) {
      for (let item of menus) {
        if (item.path === selectedKey) {
          openKeys.push(item.path)
          this.$emit('updateMenuTitle', item)
          return true
        } else if (Array.isArray(item.children)) {
          if (this.fullOpenKeys(item.children, selectedKey, openKeys)) {
            openKeys.push(item.path)
            return true
          }
        }
      }
    },
    // update-end-author:sunjianlei date:20210409 for: 修复动态功能测试菜单、带参数菜单标题错误、展开错误的问题

    // render
肖超群 authored
130
    renderItem(menu) {
肖超群 authored
131
132
133
134
135
      if (!menu.hidden) {
        return menu.children && !menu.alwaysShow ? this.renderSubMenu(menu) : this.renderMenuItem(menu)
      }
      return null
    },
肖超群 authored
136
    renderMenuItem(menu) {
肖超群 authored
137
138
      const target = menu.meta.target || null
      const tag = target && 'a' || 'router-link'
肖超群 authored
139
140
141
      let props = {to: {name: menu.name}}
      if (menu.route && menu.route === '0') {
        props = {to: {path: menu.path}}
肖超群 authored
142
143
      }
肖超群 authored
144
      const attrs = {href: menu.path, target: menu.meta.target}
肖超群 authored
145
146
147
148
149
150

      if (menu.children && menu.alwaysShow) {
        // 把有子菜单的 并且 父菜单是要隐藏子菜单的
        // 都给子菜单增加一个 hidden 属性
        // 用来给刷新页面时, selectedKeys 做控制用
        menu.children.forEach(item => {
肖超群 authored
151
          item.meta = Object.assign(item.meta, {hidden: true})
肖超群 authored
152
153
154
155
        })
      }

      return (
肖超群 authored
156
157
        <Item {...{key: menu.path}}>
          <tag {...{props, attrs}}>
肖超群 authored
158
159
160
161
162
163
            {this.renderIcon(menu.meta.icon)}
            <span>{menu.meta.title}</span>
          </tag>
        </Item>
      )
    },
肖超群 authored
164
    renderSubMenu(menu) {
肖超群 authored
165
166
167
168
169
      const itemArr = []
      if (!menu.alwaysShow) {
        menu.children.forEach(item => itemArr.push(this.renderItem(item)))
      }
      return (
肖超群 authored
170
        <SubMenu {...{key: menu.path}}>
肖超群 authored
171
172
173
174
175
176
177
178
          <span slot="title">
            {this.renderIcon(menu.meta.icon)}
            <span>{menu.meta.title}</span>
          </span>
          {itemArr}
        </SubMenu>
      )
    },
肖超群 authored
179
    renderIcon(icon) {
肖超群 authored
180
181
182
183
184
185
      if (icon === 'none' || icon === undefined) {
        return null
      }
      const props = {}
      typeof (icon) === 'object' ? props.component = icon : props.type = icon
      return (
肖超群 authored
186
        <Icon {...{props}}/>
肖超群 authored
187
188
189
190
      )
    }
  },
肖超群 authored
191
192
  render() {
    const {mode, theme, menu} = this
肖超群 authored
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
    const props = {
      mode: mode,
      theme: theme,
      openKeys: this.openKeys
    }
    const on = {
      select: obj => {
        this.selectedKeys = obj.selectedKeys
        this.$emit('select', obj)
      },
      openChange: this.onOpenChange
    }

    const menuTree = menu.map(item => {
      if (item.hidden) {
        return null
      }
      return this.renderItem(item)
    })
    // {...{ props, on: on }}
    return (
肖超群 authored
214
      <Menu vModel={this.selectedKeys} {...{props, on: on}}>
肖超群 authored
215
216
217
218
219
        {menuTree}
      </Menu>
    )
  }
}