diff --git a/package.json b/package.json index 23ce667..5b483e5 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "pnpm": ">=8.0.0" }, "dependencies": { + "@vueuse/core": "^14.0.0", "dayjs": "^1.11.18", "element-plus": "^2.11.5", "vant": "^4.9.21" diff --git a/packages/screen/src/component/DynamicTable/TableToolbar.vue b/packages/screen/src/component/DynamicTable/TableToolbar.vue new file mode 100644 index 0000000..0b11ee3 --- /dev/null +++ b/packages/screen/src/component/DynamicTable/TableToolbar.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/packages/screen/src/component/DynamicTable/index.js b/packages/screen/src/component/DynamicTable/index.js new file mode 100644 index 0000000..8a44f56 --- /dev/null +++ b/packages/screen/src/component/DynamicTable/index.js @@ -0,0 +1,6 @@ +/** + * DynamicTable 组件导出 + */ +import DynamicTable from './index.vue' + +export default DynamicTable diff --git a/packages/screen/src/component/DynamicTable/index.vue b/packages/screen/src/component/DynamicTable/index.vue new file mode 100644 index 0000000..dc43085 --- /dev/null +++ b/packages/screen/src/component/DynamicTable/index.vue @@ -0,0 +1,217 @@ + + + + + diff --git a/packages/screen/src/component/DynamicTable/useAutoHeight.js b/packages/screen/src/component/DynamicTable/useAutoHeight.js new file mode 100644 index 0000000..ea8bcec --- /dev/null +++ b/packages/screen/src/component/DynamicTable/useAutoHeight.js @@ -0,0 +1,129 @@ +/** + * 自适应高度 Hook + * 根据父容器和兄弟元素动态计算表格高度 + * + * @param {Ref} containerRef - 容器 DOM 引用 + * @param {Object} options - 配置选项 + * @param {boolean} options.enabled - 是否启用自适应高度 + * @param {number} options.minHeight - 最小高度 + * @param {number} options.offset - 额外的高度偏移 + * @param {number} options.debounce - 防抖延迟 + * @returns {{tableHeight: Ref, recalculate: Function}} + */ + +import { ref, onMounted, onUnmounted } from 'vue' +import { useResizeObserver } from '@vueuse/core' + +export function useAutoHeight(containerRef, options = {}) { + const { + enabled = true, + minHeight = 200, + offset = 0, + debounce = 100 + } = options + + const tableHeight = ref(400) + let debounceTimer = null + + /** + * 计算表格可用高度 + * 逻辑: 父容器高度 - 兄弟元素高度 - 工具栏 - 表头 - 分页器 + */ + const calculateHeight = () => { + if (!enabled || !containerRef.value) return + + const container = containerRef.value + const parentElement = container.parentElement + if (!parentElement) return + + // 1. 获取父容器可用高度 + const parentRect = parentElement.getBoundingClientRect() + const parentStyle = window.getComputedStyle(parentElement) + const parentPaddingTop = parseFloat(parentStyle.paddingTop) || 0 + const parentPaddingBottom = parseFloat(parentStyle.paddingBottom) || 0 + + // 2. 计算兄弟元素占用的高度 + let siblingsHeight = 0 + Array.from(parentElement.children).forEach(child => { + if (child !== container) { + const childRect = child.getBoundingClientRect() + const childStyle = window.getComputedStyle(child) + const marginTop = parseFloat(childStyle.marginTop) || 0 + const marginBottom = parseFloat(childStyle.marginBottom) || 0 + siblingsHeight += childRect.height + marginTop + marginBottom + } + }) + + let availableHeight = parentRect.height - parentPaddingTop - parentPaddingBottom - siblingsHeight + + // 3. 减去容器内部组件高度 + + // 工具栏 + const toolbar = container.querySelector('.dynamic-table-toolbar') + if (toolbar) { + const toolbarRect = toolbar.getBoundingClientRect() + const toolbarStyle = window.getComputedStyle(toolbar) + const marginBottom = parseFloat(toolbarStyle.marginBottom) || 0 + availableHeight -= (toolbarRect.height + marginBottom) + } + + // 表头 + const thead = container.querySelector('.el-table__header-wrapper') + if (thead) { + availableHeight -= thead.getBoundingClientRect().height + } + + // 分页器 + const pagination = container.querySelector('.el-pagination') + if (pagination) { + const paginationRect = pagination.getBoundingClientRect() + const paginationStyle = window.getComputedStyle(pagination) + const marginTop = parseFloat(paginationStyle.marginTop) || 0 + const marginBottom = parseFloat(paginationStyle.marginBottom) || 0 + availableHeight -= (paginationRect.height + marginTop + marginBottom) + } + + // 4. 应用偏移和最小高度限制 + const finalHeight = Math.max(availableHeight - offset, minHeight) + tableHeight.value = finalHeight + } + + /** + * 防抖包装 + */ + const debouncedCalculate = () => { + if (debounceTimer) clearTimeout(debounceTimer) + debounceTimer = setTimeout(calculateHeight, debounce) + } + + // 监听容器尺寸变化 + useResizeObserver(containerRef, debouncedCalculate) + + // 组件挂载后初始化 + onMounted(() => { + if (!enabled || !containerRef.value) return + + // 监听父容器尺寸变化 + const parentElement = containerRef.value.parentElement + if (parentElement) { + useResizeObserver(parentElement, debouncedCalculate) + } + + // 初始计算(延迟确保 DOM 渲染完成) + setTimeout(calculateHeight, 100) + + // 监听窗口尺寸变化(兜底) + window.addEventListener('resize', debouncedCalculate) + }) + + // 清理 + onUnmounted(() => { + window.removeEventListener('resize', debouncedCalculate) + if (debounceTimer) clearTimeout(debounceTimer) + }) + + return { + tableHeight, + recalculate: calculateHeight + } +} diff --git a/packages/screen/src/utils/request.js b/packages/screen/src/utils/request.js new file mode 100644 index 0000000..752dd6b --- /dev/null +++ b/packages/screen/src/utils/request.js @@ -0,0 +1,16 @@ +import axios from 'axios' + +const service = axios.create({ + baseURL: '', + timeout: 10000 +}) + +export async function request(config) { + const res = await service(config) + if (res === null || res === undefined) { + return res + } + if (Object.prototype.hasOwnProperty.call(res, 'data')) { + return res.data + } +} \ No newline at end of file diff --git a/packages/screen/src/views/ServiceStationManagePage/index.vue b/packages/screen/src/views/ServiceStationManagePage/index.vue index 54ea8c9..ed30620 100644 --- a/packages/screen/src/views/ServiceStationManagePage/index.vue +++ b/packages/screen/src/views/ServiceStationManagePage/index.vue @@ -1,49 +1,17 @@