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/user/index.vue b/src/views/system/user/index.vue
index d12aeedd71ff921108e71cd26816a8e56559edf2..494d497fd27c68240b0ee4817a2805cf80623731 100644
--- a/src/views/system/user/index.vue
+++ b/src/views/system/user/index.vue
@@ -6,8 +6,9 @@
-
+