add 添加自适应表格指令[若采纳,请将其他页面完善]

This commit is contained in:
于心 2025-08-06 16:53:16 +08:00
parent 9223fabde7
commit d48ab50fe2
7 changed files with 88 additions and 7 deletions

View File

@ -53,6 +53,7 @@ const style = computed(() => {
//
function toggleSearch() {
emits('update:showSearch', !props.showSearch);
nextTick(() => window.dispatchEvent(new Event('resize')));
}
//

View File

@ -0,0 +1,74 @@
import type { Directive, DirectiveBinding } from 'vue';
// 扩展 HTMLElement 类型
interface AdaptiveElement extends HTMLElement {
_resizeListener?: () => void;
}
// 配置接口
interface AdaptiveOptions {
height?: number; // 距离底部的距离,默认 90
}
const DEFAULT_HEIGHT = 105;
/**
*
*
* <div v-adaptive></div>
* <div v-adaptive="{ height: 60 }"></div>
*/
const vAdaptiveHeight: Directive<AdaptiveElement, AdaptiveOptions> = {
mounted(el, binding: DirectiveBinding<AdaptiveOptions>) {
// 获取配置
const config = binding.value || {};
const bottomHeight = typeof config.height === 'number' ? config.height : DEFAULT_HEIGHT;
// 设置高度
const updateHeight = () => {
const rect = el.getBoundingClientRect();
const top = rect.top; // 更准确
const pageHeight = window.innerHeight;
el.style.height = `${pageHeight - top - bottomHeight}px`;
el.style.overflowY = 'auto';
};
// 防抖:避免频繁触发
let resizeTimer: number;
const onResize = () => {
clearTimeout(resizeTimer);
resizeTimer = window.setTimeout(() => {
requestAnimationFrame(updateHeight);
}, 100);
};
// 保存监听器,用于销毁
el._resizeListener = onResize;
// 初始设置
updateHeight();
// 监听 resize
window.addEventListener('resize', onResize);
},
// 组件更新时重新计算(比如父组件 re-render
updated(el, binding: DirectiveBinding<AdaptiveOptions>) {
const config = binding.value || {};
const bottomHeight = typeof config.height === 'number' ? config.height : DEFAULT_HEIGHT;
const rect = el.getBoundingClientRect();
const top = rect.top;
const pageHeight = window.innerHeight;
el.style.height = `${pageHeight - top - bottomHeight}px`;
},
unmounted(el) {
if (el._resizeListener) {
window.removeEventListener('resize', el._resizeListener);
delete el._resizeListener;
}
}
};
export default vAdaptiveHeight;

View File

@ -1,9 +1,11 @@
import copyText from './common/copyText';
import adaptive from './common/adaptive';
import { hasPermi, hasRoles } from './permission';
import { App } from 'vue';
export default (app: App) => {
app.directive('copyText', copyText);
app.directive('adaptive', adaptive);
app.directive('hasPermi', hasPermi);
app.directive('hasRoles', hasRoles);
};

View File

@ -38,6 +38,7 @@
</template>
<el-table
v-adaptive="{ height: 45 }"
ref="deptTableRef"
v-loading="loading"
:data="deptList"

View File

@ -28,13 +28,16 @@
<el-button v-hasPermi="['system:menu:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:menu:remove']" type="danger" plain icon="Delete" @click="handleCascadeDelete" :loading="deleteLoading">级联删除</el-button>
<el-button v-hasPermi="['system:menu:remove']" type="danger" plain icon="Delete" @click="handleCascadeDelete" :loading="deleteLoading"
>级联删除</el-button
>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
</template>
<el-table
v-adaptive="{ height: 45 }"
ref="menuTableRef"
v-loading="loading"
:data="menuList"

View File

@ -6,8 +6,9 @@
<el-card shadow="hover">
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree
v-adaptive="{ height: 34 }"
ref="deptTreeRef"
class="mt-2"
class="mt-2 overflow-y-auto"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' } as any"

View File

@ -6,8 +6,9 @@
<el-card shadow="hover">
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree
v-adaptive="{ height: 35 }"
ref="deptTreeRef"
class="mt-2"
class="mt-2 overflow-y-auto"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' } as any"
@ -95,7 +96,7 @@
</el-row>
</template>
<el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
<el-table v-adaptive="{ height: 105 }" v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column v-if="columns[0].visible" key="userId" label="用户编号" align="center" prop="userId" />
<el-table-column v-if="columns[1].visible" key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
@ -615,9 +616,7 @@ const handleUpdate = async (row?: UserForm) => {
dialog.title = '修改用户';
Object.assign(form.value, data.user);
postOptions.value = data.posts;
roleOptions.value = Array.from(
new Map([...data.roles, ...data.user.roles].map(role => [role.roleId, role])).values()
);
roleOptions.value = Array.from(new Map([...data.roles, ...data.user.roles].map((role) => [role.roleId, role])).values());
form.value.postIds = data.postIds;
form.value.roleIds = data.roleIds;
form.value.password = '';