table组件添加时间轴和水印

96 阅读3分钟
  1. 添加 时间轴
//处理数据:
//存放原始table数据
const economicList = ref<any[]>([]);
//存放用来渲染table的数据
const groupedData = ref<any[]>([]);
 
//接口返回的数据格式:
economicList.value = [
    {
        "country": "沙特",
        "name": "xxx",
        "determine": 1,
        "event_content": "xxxxxxxxx。",
        "event_time": "2024-05-05T16:00:00.000Z",
        "id": 1054072,
    },
    {
        "country": "立陶宛",
        "name": "xxx",
        "determine": 0,
        "event_content": "xxxxxxxx。",
        "event_time": "2024-05-05T22:00:00.000Z",
        "id": 1054672,
    },
]
 
 
//处理数据
watch(
  () => economicList.value,
  (res) => {
    let bol = res.length > 0 ? true : false;
    const groups = {};
    // 根据 pub_time 分组: 通过dayjs().format("HH:mm")将event_time转化为"HH:mm"再进行分组
    res.forEach((item) => {
      const date = dayjs(item.event_time).format("HH:mm");
      if (!groups[date]) {
        groups[date] = [];
      }
      groups[date].push(item);
    });
    groupedData.value = Object.entries(groups);
  },
  { deep: true }
);
//处理table表格
<table class="table" cellspacing="0" cellpadding="0" border="0">
            <tr class="table-title">
              <td>日期时间</td>
              <td>数据</td>
              <td>重要性</td>
              <td>前值</td>
              <td>预测值</td>
              <td>公布值</td>
              <td>解读</td>
            </tr>
            <tbody v-if="groupedData?.length > 0" style="opacity: 0.8">
              <template v-for="([date, items], groupIndex) in groupedData">
                <!-- 数据行,每个数据行都包含日期 -->
                <tr
                  v-for="(item, index) in items"
                  :key="'item-' + groupIndex + '-' + index"
                  class="table-line"
                >
                  <!-- 将日期放在每个数据行的第一列 -->
                  <td v-if="index === 0" :rowspan="items.length">{{ date }}</td>
                  <td
                    v-else-if="index !== 0"
                    :rowspan="0"
                    style="display: none"
                  >
                    &nbsp;
                  </td>
                  <td>
                    {{ item.country + item.name }}
                  </td>
                  <td>
                   ...
                  </td>
                  <td>
                    ...
                  </td>
                  <td>
                    ...
                  </td>
                  <td>
                      ...
                  </td>
                  <td>
                   ...
                  </td>
                </tr>
              </template>
            </tbody>
            <tbody v-if="economicList?.length === 0 && !loading">
              ...
            </tbody>
          </table>

效果如下:

image.png

  1. 添加 水印 如果你有多张表需要加水印,实现水印的方法要写在最外层或者某个工具库中,具体可根据需求实现。
// 添加水印的方法==> res为绑定dom的id,isShow为是否添加水印
const addWatermark = (res: string, isShow: boolean) => {
  // 初始化canvas
  const canvas = document.createElement("canvas");
  const ctx: any = canvas.getContext("2d");
  // 设置canvas大小,应与目标div大小匹配或按需调整
  canvas.width = document.getElementById(res)?.clientWidth as number;
  canvas.height = document.getElementById(res)?.clientHeight as number; // 示例高度,根据需要调整
 
  // 设置水印文字和样式
  const watermarkText = "测试水印";
  const font = "18px Microsoft Yahei";
  const color = "rgba(150, 150, 150, 0.8)"; // 半透明灰色
  const angle = -Math.PI / 30; // 30度倾斜角
 
  // 绘制水印到canvas
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
 
  ctx.font = font;
  ctx.fillStyle = color;
  // ctx.globalAlpha = 0.07;
  ctx.translate(50, 50);
  ctx.rotate(angle);
  for (let x = 0; x < canvas.width; x += 200) {
    // 水印横向间隔
    for (
      let y = 0;
      y < canvas.height;
      canvas.height < 50 ? (y += canvas.height + 10) : (y += 100)
    ) {
      // 水印纵向间隔
      ctx.fillText(watermarkText, x, y);
    }
  }
 
  // 将canvas内容转为data URL,并设置为div背景
  const dataURL = canvas.toDataURL();
  if (!isShow) {
    document.getElementById(res).style.backgroundImage = ``;
  } else {
    document.getElementById(res).style.backgroundImage = `url(${dataURL})`;
  }
};

我的需求:

1) table添加水印

2) table有数据时添加水印 没有数据时去掉水印

3)表头不能有水印

因此这里我设置了两个参数==> res为绑定dom的id,isShow为是否添加水印

这里我将tbody的style设置为 style="opacity: 0.8"即可实现 表头不能有水印 的需求,同理:如果把样式加到table上即可实现整个table的水印效果,具体效果可以根据需求来:

//Vue模板
<arco-spin :loading="loading" tip="数据加载中..." class="w-100" dot>
        <div id="watermarkedDiv">
          <table class="table" cellspacing="0" cellpadding="0" border="0">
            <tr class="table-title">
              <td>日期时间</td>
              <td>数据</td>
              <td>xxx</td>
              <td>xxx</td>
              <td>xxx</td>
              <td>xxx</td>
              <td>xxx</td>
            </tr>
            <tbody v-if="groupedData?.length > 0" style="opacity: 0.8">
              ...
            </tbody>
            <tbody v-if="economicList?.length === 0 && !loading">
             ...
            </tbody>
          </table>
        </div>
      </arco-spin>
 
//js代码
watch(
  () => economicList.value,
  (res) => {
    //判断是否有数据
    let bol = res.length > 0 ? true : false;
    nextTick(() => {
      //调用添加水印的方法
      addWatermark("watermarkedDiv", bol);
    });
  },
  { deep: true }
);

注意点:

  1. 添加水印方法中一定要有以下代码,不然会导致多个图表水印文字大小不一致的bug
// 设置canvas大小,应与目标div大小匹配或按需调整
  canvas.width = document.getElementById(res)?.clientWidth as number;
  canvas.height = document.getElementById(res)?.clientHeight as number; // 示例高度,根据需要调整
  1. 调用水印方法时要加上nextTick方法,使其在下次dom更新后调用,防止水印不生效
nextTick(() => {  
      //调用添加水印的方法  
      addWatermark("watermarkedDiv", bol);  
    });

效果图:

image.png