vue2-client 1.4.63 → 1.5.0

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.
Files changed (111) hide show
  1. package/CHANGELOG.md +498 -484
  2. package/index.js +30 -30
  3. package/package.json +78 -78
  4. package/src/base-client/components/common/AddressSearchCombobox/AddressSearchCombobox.vue +225 -225
  5. package/src/base-client/components/common/CreateQuery/CreateQuery.vue +602 -601
  6. package/src/base-client/components/common/CreateQuery/CreateQueryItem.vue +713 -782
  7. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQuery.vue +436 -310
  8. package/src/base-client/components/common/CreateSimpleFormQuery/CreateSimpleFormQueryItem.vue +508 -553
  9. package/src/base-client/components/common/FormGroupEdit/FormGroupEdit.vue +151 -151
  10. package/src/base-client/components/common/FormGroupQuery/FormGroupQuery.vue +165 -165
  11. package/src/base-client/components/common/JSONToTree/jsontotree.vue +275 -275
  12. package/src/base-client/components/common/XAddForm/XAddForm.vue +325 -354
  13. package/src/base-client/components/common/XAddNativeForm/XAddNativeForm.vue +277 -327
  14. package/src/base-client/components/common/XCard/XCard.vue +64 -64
  15. package/src/base-client/components/common/XForm/XForm.vue +185 -274
  16. package/src/base-client/components/common/XForm/XFormItem.vue +485 -538
  17. package/src/base-client/components/common/XForm/index.md +177 -196
  18. package/src/base-client/components/common/XFormTable/XFormTable.vue +290 -570
  19. package/src/base-client/components/common/XFormTable/index.md +96 -96
  20. package/src/base-client/components/common/XTable/XTable.vue +504 -262
  21. package/src/base-client/components/common/XTreeOne/XTreeOne.vue +109 -109
  22. package/src/base-client/components/system/QueryParamsDetailsView/QueryParamsDetailsView.vue +281 -281
  23. package/src/base-client/components/ticket/TicketDetailsView/TicketDetailsView.vue +807 -807
  24. package/src/base-client/components/ticket/TicketDetailsView/index.md +29 -29
  25. package/src/base-client/components/ticket/TicketDetailsView/part/TicketDetailsFlow.vue +260 -260
  26. package/src/base-client/components/ticket/TicketSubmitSuccessView/TicketSubmitSuccessView.vue +532 -532
  27. package/src/base-client/components/ticket/TicketSubmitSuccessView/index.md +29 -29
  28. package/src/base-client/plugins/AppData.js +73 -73
  29. package/src/base-client/plugins/GetLoginInfoService.js +179 -179
  30. package/src/base-client/plugins/PagedList.js +177 -177
  31. package/src/base-client/plugins/compatible/LoginServiceOA.js +20 -20
  32. package/src/base-client/plugins/i18n-extend.js +32 -32
  33. package/src/components/Ellipsis/index.md +38 -38
  34. package/src/components/NumberInfo/index.md +43 -43
  35. package/src/components/STable/README.md +341 -341
  36. package/src/components/STable/index.js +318 -318
  37. package/src/components/Trend/index.md +45 -45
  38. package/src/components/checkbox/ColorCheckbox.vue +157 -157
  39. package/src/components/checkbox/ImgCheckbox.vue +163 -163
  40. package/src/components/exception/ExceptionPage.vue +70 -70
  41. package/src/components/form/FormRow.vue +52 -52
  42. package/src/components/index.js +36 -36
  43. package/src/components/menu/SideMenu.vue +62 -62
  44. package/src/components/menu/menu.js +273 -273
  45. package/src/components/page/header/index.less +40 -40
  46. package/src/components/setting/Setting.vue +235 -235
  47. package/src/components/table/StandardTable.vue +141 -141
  48. package/src/components/table/advance/ActionColumns.vue +158 -158
  49. package/src/components/table/advance/SearchArea.vue +355 -355
  50. package/src/components/tool/AStepItem.vue +60 -60
  51. package/src/components/tool/AvatarList.vue +68 -68
  52. package/src/components/tool/Drawer.vue +142 -142
  53. package/src/components/tool/TagSelect.vue +83 -83
  54. package/src/components/transition/PageToggleTransition.vue +97 -97
  55. package/src/config/CreateQueryConfig.js +307 -313
  56. package/src/config/default/admin.config.js +18 -18
  57. package/src/config/default/setting.config.js +44 -44
  58. package/src/config/replacer/resolve.config.js +67 -67
  59. package/src/layouts/AdminLayout.vue +174 -174
  60. package/src/layouts/CommonLayout.vue +42 -42
  61. package/src/layouts/ComponentLayoutOne.vue +47 -47
  62. package/src/layouts/PageLayout.vue +151 -151
  63. package/src/layouts/SinglePageView.vue +111 -111
  64. package/src/layouts/footer/PageFooter.vue +49 -49
  65. package/src/layouts/header/AdminHeader.vue +104 -104
  66. package/src/layouts/header/HeaderAvatar.vue +61 -60
  67. package/src/layouts/header/HeaderNotice.vue +167 -167
  68. package/src/layouts/header/HeaderSearch.vue +67 -67
  69. package/src/layouts/header/InstitutionDetail.vue +181 -181
  70. package/src/layouts/header/index.less +92 -92
  71. package/src/layouts/tabs/TabsHead.vue +190 -190
  72. package/src/layouts/tabs/TabsView.vue +379 -379
  73. package/src/mock/goods/index.js +108 -108
  74. package/src/pages/exception/404.vue +25 -25
  75. package/src/pages/login/Login.vue +363 -348
  76. package/src/pages/report/ReportTable.js +124 -124
  77. package/src/pages/report/ReportTableHome.vue +28 -28
  78. package/src/pages/resourceManage/orgListManage.vue +98 -98
  79. package/src/pages/system/dictionary/index.vue +43 -43
  80. package/src/pages/system/file/index.vue +317 -317
  81. package/src/pages/system/monitor/loginInfor/index.vue +36 -36
  82. package/src/pages/system/monitor/operLog/index.vue +36 -36
  83. package/src/pages/system/queryParams/index.vue +43 -43
  84. package/src/router/async/config.async.js +27 -27
  85. package/src/router/async/router.map.js +68 -68
  86. package/src/router/guards.js +113 -104
  87. package/src/router/index.js +27 -27
  88. package/src/services/api/DictionaryDetailsViewApi.js +6 -6
  89. package/src/services/api/LogDetailsViewApi.js +10 -10
  90. package/src/services/api/QueryParamsDetailsViewApi.js +6 -6
  91. package/src/services/api/TicketDetailsViewApi.js +34 -34
  92. package/src/services/api/cas.js +79 -79
  93. package/src/services/api/commonTempTable.js +10 -10
  94. package/src/services/api/index.js +17 -17
  95. package/src/services/api/logininfor/index.js +6 -6
  96. package/src/services/api/manage.js +8 -8
  97. package/src/services/apiService.js +13 -13
  98. package/src/services/user.js +53 -53
  99. package/src/store/modules/index.js +4 -4
  100. package/src/theme/default/nprogress.less +76 -76
  101. package/src/theme/default/style.less +47 -47
  102. package/src/utils/colors.js +107 -107
  103. package/src/utils/excel/Blob.js +180 -180
  104. package/src/utils/excel/Export2Excel.js +141 -141
  105. package/src/utils/formatter.js +68 -68
  106. package/src/utils/i18n.js +80 -80
  107. package/src/utils/indexedDB.js +145 -146
  108. package/src/utils/theme-color-replacer-extend.js +91 -91
  109. package/src/utils/themeUtil.js +100 -100
  110. package/src/utils/util.js +230 -230
  111. package/vue.config.js +106 -111
@@ -1,62 +1,62 @@
1
- <template>
2
- <a-layout-sider
3
- :theme="sideTheme"
4
- :class="['side-menu', 'beauty-scroll', isMobile ? null : 'shadow']"
5
- width="256px"
6
- :collapsible="collapsible"
7
- v-model="collapsed"
8
- :trigger="null">
9
- <div :class="['logo', theme]">
10
- <router-link to="/dashboard/workplace">
11
- <img :src="logoSrc" alt="logo">
12
- <h1 :style="{ fontWeight: 'bold', fontSize: systemNameFontSize }">{{ systemName }}</h1>
13
- </router-link>
14
- </div>
15
- <i-menu :theme="theme" :collapsed="collapsed" :options="menuData" @select="onSelect" class="menu"/>
16
- </a-layout-sider>
17
- </template>
18
-
19
- <script>
20
- import IMenu from './menu'
21
- import { mapState } from 'vuex'
22
- export default {
23
- name: 'SideMenu',
24
- components: { IMenu },
25
- props: {
26
- collapsible: {
27
- type: Boolean,
28
- required: false,
29
- default: false
30
- },
31
- collapsed: {
32
- type: Boolean,
33
- required: false,
34
- default: false
35
- },
36
- menuData: {
37
- type: Array,
38
- required: true
39
- },
40
- theme: {
41
- type: String,
42
- required: false,
43
- default: 'dark'
44
- }
45
- },
46
- computed: {
47
- sideTheme () {
48
- return this.theme === 'light' ? this.theme : 'dark'
49
- },
50
- ...mapState('setting', ['isMobile', 'systemName', 'logoSrc', 'systemNameFontSize'])
51
- },
52
- methods: {
53
- onSelect (obj) {
54
- this.$emit('menuSelect', obj)
55
- }
56
- }
57
- }
58
- </script>
59
-
60
- <style lang="less" scoped>
61
- @import "index";
62
- </style>
1
+ <template>
2
+ <a-layout-sider
3
+ :theme="sideTheme"
4
+ :class="['side-menu', 'beauty-scroll', isMobile ? null : 'shadow']"
5
+ width="256px"
6
+ :collapsible="collapsible"
7
+ v-model="collapsed"
8
+ :trigger="null">
9
+ <div :class="['logo', theme]">
10
+ <router-link to="/dashboard/workplace">
11
+ <img :src="logoSrc" alt="logo">
12
+ <h1 :style="{ fontWeight: 'bold', fontSize: systemNameFontSize }">{{ systemName }}</h1>
13
+ </router-link>
14
+ </div>
15
+ <i-menu :theme="theme" :collapsed="collapsed" :options="menuData" @select="onSelect" class="menu"/>
16
+ </a-layout-sider>
17
+ </template>
18
+
19
+ <script>
20
+ import IMenu from './menu'
21
+ import { mapState } from 'vuex'
22
+ export default {
23
+ name: 'SideMenu',
24
+ components: { IMenu },
25
+ props: {
26
+ collapsible: {
27
+ type: Boolean,
28
+ required: false,
29
+ default: false
30
+ },
31
+ collapsed: {
32
+ type: Boolean,
33
+ required: false,
34
+ default: false
35
+ },
36
+ menuData: {
37
+ type: Array,
38
+ required: true
39
+ },
40
+ theme: {
41
+ type: String,
42
+ required: false,
43
+ default: 'dark'
44
+ }
45
+ },
46
+ computed: {
47
+ sideTheme () {
48
+ return this.theme === 'light' ? this.theme : 'dark'
49
+ },
50
+ ...mapState('setting', ['isMobile', 'systemName', 'logoSrc', 'systemNameFontSize'])
51
+ },
52
+ methods: {
53
+ onSelect (obj) {
54
+ this.$emit('menuSelect', obj)
55
+ }
56
+ }
57
+ }
58
+ </script>
59
+
60
+ <style lang="less" scoped>
61
+ @import "index";
62
+ </style>
@@ -1,273 +1,273 @@
1
- /**
2
- * 该插件可根据菜单配置自动生成 ANTD menu组件
3
- * menuOptions示例:
4
- * [
5
- * {
6
- * name: '菜单名称',
7
- * path: '菜单路由',
8
- * meta: {
9
- * icon: '菜单图标',
10
- * invisible: 'boolean, 是否不可见, 默认 false',
11
- * },
12
- * children: [子菜单配置]
13
- * },
14
- * {
15
- * name: '菜单名称',
16
- * path: '菜单路由',
17
- * meta: {
18
- * icon: '菜单图标',
19
- * invisible: 'boolean, 是否不可见, 默认 false',
20
- * },
21
- * children: [子菜单配置]
22
- * }
23
- * ]
24
- *
25
- * i18n: 国际化配置。系统默认会根据 options route配置的 path 和 name 生成英文以及中文的国际化配置,如需自定义或增加其他语言,配置
26
- * 此项即可。如:
27
- * i18n: {
28
- * messages: {
29
- * CN: {dashboard: {name: '监控中心'}}
30
- * HK: {dashboard: {name: '監控中心'}}
31
- * }
32
- * }
33
- **/
34
- import Menu from 'ant-design-vue/es/menu'
35
- import Icon from 'ant-design-vue/es/icon'
36
- import fastEqual from 'fast-deep-equal'
37
- import { getI18nKey } from '@vue2-client/utils/routerUtil'
38
- import { mapMutations } from 'vuex'
39
-
40
- const { Item, SubMenu } = Menu
41
-
42
- const resolvePath = (path, params = {}) => {
43
- let _path = path
44
- Object.entries(params).forEach(([key, value]) => {
45
- _path = _path.replace(new RegExp(`:${key}`, 'g'), value)
46
- })
47
- return _path
48
- }
49
-
50
- const toRoutesMap = (routes) => {
51
- const map = {}
52
- routes.forEach(route => {
53
- map[route.fullPath] = route
54
- if (route.children && route.children.length > 0) {
55
- const childrenMap = toRoutesMap(route.children)
56
- Object.assign(map, childrenMap)
57
- }
58
- })
59
- return map
60
- }
61
-
62
- export default {
63
- name: 'IMenu',
64
- props: {
65
- options: {
66
- type: Array,
67
- required: true
68
- },
69
- theme: {
70
- type: String,
71
- required: false,
72
- default: 'dark'
73
- },
74
- mode: {
75
- type: String,
76
- required: false,
77
- default: 'inline'
78
- },
79
- collapsed: {
80
- type: Boolean,
81
- required: false,
82
- default: false
83
- },
84
- i18n: Object,
85
- openKeys: Array
86
- },
87
- data () {
88
- return {
89
- selectedKeys: [],
90
- sOpenKeys: [],
91
- cachedOpenKeys: []
92
- }
93
- },
94
- computed: {
95
- menuTheme () {
96
- return this.theme === 'light' ? this.theme : 'dark'
97
- },
98
- routesMap () {
99
- return toRoutesMap(this.options)
100
- }
101
- },
102
- created () {
103
- this.updateMenu()
104
- if (this.options.length > 0 && !this.options[0].fullPath) {
105
- this.formatOptions(this.options, '')
106
- }
107
- // 自定义国际化配置
108
- if (this.i18n && this.i18n.messages) {
109
- const messages = this.i18n.messages
110
- Object.keys(messages).forEach(key => {
111
- this.$i18n.mergeLocaleMessage(key, messages[key])
112
- })
113
- }
114
- },
115
- watch: {
116
- options (val) {
117
- if (val.length > 0 && !val[0].fullPath) {
118
- this.formatOptions(this.options, '')
119
- }
120
- },
121
- i18n (val) {
122
- if (val && val.messages) {
123
- const messages = this.i18n.messages
124
- Object.keys(messages).forEach(key => {
125
- this.$i18n.mergeLocaleMessage(key, messages[key])
126
- })
127
- }
128
- },
129
- collapsed (val) {
130
- if (val) {
131
- this.cachedOpenKeys = this.sOpenKeys
132
- this.sOpenKeys = []
133
- } else {
134
- this.sOpenKeys = this.cachedOpenKeys
135
- }
136
- },
137
- '$route': function () {
138
- if (this.$route.meta && this.$route.meta.singlePage) {
139
- this.setSingle(this.$route)
140
- }
141
- this.updateMenu()
142
- },
143
- sOpenKeys (val) {
144
- this.$emit('openChange', val)
145
- this.$emit('update:openKeys', val)
146
- }
147
- },
148
- methods: {
149
- ...mapMutations('account', ['setSingle']),
150
- renderIcon: function (h, icon, key) {
151
- if (this.$scopedSlots.icon && icon && icon !== 'none') {
152
- const vnodes = this.$scopedSlots.icon({ icon, key })
153
- vnodes.forEach(vnode => {
154
- vnode.data.class = vnode.data.class ? vnode.data.class : []
155
- vnode.data.class.push('anticon')
156
- })
157
- return vnodes
158
- }
159
- return !icon || icon === 'none' ? null : h(Icon, { props: { type: icon } })
160
- },
161
- renderMenuItem: function (h, menu) {
162
- let tag = 'router-link'
163
- const path = resolvePath(menu.fullPath, menu.meta.params)
164
- let config = { props: { to: { path, query: menu.meta.query } }, attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' } }
165
- if (menu.meta && menu.meta.link) {
166
- tag = 'a'
167
- config = { attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;', href: menu.meta.link, target: '_blank' } }
168
- }
169
- return h(
170
- Item, { key: menu.fullPath },
171
- [
172
- h(tag, config,
173
- [
174
- this.renderIcon(h, menu.meta ? menu.meta.icon : 'none', menu.fullPath),
175
- this.$t(getI18nKey(menu.fullPath))
176
- ]
177
- )
178
- ]
179
- )
180
- },
181
- renderSubMenu: function (h, menu) {
182
- const this_ = this
183
- const subItem = [h('span', { slot: 'title', attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' } },
184
- [
185
- this.renderIcon(h, menu.meta ? menu.meta.icon : 'none', menu.fullPath),
186
- this.$t(getI18nKey(menu.fullPath))
187
- ]
188
- )]
189
- const itemArr = []
190
- menu.children.forEach(function (item) {
191
- itemArr.push(this_.renderItem(h, item))
192
- })
193
- return h(SubMenu, { key: menu.fullPath },
194
- subItem.concat(itemArr)
195
- )
196
- },
197
- renderItem: function (h, menu) {
198
- const meta = menu.meta
199
- if (!meta || !meta.invisible) {
200
- let renderChildren = false
201
- const children = menu.children
202
- if (children !== undefined) {
203
- for (let i = 0; i < children.length; i++) {
204
- const childMeta = children[i].meta
205
- if (!childMeta || !childMeta.invisible) {
206
- renderChildren = true
207
- break
208
- }
209
- }
210
- }
211
- return (menu.children && renderChildren) ? this.renderSubMenu(h, menu) : this.renderMenuItem(h, menu)
212
- }
213
- },
214
- renderMenu: function (h, menuTree) {
215
- const this_ = this
216
- const menuArr = []
217
- menuTree.forEach(function (menu, i) {
218
- menuArr.push(this_.renderItem(h, menu, '0', i))
219
- })
220
- return menuArr
221
- },
222
- formatOptions (options, parentPath) {
223
- options.forEach(route => {
224
- const isFullPath = route.path.substring(0, 1) === '/'
225
- route.fullPath = isFullPath ? route.path : parentPath + '/' + route.path
226
- if (route.children) {
227
- this.formatOptions(route.children, route.fullPath)
228
- }
229
- })
230
- },
231
- updateMenu () {
232
- this.selectedKeys = this.getSelectedKeys()
233
- let openKeys = this.selectedKeys.filter(item => item !== '')
234
- openKeys = openKeys.slice(0, openKeys.length - 1)
235
- if (!fastEqual(openKeys, this.sOpenKeys)) {
236
- this.collapsed || this.mode === 'horizontal' ? this.cachedOpenKeys = openKeys : this.sOpenKeys = openKeys
237
- }
238
- },
239
- getSelectedKeys () {
240
- let matches = this.$route.matched
241
- const route = matches[matches.length - 1]
242
- let chose = this.routesMap[route.path]
243
- if (chose && chose.meta && chose.meta.highlight) {
244
- chose = this.routesMap[chose.meta.highlight]
245
- const resolve = this.$router.resolve({ path: chose.fullPath })
246
- matches = (resolve.resolved && resolve.resolved.matched) || matches
247
- }
248
- return matches.map(item => item.path)
249
- }
250
- },
251
- render (h) {
252
- return h(
253
- Menu,
254
- {
255
- props: {
256
- theme: this.menuTheme,
257
- mode: this.$props.mode,
258
- selectedKeys: this.selectedKeys,
259
- openKeys: this.openKeys ? this.openKeys : this.sOpenKeys
260
- },
261
- on: {
262
- 'update:openKeys': (val) => {
263
- this.sOpenKeys = val
264
- },
265
- click: (obj) => {
266
- obj.selectedKeys = [obj.key]
267
- this.$emit('select', obj)
268
- }
269
- }
270
- }, this.renderMenu(h, this.options)
271
- )
272
- }
273
- }
1
+ /**
2
+ * 该插件可根据菜单配置自动生成 ANTD menu组件
3
+ * menuOptions示例:
4
+ * [
5
+ * {
6
+ * name: '菜单名称',
7
+ * path: '菜单路由',
8
+ * meta: {
9
+ * icon: '菜单图标',
10
+ * invisible: 'boolean, 是否不可见, 默认 false',
11
+ * },
12
+ * children: [子菜单配置]
13
+ * },
14
+ * {
15
+ * name: '菜单名称',
16
+ * path: '菜单路由',
17
+ * meta: {
18
+ * icon: '菜单图标',
19
+ * invisible: 'boolean, 是否不可见, 默认 false',
20
+ * },
21
+ * children: [子菜单配置]
22
+ * }
23
+ * ]
24
+ *
25
+ * i18n: 国际化配置。系统默认会根据 options route配置的 path 和 name 生成英文以及中文的国际化配置,如需自定义或增加其他语言,配置
26
+ * 此项即可。如:
27
+ * i18n: {
28
+ * messages: {
29
+ * CN: {dashboard: {name: '监控中心'}}
30
+ * HK: {dashboard: {name: '監控中心'}}
31
+ * }
32
+ * }
33
+ **/
34
+ import Menu from 'ant-design-vue/es/menu'
35
+ import Icon from 'ant-design-vue/es/icon'
36
+ import fastEqual from 'fast-deep-equal'
37
+ import { getI18nKey } from '@vue2-client/utils/routerUtil'
38
+ import { mapMutations } from 'vuex'
39
+
40
+ const { Item, SubMenu } = Menu
41
+
42
+ const resolvePath = (path, params = {}) => {
43
+ let _path = path
44
+ Object.entries(params).forEach(([key, value]) => {
45
+ _path = _path.replace(new RegExp(`:${key}`, 'g'), value)
46
+ })
47
+ return _path
48
+ }
49
+
50
+ const toRoutesMap = (routes) => {
51
+ const map = {}
52
+ routes.forEach(route => {
53
+ map[route.fullPath] = route
54
+ if (route.children && route.children.length > 0) {
55
+ const childrenMap = toRoutesMap(route.children)
56
+ Object.assign(map, childrenMap)
57
+ }
58
+ })
59
+ return map
60
+ }
61
+
62
+ export default {
63
+ name: 'IMenu',
64
+ props: {
65
+ options: {
66
+ type: Array,
67
+ required: true
68
+ },
69
+ theme: {
70
+ type: String,
71
+ required: false,
72
+ default: 'dark'
73
+ },
74
+ mode: {
75
+ type: String,
76
+ required: false,
77
+ default: 'inline'
78
+ },
79
+ collapsed: {
80
+ type: Boolean,
81
+ required: false,
82
+ default: false
83
+ },
84
+ i18n: Object,
85
+ openKeys: Array
86
+ },
87
+ data () {
88
+ return {
89
+ selectedKeys: [],
90
+ sOpenKeys: [],
91
+ cachedOpenKeys: []
92
+ }
93
+ },
94
+ computed: {
95
+ menuTheme () {
96
+ return this.theme === 'light' ? this.theme : 'dark'
97
+ },
98
+ routesMap () {
99
+ return toRoutesMap(this.options)
100
+ }
101
+ },
102
+ created () {
103
+ this.updateMenu()
104
+ if (this.options.length > 0 && !this.options[0].fullPath) {
105
+ this.formatOptions(this.options, '')
106
+ }
107
+ // 自定义国际化配置
108
+ if (this.i18n && this.i18n.messages) {
109
+ const messages = this.i18n.messages
110
+ Object.keys(messages).forEach(key => {
111
+ this.$i18n.mergeLocaleMessage(key, messages[key])
112
+ })
113
+ }
114
+ },
115
+ watch: {
116
+ options (val) {
117
+ if (val.length > 0 && !val[0].fullPath) {
118
+ this.formatOptions(this.options, '')
119
+ }
120
+ },
121
+ i18n (val) {
122
+ if (val && val.messages) {
123
+ const messages = this.i18n.messages
124
+ Object.keys(messages).forEach(key => {
125
+ this.$i18n.mergeLocaleMessage(key, messages[key])
126
+ })
127
+ }
128
+ },
129
+ collapsed (val) {
130
+ if (val) {
131
+ this.cachedOpenKeys = this.sOpenKeys
132
+ this.sOpenKeys = []
133
+ } else {
134
+ this.sOpenKeys = this.cachedOpenKeys
135
+ }
136
+ },
137
+ '$route': function () {
138
+ if (this.$route.meta && this.$route.meta.singlePage) {
139
+ this.setSingle(this.$route)
140
+ }
141
+ this.updateMenu()
142
+ },
143
+ sOpenKeys (val) {
144
+ this.$emit('openChange', val)
145
+ this.$emit('update:openKeys', val)
146
+ }
147
+ },
148
+ methods: {
149
+ ...mapMutations('account', ['setSingle']),
150
+ renderIcon: function (h, icon, key) {
151
+ if (this.$scopedSlots.icon && icon && icon !== 'none') {
152
+ const vnodes = this.$scopedSlots.icon({ icon, key })
153
+ vnodes.forEach(vnode => {
154
+ vnode.data.class = vnode.data.class ? vnode.data.class : []
155
+ vnode.data.class.push('anticon')
156
+ })
157
+ return vnodes
158
+ }
159
+ return !icon || icon === 'none' ? null : h(Icon, { props: { type: icon } })
160
+ },
161
+ renderMenuItem: function (h, menu) {
162
+ let tag = 'router-link'
163
+ const path = resolvePath(menu.fullPath, menu.meta.params)
164
+ let config = { props: { to: { path, query: menu.meta.query } }, attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' } }
165
+ if (menu.meta && menu.meta.link) {
166
+ tag = 'a'
167
+ config = { attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;', href: menu.meta.link, target: '_blank' } }
168
+ }
169
+ return h(
170
+ Item, { key: menu.fullPath },
171
+ [
172
+ h(tag, config,
173
+ [
174
+ this.renderIcon(h, menu.meta ? menu.meta.icon : 'none', menu.fullPath),
175
+ this.$t(getI18nKey(menu.fullPath))
176
+ ]
177
+ )
178
+ ]
179
+ )
180
+ },
181
+ renderSubMenu: function (h, menu) {
182
+ const this_ = this
183
+ const subItem = [h('span', { slot: 'title', attrs: { style: 'overflow:hidden;white-space:normal;text-overflow:clip;' } },
184
+ [
185
+ this.renderIcon(h, menu.meta ? menu.meta.icon : 'none', menu.fullPath),
186
+ this.$t(getI18nKey(menu.fullPath))
187
+ ]
188
+ )]
189
+ const itemArr = []
190
+ menu.children.forEach(function (item) {
191
+ itemArr.push(this_.renderItem(h, item))
192
+ })
193
+ return h(SubMenu, { key: menu.fullPath },
194
+ subItem.concat(itemArr)
195
+ )
196
+ },
197
+ renderItem: function (h, menu) {
198
+ const meta = menu.meta
199
+ if (!meta || !meta.invisible) {
200
+ let renderChildren = false
201
+ const children = menu.children
202
+ if (children !== undefined) {
203
+ for (let i = 0; i < children.length; i++) {
204
+ const childMeta = children[i].meta
205
+ if (!childMeta || !childMeta.invisible) {
206
+ renderChildren = true
207
+ break
208
+ }
209
+ }
210
+ }
211
+ return (menu.children && renderChildren) ? this.renderSubMenu(h, menu) : this.renderMenuItem(h, menu)
212
+ }
213
+ },
214
+ renderMenu: function (h, menuTree) {
215
+ const this_ = this
216
+ const menuArr = []
217
+ menuTree.forEach(function (menu, i) {
218
+ menuArr.push(this_.renderItem(h, menu, '0', i))
219
+ })
220
+ return menuArr
221
+ },
222
+ formatOptions (options, parentPath) {
223
+ options.forEach(route => {
224
+ const isFullPath = route.path.substring(0, 1) === '/'
225
+ route.fullPath = isFullPath ? route.path : parentPath + '/' + route.path
226
+ if (route.children) {
227
+ this.formatOptions(route.children, route.fullPath)
228
+ }
229
+ })
230
+ },
231
+ updateMenu () {
232
+ this.selectedKeys = this.getSelectedKeys()
233
+ let openKeys = this.selectedKeys.filter(item => item !== '')
234
+ openKeys = openKeys.slice(0, openKeys.length - 1)
235
+ if (!fastEqual(openKeys, this.sOpenKeys)) {
236
+ this.collapsed || this.mode === 'horizontal' ? this.cachedOpenKeys = openKeys : this.sOpenKeys = openKeys
237
+ }
238
+ },
239
+ getSelectedKeys () {
240
+ let matches = this.$route.matched
241
+ const route = matches[matches.length - 1]
242
+ let chose = this.routesMap[route.path]
243
+ if (chose && chose.meta && chose.meta.highlight) {
244
+ chose = this.routesMap[chose.meta.highlight]
245
+ const resolve = this.$router.resolve({ path: chose.fullPath })
246
+ matches = (resolve.resolved && resolve.resolved.matched) || matches
247
+ }
248
+ return matches.map(item => item.path)
249
+ }
250
+ },
251
+ render (h) {
252
+ return h(
253
+ Menu,
254
+ {
255
+ props: {
256
+ theme: this.menuTheme,
257
+ mode: this.$props.mode,
258
+ selectedKeys: this.selectedKeys,
259
+ openKeys: this.openKeys ? this.openKeys : this.sOpenKeys
260
+ },
261
+ on: {
262
+ 'update:openKeys': (val) => {
263
+ this.sOpenKeys = val
264
+ },
265
+ click: (obj) => {
266
+ obj.selectedKeys = [obj.key]
267
+ this.$emit('select', obj)
268
+ }
269
+ }
270
+ }, this.renderMenu(h, this.options)
271
+ )
272
+ }
273
+ }