Commit f645680a3b9a1f75395329970551d9e5d6bd845b
1 parent
c8021ef3
feat: right-click menu supports multiple levels
Showing
15 changed files
with
138 additions
and
52 deletions
CHANGELOG.zh_CN.md
@@ -3,6 +3,7 @@ | @@ -3,6 +3,7 @@ | ||
3 | ### ✨ Features | 3 | ### ✨ Features |
4 | 4 | ||
5 | - 全局 loading 添加文本 | 5 | - 全局 loading 添加文本 |
6 | +- 右键菜单支持多级 | ||
6 | 7 | ||
7 | ### 🎫 Chores | 8 | ### 🎫 Chores |
8 | 9 | ||
@@ -13,7 +14,7 @@ | @@ -13,7 +14,7 @@ | ||
13 | - Layout 界面布局样式调整 | 14 | - Layout 界面布局样式调整 |
14 | - 优化表格渲染性能 | 15 | - 优化表格渲染性能 |
15 | - 表单折叠搜索添图标添加动画 | 16 | - 表单折叠搜索添图标添加动画 |
16 | -- routeModule 可以忽略 layou 配置不写。方便配置一级菜单 | 17 | +- routeModule 可以忽略 layout 配置不写。方便配置一级菜单 |
17 | 18 | ||
18 | ### 🐛 Bug Fixes | 19 | ### 🐛 Bug Fixes |
19 | 20 |
src/components/ContextMenu/src/index.less
1 | @import (reference) '../../../design/index.less'; | 1 | @import (reference) '../../../design/index.less'; |
2 | 2 | ||
3 | +.item-style() { | ||
4 | + li { | ||
5 | + display: inline-block; | ||
6 | + width: 100%; | ||
7 | + height: 46px !important; | ||
8 | + margin: 0 !important; | ||
9 | + line-height: 46px; | ||
10 | + | ||
11 | + span { | ||
12 | + line-height: 46px; | ||
13 | + } | ||
14 | + | ||
15 | + > div { | ||
16 | + margin: 0 !important; | ||
17 | + } | ||
18 | + | ||
19 | + &:hover { | ||
20 | + color: @text-color-base; | ||
21 | + background: #eee; | ||
22 | + } | ||
23 | + } | ||
24 | +} | ||
25 | + | ||
3 | .context-menu { | 26 | .context-menu { |
4 | position: fixed; | 27 | position: fixed; |
5 | top: 0; | 28 | top: 0; |
@@ -18,32 +41,17 @@ | @@ -18,32 +41,17 @@ | ||
18 | background-clip: padding-box; | 41 | background-clip: padding-box; |
19 | user-select: none; | 42 | user-select: none; |
20 | 43 | ||
21 | - &.hidden { | ||
22 | - display: none !important; | ||
23 | - } | 44 | + .item-style(); |
24 | 45 | ||
25 | - &__item { | ||
26 | - a { | ||
27 | - display: inline-block; | ||
28 | - width: 100%; | ||
29 | - padding: 10px 14px; | 46 | + .ant-divider { |
47 | + margin: 0 0; | ||
48 | + } | ||
30 | 49 | ||
31 | - &:hover { | ||
32 | - color: @text-color-base; | ||
33 | - background: #eee; | ||
34 | - } | 50 | + &__popup { |
51 | + .ant-divider { | ||
52 | + margin: 0 0; | ||
35 | } | 53 | } |
36 | 54 | ||
37 | - &.disabled { | ||
38 | - a { | ||
39 | - color: @disabled-color; | ||
40 | - cursor: not-allowed; | ||
41 | - | ||
42 | - &:hover { | ||
43 | - color: @disabled-color; | ||
44 | - background: unset; | ||
45 | - } | ||
46 | - } | ||
47 | - } | 55 | + .item-style(); |
48 | } | 56 | } |
49 | } | 57 | } |
src/components/ContextMenu/src/index.tsx
@@ -8,9 +8,13 @@ import { | @@ -8,9 +8,13 @@ import { | ||
8 | unref, | 8 | unref, |
9 | onUnmounted, | 9 | onUnmounted, |
10 | } from 'vue'; | 10 | } from 'vue'; |
11 | + | ||
11 | import { props } from './props'; | 12 | import { props } from './props'; |
12 | import Icon from '/@/components/Icon'; | 13 | import Icon from '/@/components/Icon'; |
14 | +import { Menu, Divider } from 'ant-design-vue'; | ||
15 | + | ||
13 | import type { ContextMenuItem } from './types'; | 16 | import type { ContextMenuItem } from './types'; |
17 | + | ||
14 | import './index.less'; | 18 | import './index.less'; |
15 | const prefixCls = 'context-menu'; | 19 | const prefixCls = 'context-menu'; |
16 | export default defineComponent({ | 20 | export default defineComponent({ |
@@ -43,12 +47,13 @@ export default defineComponent({ | @@ -43,12 +47,13 @@ export default defineComponent({ | ||
43 | top: (body.clientHeight < y + menuHeight ? y - menuHeight : y) + 'px', | 47 | top: (body.clientHeight < y + menuHeight ? y - menuHeight : y) + 'px', |
44 | }; | 48 | }; |
45 | }); | 49 | }); |
50 | + | ||
46 | function handleAction(item: ContextMenuItem, e: MouseEvent) { | 51 | function handleAction(item: ContextMenuItem, e: MouseEvent) { |
52 | + state.show = false; | ||
47 | const { handler, disabled } = item; | 53 | const { handler, disabled } = item; |
48 | if (disabled) { | 54 | if (disabled) { |
49 | return; | 55 | return; |
50 | } | 56 | } |
51 | - state.show = false; | ||
52 | if (e) { | 57 | if (e) { |
53 | e.stopPropagation(); | 58 | e.stopPropagation(); |
54 | e.preventDefault(); | 59 | e.preventDefault(); |
@@ -61,31 +66,47 @@ export default defineComponent({ | @@ -61,31 +66,47 @@ export default defineComponent({ | ||
61 | 66 | ||
62 | const { showIcon } = props; | 67 | const { showIcon } = props; |
63 | return ( | 68 | return ( |
64 | - <span style="display: inline-block; width: 100%;"> | 69 | + <span style="display: inline-block; width: 100%;" onClick={handleAction.bind(null, item)}> |
65 | {showIcon && icon && <Icon class="mr-2" icon={icon} />} | 70 | {showIcon && icon && <Icon class="mr-2" icon={icon} />} |
66 | <span>{label}</span> | 71 | <span>{label}</span> |
67 | </span> | 72 | </span> |
68 | ); | 73 | ); |
69 | } | 74 | } |
70 | function renderMenuItem(items: ContextMenuItem[]) { | 75 | function renderMenuItem(items: ContextMenuItem[]) { |
71 | - return items.map((item) => { | ||
72 | - const { disabled, label } = item; | 76 | + return items.map((item, index) => { |
77 | + const { disabled, label, children, divider = false } = item; | ||
73 | 78 | ||
74 | - return ( | ||
75 | - <li class={`${prefixCls}__item ${disabled ? 'disabled' : ''}`} key={label}> | ||
76 | - <a onClick={handleAction.bind(null, item)} style="color:#333;"> | ||
77 | - {renderContent(item)} | ||
78 | - </a> | ||
79 | - </li> | 79 | + const DividerComp = divider ? <Divider key={`d-${index}`} /> : null; |
80 | + if (!children || children.length === 0) { | ||
81 | + return [ | ||
82 | + <Menu.Item disabled={disabled} class={`${prefixCls}__item`} key={label}> | ||
83 | + {() => [renderContent(item)]} | ||
84 | + </Menu.Item>, | ||
85 | + DividerComp, | ||
86 | + ]; | ||
87 | + } | ||
88 | + return !state.show ? null : ( | ||
89 | + <Menu.SubMenu key={label} disabled={disabled} popupClassName={`${prefixCls}__popup `}> | ||
90 | + {{ | ||
91 | + title: () => renderContent(item), | ||
92 | + default: () => [renderMenuItem(children)], | ||
93 | + }} | ||
94 | + </Menu.SubMenu> | ||
80 | ); | 95 | ); |
81 | }); | 96 | }); |
82 | } | 97 | } |
83 | return () => { | 98 | return () => { |
84 | const { items } = props; | 99 | const { items } = props; |
85 | - return ( | ||
86 | - <ul class={[prefixCls, !state.show && 'hidden']} ref={wrapRef} style={unref(getStyle)}> | ||
87 | - {renderMenuItem(items)} | ||
88 | - </ul> | 100 | + return !state.show ? null : ( |
101 | + <Menu | ||
102 | + inlineIndent={12} | ||
103 | + mode="vertical" | ||
104 | + class={[prefixCls]} | ||
105 | + ref={wrapRef} | ||
106 | + style={unref(getStyle)} | ||
107 | + > | ||
108 | + {() => renderMenuItem(items)} | ||
109 | + </Menu> | ||
89 | ); | 110 | ); |
90 | }; | 111 | }; |
91 | }, | 112 | }, |
src/components/Description/src/index.tsx
@@ -23,6 +23,7 @@ export default defineComponent({ | @@ -23,6 +23,7 @@ export default defineComponent({ | ||
23 | ...unref(propsRef), | 23 | ...unref(propsRef), |
24 | }; | 24 | }; |
25 | }); | 25 | }); |
26 | + | ||
26 | const getProps = computed(() => { | 27 | const getProps = computed(() => { |
27 | const opt = { | 28 | const opt = { |
28 | ...props, | 29 | ...props, |
@@ -31,12 +32,14 @@ export default defineComponent({ | @@ -31,12 +32,14 @@ export default defineComponent({ | ||
31 | }; | 32 | }; |
32 | return opt; | 33 | return opt; |
33 | }); | 34 | }); |
35 | + | ||
34 | /** | 36 | /** |
35 | * @description: 是否使用标题 | 37 | * @description: 是否使用标题 |
36 | */ | 38 | */ |
37 | const useWrapper = computed(() => { | 39 | const useWrapper = computed(() => { |
38 | return !!unref(getMergeProps).title; | 40 | return !!unref(getMergeProps).title; |
39 | }); | 41 | }); |
42 | + | ||
40 | /** | 43 | /** |
41 | * @description: 获取配置Collapse | 44 | * @description: 获取配置Collapse |
42 | */ | 45 | */ |
@@ -49,6 +52,7 @@ export default defineComponent({ | @@ -49,6 +52,7 @@ export default defineComponent({ | ||
49 | }; | 52 | }; |
50 | } | 53 | } |
51 | ); | 54 | ); |
55 | + | ||
52 | /** | 56 | /** |
53 | * @description:设置desc | 57 | * @description:设置desc |
54 | */ | 58 | */ |
@@ -57,9 +61,11 @@ export default defineComponent({ | @@ -57,9 +61,11 @@ export default defineComponent({ | ||
57 | const mergeProps = deepMerge(unref(propsRef) || {}, descProps); | 61 | const mergeProps = deepMerge(unref(propsRef) || {}, descProps); |
58 | propsRef.value = cloneDeep(mergeProps); | 62 | propsRef.value = cloneDeep(mergeProps); |
59 | } | 63 | } |
64 | + | ||
60 | const methods: DescInstance = { | 65 | const methods: DescInstance = { |
61 | setDescProps, | 66 | setDescProps, |
62 | }; | 67 | }; |
68 | + | ||
63 | emit('register', methods); | 69 | emit('register', methods); |
64 | 70 | ||
65 | // 防止换行 | 71 | // 防止换行 |
@@ -95,6 +101,7 @@ export default defineComponent({ | @@ -95,6 +101,7 @@ export default defineComponent({ | ||
95 | 101 | ||
96 | const width = contentMinWidth; | 102 | const width = contentMinWidth; |
97 | return ( | 103 | return ( |
104 | + // @ts-ignore | ||
98 | <Descriptions.Item label={renderLabel(item)} key={field} span={span}> | 105 | <Descriptions.Item label={renderLabel(item)} key={field} span={span}> |
99 | {() => | 106 | {() => |
100 | contentMinWidth ? ( | 107 | contentMinWidth ? ( |
@@ -113,13 +120,15 @@ export default defineComponent({ | @@ -113,13 +120,15 @@ export default defineComponent({ | ||
113 | ); | 120 | ); |
114 | }); | 121 | }); |
115 | } | 122 | } |
123 | + | ||
116 | const renderDesc = () => { | 124 | const renderDesc = () => { |
117 | return ( | 125 | return ( |
118 | - <Descriptions class={`${prefixCls}`} {...{ ...attrs, ...unref(getProps) }}> | 126 | + <Descriptions class={`${prefixCls}`} {...{ ...attrs, ...(unref(getProps) as any) }}> |
119 | {() => renderItem()} | 127 | {() => renderItem()} |
120 | </Descriptions> | 128 | </Descriptions> |
121 | ); | 129 | ); |
122 | }; | 130 | }; |
131 | + | ||
123 | const renderContainer = () => { | 132 | const renderContainer = () => { |
124 | const content = props.useCollapse ? renderDesc() : <div>{renderDesc()}</div>; | 133 | const content = props.useCollapse ? renderDesc() : <div>{renderDesc()}</div>; |
125 | // 减少dom层级 | 134 | // 减少dom层级 |
src/components/Description/src/useDescription.ts
@@ -10,7 +10,7 @@ export function useDescription(props?: Partial<DescOptions>): UseDescReturnType | @@ -10,7 +10,7 @@ export function useDescription(props?: Partial<DescOptions>): UseDescReturnType | ||
10 | const descRef = ref<DescInstance | null>(null); | 10 | const descRef = ref<DescInstance | null>(null); |
11 | const loadedRef = ref(false); | 11 | const loadedRef = ref(false); |
12 | 12 | ||
13 | - function getDescription(instance: DescInstance) { | 13 | + function register(instance: DescInstance) { |
14 | if (unref(loadedRef) && isProdMode()) { | 14 | if (unref(loadedRef) && isProdMode()) { |
15 | return; | 15 | return; |
16 | } | 16 | } |
@@ -18,10 +18,11 @@ export function useDescription(props?: Partial<DescOptions>): UseDescReturnType | @@ -18,10 +18,11 @@ export function useDescription(props?: Partial<DescOptions>): UseDescReturnType | ||
18 | props && instance.setDescProps(props); | 18 | props && instance.setDescProps(props); |
19 | loadedRef.value = true; | 19 | loadedRef.value = true; |
20 | } | 20 | } |
21 | + | ||
21 | const methods: DescInstance = { | 22 | const methods: DescInstance = { |
22 | setDescProps: (descProps: Partial<DescOptions>): void => { | 23 | setDescProps: (descProps: Partial<DescOptions>): void => { |
23 | unref(descRef)!.setDescProps(descProps); | 24 | unref(descRef)!.setDescProps(descProps); |
24 | }, | 25 | }, |
25 | }; | 26 | }; |
26 | - return [getDescription, methods]; | 27 | + return [register, methods]; |
27 | } | 28 | } |
src/components/Icon/index.tsx
@@ -32,6 +32,7 @@ export default defineComponent({ | @@ -32,6 +32,7 @@ export default defineComponent({ | ||
32 | const { icon, prefix } = props; | 32 | const { icon, prefix } = props; |
33 | return `${prefix ? prefix + ':' : ''}${icon}`; | 33 | return `${prefix ? prefix + ':' : ''}${icon}`; |
34 | }); | 34 | }); |
35 | + | ||
35 | const update = async () => { | 36 | const update = async () => { |
36 | const el = unref(elRef); | 37 | const el = unref(elRef); |
37 | if (el) { | 38 | if (el) { |
@@ -67,6 +68,7 @@ export default defineComponent({ | @@ -67,6 +68,7 @@ export default defineComponent({ | ||
67 | }); | 68 | }); |
68 | 69 | ||
69 | watch(() => props.icon, update, { flush: 'post' }); | 70 | watch(() => props.icon, update, { flush: 'post' }); |
71 | + | ||
70 | onMounted(update); | 72 | onMounted(update); |
71 | 73 | ||
72 | return () => ( | 74 | return () => ( |
src/components/Menu/src/BasicMenu.tsx
@@ -55,6 +55,7 @@ export default defineComponent({ | @@ -55,6 +55,7 @@ export default defineComponent({ | ||
55 | } | 55 | } |
56 | return menuState.openKeys; | 56 | return menuState.openKeys; |
57 | }); | 57 | }); |
58 | + | ||
58 | // menu外层样式 | 59 | // menu外层样式 |
59 | const getMenuWrapStyle = computed((): any => { | 60 | const getMenuWrapStyle = computed((): any => { |
60 | const { showLogo, search } = props; | 61 | const { showLogo, search } = props; |
@@ -130,6 +131,7 @@ export default defineComponent({ | @@ -130,6 +131,7 @@ export default defineComponent({ | ||
130 | menuState.selectedKeys = [path]; | 131 | menuState.selectedKeys = [path]; |
131 | emit('menuClick', menu); | 132 | emit('menuClick', menu); |
132 | } | 133 | } |
134 | + | ||
133 | function handleMenuChange() { | 135 | function handleMenuChange() { |
134 | const { flatItems } = props; | 136 | const { flatItems } = props; |
135 | if (!unref(flatItems) || flatItems.length === 0) { | 137 | if (!unref(flatItems) || flatItems.length === 0) { |
src/components/Menu/src/useSearchInput.ts
@@ -48,9 +48,11 @@ export function useSearchInput({ | @@ -48,9 +48,11 @@ export function useSearchInput({ | ||
48 | openKeys = es6Unique(openKeys); | 48 | openKeys = es6Unique(openKeys); |
49 | menuState.openKeys = openKeys; | 49 | menuState.openKeys = openKeys; |
50 | } | 50 | } |
51 | + | ||
51 | // 搜索框点击 | 52 | // 搜索框点击 |
52 | function handleInputClick(e: any): void { | 53 | function handleInputClick(e: any): void { |
53 | emit('clickSearchInput', e); | 54 | emit('clickSearchInput', e); |
54 | } | 55 | } |
56 | + | ||
55 | return { handleInputChange, handleInputClick }; | 57 | return { handleInputChange, handleInputClick }; |
56 | } | 58 | } |
src/components/Preview/src/index.tsx
@@ -219,6 +219,7 @@ export default defineComponent({ | @@ -219,6 +219,7 @@ export default defineComponent({ | ||
219 | </div> | 219 | </div> |
220 | ); | 220 | ); |
221 | }; | 221 | }; |
222 | + | ||
222 | const renderIndex = () => { | 223 | const renderIndex = () => { |
223 | if (!unref(getIsMultipleImage)) { | 224 | if (!unref(getIsMultipleImage)) { |
224 | return null; | 225 | return null; |
src/hooks/web/useWatermark.ts
@@ -3,6 +3,7 @@ import { getCurrentInstance, onBeforeUnmount, ref, Ref, unref } from 'vue'; | @@ -3,6 +3,7 @@ import { getCurrentInstance, onBeforeUnmount, ref, Ref, unref } from 'vue'; | ||
3 | const domSymbol = Symbol('watermark-dom'); | 3 | const domSymbol = Symbol('watermark-dom'); |
4 | 4 | ||
5 | export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.body)) { | 5 | export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.body)) { |
6 | + let func: Fn = () => {}; | ||
6 | const id = domSymbol.toString(); | 7 | const id = domSymbol.toString(); |
7 | const clear = () => { | 8 | const clear = () => { |
8 | const domId = document.getElementById(id); | 9 | const domId = document.getElementById(id); |
@@ -10,6 +11,7 @@ export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.bo | @@ -10,6 +11,7 @@ export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.bo | ||
10 | const el = unref(appendEl); | 11 | const el = unref(appendEl); |
11 | el && el.removeChild(domId); | 12 | el && el.removeChild(domId); |
12 | } | 13 | } |
14 | + window.addEventListener('resize', func); | ||
13 | }; | 15 | }; |
14 | const createWatermark = (str: string) => { | 16 | const createWatermark = (str: string) => { |
15 | clear(); | 17 | clear(); |
@@ -45,7 +47,7 @@ export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.bo | @@ -45,7 +47,7 @@ export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.bo | ||
45 | 47 | ||
46 | function setWatermark(str: string) { | 48 | function setWatermark(str: string) { |
47 | createWatermark(str); | 49 | createWatermark(str); |
48 | - const func = () => { | 50 | + func = () => { |
49 | createWatermark(str); | 51 | createWatermark(str); |
50 | }; | 52 | }; |
51 | window.addEventListener('resize', func); | 53 | window.addEventListener('resize', func); |
@@ -53,7 +55,6 @@ export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.bo | @@ -53,7 +55,6 @@ export function useWatermark(appendEl: Ref<HTMLElement | null> = ref(document.bo | ||
53 | if (instance) { | 55 | if (instance) { |
54 | onBeforeUnmount(() => { | 56 | onBeforeUnmount(() => { |
55 | clear(); | 57 | clear(); |
56 | - window.addEventListener('resize', func); | ||
57 | }); | 58 | }); |
58 | } | 59 | } |
59 | } | 60 | } |
src/router/routes/modules/demo/feat.ts
@@ -18,7 +18,7 @@ export default { | @@ -18,7 +18,7 @@ export default { | ||
18 | { | 18 | { |
19 | path: '/icon', | 19 | path: '/icon', |
20 | name: 'IconDemo', | 20 | name: 'IconDemo', |
21 | - component: () => import('/@/views/demo/comp/icon/index.vue'), | 21 | + component: () => import('/@/views/demo/feat/icon/index.vue'), |
22 | meta: { | 22 | meta: { |
23 | title: '图标', | 23 | title: '图标', |
24 | }, | 24 | }, |
@@ -43,7 +43,7 @@ export default { | @@ -43,7 +43,7 @@ export default { | ||
43 | { | 43 | { |
44 | path: '/click-out-side', | 44 | path: '/click-out-side', |
45 | name: 'ClickOutSideDemo', | 45 | name: 'ClickOutSideDemo', |
46 | - component: () => import('/@/views/demo/comp/click-out-side/index.vue'), | 46 | + component: () => import('/@/views/demo/feat/click-out-side/index.vue'), |
47 | meta: { | 47 | meta: { |
48 | title: 'ClickOutSide组件', | 48 | title: 'ClickOutSide组件', |
49 | }, | 49 | }, |
src/views/demo/comp/button/index.vue
@@ -7,8 +7,6 @@ | @@ -7,8 +7,6 @@ | ||
7 | show-icon | 7 | show-icon |
8 | /> | 8 | /> |
9 | 9 | ||
10 | - <Alert message="按钮扩展" type="info" show-icon class="mt-4" /> | ||
11 | - | ||
12 | <div class="my-2"> | 10 | <div class="my-2"> |
13 | <h3>success</h3> | 11 | <h3>success</h3> |
14 | <a-button color="success">成功</a-button> | 12 | <a-button color="success">成功</a-button> |
src/views/demo/comp/click-out-side/index.vue renamed to src/views/demo/feat/click-out-side/index.vue
1 | <template> | 1 | <template> |
2 | - <div class="px-10"> | ||
3 | - <Alert message="点内外部触发事件" show-icon class="mt-4"></Alert> | 2 | + <div class="p-10"> |
3 | + <Alert message="点内外部触发事件" show-icon></Alert> | ||
4 | <ClickOutSide @clickOutside="handleClickOutside" class="flex justify-center mt-10"> | 4 | <ClickOutSide @clickOutside="handleClickOutside" class="flex justify-center mt-10"> |
5 | <div @click="innerClick" class="demo-box"> | 5 | <div @click="innerClick" class="demo-box"> |
6 | {{ text }} | 6 | {{ text }} |
src/views/demo/feat/context-menu/index.vue
@@ -3,6 +3,10 @@ | @@ -3,6 +3,10 @@ | ||
3 | <CollapseContainer title="Simple"> | 3 | <CollapseContainer title="Simple"> |
4 | <a-button type="primary" @contextmenu="handleContext">Right Click on me</a-button> | 4 | <a-button type="primary" @contextmenu="handleContext">Right Click on me</a-button> |
5 | </CollapseContainer> | 5 | </CollapseContainer> |
6 | + | ||
7 | + <CollapseContainer title="Multiple" class="mt-4"> | ||
8 | + <a-button type="primary" @contextmenu="handleMultipleContext">Right Click on me</a-button> | ||
9 | + </CollapseContainer> | ||
6 | </div> | 10 | </div> |
7 | </template> | 11 | </template> |
8 | <script lang="ts"> | 12 | <script lang="ts"> |
@@ -36,7 +40,44 @@ | @@ -36,7 +40,44 @@ | ||
36 | ], | 40 | ], |
37 | }); | 41 | }); |
38 | } | 42 | } |
39 | - return { handleContext }; | 43 | + |
44 | + function handleMultipleContext(e: MouseEvent) { | ||
45 | + createContextMenu({ | ||
46 | + event: e, | ||
47 | + items: [ | ||
48 | + { | ||
49 | + label: 'New', | ||
50 | + icon: 'ant-design:plus-outlined', | ||
51 | + | ||
52 | + children: [ | ||
53 | + { | ||
54 | + label: 'New1-1', | ||
55 | + icon: 'ant-design:plus-outlined', | ||
56 | + divider: true, | ||
57 | + children: [ | ||
58 | + { | ||
59 | + label: 'New1-1-1', | ||
60 | + handler: () => { | ||
61 | + createMessage.success('click new'); | ||
62 | + }, | ||
63 | + }, | ||
64 | + { | ||
65 | + label: 'New1-2-1', | ||
66 | + disabled: true, | ||
67 | + }, | ||
68 | + ], | ||
69 | + }, | ||
70 | + { | ||
71 | + label: 'New1-2', | ||
72 | + icon: 'ant-design:plus-outlined', | ||
73 | + }, | ||
74 | + ], | ||
75 | + }, | ||
76 | + ], | ||
77 | + }); | ||
78 | + } | ||
79 | + | ||
80 | + return { handleContext, handleMultipleContext }; | ||
40 | }, | 81 | }, |
41 | }); | 82 | }); |
42 | </script> | 83 | </script> |
src/views/demo/comp/icon/index.vue renamed to src/views/demo/feat/icon/index.vue
@@ -12,7 +12,7 @@ | @@ -12,7 +12,7 @@ | ||
12 | </div> | 12 | </div> |
13 | </CollapseContainer> | 13 | </CollapseContainer> |
14 | 14 | ||
15 | - <CollapseContainer title="IconIfy 组件使用" class="mt-5"> | 15 | + <CollapseContainer title="IconIfy 组件使用" class="my-5"> |
16 | <div class="flex justify-around flex-wrap"> | 16 | <div class="flex justify-around flex-wrap"> |
17 | <Icon icon="fa-solid:address-book" :size="30" /> | 17 | <Icon icon="fa-solid:address-book" :size="30" /> |
18 | <Icon icon="mdi-light:bank" :size="30" /> | 18 | <Icon icon="mdi-light:bank" :size="30" /> |
@@ -23,7 +23,6 @@ | @@ -23,7 +23,6 @@ | ||
23 | 23 | ||
24 | <Alert | 24 | <Alert |
25 | show-icon | 25 | show-icon |
26 | - class="mt-5" | ||
27 | message="推荐使用Iconify组件" | 26 | message="推荐使用Iconify组件" |
28 | description="Icon组件基本包含所有的图标,在下面网址内你可以查询到你想要的任何图标。并且打包只会打包所用到的图标。唯一不足的可能就是需要连接外网进行使用。" | 27 | description="Icon组件基本包含所有的图标,在下面网址内你可以查询到你想要的任何图标。并且打包只会打包所用到的图标。唯一不足的可能就是需要连接外网进行使用。" |
29 | /> | 28 | /> |