fix: 在VxeTable固定列时, getPopupContainer会导致宽度不够, 弹出层样式异常 解决办法(将弹窗元素挂载到VXe滚动容器上

This commit is contained in:
dap 2024-11-02 15:08:18 +08:00
parent 7442c6f15b
commit 9f33320bea
22 changed files with 83 additions and 42 deletions

View File

@ -1,3 +1,9 @@
# 1.0.1
**BUG FIXES**
- 在VxeTable固定列时, getPopupContainer会导致宽度不够, 弹出层样式异常 解决办法(将弹窗元素挂载到VXe滚动容器上)
# 1.0.0
**FEATURES**

View File

@ -1,6 +1,6 @@
{
"name": "@vben/web-antd",
"version": "1.0.0-beta",
"version": "1.0.0",
"homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {

View File

@ -4,7 +4,7 @@ import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -199,7 +199,7 @@ async function handleUnlock() {
{{ $t('pages.common.info') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="() => handleDelete(row)"

View File

@ -2,7 +2,7 @@
import type { Recordable } from '@vben/types';
import { Page, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Popconfirm } from 'ant-design-vue';
@ -58,7 +58,7 @@ async function handleForceOffline(row: Recordable<any>) {
<BasicTable table-title="在线用户列表">
<template #action="{ row }">
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
:title="`确认强制下线[${row.userName}]?`"
placement="left"
@confirm="handleForceOffline(row)"

View File

@ -5,7 +5,7 @@ import { ref } from 'vue';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
@ -172,7 +172,7 @@ const { hasAccessByCodes } = useAccess();
</ghost-button>
<Popconfirm
:disabled="row.id === 1"
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -4,7 +4,7 @@ import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -174,7 +174,7 @@ async function handleRefreshCache() {
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -6,7 +6,7 @@ import { nextTick } from 'vue';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import {
eachTree,
getPopupContainer,
getVxePopupContainer,
listToTree,
removeEmptyChildren,
} from '@vben/utils';
@ -166,7 +166,7 @@ function setExpandOrCollapse(expand: boolean) {
{{ $t('pages.common.add') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -4,7 +4,7 @@ import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -144,7 +144,7 @@ emitter.on('rowClick', async (value) => {
<template>
<div>
<BasicTable table-title="字典数据列表">
<BasicTable id="dict-data" table-title="字典数据列表">
<template #toolbar-tools>
<Space>
<a-button
@ -187,7 +187,9 @@ emitter.on('rowClick', async (value) => {
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="
(node) => getVxePopupContainer(node, 'dict-data')
"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -5,7 +5,7 @@ import { computed, ref } from 'vue';
import { useAccess } from '@vben/access';
import { useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import {
Dropdown,
@ -188,7 +188,7 @@ const couldSyncTenantDict = computed(() => {
<template>
<div>
<BasicTable table-title="字典类型列表">
<BasicTable id="dict-type" table-title="字典类型列表">
<template #toolbar-tools>
<Space>
<Dropdown>
@ -243,7 +243,9 @@ const couldSyncTenantDict = computed(() => {
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="
(node) => getVxePopupContainer(node, 'dict-type')
"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -8,7 +8,7 @@ import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Fallback } from '@vben/common-ui';
import {
eachTree,
getPopupContainer,
getVxePopupContainer,
listToTree,
removeEmptyChildren,
} from '@vben/utils';
@ -174,7 +174,7 @@ const isAdmin = computed(() => {
{{ $t('pages.common.add') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -4,7 +4,7 @@ import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -153,7 +153,7 @@ function handleMultiDelete() {
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -5,7 +5,7 @@ import { ref } from 'vue';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -169,7 +169,7 @@ const { hasAccessByCodes } = useAccess();
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -6,7 +6,7 @@ import { useRouter } from 'vue-router';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import {
Image,
@ -219,7 +219,7 @@ const [FileUploadModal, fileUploadApi] = useVbenModal({
{{ $t('pages.common.download') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -4,7 +4,7 @@ import type { Recordable } from '@vben/types';
import { ref } from 'vue';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -187,7 +187,7 @@ function handleMultiDelete() {
{{ $t('pages.common.edit') }}
</GhostButton>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -5,7 +5,7 @@ import { nextTick, ref } from 'vue';
import { useRoute } from 'vue-router';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
@ -157,7 +157,7 @@ function handleMultipleAuthCancel() {
</template>
<template #action="{ row }">
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
:title="`是否取消授权用户[${row.userName} - ${row.nickName}]?`"
placement="left"
@confirm="handleAuthCancel(row)"

View File

@ -11,7 +11,7 @@ import {
useVbenModal,
type VbenFormProps,
} from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import {
Dropdown,
@ -222,7 +222,7 @@ function handleAssignRole(record: Recordable<any>) {
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"
@ -237,7 +237,7 @@ function handleAssignRole(record: Recordable<any>) {
</Popconfirm>
</Space>
<Dropdown
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="bottomRight"
>
<template #overlay>

View File

@ -6,7 +6,7 @@ import { computed, ref } from 'vue';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Fallback } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -205,7 +205,7 @@ const isSuperAdmin = computed(() => {
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
:title="`确认同步[${row.companyName}]的套餐吗?`"
placement="left"
@confirm="handleSync(row)"
@ -218,7 +218,7 @@ const isSuperAdmin = computed(() => {
</ghost-button>
</Popconfirm>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -6,7 +6,7 @@ import { computed, ref } from 'vue';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Fallback } from '@vben/common-ui';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -192,7 +192,7 @@ const isSuperAdmin = computed(() => {
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -12,7 +12,7 @@ import {
} from '@vben/common-ui';
import { $t } from '@vben/locales';
import { preferences } from '@vben/preferences';
import { getPopupContainer } from '@vben/utils';
import { getVxePopupContainer } from '@vben/utils';
import {
Avatar,
@ -266,7 +266,7 @@ const { hasAccessByCodes } = useAccess();
{{ $t('pages.common.edit') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"
@ -281,7 +281,7 @@ const { hasAccessByCodes } = useAccess();
</Popconfirm>
</Space>
<Dropdown
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="bottomRight"
>
<template #overlay>

View File

@ -5,6 +5,7 @@ import { nextTick, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { message, Modal, Popconfirm, Space } from 'ant-design-vue';
import dayjs from 'dayjs';
@ -263,6 +264,7 @@ function handleImport() {
{{ $t('pages.common.edit') }}
</a-button>
<Popconfirm
:get-popup-container="getVxePopupContainer"
:title="`确认同步[${row.tableName}]?`"
placement="left"
@confirm="handleSync(row)"
@ -285,6 +287,7 @@ function handleImport() {
生成代码
</a-button>
<Popconfirm
:get-popup-container="getVxePopupContainer"
:title="`确认删除[${row.tableName}]?`"
placement="left"
@confirm="handleDelete(row)"

View File

@ -4,7 +4,7 @@ import type { Recordable } from '@vben/types';
import { nextTick } from 'vue';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { getPopupContainer, listToTree } from '@vben/utils';
import { getVxePopupContainer, listToTree } from '@vben/utils';
import { Popconfirm, Space } from 'ant-design-vue';
@ -130,7 +130,7 @@ function collapseAll() {
{{ $t('pages.common.add') }}
</ghost-button>
<Popconfirm
:get-popup-container="getPopupContainer"
:get-popup-container="getVxePopupContainer"
placement="left"
title="确认删除?"
@confirm="handleDelete(row)"

View File

@ -4,3 +4,31 @@
export function getPopupContainer(node?: HTMLElement): HTMLElement {
return (node?.parentNode as HTMLElement) ?? document.body;
}
/**
* VxeTable专用弹窗层
* 解决问题: https://gitee.com/dapppp/ruoyi-plus-vben5/issues/IB1DM3
* getPopupContainer一样
* (body下) ID & ID参数传入该函数
* <BasicTable id="xxx" />
* getVxePopupContainer="(node) => getVxePopupContainer(node, 'xxx')"
* @param _node
* @param id id ()>= ID
* @returns
*/
export function getVxePopupContainer(
_node?: HTMLElement,
id?: string,
): HTMLElement {
let selector = 'div.vxe-table--body-wrapper.body--wrapper';
if (id) {
selector = `div#${id} ${selector}`;
}
// 挂载到vxe-table的滚动区域
const vxeTableContainerNode = document.querySelector(selector);
if (!vxeTableContainerNode) {
console.warn('无法找到vxe-table元素, 将会挂载到body.');
return document.body;
}
return vxeTableContainerNode as HTMLElement;
}