惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
WordPress大学
WordPress大学
The Cloudflare Blog
云风的 BLOG
云风的 BLOG
博客园 - Franky
D
Docker
小众软件
小众软件
阮一峰的网络日志
阮一峰的网络日志
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
U
Unit 42
M
MIT News - Artificial intelligence
B
Blog
GbyAI
GbyAI
C
Check Point Blog
P
Proofpoint News Feed
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
雷峰网
雷峰网
IT之家
IT之家
Google DeepMind News
Google DeepMind News
V
V2EX
Stack Overflow Blog
Stack Overflow Blog

Hyde Blog

Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog
Hyde Blog
Hyde · 2025-10-05 · via Hyde Blog

vue

// 贡献图组件
<script setup lang="ts" name="ContributeChart">
import * as echarts from "echarts";
import { ref, watch, nextTick, computed, useTemplateRef } from "vue";
import { useData } from "vitepress";
import { formatDate, usePosts } from "vitepress-theme-teek";

const { isDark } = useData();
const posts = usePosts();

// 今天
const today = formatDate(new Date(), "yyyy-MM-dd");
// 获取一年前的时间
const beforeOnYear = formatDate(new Date(new Date().getTime() - 365 * 24 * 60 * 60 * 1000), "yyyy-MM-dd");

// 贡献图数据
const contributeList = computed(() => {
  const contributeObject = ref({});

  posts.value.sortPostsByDate.forEach(item => {
    if (!item.date) return;

    const date = item.date.substring(0, 10);
    if (contributeObject.value[date]) contributeObject.value[date]++;
    else contributeObject.value[date] = 1;
  });

  const contributeDays = Object.keys(contributeObject.value);

  return contributeDays.map((item: string) => [item, contributeObject.value[item]]).reverse();
});

const chartRef = useTemplateRef("chartRef");
const contributeChart = ref();

// Echarts 配置项
const option = {
  tooltip: {
    formatter: function (params) {
      return `${params.value[0]} <br/> ${params.value[1]} 篇文章`;
    },
  },
  visualMap: {
    show: false,
    min: 0,
    max: 5,
    inRange: {
      color: ["#ebedf0", "#c6e48b", "#7bc96f", "#239a3b", "#196127", "#196127"],
    },
  },
  calendar: {
    left: "center",
    itemStyle: {
      color: "#ebedf0",
      borderWidth: 5,
      borderColor: "#fff",
      shadowBlur: 0,
    },
    cellSize: [20, 20],
    range: [beforeOnYear, today],
    splitLine: true,
    dayLabel: {
      firstDay: 7,
      nameMap: "ZH",
      color: "#3c3c43",
    },
    monthLabel: {
      color: "#3c3c43",
    },
    yearLabel: {
      show: true,
      position: "right",
    },
    silent: {
      show: false,
    },
  },
  series: {
    type: "heatmap",
    coordinateSystem: "calendar",
    data: [],
  },
};

// 渲染贡献图
const renderChart = (data: any) => {
  option.calendar.itemStyle.borderColor = isDark.value ? "#1b1b1f" : "#fff";
  option.calendar.itemStyle.color = isDark.value ? "#787878" : "#ebedf0";

  if (contributeChart.value) echarts.dispose(contributeChart.value);
  // if (chartRef.value) contributeChart.value = echarts.init(chartRef.value);
  if (chartRef.value) contributeChart.value = echarts.init(chartRef.value as HTMLElement);

  option.series.data = data;
  contributeChart.value?.setOption(option);
};

watch(
  contributeList,
  async newValue => {
    await nextTick();
    renderChart(newValue);
  },
  { immediate: true }
);

watch(isDark, () => {
  renderChart(contributeList.value);
});
</script>

<template>
  <div class="contribute__chart">
    <div class="chart__box" ref="chartRef"></div>
  </div>
</template>

<style>
.tk-article-page.tk-archives {
  width: 1220px;
}

.tk-archives .contribute__chart {
  width: 100%;
  height: 260px;
}

.tk-archives .contribute__chart .chart__box {
  margin: auto;
  width: 100%;
  height: 100%;
}
</style>

vue

<script setup lang="ts" name="TeekLayoutProvider">
// @ts-ignore
import ContributeChart from "./ContributeChart.vue"; //导入贡献图组件
</script>

<template>
    //其他组件...
    <template #teek-archives-top-before>
        <!-- 贡献图组件 -->
        <ContributeChart />
    </template>
  </Teek.Layout>
</template>