一个逐渐完善的万能table(一)

2 篇文章 0 订阅
1 篇文章 0 订阅

背景

由于公司业务很多地方用到table,每个地方功能不一,抽时间整理了一份。如果遇到其他暂无的功能,请在底下留言,看到后第一时间码:😁😁😁😁😁

主要功能如下

  • 自定义列数
  • 自定义下拉多选
  • 自定义下拉单选
  • 自定义日历
  • 超出一行显示省略号
  • 超出一行显示图标(可自定义)

主要参数如下

  • informations:父组件传过来的数据
  • triangle: 是否有下拉选项
  • showSelect: 多个下拉框时,表示当前点击的下拉框 true/false
  • triangleTyle: 0 多选 1 单选 2日历
  • isEllipsisIcon:超出是否显示图标 默认不显示
  • imgUrl:超出显示的图标
  • columnNum:每行几列(自定义)
  • column:每行几列(默认)
  • isEllipsisSymbol:超出是否显示省略号,默认不显示
  • selectDate:下拉列表的数据

正文

新建两个文件,father.vue和child.vue,父组件将子组件引入即可

父组件

<template>
  <div class="page-box">
    <UseTable :informations="examineInfos"></UseTable>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import UseTable from '../widgets/table.vue'
const examineInfos = ref({
      list: [
        {
          label: '收入',
          content: '10万元',
        },
        {
          label: '支出',
          content: '10万元',
        },
        {
          label: '人员',
          content: '10人',
        },
        {
          label: '总额',
          content: '10万元',
        },
        {
          label: '入园时间',
          content: '2022-08-10',
        },
        {
          label: '是否成交',
          content: '已成交',
        },
        {
          label: '员工数量',
          content: '10人',
        },
        {
          label: '手机号',
          content: 13888888888,
        },
        {
          label: '类别',
          content: 'A类别',
        },
        {
          label: '账号管理人',
          content: 'bear',
        },
        {
          label: '手机号',
          content: '13888888888',
        },
        {
          label: '邮箱',
          content: '暂未绑定邮箱',
        },
      ],
      column: 2,
    })
</script>

子组件

<template>
  <div class="examineInfoList">
    <ul>
      <li
        v-for="(item, index) in informations.list"
        :key="index"
        :style="item.itemWidth"
      >
        <span class="colorSpan">{{ item.label }}</span>
        <div :class="[item.isEllipsisIcon && 'isEllipsisIcon']">
          <span
            :class="[
              item.triangle && 'triangle',
              item.showSelect && 'rotate',
              item.isEllipsisSymbol && 'isEllipsisSymbol',
            ]"
            @click="changeSelect(index)"
          >
            <template v-if="item.triangleTyle == 0">
              <template
                v-for="(selectItem, selectIndex) in allCheckSelect"
                :key="selectIndex"
                >{{ selectItem.name }}</template
              ></template
            ><template v-else-if="item.triangleTyle == 1">{{
              choseRadio ? choseRadio.name : ''
            }}</template>
            <el-date-picker
            v-else-if="item.triangleTyle == 2"
        v-model="completionTimeLimitPlaeholder"
        type="date"
        placeholder="Pick a day"
        @change="timeChange"
      />
            <template v-else>{{ item.content }}</template></span
          >
          <div v-if="item.showSelect" class="triangleBox">
            <el-checkbox-group
              v-if="item.triangleTyle == 0"
              v-model="allCheckSelect"
            >
              <el-checkbox
                v-for="items in item.selectDate"
                :key="items.value"
                :label="items"
                size="large"
                @change="handleChoseSelect(index)"
                >{{ items.name }}
              </el-checkbox>
            </el-checkbox-group>
            <el-radio-group v-if="item.triangleTyle == 1" v-model="choseRadio">
              <el-radio
                v-for="items in item.selectDate"
                :key="items.value"
                :label="items"
                @change="handleChoseRadio(index)"
                >{{ items.name }}</el-radio
              >
            </el-radio-group>
          </div>
          <p v-if="item.isEllipsisIcon">
            <el-tooltip effect="light" placement="right" trigger="hover">
              <template #content>
                <span class="popperClass">{{ item.content }}</span>
              </template>
              <el-button>
                <img
                  :src="informations.imgUrl ? informations.imgUrl : imgUrl"
                  alt=""
                />
              </el-button>
            </el-tooltip>
          </p>
        </div>
      </li>
    </ul>
  </div>
</template>
<script name="UsecenterTable" setup>
import { computed, ref, onMounted, onUpdated } from 'vue'
const props = defineProps({
  informations: {
    type: Object,
    default: () => {
      return {}
    },
  },
})
const informations = computed(() => {
  const { list, column } = props.informations
  if (list) {
    list.map((item) => {
      if (item.columnNum) {
        item.itemWidth = 'width:' + 100 / item.columnNum + '%'
      } else {
        item.itemWidth = 'width:' + 100 / column + '%'
      }
    })
  }
  return props.informations
})
// select
const allCheckSelect = ref()
const emits = defineEmits([
  'choseSelectDate',
  'choseRadioDate',
  'completionTime',
])
const handleChoseSelect = (index) => {
  informations.value.list[index].showSelect =
    !informations.value.list[index].showSelect
  emits('choseSelectDate', allCheckSelect)
}
const changeSelect = (index) => {
  informations.value.list[index].showSelect =
    !informations.value.list[index].showSelect
}
//radio
const choseRadio = ref(null)
const handleChoseRadio = (index) => {
  // eslint-disable-next-line no-console
  console.log(choseRadio)
  informations.value.list[index].showSelect =
    !informations.value.list[index].showSelect
  emits('choseRadioDate', choseRadio)
}
// 日历
let completionTimeLimitPlaeholder = ref('请选择日期')
const timeChange = (val) => {
  console.log(val)
  completionTimeLimitPlaeholder.value = val
  emits('completionTime', val)
}
const imgUrl = ref('../assets/vue.svg')
</script>
<style scoped>
.examineInfoList {
  border: 1px solid #e9eeff;
  opacity: 1;
  border-radius: 0px;
  width: 100%;
  display: flex;
  flex-direction: column;
}
.examineInfoList > ul {
  display: flex;
  flex-wrap: wrap;
}
.examineInfoList > ul > li {
  display: flex;
  border-bottom: 1px solid #e9eeff;
}
.examineInfoList > ul > li:last-child {
  border: none;
}
.examineInfoList > ul > li span {
  font-size: 18px;
  font-weight: 400;
  color: #666666;
  padding: 20px 30px;
  line-height: 20px;
}
.examineInfoList > ul > li span.colorSpan {
  display: flex;
  align-items: center;
  background: #f9faff;
  font-size: 18px;
  font-weight: 400;
  line-height: 0px;
  color: #00165d;
  flex: 1;
  max-width: 200px;
}
.examineInfoList > ul > li > div {
  flex: 1.51;
  display: flex;
  position: relative;
}
.examineInfoList > ul > li div.isEllipsisIcon {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.examineInfoList > ul > li > div > p {
  background-color: #ffffff;
  width: 60px;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  right: 0;
}
.examineInfoList > ul > li > div > p img {
  width: 18px;
  height: 18px;
  position: absolute;
  right: 20px;
  top: 50%;
  transform: translateY(-50%);
  background-color: #ffffff;
  cursor: pointer;
}
.examineInfoList > ul > li > div span {
  flex: 1;
  display: flex;
  align-items: center;
}
.examineInfoList > ul > li > div span.isEllipsisSymbol {
  width: 100%;
  word-break: break-all;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1; /* 这里是超出几行省略 */
  overflow: hidden;
  border: 20px solid #ffffff;
  box-sizing: border-box;
  padding: 0 10px;
}
.examineInfoList > ul > li > div span.triangle {
  cursor: pointer;
}
.examineInfoList > ul > li > div span.triangle::after {
  content: '';
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-top: 10px solid #c9c9c9;
  width: 0;
  height: 0;
  position: absolute;
  right: 30px;
  top: 50%;
  transform: translateY(-50%);
  transform: translateY(-50%) rotate(0deg);
  transition: transform 0.3s ease-in-out;
}
.examineInfoList > ul > li > div span.triangle.rotate::after {
  transform: translateY(-50%) rotate(180deg);
}
.examineInfoList > ul > li > div .triangleBox {
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  background: #ffffff;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.1);
  z-index: 1;
}

:deep(.el-checkbox) {
  font-size: 16px;
  font-weight: 400;
  line-height: 34px;
  color: #00165d;
  padding: 15px 20px;
}
:deep(.el-checkbox-group) {
  display: flex;
  flex-direction: column;
}
:deep(.it-date-picker) {
  margin-bottom: 0;
}
.popperClass {
  width: 200px;
  display: flex;
  padding: 10px;
  font-size: 0.18rem;
  font-weight: 400;
  color: #666666;
  line-height: 0.2rem;
}
</style>
<style>
.el-popper__arrow {
  display: block !important;
}
.el-popper.is-light {
  margin-top: 8px !important;
}
.el-button.el-tooltip__trigger {
  border: none !important;
}
</style>

以上就是完整代码,这里下载🤞。如果不如之处还望多多指点,需要其他功能请在评论区留言,收到后第一时间码。觉得有用抬抬小手点一下赞👍👍~~~~😊😊😊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大笨熊不熊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值