vue3实现可自定义字段的table组件

🚀 个人简介:某大型测绘遥感企业资深Webgis开发工程师,软件设计师(中级)、优快云优质创作者
💟 作 者:柳晓黑胡椒❣️
📝 专 栏:vue实践
🌈 若有帮助,还请关注点赞收藏,不行的话我再努努力💪💪💪

需求背景

由于项目业务列表字段较多,需要封装一个可自定义字段的table组件

解决思路

1.基本功

实现效果

index.vue

<!--闸门-->
<template>
  <div class="gate-wrap" ref="wrapRef">
    <el-form>
      <div class="top">
        <div class="left-area">
          <el-form-item label="闸站ID:">
            <el-input v-model="formData.sluiceId" placeholder="请输入搜案关键字" @keydown.enter="getlist" clearable
                      @clear="reset">
              <template #suffix>
                <el-icon @click="getlist">
                  <search/>
                </el-icon>
              </template>
            </el-input>
          </el-form-item>
          <el-button @click="reset" style="margin-right:5px">
            <el-icon>
              <Refresh/>
            </el-icon>
            <span>重置</span>
          </el-button>
          <el-button type="primary" @click="getlist">
            <el-icon>
              <Search/>
            </el-icon>
            <span>查询</span>
          </el-button>
        </div>
        <div class="right-area">
          <el-button type="primary" @click="refreshData">
            <el-icon>
              <Fold/>
            </el-icon>
            <span style="margin-right: 5px">更新</span>
          </el-button>
          <el-button type="primary" @click="drawerShow = true">
            <el-icon>
              <Fold/>
            </el-icon>
            <span style="margin-right: 5px">自定义设置</span>
          </el-button>
        </div>
      </div>
    </el-form>
    <div class="table-area">
      <el-table ref="tableRef" :data="listData" height="calc(100% - 40px)" stripe>
        <el-table-column type="index" width="55" align="center" label="序号" fixed="left"/>
        <el-table-column v-for="(item, index) in showKeyArr"
                         :key="index" :label=item.name :prop=item.props
                         :width="showKeyArr.length< props.maxRow? 'auto':item.width ? item.width :'100'"
                         :fixed="item.fixed" :sortable="item.sortable" :filter-multiple="false"
                         show-overflow-tooltip>
          <template #default="{row}">
            <span>{{ formatVal(item.props, row[item.props], item.unit, item.dictKey) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" :width="showKeyArr.length?165:'auto'" fixed="right">
          <template #default="{row}">
            <div class="operation-area">
              <el-button type="primary" @click="editFn(row,3)" size="small">
                <span style="margin-right: 3px">详情</span>
                <el-icon>
                  <ArrowRight/>
                </el-icon>
              </el-button>
              <el-button type="primary" @click="editFn(row,2)" size="small">
                <span style="margin-right: 3px">修改</span>
                <el-icon>
                  <Edit/>
                </el-icon>
              </el-button>
              <!--              <el-button type="danger" @click="delFn(row)" size="small">-->
              <!--                <span style="margin-right: 3px">删除</span>-->
              <!--                <el-icon>-->
              <!--                  <Delete/>-->
              <!--                </el-icon>-->
              <!--              </el-button>-->
            </div>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination class="dialong-pagination" layout="total,prev, pager, next,sizes"
                     :total="pages.total"
                     @current-change="getlist" size="small" @size-change="(pages.pageNum=1, getlist())"
                     v-model:current-page="pages.pageNum" v-model:page-size="pages.pageSize"/>
      <el-dialog v-model="editDialogShow" :title="typeName" append-to-body
                 class="table-dialog" destroy-on-close width="1000" :height="800"
                 @close="(editDialogShow = false,curRow= {})">
        <edit-dialog :data="curRow" :editType="editType" @submit="submit" @close="editDialogShow = false"/>
      </el-dialog>
      <el-drawer v-model="drawerShow" title="自定义配置" append-to-body size="480px">
        <div class="table-drawer-box">
          <div class="t1">支持自定义设置列表展示的字段</div>
          <div class="allBox">
            <el-checkbox v-model="isCheckedAll" @change="allCheckboxChange" :indeterminate="isIndeterminate" label="全选"
                         size="large"/>
          </div>
          <div class="t1">基础数据字段</div>
          <div class="list">
            <el-checkbox :key="index" @change="checkboxChange($event,item.props)" size="large" :disabled="item.disabled"
                         v-for="(item, index) in allKeyArr.slice(0,15)" v-model="item.show" :label="item.name"/>
          </div>
          <div class="t1">运行数据字段</div>
          <div class="list">
            <el-checkbox :key="index" @change="checkboxChange($event,item.props)" size="large" :disabled="item.disabled"
                         v-for="(item, index) in allKeyArr.slice(15)" v-model="item.show" :label="item.name"/>
          </div>
        </div>
      </el-drawer>
    </div>
  </div>
</template>

<script lang="ts" setup>
import {onMounted, reactive, toRefs, ref, computed, defineProps} from "vue";
import {formatVal} from "@/utils/dictionary"
import {keyArrList} from "@/views/basicData/tableData.ts"
import {updateGatePage, getGatePage, refreshGatePage, getGatePageInfo} from "@/api/basicData"
import {ElMessage, ElMessageBox} from "element-plus";
import {useRouter} from "vue-router";
// Component
import EditDialog from "./editDialog.vue"
// Props
const props = defineProps(['maxRow'])
// Ref
const tableRef = ref(null)
const wrapRef = ref(null)
const router = useRouter()

const typeName = computed(() => {
  const name = '闸门'
  switch (model.editType) {
    case 1:
      return '新增' + name
    case 2:
      return '编辑' + name
    case 3:
      return name + '详情'
  }
})

const model = reactive({
  listData: [],
  formData: {},
  pages: {
    pageNum: 1,
    pageSize: 10,
    total: 0
  },
  editDialogShow: false,
  drawerShow: false,
  editType: 1,
  curRow: {},
  allKeyArr: [],
  showKeyArr: [],
  isCheckedAll: false,
  isIndeterminate: false,
})
const {
  listData,
  formData,
  pages,
  editDialogShow,
  drawerShow,
  editType,
  curRow,
  allKeyArr,
  showKeyArr,
  isCheckedAll,
  isIndeterminate,
} = toRefs(model)

onMounted(() => {
  getlist()
  getallKeyArr()
})

const refreshData = async () => {
  await refreshGatePage()
  ElMessage.success("数据更新成功")
  getlist()
}

const allCheckboxChange = (bool) => {
  model.isIndeterminate = false
  model.allKeyArr = model.allKeyArr.map(item => ({...item, show: item.disabled || bool}))
  model.showKeyArr = model.allKeyArr.filter(item => item.show)
}

const checkboxChange = () => {
  model.showKeyArr = model.allKeyArr.filter(item => item.show)
  switch (true) {
    case !model.showKeyArr.length:
      model.isCheckedAll = false
      model.isIndeterminate = false
      break
    case model.showKeyArr.length === model.allKeyArr.length:
      model.isCheckedAll = true
      model.isIndeterminate = false
      break
    default:
      model.isCheckedAll = false
      model.isIndeterminate = true
      break
  }
}

const submit = async (data) => {
  if (data.sluiceId) {
    await updateGatePage([data])
    getlist()
    ElMessage.success("编辑成功")
    model.editDialogShow = false
  } else {
    ElMessage.success("新增成功")
    model.editDialogShow = false
  }
}

const delFn = async (row) => {
  await ElMessageBox.confirm("删除之后,该阀门数据将不可恢复。", `是否删除该名称为 ${row.name}的阀门?`, {
    type: 'warning',
  })
  getlist()
  ElMessage.success("删除成功")
}

const editFn = async (row, type) => {
  model.editType = type
  const {data} = await getGatePageInfo(row.sluiceId)
  model.curRow = data
  model.editDialogShow = true
}

const getlist = async () => {
  const params = {
    ...model.formData,
    ...model.pages,
  }
  const {data} = await getGatePage(params)
  model.listData = data.list || []
  model.pages.total = data.total
}

const reset = () => {
  model.formData = {}
  getlist()
}

const getallKeyArr = () => {
  model.allKeyArr = keyArrList["gate"].map(item => ({...item, show: true}))
  checkboxChange()
}
</script>

<style lang="scss" scoped>
.gate-wrap {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  height: 100%;
  padding: 5px;

  .top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    overflow: hidden;
    height: 40px;
    margin-bottom: 15px;

    .left-area {
      opacity: 0;
      pointer-events: none;

      > * {
        margin-right: 26px;
      }
    }

    :deep(.el-form-item--default) {
      margin-bottom: 0;
    }

    > div {
      display: flex;
      align-items: center;

      .el-button {
        margin-left: 15px;
      }
    }

  }

  .table-area {
    position: relative;
    flex: 1;
    height: calc(100% - 60px);

    .select-text {
      color: #409eff;
      cursor: default;
    }

    .operation-area {
      display: flex;
      justify-content: center;
    }

    .dialong-pagination {
      position: absolute;
      bottom: 0;
      display: flex;
      justify-content: flex-end;
      width: 100%;
    }
  }
}

</style>

<style lang="scss">
.table-dialog {
  .el-dialog__body {
    height: calc(100% - 35px) !important;
  }
}
</style>


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳晓黑胡椒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值