2929 />
3030 </div >
3131 <el-table
32- :data =" tableData "
32+ :data =" pagedTableData "
3333 :span-method =" spanMethod"
3434 v-loading =" loading"
35+ :max-height =" tableMaxHeight"
3536 @selection-change =" handleSelectionChange"
3637 @cell-mouse-enter =" cellMouseEnter"
3738 @cell-mouse-leave =" cellMouseLeave"
114115 </template >
115116 </el-table-column >
116117 </el-table >
118+ <div class =" app-table__pagination mt-16" >
119+ <el-pagination
120+ v-model:current-page =" pageNum"
121+ v-model:page-size =" pageSize"
122+ :total =" groupedByKey.length"
123+ layout =" total, prev, pager, next, sizes"
124+ :page-sizes =" [10, 20, 50, 100]"
125+ />
126+ </div >
117127 </el-drawer >
118128 <CreateTagDialog ref =" createTagDialogRef" @refresh =" getList" />
119129 <EditTagDialog ref =" editTagDialogRef" @refresh =" getList" />
@@ -159,6 +169,9 @@ const debugVisible = ref(false)
159169const filterText = ref (' ' )
160170const tags = ref <Array <any >>([])
161171const currentMouseId = ref <number | null >(null )
172+ const pageNum = ref (1 )
173+ const pageSize = ref (20 )
174+ const tableMaxHeight = computed (() => ` calc(100vh - 260px) ` )
162175
163176function cellMouseEnter(row : any ) {
164177 currentMouseId .value = row .id
@@ -168,7 +181,7 @@ function cellMouseLeave() {
168181 currentMouseId .value = null
169182}
170183
171- // 将原始数据转换为表格数据
184+ // 1) 仍然把后端全量 tags 转成“扁平行”,每行带上 keyIndex
172185const tableData = computed (() => {
173186 const result: any [] = []
174187 tags .value .forEach ((tag : any ) => {
@@ -178,31 +191,46 @@ const tableData = computed(() => {
178191 id: value .id ,
179192 key: tag .key ,
180193 value: value .value ,
181- keyIndex: index , // 用于判断是否为第一行
194+ keyIndex: index , // 同一个 key 下第几行
182195 })
183196 })
184197 }
185198 })
186199 return result
187200})
188201
189- // 合并单元格方法
190- const spanMethod = ({ row , column , rowIndex , columnIndex }: any ) => {
202+ // 2) 按 key 分组(保持 key 的出现顺序)
203+ const groupedByKey = computed (() => {
204+ const map = new Map <string , any []>()
205+ for (const row of tableData .value ) {
206+ if (! map .has (row .key )) map .set (row .key , [])
207+ map .get (row .key )! .push (row )
208+ }
209+ // 每个元素代表一个 key 分组
210+ return Array .from (map .entries ()).map (([key , rows ]) => ({ key , rows }))
211+ })
212+
213+ // 3) 按“key 分组”做分页:每页 pageSize 个 key
214+ const pagedGroups = computed (() => {
215+ const start = (pageNum .value - 1 ) * pageSize .value
216+ const end = start + pageSize .value
217+ return groupedByKey .value .slice (start , end )
218+ })
219+
220+ // 4) 当前页表格数据:把当前页的若干个 key 分组展开为行
221+ const pagedTableData = computed (() => {
222+ return pagedGroups .value .flatMap ((g ) => g .rows )
223+ })
224+
225+ // 5) 合并单元格:只在当前页内合并,同一个 key 的第一行 rowspan=该 key 在当前页的行数
226+ const spanMethod = ({ row , columnIndex }: any ) => {
227+ // 注意:你现在有 selection 列,所以 key 列索引是 1;如需同时合并 value 列按需调整
191228 if (columnIndex === 0 || columnIndex === 1 ) {
192- // key列 (由于添加了选择列,索引变为1)
193229 if (row .keyIndex === 0 ) {
194- // 计算当前key有多少个值
195- const sameKeyCount = tableData .value .filter ((item ) => item .key === row .key ).length
196- return {
197- rowspan: sameKeyCount ,
198- colspan: 1 ,
199- }
200- } else {
201- return {
202- rowspan: 0 ,
203- colspan: 0 ,
204- }
230+ const sameKeyCount = pagedTableData .value .filter ((item ) => item .key === row .key ).length
231+ return { rowspan: sameKeyCount , colspan: 1 }
205232 }
233+ return { rowspan: 0 , colspan: 0 }
206234 }
207235}
208236
@@ -281,12 +309,14 @@ function getList() {
281309 .getTags (id , params , loading )
282310 .then ((res : any ) => {
283311 tags .value = res .data
312+ pageNum .value = 1
284313 })
285314}
286315
287316const open = () => {
288317 filterText .value = ' '
289318 debugVisible .value = true
319+ pageNum .value = 1
290320 getList ()
291321}
292322
0 commit comments