table 设置字段展示

269 阅读2分钟

目的

后台的 table 展示的数据很多的时候会看不过来,而且每个使用者需要看的数据可能有自己的想法。故此设计了设置字段展示的组件

技术背景:naive vue3 pinia localStorage

方案

graph TD
Page --> Pinia
Component --> Pinia
Pinia --> localStorage
localStorage --> Pinia

Page

image.png

@/views/comp/table/title.vue

import useTableStore from '@/pinia/modules/table'
import TableTitle from '@/components/Table/title.vue'
const tableStore = useTableStore()

const columns: DataTableColumns<ItemType> = [
  {
    title: 'Name',
    key: 'name',
  },
  {
    title: 'Age',
    key: 'age',
  },
]
tableStore.init(columns as { title: string; key: string }[], name)

columns 通过 tableStore.init 初始化,同时保证 columns 不被修改

<template>
  <n-space vertical>
    <TableTitle :columns="columns" :name="name"></TableTitle>
    <n-data-table
      :columns="tableStore.getColumns(columns, name)"
      :data="dataSource"
    ></n-data-table>
  </n-space>
</template>

html 中的 table 绑定的 columnstableStore.getColumns 方法返回

Component

image.png

image.png

@/components/Table/title.vue

import { DataTableColumns, useDialog } from 'naive-ui'
import { h, PropType } from 'vue'
import CustomCheckbox from './checkbox.vue'
const dialog = useDialog()
const props = defineProps({
  columns: {
    required: true,
    type: Array as PropType<DataTableColumns<any>>,
  },
  name: {
    required: true,
    type: String,
  },
})

function custom() {
  dialog.create({
    title: '自定义字段设置',
    showIcon: false,
    style: 'width: 50vw',
    content: () =>
      h(
        CustomCheckbox,
        {
          columns: props.columns,
          name: props.name,
        },
        () => ''
      ),
  })
}
<template>
  <n-button type="primary" @click="custom">设置列表字段</n-button>
</template>

@/components/Table/checkbox.vue

import { onMounted, PropType, ref, Ref } from 'vue'
import useTableStore from '@/pinia/modules/table'
import { DataTableColumns } from 'naive-ui'

onMounted(() => {
  const findItem = tableStore.data.find((v) => v.name === props.name)
  list.value = findItem?.columnCheckList as string[]
})
const tableStore = useTableStore()
const props = defineProps({
  columns: {
    required: true,
    type: Array as PropType<DataTableColumns<any>>,
  },
  name: {
    required: true,
    type: String,
  },
})

// 选中 column
const list: Ref<string[]> = ref([])

function changeCheckbox(value: string[]) {
  tableStore.updateColumns(value, props.name)
}
<template>
  <n-checkbox-group
    v-model:value="list"
    @update:value="changeCheckbox"
    :min="1"
  >
    <n-grid :x-gap="12" :y-gap="8" :cols="3">
      <n-gi v-for="item in columns" :key="(item as any).key">
        <n-checkbox :value="(item as any).key" :label="(item as any ).title" />
      </n-gi>
    </n-grid>
  </n-checkbox-group>
</template>

将 table 的 column 展示成 checkbox 让使用者自由勾选需要的

这里限制至少勾选一个

Pinia

import { getTableField, setTableField } from '@/utils/auth'
import { DataTableColumns } from 'naive-ui'
import { defineStore } from 'pinia'

interface stateType {
  data: {
    name: string // 页面 name 唯一值
    columnAllList: string[] // table 所有的 column
    columnCheckList: string[] // table 展示的 column
  }[]
}

const useTableStore = defineStore({
  id: 'table',
  state: (): stateType => ({
    data: getTableField(),
  }),
  actions: {
    /**
     * 初始化,将cloumns记录到data
     * @param columns table 所有的 column
     * @param name 页面 name
     */
    init(columns: DataTableColumns<any>, name: string) {
      // 查找 data 中是否存在 name 对应的数值
      const findItem = this.data.find((v) => v.name === name)
      if (!findItem) {
        const list: string[] = []
        columns.forEach((v) => {
          list.push((v as { key: string }).key)
        })
        this.data.push({
          name,
          columnAllList: list,
          columnCheckList: list,
        })
      }

      // 保存到本地
      setTableField(this.data)
    },

    /**
     * 获取页面 table 的 columns
     * @param columns table 所有的 column
     * @param name 页面 name
     * @returns columns
     */
    getColumns(columns: DataTableColumns<any>, name: string) {
      const findItem = this.data.find((v) => v.name === name)
      return columns.filter((v) =>
        findItem?.columnCheckList.includes((v as { key: string }).key)
      )
    },

    /**
     * 设置 columns
     * @param columnCheckList 页面选中的 column
     * @param name 页面 name
     */
    updateColumns(columnCheckList: string[], name: string) {
      for (let i = 0; i < this.data.length; i++) {
        if (this.data[i].name === name) {
          this.data[i].columnCheckList = columnCheckList
          break
        }
      }

      // 保存到本地
      setTableField(this.data)
    },
  },
})

export default useTableStore

localStorage

@/utils/auth.ts

import pkg from './../../package.json'
const TableField = `${name}-TableTitle`

export function getTableField() {
  const listStr = localStorage.getItem(TableField) || '[]'
  let list = []
  try {
    list = JSON.parse(listStr)
  } catch (err) {}
  return list
}
export function setTableField(field: any[]) {
  return localStorage.setItem(TableField, JSON.stringify(field))
}

总结

这种设置列表字段的小功能可以一定程度上提升工作效率