vue 3.0 详情table 支持动态列

<template>
  <div class="detail-table">
    <div
      v-for="(row, key) in config"
      :key="key"
      class="detail-item"
      :style="{ width: `${cellWidth(key)}` }"
    >
      <div class="detail-label">{{ row }}</div>
      <div class="detail-value">
        <slot :name="key" :row="data">
          {{ data[key] || '' }}
        </slot>
      </div>
    </div>
  </div>
</template>

<script setup name="DetailTable">
import NP from '@/utils/number-precision'
NP.enableBoundaryChecking(false)
const props = defineProps({
  data: {
    type: Object,
    required: true,
    default: () => {}
  },
  config: {
    type: Object,
    required: true,
    default: () => {}
  },
  columnsPerRow: {
    type: Number,
    required: false,
    default: 3
  },
  colums: {
    type: Object,
    required: false,
    default: () => {}
  }
})
function cellWidth(key) {
  const { columnsPerRow, colums } = props
  let base = NP.divide(100, columnsPerRow)
  if (!isEmptyObject(colums)) {
    if (Object.keys(colums).includes(key)) {
      if (colums[key] % columnsPerRow === 0) {
        base = 99.9
      } else {
        base = NP.times(props.colums[key], base)
      }
    }
  }
  return `${base}%`
}
function isEmptyObject(obj) {
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      return false
    }
  }
  return true
}
</script>

<style lang="scss" scoped>
.detail-table {
  display: flex;
  flex-wrap: wrap;
  .detail-item {
    border: 1px solid #d9d9d9;
    margin-top: -1px;
    margin-left: -1px;
    min-height: 38px;
    display: flex;
    .detail-label {
      font-weight: bold;
      border-right: 1px solid #d9d9d9;
      display: flex;
      width: 130px;
      padding: 0 10px;
      text-align: center;
      background: #f3f3f3;
      align-items: center;
      justify-content: center;
    }

    .detail-value {
      display: flex;
      align-items: center;
      flex: 1;
      background: #fff;
      word-wrap: break-word;
      word-break: break-all;
      padding-left: 10px;
    }
  }
}
</style>

<a-collapse-panel key="1" header="基本信息">
          <detail-table :config="basic" :data="info">
            <template #type="{ row }">
              {{ $formatDict(row.type, sys_supplier_type) }}
            </template>
          </detail-table>
        </a-collapse-panel>
<script setup>


const basic = {
  code: '供应商编码',
  name: '供应商名称',
  SettlementMethod: '结算方式',
  remark: '备注'
}
</script>

优化版

<template>
  <div class="detail-table">
    <div
      v-for="(row, key) in config"
      :key="key"
      class="detail-item"
      :style="cellWidth(key)"
    >
      <div class="detail-label">{{ row }}</div>
      <div class="detail-value">
        <slot :name="key" :row="data">
          {{ data[key] || '' }}
        </slot>
      </div>
    </div>
  </div>
</template>

<script setup name="DetailTable">
import NP from '@/utils/number-precision'
NP.enableBoundaryChecking(false)
const props = defineProps({
  data: {
    type: Object,
    required: true,
    default: () => {}
  },
  config: {
    type: Object,
    required: true,
    default: () => {}
  },
  columnsPerRow: {
    type: Number,
    required: false,
    default: 8
  },
  colums: {
    type: Object,
    required: false,
    default: () => {}
  }
})
function cellWidth(key) {
  const { columnsPerRow, colums } = props
  let flexBasis = (columnsPerRow / 24) * 100
  if (!isEmptyObject(colums)) {
    if (Object.keys(colums).includes(key)) {
      flexBasis = (colums[key] / 24) * 100
    }
  }
  return {
    flex: `1 1 ${flexBasis}%`
  }
}
function isEmptyObject(obj) {
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      return false
    }
  }
  return true
}
</script>

<style lang="scss" scoped>
.detail-table {
  display: flex;
  flex-wrap: wrap;
  .detail-item {
    border: 1px solid #d9d9d9;
    margin-top: -1px;
    margin-left: -1px;
    min-height: 38px;
    display: flex;
    .detail-label {
      font-weight: bold;
      border-right: 1px solid #d9d9d9;
      display: flex;
      width: 130px;
      padding: 0 10px;
      text-align: center;
      background: #f3f3f3;
      align-items: center;
      justify-content: center;
    }

    .detail-value {
      display: flex;
      align-items: center;
      flex: 1;
      background: #fff;
      word-wrap: break-word;
      word-break: break-all;
      padding-left: 10px;
    }
  }
}
</style>

 <detail-table
            :config="basic"
            :data="info"
            :colums="{
              remark: 16
            }"
          >
            <template #type="{ row }">
              {{ $formatDict(row.type, sys_supplier_type) }}
            </template>
          </detail-table>
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

web_Hsir

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

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

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

打赏作者

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

抵扣说明:

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

余额充值