Skip to content

公告

版权

提示

本文是在 博主VitePress 文章:《公告》 基础上增加了自己实践过程的一些细节,转载无需和我联系,但请注明文章来源。如果侵权之处,请联系博主进行删除,谢谢~

创建

  • Demo\docs-base\.vitepress\theme\components 文件夹,新建 notice.vue 组件编写
md
Demo
├─ .vitepress
│ └─ config.mts
│ └─ theme
│ │ ├─ components
│ │ │ └─ notice.vue
│ │ └─ index.ts
└─ index.md
  • 在 notice.vue 填入如下代码,保存

说明

提示

由于基于《Youbg Kbt》大佬开源的《vitepress-theme-Teek》,大佬开源的主题本身自带了仿vuepress-reco公告,所以这里选择的是仿常见的影视页公告

vue
<script setup lang="ts">
import { ref } from "vue";
const visible = ref(true);

function closetz() {
  visible.value = false;
}

setTimeout(function () {
  visible.value = false;
}, 5000);
</script>

<template>
  <div v-if="visible" class="notice-background" style="display: block;"></div>

  <div v-if="visible" class="notice">
    <h3 class="notice-title">网站公告</h3>

    <div class="notice-describe">
      <p>本次更新:新公告样式</p>
      <p class="notice-domain">
        <strong>
          详细教程:
          <a
            href="https://vitepress.yiov.top/layout.html#%E5%85%AC%E5%91%8A"
            target="_blank"
            >vitepress.yiov.top</a
          >
        </strong>
      </p>
      <p>QQ 频道:******(无效二维码)</p>
      <img class="notice-img" src="/qrcode.png" />
    </div>

    <div class="notice-footer">
      <div class="notice-btn" @click="closetz">朕知道了</div>
    </div>
  </div>
</template>

<style scoped>
.notice-img {
  z-index: 9999;
}

/* 全屏遮罩层 */
.notice-background {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: none;
  z-index: 99;
  pointer-events: none;
}

/* 通知 */
.notice {
  z-index: 999;
  padding: 25px;
  background: #fff;
  width: 350px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
  border-radius: 18px;
  box-sizing: border-box;
  box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.05), 0 1.5rem 2.2rem rgba(0, 0, 0, 0.1);
}

@media (max-width: 640px) {
  .notice {
    width: 82%;
    padding: 25px;
  }
}

.notice-title {
  text-align: center;
  color: #3c3c3c;
  font-size: 20px;
  font-weight: 900;
}

.notice-describe p {
  color: #3c3c3c;
  padding: 10px 0;
  font-size: 15px;
}

.notice-describe p strong {
  color: #3c3c3c;
}

.notice-describe p a {
  color: #eb0e0e;
}

.notice-domain {
  background: #f3f5f7;
  text-align: center;
  border-radius: 10px;
}

/* 通知底部 */
.notice-footer {
  padding: 20px 0 0;
  text-align: center;
}

.notice-btn {
  text-align: center;
  cursor: pointer;
  border-radius: 50px;
  font-weight: 700;
  padding: 0 30px;
  color: #fff;
  background: linear-gradient(to right, #1e69f5 0%, #093ce5 100%);
  box-shadow: 0 10px 12px -4px rgb(0 0 0 / 40%);
  line-height: 40px;
  font-size: 14px;
  display: inline-block;
  text-wrap: nowrap;
}
</style>
vue
<script setup lang="ts">
import { ref } from "vue";
const visible = ref(true);

function closeBulletin() {
  visible.value = false;
}

setTimeout(function () {
  visible.value = false;
}, 5000);
</script>

<template>
  <div v-if="visible" class="bulletin-wrapper" style="width: 300px;">
    <div class="bulletin-title">
      <span class="bulletin-icon left">
        <svg
          class="bulletin-icon"
          xmlns="http://www.w3.org/2000/svg"
          xmlns:xlink="http://www.w3.org/1999/xlink"
          viewBox="0 0 32 32"
          style="width: 20px; height: 20px; font-size: 20px; color: rgb(255, 255, 255);"
        >
          <path
            d="M27.16 8.08l-1.53 1.29a10 10 0 0 1-.29 13.23l1.47 1.4a12 12 0 0 0 .35-15.88z"
            fill="currentColor"
          ></path>
          <path
            d="M21.58 12a6 6 0 0 1-.18 7.94l1.47 1.36a8 8 0 0 0 .23-10.59z"
            fill="currentColor"
          ></path>
          <path
            d="M18 30a1 1 0 0 1-.71-.3L9.67 22H3a1 1 0 0 1-1-1V11a1 1 0 0 1 1-1h6.67l7.62-7.7a1 1 0 0 1 1.41 0a1 1 0 0 1 .3.7v26a1 1 0 0 1-1 1zM4 20h6.08a1 1 0 0 1 .71.3L17 26.57V5.43l-6.21 6.27a1 1 0 0 1-.71.3H4z"
            fill="currentColor"
          ></path>
        </svg>
        <span>公告</span>
      </span>
      <svg
        class="btn-close"
        @click="closeBulletin"
        t="1573745677073"
        viewBox="0 0 1024 1024"
        version="1.1"
        xmlns="http://www.w3.org/2000/svg"
        p-id="4448"
        width="22"
        height="22"
      >
        <path
          d="M512 34.133333a486.4 486.4 0 1 0 486.4 486.4A486.4 486.4 0 0 0 512 34.133333z m209.4848 632.8064l-55.6032 55.466667-151.517867-151.125333-151.517866 151.1168-55.6032-55.466667 151.517866-151.108267L307.242667 364.714667l55.6032-55.466667 151.517866 151.125333 151.517867-151.1168 55.6032 55.466667-151.517867 151.099733z m0 0"
          p-id="4449"
        ></path>
      </svg>
    </div>

    <div class="bulletin-content">
      <h3 class="bulletin-h3">本次更新:</h3>
      <p class="bulletin-p">
        公告样式,参考自
        <a
          class="bulletin-link"
          href="https://theme-reco.vuejs.press/"
          target="_blank"
          >VuePress-Reco</a
        >
      </p>
      <p class="bulletin-p">QQ 频道:******(无效二维码)</p>
      <img class="bulletin-img" src="/qrcode.png" />
      <hr />
      <div class="btn-group">
        <a class="btn" href="https://vitepress.dev/zh/" target="_blank">官网</a>
      </div>
    </div>
  </div>
</template>

<style>
.bulletin-wrapper {
  position: fixed;
  top: 5rem;
  right: 1rem;
  z-index: 30;
  box-sizing: border-box;
  border-radius: 1.2rem;
  overflow-y: auto;
  background-color: #1b1446;
  box-shadow: 0 10px 30px 0 rgb(0 0 0 / 40%);
}

.bulletin-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: rgb(255 255 255);
  padding: 1rem;
}

.bulletin-icon {
  display: inline-flex;
}

.bulletin-icon.left {
  flex-direction: row;
  align-items: center;
}

.bulletin-icon.left > svg {
  margin-right: 0.375rem;
}

.btn-close {
  cursor: pointer;
  fill: currentColor;
}

.bulletin-content {
  padding: 1.5rem 2rem;
  background-color: #ffffff;
}

.bulletin-h3 {
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
  color: #000000;
  font-size: 19px;
  font-weight: bolder;
}

.bulletin-p {
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
  color: #000000;
  font-size: 16px;
}

.bulletin-link {
  color: red;
}

.bulletin-img {
  width: 100%;
}

hr {
  margin-top: 1.5rem;
  margin-bottom: 1.5rem;
  border-top-width: 1px;
  border-style: solid;
  border-color: #1b1446;
}

.btn-group {
  text-align: center;
}

.btn {
  display: inline-block;
  height: 3.5rem;
  width: 3.5rem;
  cursor: pointer;
  border-radius: 50%;
  background-color: #1b1446;
  text-align: center;
  line-height: 3.5rem;
  color: #ffffff;
}
</style>

配置

提示

  • Demo\docs-base\.vitepress\theme\index.ts中配置引入
ts
/* Demo\docs-base\.vitepress\theme\index.ts */
import NoticeContent from "./components/NoticeContent.vue";
import notice from "./components/notice.vue";  

export default {
  extends: Teek,
  Layout: defineComponent({
    name: "LayoutProvider",
    setup() {
      const { frontmatter } = useData();
      const { start, stop } = useFooterRuntime();

      watch(
        frontmatter,
        () => {
          nextTick(() => {
            if (frontmatter.value.layout === "home") start();
            else stop();
          });
        },
        { immediate: true }
      );

      return () =>
        h(Teek.Layout, null, {
          "layout-top": () => h(notice), // 使用layout-top插槽
          "Teek-notice-content": () => h(NoticeContent),
        });
    },
  }),
};
最近更新