feat(web-admin): viewport-fill list height for CRM menu pages
Wire contract, quote, customer, product, and price-letter lists to useListTableViewportHeight. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
7f8cd18b4d
commit
6f7461d009
5 files changed
+88
-11
No files matched your search
@@ -156,10 +156,13 @@
|
||||
|
||||
<div class="list-body list-wrap"> <!-- 操作按钮栏 + 数据表格 -->
|
||||
<div ref="contractTableWrapRef" class="contract-table-wrap">
|
||||
<ListTable table-key="crm-contract"
|
||||
<ListTable
|
||||
ref="contractTableRef"
|
||||
table-key="crm-contract"
|
||||
v-loading="loading"
|
||||
class="list-table"
|
||||
stripe
|
||||
:height="tableHeight"
|
||||
:data="contractList"
|
||||
row-key="id"
|
||||
@selection-change="handleSelectionChange"
|
||||
@@ -465,7 +468,9 @@
|
||||
/>
|
||||
<el-table-column v-if="isColumnVisible('remark')" label="备注" align="center" prop="remark" min-width="200" show-overflow-tooltip />
|
||||
</ListTable>
|
||||
</div>
|
||||
|
||||
<div ref="contractBelowRef">
|
||||
<ListColumnStatsRow
|
||||
ref="contractStatsRowRef"
|
||||
storage-key="crm-contract-column-stats"
|
||||
@@ -474,7 +479,6 @@
|
||||
:table-wrap-el="contractTableWrapRef"
|
||||
:get-cell-value="getContractStatCellValue"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="pagination list-pager-bar">
|
||||
<div class="list-pager-selected">
|
||||
@@ -492,6 +496,7 @@
|
||||
@current-change="getList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -526,7 +531,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ContractListPage">
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue';
|
||||
import { ref, reactive, computed, onMounted, watch, nextTick } from 'vue';
|
||||
import {
|
||||
listContract,
|
||||
getContract as getContractDetail,
|
||||
@@ -576,6 +581,7 @@ import ListExportDropdown from '@/components/business/list-export-dropdown/index
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListColumnStatsRow from '@/components/business/list-column-stats-row/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
|
||||
import { buildStatsRowColumns } from '@/utils/list-column-stats'
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -1027,8 +1033,16 @@ const CONTRACT_MONEY_STAT_PROPS = new Set([
|
||||
])
|
||||
|
||||
const contractTableWrapRef = ref<HTMLElement | null>(null)
|
||||
const contractBelowRef = ref<HTMLElement | null>(null)
|
||||
const contractTableRef = ref<any>(null)
|
||||
const contractStatsRowRef = ref<{ resync?: () => void } | null>(null)
|
||||
|
||||
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
|
||||
tableEl: contractTableWrapRef,
|
||||
pagerEl: contractBelowRef,
|
||||
tableRef: contractTableRef
|
||||
})
|
||||
|
||||
const contractStatsRowColumns = computed(() =>
|
||||
buildStatsRowColumns({
|
||||
leadingSpacers: 2,
|
||||
@@ -1341,6 +1355,7 @@ onMounted(() => {
|
||||
} else {
|
||||
handleViewChange()
|
||||
}
|
||||
nextTick(() => recalcTableHeight())
|
||||
})
|
||||
|
||||
watch(formDialogVisible, (visible) => {
|
||||
|
||||
@@ -183,8 +183,12 @@
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<div class="list-body list-wrap">
|
||||
<ListTable table-key="crm-customer"
|
||||
<div ref="customerTableWrapRef" class="list-table-viewport-anchor">
|
||||
<ListTable
|
||||
ref="customerTableRef"
|
||||
table-key="crm-customer"
|
||||
class="list-table"
|
||||
:height="tableHeight"
|
||||
:data="customerList"
|
||||
v-loading="loading"
|
||||
stripe
|
||||
@@ -615,7 +619,8 @@
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</ListTable>
|
||||
<div class="pagination list-pager-bar">
|
||||
</div>
|
||||
<div ref="customerPagerRef" class="pagination list-pager-bar">
|
||||
<div class="list-pager-selected">
|
||||
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
|
||||
</div>
|
||||
@@ -693,6 +698,7 @@ import ListExportDropdown from '@/components/business/list-export-dropdown/index
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
|
||||
|
||||
const dictStore = useDictStore()
|
||||
|
||||
@@ -789,6 +795,15 @@ const {
|
||||
]
|
||||
})
|
||||
|
||||
const customerTableWrapRef = ref<HTMLElement | null>(null)
|
||||
const customerPagerRef = ref<HTMLElement | null>(null)
|
||||
const customerTableRef = ref<any>(null)
|
||||
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
|
||||
tableEl: customerTableWrapRef,
|
||||
pagerEl: customerPagerRef,
|
||||
tableRef: customerTableRef
|
||||
})
|
||||
|
||||
const customerExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('customerName')) cols.unshift('customerName')
|
||||
@@ -1025,6 +1040,7 @@ watchDebounced(
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
nextTick(() => recalcTableHeight())
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -132,8 +132,12 @@
|
||||
</div>
|
||||
|
||||
<div class="list-body list-wrap">
|
||||
<ListTable table-key="crm-price-letter"
|
||||
<div ref="priceLetterTableWrapRef" class="list-table-viewport-anchor">
|
||||
<ListTable
|
||||
ref="priceLetterTableRef"
|
||||
table-key="crm-price-letter"
|
||||
class="list-table"
|
||||
:height="tableHeight"
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
stripe
|
||||
@@ -239,8 +243,9 @@
|
||||
header-align="center"
|
||||
/>
|
||||
</ListTable>
|
||||
</div>
|
||||
|
||||
<div class="pagination list-pager-bar">
|
||||
<div ref="priceLetterPagerRef" class="pagination list-pager-bar">
|
||||
<div class="list-pager-selected">
|
||||
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
|
||||
</div>
|
||||
@@ -612,6 +617,7 @@
|
||||
} from '@/utils/crm/price-letter-template'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
|
||||
import { formatMoneyDisplay } from '@/utils/money-format'
|
||||
import { $modal } from '@/utils/modal'
|
||||
import { fetchProductOptions } from '@/api/crm/product'
|
||||
@@ -661,6 +667,15 @@
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('crm-price-letter-list-columns', listColumnDefs)
|
||||
|
||||
const priceLetterTableWrapRef = ref<HTMLElement | null>(null)
|
||||
const priceLetterPagerRef = ref<HTMLElement | null>(null)
|
||||
const priceLetterTableRef = ref<any>(null)
|
||||
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
|
||||
tableEl: priceLetterTableWrapRef,
|
||||
pagerEl: priceLetterPagerRef,
|
||||
tableRef: priceLetterTableRef
|
||||
})
|
||||
|
||||
const formDialogVisible = ref(false)
|
||||
const isEdit = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
@@ -1363,6 +1378,7 @@ ${preparedHtml}
|
||||
onMounted(() => {
|
||||
getList()
|
||||
searchProducts('')
|
||||
nextTick(() => recalcTableHeight())
|
||||
})
|
||||
|
||||
// 筛选区变化时清空简易检索并查询(勿把 quickSearch 放进依赖)
|
||||
|
||||
@@ -128,9 +128,12 @@
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<div class="list-body list-wrap">
|
||||
<div ref="productTableWrapRef" class="list-table-viewport-anchor">
|
||||
<ListTable
|
||||
ref="productTableRef"
|
||||
table-key="crm-product"
|
||||
class="list-table"
|
||||
:height="tableHeight"
|
||||
:data="productList"
|
||||
v-loading="loading"
|
||||
stripe
|
||||
@@ -268,10 +271,11 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ListTable>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination list-pager-bar">
|
||||
<div ref="productPagerRef" class="pagination list-pager-bar">
|
||||
<div class="list-pager-selected">
|
||||
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
|
||||
</div>
|
||||
@@ -392,7 +396,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import type { UploadFile } from 'element-plus'
|
||||
import {
|
||||
@@ -429,6 +433,7 @@
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
|
||||
import {
|
||||
fetchCategoryTree,
|
||||
fetchProductList,
|
||||
@@ -487,6 +492,15 @@
|
||||
const { visibleColumns, checkAll, isIndeterminate, isColumnVisible, resetToDefault } =
|
||||
usePersistedListColumns('crm-product-list-columns-v2', listColumnDefs)
|
||||
|
||||
const productTableWrapRef = ref<HTMLElement | null>(null)
|
||||
const productPagerRef = ref<HTMLElement | null>(null)
|
||||
const productTableRef = ref<any>(null)
|
||||
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
|
||||
tableEl: productTableWrapRef,
|
||||
pagerEl: productPagerRef,
|
||||
tableRef: productTableRef
|
||||
})
|
||||
|
||||
function getProductExportFilterParams() {
|
||||
const quickKeyword = quickSearchKeyword.value?.trim()
|
||||
return {
|
||||
@@ -815,6 +829,7 @@
|
||||
onMounted(() => {
|
||||
getCategoryOptions()
|
||||
getList()
|
||||
nextTick(() => recalcTableHeight())
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -133,10 +133,13 @@
|
||||
|
||||
<div class="list-body list-wrap">
|
||||
<div ref="quoteTableWrapRef" class="quote-table-wrap">
|
||||
<ListTable table-key="crm-quote"
|
||||
<ListTable
|
||||
ref="quoteTableRef"
|
||||
table-key="crm-quote"
|
||||
v-loading="loading"
|
||||
class="list-table"
|
||||
stripe
|
||||
:height="tableHeight"
|
||||
:data="quoteList"
|
||||
row-key="id"
|
||||
@selection-change="handleSelectionChange"
|
||||
@@ -389,7 +392,9 @@
|
||||
/>
|
||||
<el-table-column v-if="isColumnVisible('remark')" label="备注" align="center" prop="remark" min-width="200" show-overflow-tooltip />
|
||||
</ListTable>
|
||||
</div>
|
||||
|
||||
<div ref="quoteBelowRef">
|
||||
<div
|
||||
ref="quoteStatsScrollRef"
|
||||
class="quote-list-stats-row"
|
||||
@@ -439,7 +444,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pagination list-pager-bar">
|
||||
<div class="list-pager-selected">
|
||||
@@ -457,6 +461,7 @@
|
||||
@current-change="getList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -878,6 +883,7 @@ import ListToolbarDateShortcuts from '@/components/core/list-toolbar-date-shortc
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { useListTableViewportHeight } from '@/composables/useListTableViewportHeight'
|
||||
import {
|
||||
COLUMN_STAT_METHOD_OPTIONS,
|
||||
QUOTE_MONEY_STAT_PROPS,
|
||||
@@ -1971,6 +1977,14 @@ function pickColumnStat(prop: string, method: ColumnStatMethod | '') {
|
||||
}
|
||||
|
||||
const quoteTableWrapRef = ref<HTMLElement | null>(null)
|
||||
const quoteBelowRef = ref<HTMLElement | null>(null)
|
||||
const quoteTableRef = ref<any>(null)
|
||||
|
||||
const { tableHeight, recalc: recalcTableHeight } = useListTableViewportHeight({
|
||||
tableEl: quoteTableWrapRef,
|
||||
pagerEl: quoteBelowRef,
|
||||
tableRef: quoteTableRef
|
||||
})
|
||||
const quoteStatsScrollRef = ref<HTMLElement | null>(null)
|
||||
let quoteStatsScrollSyncing = false
|
||||
let quoteHeaderResizeObserver: ResizeObserver | null = null
|
||||
@@ -3053,6 +3067,7 @@ onMounted(() => {
|
||||
setTimeout(() => scheduleSyncStatsColumnWidths(), 150);
|
||||
setTimeout(() => scheduleSyncStatsColumnWidths(), 400);
|
||||
window.addEventListener('resize', scheduleSyncStatsColumnWidths);
|
||||
nextTick(() => recalcTableHeight());
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
Reference in new issue
Block a user