table_s2.vue 6.37 KB
<script lang="ts" setup name="TableS2">
import { TableSheet, DataCell } from '@antv/s2';
import { debounce } from 'lodash-es'
import { shallowRef, reactive, computed, ref } from "vue";

const props = defineProps({
  tableInfo: {
    type: Object,
    default: {}
  }
})

const s2Options = {
  width: 600,
  height: 480,
  showSeriesNumber: true,
};

const BORDER_COLOR = '#d9d9d9';
const BACK_COLOR = '#fff';
const HEADER_BACK_COLOR = '#f2f2f2';
const CELL_ACTIVE_BACK_COLOR = '#F5F8FF';

const customTheme = {
  background: {
    color: HEADER_BACK_COLOR,
  },
  cornerCell: {
    cell: {
      horizontalBorderColor: BORDER_COLOR,
      verticalBorderColor: BORDER_COLOR,
      backgroundColor: HEADER_BACK_COLOR,
    },
    text: {
      fill: 'var(--el-color-regular)',
      fontSize: 12,
      textAlign: 'left',
    },
    bolderText: {
      fill: 'var(--el-color-regular)',
      fontSize: 12,
      opacity: 1,
      fontWeight: 400
    },
  },
  splitLine: {
    horizontalBorderColor: BORDER_COLOR,
    horizontalBorderColorOpacity: 1,
    horizontalBorderWidth: 2,
    verticalBorderColor: BORDER_COLOR,
    verticalBorderColorOpacity: 1,
    verticalBorderWidth: 2,
    showRightShadow: true,
    shadowWidth: 10,
    shadowColors: {
      left: 'rgba(0,0,0,0.1)',
      right: 'rgba(0,0,0,0)',
    },
  },
  rowCell: {
    text: {
      fill: 'var(--el-color-regular)',
      opacity: 1,
      fontSize: 12,
      fontWeight: 400,
      textAlign: 'left'
    },
    cell: {
      backgroundColor: HEADER_BACK_COLOR,
      interactionState: {
        hover: {
          backgroundColor: CELL_ACTIVE_BACK_COLOR,
          backgroundOpacity: 1,
        },
        selected: {
          backgroundColor: 'rgb(63, 69, 97)',
        },
      },
      horizontalBorderColor: BORDER_COLOR,
      verticalBorderColor: BORDER_COLOR,
      verticalBorderWidth: 1,
    },
  },
  colCell: {
    cell: {
      horizontalBorderColor: BORDER_COLOR,
      verticalBorderColor: BORDER_COLOR,
      verticalBorderWidth: 2,
      horizontalBorderWidth: 2,
      backgroundColor: HEADER_BACK_COLOR,
      interactionState: {
        hover: {
          backgroundColor: HEADER_BACK_COLOR,
          backgroundOpacity: 1,
        },
        selected: {
          backgroundColor: 'rgb(63, 69, 97)',
        },
      },
    },
    text: {
      fill: 'var(--el-color-regular)',
      fontSize: 12,
      textAlign: 'left'
    },
    bolderText: {
      fill: 'var(--el-color-regular)',
      opacity: 1,
      fontSize: 12,
      textAlign: 'left',
      fontWeight: 400
    },
  },
  dataCell: {
    icon: {
      size: 14,
      margin: {
        left: 10,
      },
    },
    cell: {
      interactionState: {
        hover: {
          backgroundColor: CELL_ACTIVE_BACK_COLOR,
          backgroundOpacity: 1,
        },
        hoverFocus: {
          backgroundColor: CELL_ACTIVE_BACK_COLOR,
          backgroundOpacity: 1,
          // borderColor: 'blue',
        },
        selected: {
          backgroundColor: CELL_ACTIVE_BACK_COLOR,
          backgroundOpacity: 1,
        },
        unselected: {
          backgroundOpacity: 1,
          opacity: 1,
        },
        prepareSelect: {
          borderColor: CELL_ACTIVE_BACK_COLOR,
        },
      },
      crossBackgroundColor: BACK_COLOR,
      horizontalBorderColor: BORDER_COLOR,
      verticalBorderColor: BORDER_COLOR,
      verticalBorderWidth: 2,
      horizontalBorderWidth: 2,
      backgroundColorOpacity: 0.9,
      backgroundColor: HEADER_BACK_COLOR,
    },
    text: {
      fill: 'var(--el-color-regular)',
      fontSize: 14,
      textAlign: 'left'
    },
  },
};

const s2DataConfig = {
  fields: {
    columns: ['province', 'city', 'type', 'price', 'cost'],
  },
  meta: [
    {
      field: 'province',
      name: '省份',
    },
    {
      field: 'city',
      name: '城市',
    },
    {
      field: 'type',
      name: '商品类别',
    },
    {
      field: 'price',
      name: '价格',
    },
    {
      field: 'cost',
      name: '成本',
    },
  ],
  data: [
    {
      "province": "浙江",
      "city": "杭州",
      "type": "笔",
      "price": 1
    },
    {
      "province": "浙江",
      "city": "杭州",
      "type": "纸张",
      "price": 2
    },
    {
      "province": "浙江",
      "city": "舟山",
      "type": "笔",
      "price": 17
    },
    {
      "province": "浙江",
      "city": "舟山",
      "type": "纸张",
      "price": 6
    },
    {
      "province": "吉林",
      "city": "长春",
      "type": "笔",
      "price": 8
    },
    {
      "province": "吉林",
      "city": "白山",
      "type": "笔",
      "price": 12
    },
    {
      "province": "吉林",
      "city": "长春",
      "type": "纸张",
      "price": 3
    },
    {
      "province": "吉林",
      "city": "白山",
      "type": "纸张",
      "price": 25
    },
    {
      "province": "浙江",
      "city": "杭州",
      "type": "笔",
      "price": 20
    },
    {
      "province": "浙江",
      "city": "杭州",
      "type": "纸张",
      "price": 10
    },
    {
      "province": "浙江",
      "city": "舟山",
      "type": "笔",
      "price": 15
    },
    {
      "province": "浙江",
      "city": "舟山",
      "type": "纸张",
      "price": 2
    },
    {
      "province": "吉林",
      "city": "长春",
      "type": "笔",
      "price": 15
    },
    {
      "province": "吉林",
      "city": "白山",
      "type": "笔",
      "price": 30
    },
    {
      "province": "吉林",
      "city": "长春",
      "type": "纸张",
      "price": 40
    },
    {
      "province": "吉林",
      "city": "白山",
      "type": "纸张",
      "price": 50
    }
  ],
};

onBeforeMount(() => {

})

onMounted(() => {
  const s2Container = document.getElementById(props.tableInfo.id);
  const s2 = new TableSheet(s2Container, s2DataConfig, s2Options);
  s2.setThemeCfg({ theme: customTheme });
  s2.render();

  const debounceRender = debounce((width, height) => {
    s2.changeSheetSize(width, height)
    s2.render(false) // 不重新加载数据
  }, 100)

  const resizeObserver = new ResizeObserver(([entry] = []) => {
    const [size] = entry.borderBoxSize || [];
    debounceRender(size.inlineSize, size.blockSize)
  });
  resizeObserver.observe(s2Container);
})
</script>

<template>
  <div class="table_panel" :id="props.tableInfo.id"></div>
</template>

<style lang="scss" scoped>
.table_panel {
  width: 100%;
  height: 100%;
}
</style>