diff --git a/src/components/ContextMenu/index.ts b/src/components/ContextMenu/index.ts index f53c42f0694..0ad16d0a7f8 100644 --- a/src/components/ContextMenu/index.ts +++ b/src/components/ContextMenu/index.ts @@ -1,62 +1,2 @@ -import contextMenuVue from './src/index'; -import { isClient } from '/@/utils/is'; -import { Options, Props } from './src/types'; -import { createVNode, render } from 'vue'; -const menuManager: { - domList: Element[]; - resolve: Fn; -} = { - domList: [], - resolve: () => {}, -}; -export const createContextMenu = function (options: Options) { - const { event } = options || {}; - try { - event.preventDefault(); - } catch (e) { - console.log(e); - } - - if (!isClient) return; - return new Promise((resolve) => { - const container = document.createElement('div'); - const propsData: Partial = {}; - if (options.styles !== undefined) propsData.styles = options.styles; - if (options.items !== undefined) propsData.items = options.items; - if (options.event !== undefined) { - propsData.customEvent = event; - propsData.axis = { x: event.clientX, y: event.clientY }; - } - const vm = createVNode(contextMenuVue, propsData); - render(vm, container); - const bodyClick = function () { - menuManager.resolve(''); - }; - menuManager.domList.push(container); - const remove = function () { - menuManager.domList.forEach((dom: Element) => { - try { - document.body.removeChild(dom); - } catch (error) {} - }); - document.body.removeEventListener('click', bodyClick); - document.body.removeEventListener('scroll', bodyClick); - }; - menuManager.resolve = function (...arg: any) { - resolve(arg[0]); - remove(); - }; - remove(); - document.body.appendChild(container); - document.body.addEventListener('click', bodyClick); - document.body.addEventListener('scroll', bodyClick); - }); -}; -export const unMountedContextMenu = function () { - if (menuManager) { - menuManager.resolve(''); - menuManager.domList = []; - } -}; - +export { createContextMenu, destroyContextMenu } from './src/createContextMenu'; export * from './src/types'; diff --git a/src/components/ContextMenu/src/createContextMenu.ts b/src/components/ContextMenu/src/createContextMenu.ts new file mode 100644 index 00000000000..62ae9e6fe1d --- /dev/null +++ b/src/components/ContextMenu/src/createContextMenu.ts @@ -0,0 +1,73 @@ +import contextMenuVue from './index'; +import { isClient } from '/@/utils/is'; +import { CreateContextOptions, ContextMenuProps } from './types'; +import { createVNode, render } from 'vue'; + +const menuManager: { + domList: Element[]; + resolve: Fn; +} = { + domList: [], + resolve: () => {}, +}; + +export const createContextMenu = function (options: CreateContextOptions) { + const { event } = options || {}; + + event && event?.preventDefault(); + + if (!isClient) return; + return new Promise((resolve) => { + const body = document.body; + + const container = document.createElement('div'); + const propsData: Partial = {}; + if (options.styles) { + propsData.styles = options.styles; + } + + if (options.items) { + propsData.items = options.items; + } + + if (options.event) { + propsData.customEvent = event; + propsData.axis = { x: event.clientX, y: event.clientY }; + } + + const vm = createVNode(contextMenuVue, propsData); + render(vm, container); + + const handleClick = function () { + menuManager.resolve(''); + }; + + menuManager.domList.push(container); + + const remove = function () { + menuManager.domList.forEach((dom: Element) => { + try { + dom && body.removeChild(dom); + } catch (error) {} + }); + body.removeEventListener('click', handleClick); + body.removeEventListener('scroll', handleClick); + }; + + menuManager.resolve = function (...arg: any) { + remove(); + resolve(arg[0]); + }; + remove(); + body.appendChild(container); + body.addEventListener('click', handleClick); + body.addEventListener('scroll', handleClick); + }); +}; + +export const destroyContextMenu = function () { + if (menuManager) { + menuManager.resolve(''); + menuManager.domList = []; + } +}; diff --git a/src/components/ContextMenu/src/index.less b/src/components/ContextMenu/src/index.less index 30c5774d383..73a7b335c46 100644 --- a/src/components/ContextMenu/src/index.less +++ b/src/components/ContextMenu/src/index.less @@ -1,22 +1,28 @@ @import (reference) '../../../design/index.less'; +@default-height: 42px !important; + +@small-height: 36px !important; + +@large-height: 36px !important; + .item-style() { li { display: inline-block; width: 100%; - height: 46px !important; + height: @default-height; margin: 0 !important; - line-height: 46px; + line-height: @default-height; span { - line-height: 46px; + line-height: @default-height; } > div { margin: 0 !important; } - &:hover { + &:not(.ant-menu-item-disabled):hover { color: @text-color-base; background: #eee; } @@ -27,10 +33,9 @@ position: fixed; top: 0; left: 0; - z-index: 1500; + z-index: 200; display: block; width: 156px; - min-width: 10rem; margin: 0; list-style: none; background-color: #fff; diff --git a/src/components/ContextMenu/src/index.tsx b/src/components/ContextMenu/src/index.tsx index 27fa5e320c0..5661a51561e 100644 --- a/src/components/ContextMenu/src/index.tsx +++ b/src/components/ContextMenu/src/index.tsx @@ -1,99 +1,98 @@ -import { - defineComponent, - nextTick, - onMounted, - reactive, - computed, - ref, - unref, - onUnmounted, -} from 'vue'; +import './index.less'; + +import type { ContextMenuItem, ItemContentProps } from './types'; +import type { FunctionalComponent, CSSProperties } from 'vue'; + +import { defineComponent, nextTick, onMounted, computed, ref, unref, onUnmounted } from 'vue'; -import { props } from './props'; import Icon from '/@/components/Icon'; import { Menu, Divider } from 'ant-design-vue'; -import type { ContextMenuItem } from './types'; +import { props } from './props'; -import './index.less'; const prefixCls = 'context-menu'; + +const ItemContent: FunctionalComponent = (props) => { + const { item } = props; + return ( + + {props.showIcon && item.icon && } + {item.label} + + ); +}; + export default defineComponent({ name: 'ContextMenu', props, setup(props) { - const wrapRef = ref>(null); - const state = reactive({ - show: false, - }); + const wrapRef = ref(null); + const showRef = ref(false); + + const getStyle = computed( + (): CSSProperties => { + const { axis, items, styles, width } = props; + const { x, y } = axis || { x: 0, y: 0 }; + const menuHeight = (items || []).length * 40; + const menuWidth = width; + const body = document.body; + + const left = body.clientWidth < x + menuWidth ? x - menuWidth : x; + const top = body.clientHeight < y + menuHeight ? y - menuHeight : y; + return { + ...styles, + width: `${width}px`, + left: `${left + 1}px`, + top: `${top + 1}px`, + }; + } + ); onMounted(() => { - nextTick(() => { - state.show = true; - }); + nextTick(() => (showRef.value = true)); }); onUnmounted(() => { const el = unref(wrapRef); el && document.body.removeChild(el); }); - const getStyle = computed(() => { - const { axis, items, styles, width } = props; - const { x, y } = axis || { x: 0, y: 0 }; - const menuHeight = (items || []).length * 40; - const menuWidth = width; - const body = document.body; - return { - ...(styles as any), - width: `${width}px`, - left: (body.clientWidth < x + menuWidth ? x - menuWidth : x) + 'px', - top: (body.clientHeight < y + menuHeight ? y - menuHeight : y) + 'px', - }; - }); function handleAction(item: ContextMenuItem, e: MouseEvent) { - state.show = false; const { handler, disabled } = item; - if (disabled) { - return; - } - if (e) { - e.stopPropagation(); - e.preventDefault(); - } + if (disabled) return; + showRef.value = false; - handler && handler(); - } - - function renderContent(item: ContextMenuItem) { - const { icon, label } = item; - - const { showIcon } = props; - return ( - - {showIcon && icon && } - {label} - - ); + e?.stopPropagation(); + e?.preventDefault(); + handler?.(); } function renderMenuItem(items: ContextMenuItem[]) { - return items.map((item, index) => { + return items.map((item) => { const { disabled, label, children, divider = false } = item; - const DividerComp = divider ? : null; + const DividerComp = divider ? : null; if (!children || children.length === 0) { - return [ - - {() => [renderContent(item)]} - , - DividerComp, - ]; + return ( + <> + + {() => [ + , + ]} + + {DividerComp} + + ); } - return !state.show ? null : ( - + if (!unref(showRef)) return null; + + return ( + {{ - title: () => renderContent(item), - default: () => [renderMenuItem(children)], + title: () => ( + + ), + default: () => renderMenuItem(children), }} ); @@ -101,11 +100,12 @@ export default defineComponent({ } return () => { const { items } = props; - return !state.show ? null : ( + if (!unref(showRef)) return null; + return ( diff --git a/src/components/ContextMenu/src/props.ts b/src/components/ContextMenu/src/props.ts index e633cb1ee9f..eff994ca185 100644 --- a/src/components/ContextMenu/src/props.ts +++ b/src/components/ContextMenu/src/props.ts @@ -1,16 +1,16 @@ -import type { PropType } from 'vue'; +import type { PropType, CSSProperties } from 'vue'; import type { Axis, ContextMenuItem } from './types'; export const props = { width: { type: Number as PropType, - default: 180, + default: 156, }, customEvent: { type: Object as PropType, default: null, }, styles: { - type: Object as PropType, + type: Object as PropType, default: null, }, showIcon: { @@ -31,8 +31,4 @@ export const props = { return []; }, }, - resolve: { - type: Function as PropType, - default: null, - }, }; diff --git a/src/components/ContextMenu/src/types.ts b/src/components/ContextMenu/src/types.ts index 6f9b5164316..658415a0f39 100644 --- a/src/components/ContextMenu/src/types.ts +++ b/src/components/ContextMenu/src/types.ts @@ -11,15 +11,14 @@ export interface ContextMenuItem { divider?: boolean; children?: ContextMenuItem[]; } -export interface Options { +export interface CreateContextOptions { event: MouseEvent; icon?: string; styles?: any; items?: ContextMenuItem[]; } -export type Props = { - resolve?: (...arg: any) => void; +export interface ContextMenuProps { event?: MouseEvent; styles?: any; items: ContextMenuItem[]; @@ -27,4 +26,10 @@ export type Props = { axis?: Axis; width?: number; showIcon?: boolean; -}; +} + +export interface ItemContentProps { + showIcon: boolean; + item: ContextMenuItem; + handler: Fn; +} diff --git a/src/components/Drawer/src/BasicDrawer.tsx b/src/components/Drawer/src/BasicDrawer.tsx index 08336c79408..9a5bd01ee4a 100644 --- a/src/components/Drawer/src/BasicDrawer.tsx +++ b/src/components/Drawer/src/BasicDrawer.tsx @@ -22,7 +22,7 @@ export default defineComponent({ props: basicProps, emits: ['visible-change', 'ok', 'close', 'register'], setup(props, { slots, emit, attrs }) { - const scrollRef = ref(null); + const scrollRef = ref(null); const visibleRef = ref(false); const propsRef = ref | null>(null); diff --git a/src/components/Modal/src/BasicModal.tsx b/src/components/Modal/src/BasicModal.tsx index 0cc8caac21e..9392124bab6 100644 --- a/src/components/Modal/src/BasicModal.tsx +++ b/src/components/Modal/src/BasicModal.tsx @@ -22,7 +22,7 @@ export default defineComponent({ setup(props, { slots, emit, attrs }) { const visibleRef = ref(false); const propsRef = ref | null>(null); - const modalWrapperRef = ref(null); + const modalWrapperRef = ref(null); // modal Bottom and top height const extHeightRef = ref(0); // Unexpanded height of the popup diff --git a/src/components/Modal/src/ModalWrapper.tsx b/src/components/Modal/src/ModalWrapper.tsx index 111edf70055..5df0dd70069 100644 --- a/src/components/Modal/src/ModalWrapper.tsx +++ b/src/components/Modal/src/ModalWrapper.tsx @@ -55,7 +55,7 @@ export default defineComponent({ emits: ['heightChange', 'getExtHeight'], setup(props: ModalWrapperProps, { slots, emit }) { const wrapperRef = ref(null); - const spinRef = ref(null); + const spinRef = ref(null); const realHeightRef = ref(0); // 重试次数 // let tryCount = 0; @@ -126,6 +126,8 @@ export default defineComponent({ await nextTick(); const spinEl = unref(spinRef); + if (!spinEl) return; + const spinContainerEl = spinEl.$el.querySelector('.ant-spin-container') as HTMLElement; if (!spinContainerEl) return; diff --git a/src/components/Table/src/BasicTable.vue b/src/components/Table/src/BasicTable.vue index 9cd904b8743..5f6d550f9a9 100644 --- a/src/components/Table/src/BasicTable.vue +++ b/src/components/Table/src/BasicTable.vue @@ -74,7 +74,7 @@ components: { Table, BasicForm }, emits: ['fetch-success', 'fetch-error', 'selection-change', 'register'], setup(props, { attrs, emit, slots }) { - const tableElRef = ref(null); + const tableElRef = ref(null); const wrapRef = ref>(null); const innerPropsRef = ref>(); const [registerForm, { getFieldsValue }] = useForm(); @@ -241,10 +241,8 @@ if (unref(getMergeProps).showSummary) { nextTick(() => { const tableEl = unref(tableElRef); - if (!tableEl) { - return; - } - const bodyDomList = tableEl.$el.querySelectorAll('.ant-table-body') as HTMLDivElement[]; + if (!tableEl) return; + const bodyDomList = tableEl.$el.querySelectorAll('.ant-table-body'); const bodyDom = bodyDomList[0]; useEventListener({ el: bodyDom, diff --git a/src/hooks/web/useContextMenu.ts b/src/hooks/web/useContextMenu.ts index dceca0a312f..d3c53ce68a7 100644 --- a/src/hooks/web/useContextMenu.ts +++ b/src/hooks/web/useContextMenu.ts @@ -1,12 +1,12 @@ import { onUnmounted, getCurrentInstance } from 'vue'; -import { createContextMenu, unMountedContextMenu } from '/@/components/ContextMenu'; +import { createContextMenu, destroyContextMenu } from '/@/components/ContextMenu'; import type { ContextMenuItem } from '/@/components/ContextMenu'; export type { ContextMenuItem }; export function useContextMenu(authRemove = true) { if (getCurrentInstance() && authRemove) { onUnmounted(() => { - unMountedContextMenu(); + destroyContextMenu(); }); } - return [createContextMenu, unMountedContextMenu]; + return [createContextMenu, destroyContextMenu]; } diff --git a/src/layouts/default/content/index.less b/src/layouts/default/content/index.less index 72c2e39c6d1..42bd51b6590 100644 --- a/src/layouts/default/content/index.less +++ b/src/layouts/default/content/index.less @@ -19,7 +19,7 @@ } > .basic-loading { - margin-bottom: 30%; + margin-bottom: 15%; } } } diff --git a/src/layouts/default/header/LayoutHeader.tsx b/src/layouts/default/header/LayoutHeader.tsx index 84fae61610e..30dd5c14b98 100644 --- a/src/layouts/default/header/LayoutHeader.tsx +++ b/src/layouts/default/header/LayoutHeader.tsx @@ -60,10 +60,10 @@ export default defineComponent({ }, }, setup(props) { - let logoEl: Element | null; + let logoEl: Element | null | undefined; const logoWidthRef = ref(200); - const logoRef = ref(null); + const logoRef = ref(null); const { refreshPage } = useTabs(); const { getShowTopMenu, getShowHeaderTrigger, getSplit, getTopMenuAlign } = useMenuSetting(); @@ -91,7 +91,7 @@ export default defineComponent({ if (!unref(getShowTopMenu)) return; let width = 0; if (!logoEl) { - logoEl = logoRef.value.$el; + logoEl = unref(logoRef)?.$el; } else { width += logoEl.clientWidth; } diff --git a/src/layouts/default/header/LayoutMultipleHeader.tsx b/src/layouts/default/header/LayoutMultipleHeader.tsx index a243432010b..85c0285b836 100644 --- a/src/layouts/default/header/LayoutMultipleHeader.tsx +++ b/src/layouts/default/header/LayoutMultipleHeader.tsx @@ -39,26 +39,30 @@ export default defineComponent({ return unref(getShowMultipleTab) && !unref(getFullContent); }); - const getPlaceholderDomStyle = computed(() => { - return { - height: `${unref(placeholderHeightRef)}px`, - }; - }); + const getPlaceholderDomStyle = computed( + (): CSSProperties => { + return { + height: `${unref(placeholderHeightRef)}px`, + }; + } + ); const getIsShowPlaceholderDom = computed(() => { return unref(getFixed) || unref(getShowFullHeaderRef); }); - const getWrapStyle = computed(() => { - const style: CSSProperties = {}; - if (unref(getFixed)) { - style.width = unref(getCalcContentWidth); + const getWrapStyle = computed( + (): CSSProperties => { + const style: CSSProperties = {}; + if (unref(getFixed)) { + style.width = unref(getCalcContentWidth); + } + if (unref(getShowFullHeaderRef)) { + style.top = `${unref(fullHeaderHeightRef)}px`; + } + return style; } - if (unref(getShowFullHeaderRef)) { - style.top = `${unref(fullHeaderHeightRef)}px`; - } - return style; - }); + ); const getIsFixed = computed(() => { return unref(getFixed) || unref(getShowFullHeaderRef); diff --git a/src/layouts/default/header/index.less b/src/layouts/default/header/index.less index 0fcaca26afd..8f9bb671d09 100644 --- a/src/layouts/default/header/index.less +++ b/src/layouts/default/header/index.less @@ -20,7 +20,6 @@ &__left { display: flex; - // flex-grow: 1; align-items: center; .layout-trigger { diff --git a/src/layouts/default/multitabs/index.less b/src/layouts/default/multitabs/index.less index ff636b0e406..1e052ab8e1f 100644 --- a/src/layouts/default/multitabs/index.less +++ b/src/layouts/default/multitabs/index.less @@ -40,9 +40,12 @@ height: 12px; font-size: 12px; color: inherit; + visibility: hidden; transition: none; &:hover { + visibility: visible; + svg { width: 0.8em; } @@ -69,6 +72,10 @@ display: none; } + .ant-tabs-close-x { + visibility: visible; + } + svg { width: 0.7em; fill: @white;