feat(web-admin): viewport-fill list height for system manage menus

Wire 系统信息 lists (tenant/dict/menu/dept/role/user/post/operlog) and
临时存放 CRM lists under 系统管理 to useListTableViewportHeight, with
onActivated recalc for keep-alive pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-09-01 19:42:20 +08:00
1 parent f457d5e106
commit 506cc7991a
19 files changed
+7871 -5820

No files matched your search

+27 -6
View File
@@ -88,7 +88,10 @@
</div>
<div class="list-body list-wrap">
<ListTable table-key="system-dept"
<div ref="sysDeptTableWrapRef" class="table-scroll bx-list-table-wrap">
<ListTable
ref="sysDeptTableRef"
:height="tableHeight" table-key="system-dept"
ref="tableRef"
:key="listTableKey"
class="list-table"
@@ -165,12 +168,13 @@
header-align="center"
/>
</ListTable>
</div>
<div class="pagination list-pager-bar">
</div>
<div ref="sysDeptBelowRef">
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
</div>
</div>
<el-dialog
@@ -316,7 +320,8 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
import { ref, reactive, computed, watch, onMounted, nextTick } from 'vue'
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
import { ref, reactive, computed, watch, onMounted, nextTick , onActivated } from 'vue'
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
import { syncViewRowFromTree } from '@/utils/view-dialog-refresh'
import { ElMessage, ElMessageBox } from 'element-plus'
@@ -360,6 +365,15 @@ const {
resetToDefault
} = usePersistedListColumns('system-dept-list-columns', listColumnDefs)
const sysDeptTableWrapRef = ref<HTMLElement | null>(null)
const sysDeptBelowRef = ref<HTMLElement | null>(null)
const sysDeptTableRef = ref<any>(null)
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableEl: sysDeptTableWrapRef,
pagerEl: sysDeptBelowRef,
tableRef: sysDeptTableRef
})
/** 可选列显隐变化时重建树表,避免 EP 树表与 v-if 列不同步导致错位 */
const listTableKey = computed(() => visibleColumns.value.join('|'))
@@ -871,7 +885,14 @@ const dictStore = useDictStore()
loadData()
loadDeptTreeForSelect()
loadDictOptions()
})
nextTick(() => recalcTableHeight())
})
onActivated(() => {
nextTick(() => recalcTableHeight())
})
</script>
<style scoped lang="scss">
+28 -4
View File
@@ -94,7 +94,10 @@
</div>
<div class="list-body list-wrap">
<ListTable table-key="system-dict"
<div ref="sysDictTableWrapRef" class="table-scroll bx-list-table-wrap">
<ListTable
ref="sysDictTableRef"
:height="tableHeight" table-key="system-dict"
class="list-table"
:data="tableData"
v-loading="loading"
@@ -148,7 +151,10 @@
header-align="center"
/>
</ListTable>
<div class="pagination list-pager-bar">
</div>
<div ref="sysDictBelowRef">
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
@@ -163,6 +169,7 @@
@current-change="(val) => ((pagination.page = val), loadData())"
/>
</div>
</div>
</div>
<el-dialog
@@ -526,7 +533,8 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
import { ref, reactive, onMounted, computed } from 'vue'
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
import { ref, reactive, onMounted, computed , onActivated } from 'vue'
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
import { syncViewRowFromFlatList } from '@/utils/view-dialog-refresh'
import { ElMessage, ElMessageBox } from 'element-plus'
@@ -571,6 +579,15 @@ import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
resetToDefault
} = usePersistedListColumns('system-dict-list-columns', listColumnDefs)
const sysDictTableWrapRef = ref<HTMLElement | null>(null)
const sysDictBelowRef = ref<HTMLElement | null>(null)
const sysDictTableRef = ref<any>(null)
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableEl: sysDictTableWrapRef,
pagerEl: sysDictBelowRef,
tableRef: sysDictTableRef
})
const dictDataListColumnDefs = [
{ prop: 'dictValue', label: '数据值' },
{ prop: 'tagType', label: '标签颜色' },
@@ -981,7 +998,14 @@ import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
onMounted(() => {
loadData()
})
nextTick(() => recalcTableHeight())
})
onActivated(() => {
nextTick(() => recalcTableHeight())
})
</script>
<style scoped lang="scss">
+27 -6
View File
@@ -87,7 +87,10 @@
</div>
<div class="list-body list-wrap">
<ListTable table-key="system-menu"
<div ref="sysMenuTableWrapRef" class="table-scroll bx-list-table-wrap">
<ListTable
ref="sysMenuTableRef"
:height="tableHeight" table-key="system-menu"
ref="tableRef"
class="list-table"
:data="tableData"
@@ -199,12 +202,13 @@
</template>
</el-table-column>
</ListTable>
</div>
<div class="pagination list-pager-bar">
</div>
<div ref="sysMenuBelowRef">
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
</div>
</div>
<el-dialog
@@ -326,7 +330,8 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
import { ref, reactive, computed, onMounted, nextTick , onActivated } from 'vue'
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
import { syncViewRowFromTree } from '@/utils/view-dialog-refresh'
import { ElMessage, ElMessageBox } from 'element-plus'
@@ -363,6 +368,15 @@ import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
resetToDefault
} = usePersistedListColumns('system-menu-list-columns', listColumnDefs)
const sysMenuTableWrapRef = ref<HTMLElement | null>(null)
const sysMenuBelowRef = ref<HTMLElement | null>(null)
const sysMenuTableRef = ref<any>(null)
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableEl: sysMenuTableWrapRef,
pagerEl: sysMenuBelowRef,
tableRef: sysMenuTableRef
})
const dictStore = useDictStore()
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
@@ -694,7 +708,14 @@ import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
onMounted(() => {
loadData()
})
nextTick(() => recalcTableHeight())
})
onActivated(() => {
nextTick(() => recalcTableHeight())
})
</script>
<style scoped lang="scss">
+26 -2
View File
@@ -82,7 +82,10 @@
</div>
<div class="list-body list-wrap">
<ListTable table-key="system-operlog"
<div ref="sysOperlogTableWrapRef" class="table-scroll bx-list-table-wrap">
<ListTable
ref="sysOperlogTableRef"
:height="tableHeight" table-key="system-operlog"
class="list-table"
:data="tableData"
stripe
@@ -166,7 +169,10 @@
/>
</ListTable>
<div class="pagination list-pager-bar">
</div>
<div ref="sysOperlogBelowRef">
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
@@ -181,6 +187,7 @@
@current-change="fetchList"
/>
</div>
</div>
</div>
</section>
@@ -248,6 +255,7 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
import { RefreshLeft, Search, View } from '@element-plus/icons-vue'
import { list as listOperLog, exportOperLog, detail as getOperLogDetail } from '@/api/monitor/operlog'
import type { OperLogVO, OperLogQuery } from '@/api/monitor/operlog/types'
@@ -274,6 +282,15 @@ const {
resetToDefault
} = usePersistedListColumns('system-operlog-list-columns', listColumnDefs)
const sysOperlogTableWrapRef = ref<HTMLElement | null>(null)
const sysOperlogBelowRef = ref<HTMLElement | null>(null)
const sysOperlogTableRef = ref<any>(null)
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableEl: sysOperlogTableWrapRef,
pagerEl: sysOperlogBelowRef,
tableRef: sysOperlogTableRef
})
const loading = ref(false)
const tableData = ref<OperLogVO[]>([])
const selectedRows = ref<OperLogVO[]>([])
@@ -388,7 +405,14 @@ watchDebounced(
onMounted(() => {
fetchList()
nextTick(() => recalcTableHeight())
})
onActivated(() => {
nextTick(() => recalcTableHeight())
})
</script>
<style scoped lang="scss">
+28 -4
View File
@@ -95,7 +95,10 @@
</div>
<div class="list-body list-wrap">
<ListTable table-key="system-post"
<div ref="sysPostTableWrapRef" class="table-scroll bx-list-table-wrap">
<ListTable
ref="sysPostTableRef"
:height="tableHeight" table-key="system-post"
class="list-table"
:data="tableData"
v-loading="loading"
@@ -155,7 +158,10 @@
header-align="center"
/>
</ListTable>
<div class="pagination list-pager-bar">
</div>
<div ref="sysPostBelowRef">
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
@@ -170,6 +176,7 @@
@current-change="(val) => ((pagination.page = val), loadData())"
/>
</div>
</div>
</div>
<el-dialog
@@ -365,7 +372,8 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
import { ref, reactive, computed, onMounted, nextTick , onActivated } from 'vue'
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
import { syncViewRowFromFlatList } from '@/utils/view-dialog-refresh'
import { ElMessage, ElMessageBox } from 'element-plus'
@@ -414,6 +422,15 @@ import { useDictStore } from '@/store/modules/dict'
resetToDefault
} = usePersistedListColumns('system-post-list-columns', listColumnDefs)
const sysPostTableWrapRef = ref<HTMLElement | null>(null)
const sysPostBelowRef = ref<HTMLElement | null>(null)
const sysPostTableRef = ref<any>(null)
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableEl: sysPostTableWrapRef,
pagerEl: sysPostBelowRef,
tableRef: sysPostTableRef
})
const dictStore = useDictStore()
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
@@ -869,7 +886,14 @@ import { useDictStore } from '@/store/modules/dict'
onMounted(() => {
loadData()
loadDictOptions()
})
nextTick(() => recalcTableHeight())
})
onActivated(() => {
nextTick(() => recalcTableHeight())
})
</script>
<style scoped lang="scss">
+41 -18
View File
@@ -107,7 +107,10 @@
</div>
<div class="list-body list-wrap">
<ListTable
<div ref="sysRoleTableWrapRef" class="table-scroll bx-list-table-wrap">
<ListTable
ref="sysRoleTableRef"
:height="tableHeight"
table-key="system-role"
class="list-table"
:data="tableData"
@@ -172,22 +175,25 @@
header-align="center"
/>
</ListTable>
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
</div>
<div ref="sysRoleBelowRef">
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-pagination
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="
(val: number) => ((pagination.page = 1), (pagination.pageSize = val), loadData())
"
@current-change="(val: number) => ((pagination.page = val), loadData())"
/>
<el-pagination
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="
(val: number) => ((pagination.page = 1), (pagination.pageSize = val), loadData())
"
@current-change="(val: number) => ((pagination.page = val), loadData())"
/>
</div>
</div>
</div>
@@ -202,7 +208,8 @@
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import RoleManageDialogs from '@/components/business/role-manage-dialogs/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
import { ref, reactive, onMounted, computed } from 'vue'
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
import { ref, reactive, onMounted, computed , onActivated } from 'vue'
import {
canDeleteByCreator,
filterDeletableByCreator,
@@ -234,6 +241,15 @@
const { visibleColumns, checkAll, isIndeterminate, isColumnVisible, resetToDefault } =
usePersistedListColumns('system-role-list-columns', listColumnDefs)
const sysRoleTableWrapRef = ref<HTMLElement | null>(null)
const sysRoleBelowRef = ref<HTMLElement | null>(null)
const sysRoleTableRef = ref<any>(null)
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableEl: sysRoleTableWrapRef,
pagerEl: sysRoleBelowRef,
tableRef: sysRoleTableRef
})
const dictStore = useDictStore()
const dataScopeLabel = (code: string) => dictStore.getLabel('sys_data_scope', code)
@@ -377,5 +393,12 @@
onMounted(() => {
loadData()
})
nextTick(() => recalcTableHeight())
})
onActivated(() => {
nextTick(() => recalcTableHeight())
})
</script>
+28 -4
View File
@@ -97,7 +97,10 @@
</div>
<div class="list-body list-wrap">
<ListTable table-key="system-tenant"
<div ref="sysTenantTableWrapRef" class="table-scroll bx-list-table-wrap">
<ListTable
ref="sysTenantTableRef"
:height="tableHeight" table-key="system-tenant"
class="list-table"
:data="tableData"
v-loading="loading"
@@ -177,7 +180,10 @@
header-align="center"
/>
</ListTable>
<div class="pagination list-pager-bar">
</div>
<div ref="sysTenantBelowRef">
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
@@ -192,6 +198,7 @@
@current-change="(val) => ((pagination.page = val), loadData())"
/>
</div>
</div>
</div>
<el-dialog
@@ -286,7 +293,8 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
import { ref, reactive, onMounted, computed } from 'vue'
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
import { ref, reactive, onMounted, computed , onActivated } from 'vue'
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
import { syncViewRowFromFlatList } from '@/utils/view-dialog-refresh'
import { ElMessage, ElMessageBox } from 'element-plus'
@@ -330,6 +338,15 @@ import { syncViewRowFromFlatList } from '@/utils/view-dialog-refresh'
resetToDefault
} = usePersistedListColumns('system-tenant-list-columns', listColumnDefs)
const sysTenantTableWrapRef = ref<HTMLElement | null>(null)
const sysTenantBelowRef = ref<HTMLElement | null>(null)
const sysTenantTableRef = ref<any>(null)
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableEl: sysTenantTableWrapRef,
pagerEl: sysTenantBelowRef,
tableRef: sysTenantTableRef
})
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
const quickSearchKeyword = ref('')
const tableData = ref<Api.Tenant.TenantItem[]>([])
@@ -595,7 +612,14 @@ import { syncViewRowFromFlatList } from '@/utils/view-dialog-refresh'
onMounted(() => {
loadData()
})
nextTick(() => recalcTableHeight())
})
onActivated(() => {
nextTick(() => recalcTableHeight())
})
</script>
<style scoped lang="scss">
+40 -18
View File
@@ -118,7 +118,10 @@
</div>
<div class="list-body list-wrap">
<ListTable
<div ref="sysUserTableWrapRef" class="table-scroll bx-list-table-wrap">
<ListTable
ref="sysUserTableRef"
:height="tableHeight"
table-key="system-user"
class="list-table"
:data="tableData"
@@ -228,23 +231,25 @@
header-align="center"
/>
</ListTable>
</div>
<div ref="sysUserBelowRef">
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
<el-pagination
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="
(val: number) => ((pagination.page = 1), (pagination.pageSize = val), loadData())
"
@current-change="(val: number) => ((pagination.page = val), loadData())"
/>
</div>
<el-pagination
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 100, 500]"
layout="total, sizes, prev, pager, next"
@size-change="
(val: number) => ((pagination.page = 1), (pagination.pageSize = val), loadData())
"
@current-change="(val: number) => ((pagination.page = val), loadData())"
/>
</div>
</div>
</div>
@@ -388,7 +393,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { ref, reactive, computed, onMounted, watch , onActivated } from 'vue'
import {
canDeleteByCreator,
filterDeletableByCreator,
@@ -414,6 +419,7 @@
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
import {
fetchUserList,
fetchExportUsers,
@@ -497,6 +503,15 @@
const { visibleColumns, checkAll, isIndeterminate, isColumnVisible, resetToDefault } =
usePersistedListColumns('system-user-list-columns', listColumnDefs)
const sysUserTableWrapRef = ref<HTMLElement | null>(null)
const sysUserBelowRef = ref<HTMLElement | null>(null)
const sysUserTableRef = ref<any>(null)
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
tableEl: sysUserTableWrapRef,
pagerEl: sysUserBelowRef,
tableRef: sysUserTableRef
})
function getUserExportFilterParams() {
const quickKeyword = quickSearchKeyword.value?.trim()
return {
@@ -867,7 +882,14 @@
loadDeptTree()
loadData()
loadRoleOptions()
})
nextTick(() => recalcTableHeight())
})
onActivated(() => {
nextTick(() => recalcTableHeight())
})
</script>
<style scoped lang="scss">