提交 | 用户 | age
|
2f6253
|
1 |
import type { PropType } from 'vue'; |
陈 |
2 |
import type { Menu } from '/@/router/types'; |
|
3 |
|
|
4 |
import { computed, defineComponent, unref, ref, onMounted, watch } from 'vue'; |
|
5 |
import { BasicMenu } from '/@/components/Menu/index'; |
|
6 |
import Logo from '/@/layouts/Logo.vue'; |
|
7 |
|
|
8 |
import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; |
|
9 |
|
|
10 |
// store |
|
11 |
import { appStore } from '/@/store/modules/app'; |
|
12 |
import { menuStore } from '/@/store/modules/menu'; |
|
13 |
|
|
14 |
import { |
|
15 |
getMenus, |
|
16 |
getFlatMenus, |
|
17 |
getShallowMenus, |
|
18 |
getChildrenMenus, |
|
19 |
getFlatChildrenMenus, |
|
20 |
getCurrentParentPath, |
|
21 |
} from '/@/router/menus/index'; |
|
22 |
import { useRouter } from 'vue-router'; |
|
23 |
import { useThrottle } from '/@/hooks/core/useThrottle'; |
|
24 |
import { permissionStore } from '/@/store/modules/permission'; |
6bffdb
|
25 |
// import { useTabs } from '/@/hooks/web/useTabs'; |
V |
26 |
// import { PageEnum } from '/@/enums/pageEnum'; |
2f6253
|
27 |
|
陈 |
28 |
// import |
|
29 |
export default defineComponent({ |
|
30 |
name: 'DefaultLayoutMenu', |
|
31 |
props: { |
|
32 |
theme: { |
|
33 |
type: String as PropType<string>, |
|
34 |
default: '', |
|
35 |
}, |
|
36 |
splitType: { |
|
37 |
type: Number as PropType<MenuSplitTyeEnum>, |
|
38 |
default: MenuSplitTyeEnum.NONE, |
|
39 |
}, |
|
40 |
parentMenuPath: { |
|
41 |
type: String as PropType<string>, |
|
42 |
default: '', |
|
43 |
}, |
|
44 |
showSearch: { |
|
45 |
type: Boolean as PropType<boolean>, |
|
46 |
default: true, |
|
47 |
}, |
770283
|
48 |
isTop: { |
V |
49 |
type: Boolean as PropType<boolean>, |
|
50 |
default: false, |
|
51 |
}, |
2f6253
|
52 |
menuMode: { |
陈 |
53 |
type: [String] as PropType<MenuModeEnum | null>, |
|
54 |
default: '', |
|
55 |
}, |
|
56 |
}, |
|
57 |
setup(props) { |
4ff6b7
|
58 |
// Menu array |
2f6253
|
59 |
const menusRef = ref<Menu[]>([]); |
4ff6b7
|
60 |
// flat menu array |
2f6253
|
61 |
const flatMenusRef = ref<Menu[]>([]); |
6bffdb
|
62 |
const { currentRoute, push } = useRouter(); |
2f6253
|
63 |
|
4ff6b7
|
64 |
// get app config |
2f6253
|
65 |
const getProjectConfigRef = computed(() => { |
陈 |
66 |
return appStore.getProjectConfig; |
|
67 |
}); |
|
68 |
|
4ff6b7
|
69 |
// get is Horizontal |
2f6253
|
70 |
const getIsHorizontalRef = computed(() => { |
陈 |
71 |
return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL; |
|
72 |
}); |
|
73 |
|
|
74 |
const [throttleHandleSplitLeftMenu] = useThrottle(handleSplitLeftMenu, 50); |
|
75 |
|
4ff6b7
|
76 |
// Route change split menu |
2f6253
|
77 |
watch( |
陈 |
78 |
[() => unref(currentRoute).path, () => props.splitType], |
|
79 |
async ([path, splitType]: [string, MenuSplitTyeEnum]) => { |
|
80 |
if (splitType !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontalRef)) return; |
|
81 |
const parentPath = await getCurrentParentPath(path); |
|
82 |
parentPath && throttleHandleSplitLeftMenu(parentPath); |
|
83 |
}, |
|
84 |
{ |
|
85 |
immediate: true, |
|
86 |
} |
|
87 |
); |
4f6b65
|
88 |
|
4ff6b7
|
89 |
// Menu changes |
2f6253
|
90 |
watch( |
4ff6b7
|
91 |
[() => permissionStore.getLastBuildMenuTimeState, () => permissionStore.getBackMenuListState], |
2f6253
|
92 |
() => { |
陈 |
93 |
genMenus(); |
|
94 |
} |
|
95 |
); |
|
96 |
|
4ff6b7
|
97 |
// split Menu changes |
2f6253
|
98 |
watch([() => appStore.getProjectConfig.menuSetting.split], () => { |
陈 |
99 |
if (props.splitType !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontalRef)) return; |
|
100 |
genMenus(); |
|
101 |
}); |
|
102 |
|
4ff6b7
|
103 |
// Handle left menu split |
2f6253
|
104 |
async function handleSplitLeftMenu(parentPath: string) { |
陈 |
105 |
const isSplitMenu = unref(getProjectConfigRef).menuSetting.split; |
|
106 |
if (!isSplitMenu) return; |
|
107 |
const { splitType } = props; |
4ff6b7
|
108 |
// spilt mode left |
2f6253
|
109 |
if (splitType === MenuSplitTyeEnum.LEFT) { |
陈 |
110 |
const children = await getChildrenMenus(parentPath); |
96c10d
|
111 |
if (!children) { |
V |
112 |
appStore.commitProjectConfigState({ |
|
113 |
menuSetting: { |
4f6b65
|
114 |
hidden: false, |
96c10d
|
115 |
}, |
V |
116 |
}); |
|
117 |
flatMenusRef.value = []; |
|
118 |
menusRef.value = []; |
|
119 |
return; |
|
120 |
} |
2f6253
|
121 |
const flatChildren = await getFlatChildrenMenus(children); |
96c10d
|
122 |
appStore.commitProjectConfigState({ |
V |
123 |
menuSetting: { |
4f6b65
|
124 |
hidden: true, |
96c10d
|
125 |
}, |
V |
126 |
}); |
2f6253
|
127 |
flatMenusRef.value = flatChildren; |
陈 |
128 |
menusRef.value = children; |
|
129 |
} |
|
130 |
} |
|
131 |
|
4ff6b7
|
132 |
// get menus |
2f6253
|
133 |
async function genMenus() { |
陈 |
134 |
const isSplitMenu = unref(getProjectConfigRef).menuSetting.split; |
|
135 |
|
4ff6b7
|
136 |
// normal mode |
2f6253
|
137 |
const { splitType } = props; |
陈 |
138 |
if (splitType === MenuSplitTyeEnum.NONE || !isSplitMenu) { |
|
139 |
flatMenusRef.value = await getFlatMenus(); |
|
140 |
menusRef.value = await getMenus(); |
|
141 |
return; |
|
142 |
} |
|
143 |
|
4ff6b7
|
144 |
// split-top |
2f6253
|
145 |
if (splitType === MenuSplitTyeEnum.TOP) { |
陈 |
146 |
const parentPath = await getCurrentParentPath(unref(currentRoute).path); |
|
147 |
menuStore.commitCurrentTopSplitMenuPathState(parentPath); |
|
148 |
const shallowMenus = await getShallowMenus(); |
|
149 |
|
|
150 |
flatMenusRef.value = shallowMenus; |
|
151 |
menusRef.value = shallowMenus; |
|
152 |
return; |
|
153 |
} |
|
154 |
} |
|
155 |
|
|
156 |
function handleMenuClick(menu: Menu) { |
|
157 |
const { path } = menu; |
|
158 |
if (path) { |
|
159 |
const { splitType } = props; |
4ff6b7
|
160 |
// split mode top |
2f6253
|
161 |
if (splitType === MenuSplitTyeEnum.TOP) { |
陈 |
162 |
menuStore.commitCurrentTopSplitMenuPathState(path); |
|
163 |
} |
6bffdb
|
164 |
push(path); |
2f6253
|
165 |
} |
陈 |
166 |
} |
|
167 |
|
|
168 |
async function beforeMenuClickFn(menu: Menu) { |
|
169 |
const { meta: { externalLink } = {} } = menu; |
|
170 |
|
|
171 |
if (externalLink) { |
|
172 |
window.open(externalLink, '_blank'); |
|
173 |
return false; |
|
174 |
} |
|
175 |
|
|
176 |
return true; |
|
177 |
} |
|
178 |
|
|
179 |
function handleClickSearchInput() { |
|
180 |
if (menuStore.getCollapsedState) { |
|
181 |
menuStore.commitCollapsedState(false); |
|
182 |
} |
|
183 |
} |
|
184 |
|
|
185 |
const showSearchRef = computed(() => { |
|
186 |
const { showSearch, type, mode } = unref(getProjectConfigRef).menuSetting; |
|
187 |
return ( |
|
188 |
showSearch && |
|
189 |
props.showSearch && |
|
190 |
!(type === MenuTypeEnum.MIX && mode === MenuModeEnum.HORIZONTAL) |
|
191 |
); |
|
192 |
}); |
|
193 |
|
4f6b65
|
194 |
onMounted(() => { |
V |
195 |
genMenus(); |
|
196 |
}); |
|
197 |
|
2f6253
|
198 |
return () => { |
陈 |
199 |
const { |
|
200 |
showLogo, |
e79e54
|
201 |
menuSetting: { |
V |
202 |
type: menuType, |
|
203 |
mode, |
|
204 |
theme, |
|
205 |
collapsed, |
|
206 |
collapsedShowTitle, |
|
207 |
collapsedShowSearch, |
4ff6b7
|
208 |
accordion, |
e79e54
|
209 |
}, |
2f6253
|
210 |
} = unref(getProjectConfigRef); |
陈 |
211 |
|
|
212 |
const isSidebarType = menuType === MenuTypeEnum.SIDEBAR; |
|
213 |
const isShowLogo = showLogo && isSidebarType; |
|
214 |
const themeData = props.theme || theme; |
|
215 |
return ( |
|
216 |
<BasicMenu |
|
217 |
beforeClickFn={beforeMenuClickFn} |
|
218 |
onMenuClick={handleMenuClick} |
|
219 |
type={menuType} |
|
220 |
mode={props.menuMode || mode} |
|
221 |
class="layout-menu" |
5737e4
|
222 |
collapsedShowTitle={collapsedShowTitle} |
2f6253
|
223 |
theme={themeData} |
陈 |
224 |
showLogo={isShowLogo} |
e79e54
|
225 |
search={unref(showSearchRef) && (collapsedShowSearch ? true : !collapsed)} |
2f6253
|
226 |
items={unref(menusRef)} |
陈 |
227 |
flatItems={unref(flatMenusRef)} |
|
228 |
onClickSearchInput={handleClickSearchInput} |
|
229 |
appendClass={props.splitType === MenuSplitTyeEnum.TOP} |
770283
|
230 |
isTop={props.isTop} |
4ff6b7
|
231 |
accordion={accordion} |
2f6253
|
232 |
> |
陈 |
233 |
{{ |
|
234 |
header: () => |
|
235 |
isShowLogo && ( |
4f6b65
|
236 |
<Logo |
V |
237 |
showTitle={!collapsed} |
|
238 |
class={[`layout-menu__logo`, themeData]} |
|
239 |
theme={themeData} |
|
240 |
/> |
2f6253
|
241 |
), |
陈 |
242 |
}} |
|
243 |
</BasicMenu> |
|
244 |
); |
|
245 |
}; |
|
246 |
}, |
|
247 |
}); |