diff --git a/src/components/RightToolbar/index.vue b/src/components/RightToolbar/index.vue
index 02a55f78e66d9d88906d6f089349838f9d4f0f9a..899b074ad6b4fdbe3d44096940bbb37b965e27a5 100644
--- a/src/components/RightToolbar/index.vue
+++ b/src/components/RightToolbar/index.vue
@@ -53,6 +53,7 @@ const style = computed(() => {
// 搜索
function toggleSearch() {
emits('update:showSearch', !props.showSearch);
+ nextTick(() => window.dispatchEvent(new Event('resize')));
}
// 刷新
diff --git a/src/directive/common/adaptive.ts b/src/directive/common/adaptive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d4472b3d24df99759cd906f18e1f512eaf065ce4
--- /dev/null
+++ b/src/directive/common/adaptive.ts
@@ -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;
+
+/**
+ * 自适应高度指令
+ * 用法:
+ *
+ *
+ */
+const vAdaptiveHeight: Directive = {
+ mounted(el, binding: DirectiveBinding) {
+ // 获取配置
+ 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) {
+ 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;
diff --git a/src/directive/index.ts b/src/directive/index.ts
index ef25ee897f6bec346588fae6324e41a4ba2ffed8..8d660c9983c20e3b6225fff5c0024d0bb439982b 100644
--- a/src/directive/index.ts
+++ b/src/directive/index.ts
@@ -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);
};
diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue
index 56f4b1766714c67d9c16e29be550452bd7bbda05..28a0a5c5b1a059e9d242986ad9a803e9baaaf716 100644
--- a/src/views/system/dept/index.vue
+++ b/src/views/system/dept/index.vue
@@ -38,6 +38,7 @@
新增
- 级联删除
+ 级联删除
-
+
@@ -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 = '';