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

推荐订阅源

H
Help Net Security
Scott Helme
Scott Helme
爱范儿
爱范儿
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
阮一峰的网络日志
阮一峰的网络日志
博客园 - Franky
V
V2EX
腾讯CDC
博客园_首页
博客园 - 司徒正美
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tailwind CSS Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
小众软件
小众软件
J
Java Code Geeks
大猫的无限游戏
大猫的无限游戏
月光博客
月光博客
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog
雷峰网
雷峰网
Stack Overflow Blog
Stack Overflow Blog
IT之家
IT之家
罗磊的独立博客
Recorded Future
Recorded Future
博客园 - 聂微东
O
OpenAI News
S
Secure Thoughts
Hacker News: Ask HN
Hacker News: Ask HN
S
Schneier on Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
Y
Y Combinator Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Project Zero
Project Zero
宝玉的分享
宝玉的分享
K
Kaspersky official blog
N
Netflix TechBlog - Medium
T
The Exploit Database - CXSecurity.com
Google Online Security Blog
Google Online Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Webroot Blog
Webroot Blog
云风的 BLOG
云风的 BLOG
Simon Willison's Weblog
Simon Willison's Weblog
C
Check Point Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
LINUX DO - 热门话题
美团技术团队
L
Lohrmann on Cybersecurity

qlAD 的技术笔记

2026 年 6 月 7 日 -- 我有社交恐惧症,恐惧外面到处雷电风雨声(大学生活记录) 手把手带你实现哈希表(C/C++ 数据结构) 手把手带你实现图结构(C/C++ 数据结构) 手把手带你实现二叉树(C/C++ 数据结构) 手把手带你实现栈和队列(C/C++ 数据结构) 手把手带你实现单/双链表(C/C++ 数据结构) 手把手带你实现动态数组(C/C++ 数据结构) 2026 年 1 月 2 日 -- 我不怕冷,因为我内心炽热 【2025 年度总结】(大学生活记录) 2025 年 12 月 2 日 -- 省电模式:大一 100 天耗电日志(大学生活记录) 蓝桥杯备赛第一期 —— 枚举与模拟 2025 年 11 月 3 日 -- 用爱发电、大爱无私(大学生活记录) 使用循环嵌套输出规则图形找规律讲解(嵌套循环-图形输出) 2025 年 10 月 1 日 -- 二字开头第一年的生日记录及感悟随笔(大学生活记录) Python 初级 04 -- 目前为止 Python 中你们做题可能会遇到的问题以及七七八八 2025 年 9 月 24 日 -- 开学后的第一课及军训汇演(大学生活记录) Python 初级 03 -- 程序设计的三种结构之选择结构和循环结构 Python 初级 02 -- 基础的数据类型和输入输出 2025 年 9 月 17 日 -- 大连 2025 国际大体联足球世界杯(大学生活记录) Python 初级 01 -- 初识编程、理解计算机语言及程序运行方式 适合大一新生学习编程的前一课 -- 编程先导(编程的本质) 2025 年 9 月 12 日 -- 三天军训感受以及一些七七八八(大学生活记录) 2025 年 9 月 9 日 -- 体检、军训前的准备(大学生活记录) 适合大一新生的计算机基础知识 -- 个人认为足够版 2025 年 9 月 7 日 -- 既来之、则安之(大学生活记录) C++ 程序的内存布局 —— 代码区、全局/静态区、栈区和堆区 联想小新 pro 16 2025 开箱记录:跳过联网、office 激活、更换 win 11 专业版 R 语言中的数学函数 计算机软件著作权申请过程记录 从聚类到回归:用 Python 解析鸢尾花数据集的完整数据科学流程 条件概率、全概率与贝叶斯公式 —— 一篇文章带你死磕概率公式 高中化学物质反应规则表 —— 方程式之间也有规律可循 集合元素性质、关系、子集公式、基本运算 —— 一篇文章带你全方面死磕集合 如何为你的项目选择合适的许可证 -- 全方位指南 解释 3:1 和 9:3:3:1 的详细来源 —— 建立减数分裂与孟德尔遗传学定律之间的联系 重新设置磁盘分区以及 Btrfs 子卷(subvolume)布局的无损方案 零基础实战:用 Docker 启动 dockermailserver 绕过 25 端口封锁搭建个人邮箱服务器 基于 GitHub Actions + OSS 的自托管 APT 仓库全面指南 如何在安装 Debian 时配置 Btrfs 子卷 | 详细分步指南 一个合格的个人网站站长应该知道哪些事? CSS 基础入门教程 —— 选择器、样式声明 HTML 基础入门 —— 基本结构和语法 给博客添加一个文章数据统计的页面 Git 学习笔记(命令备忘表) Anki 牌组选项详细解释与设置 手动编译带有 KernelSU 的 OnePlus 6 内核 安卓类原生系统补全计划 —— PixelExperience(一加 OnePlus) 如何使用 use-sound 为 React 应用添加声音效果 标准化项目的 GitHub Flow 工作流 如何搭建设计自己的博客网站? 配置 GitHub Actions 实现自动化提交百度收录 第00期 | 环境搭建 & 递归 (一) | 基本数列递归 逐字符讲解 C 语言 HelloWorld 程序 2023 年回顾 🤟 Anki:记忆神器,助你高效学习 Gentoo 学习笔记 美化你的 PixelExperience OS Markdown 语法指南 搭建 OneDrive 目录索引 为什么用 65 表示大写字母 A
使用安知鱼主题同款的 Twikoo 评论组件
qlAD · 2024-10-05 · via qlAD 的技术笔记

cover

一、私有部署(Docker)

私有部署涉及终端操作、申请证书、配置反向代理或负载均衡等高级操作,如果对这些不太了解,建议优先选择其他方式部署。

1、Docker Compose

version: "3.8"

services:
  twikoo:
    image: imaegoo/twikoo
    container_name: twikoo
    restart: unless-stopped
    ports:
      - 8888:8080
    environment:
      TWIKOO_THROTTLE: 1000
    volumes:
      - twikoo_data:/app/data

volumes:
  twikoo_data:
    external: true

在 8888:8080 中,8888 表示宿主机的端口,8080 表示容器内的端口。这意味着宿主机的 8888 将映射到容器内的 8080 端口,以便外部通过 ip:8888 访问容器内的服务。

为了保证数据不丢失,这里使用了外部 volumes,默认在 /var/lib/docker/volumes/twikoo_data。这允许容器重新创建或更新时,数据仍然保留在宿主机上,而不会被删除或覆盖。

使用 docker compose 运行来创建容器

通过浏览器访问 ip:8888 查询 Twikoo 是否运行成功。

Twikoo 运行成功示例

2、评论数据的处理

Twikoo 的数据格式为 json 文件,文件位置在容器中的 data 目录,因为使用了 volumes 所以可以在宿主机上找到。

单条评论数据示例:

{
  "_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "uid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "nick": "qlAD",
  "mail": "qlad_adgk@163.com",
  "mailMd5": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "link": "www.qladgk.com",
  "ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36",
  "ip": "12.13.14.15",
  "master": true,
  "url": "/links",
  "href": "https://qladgk.com/links",
  "comment": "<p>已添加,预计今日更新</p>\n",
  "pid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "rid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "isSpam": false,
  "created": 1111111111111,
  "updated": 1111111111111,
  "ipRegion": "陕西省 XX市 电信",
  "meta": { "revision": 0, "created": 1111111111111, "version": 0 },
  "$loki": 20
}

你可以对原 json 数据文件进行修改、导入、导出。

或者使用 Twikoo 的后台管理面板进行数据的操作。

Twikoo 管理面板

3、后续处理步骤

配置前置代理实现 HTTPS 访问(可以用 Nginx、负载均衡或 Cloudflare 等)

二、样式魔改

可以直接去看安知鱼主题的 GitHub 仓库,里面有 Twikoo 的 styl 文件

CSS 的版本如下:

/* 颜色 */
:root {
  --twikoo-theme-op: #4259ef23;
  --twikoo-white: #fff;
  --twikoo-main: var(--twikoo-theme);
  --twikoo-shadow-black: 0 0 12px 4px rgba(0, 0, 0, 0.05);
  --twikoo-shadow-border: 0 8px 16px -4px #2c2d300c;
  --style-border: 1px solid var(--twikoo-card-border);
  --style-border-hover: 2px solid var(--twikoo-main);
  --style-border-dashed: 1px dashed var(--twikoo-theme-op);
  --style-border-avatar: 4px solid var(--twikoo-background);
  --style-border-always: 2px solid var(--twikoo-card-border);
}

.light {
  --twikoo-theme: #a78bfa;
  --twikoo-theme-op: #a78bfa23;
  --twikoo-green: #57bd6a;
  --twikoo-fontcolor: #363636;
  --twikoo-background: #f7f9fe;
  --twikoo-maskbg: rgba(255, 255, 255, 0.6);
  --twikoo-lighttext: var(--twikoo-main);
  --twikoo-secondtext: rgba(60, 60, 67, 0.6);
  --twikoo-secondbg: #edf0f7;
  --twikoo-card-bg: #fff;
  --twikoo-shadow-lightblack: 0 5px 12px -5px rgba(102, 68, 68, 0);
  --twikoo-card-border: #c0c6d8;
}

.dark {
  --twikoo-theme: #a78bfa;
  --twikoo-theme-op: #a78bfa23;
  --twikoo-green: #57bd6a;
  --twikoo-fontcolor: #f7f7fa;
  --twikoo-background: #18171d;
  --twikoo-maskbg: rgba(0, 0, 0, 0.6);
  --twikoo-lighttext: #f2b94b;
  --twikoo-secondtext: #a1a2b8;
  --twikoo-secondbg: #30343f;
  --twikoo-card-bg: #1d1b26;
  --twikoo-shadow-lightblack: 0 5px 12px -5px rgba(102, 68, 68, 0);
  --twikoo-card-border: #42444a;
}

.OwO .OwO-body {
  min-width: 31.25rem;
}
.twikoo svg {
  color: var(--twikoo-fontcolor);
}
/* 评论区表情放大 */
@keyframes owoIn {
  0% {
    transform: translate(0, -95%);
    opacity: 0;
  }
  100% {
    transform: translate(0, -112%);
    opacity: 1;
  }
}

#owo-big {
  position: fixed;
  align-items: center;
  background-color: rgb(255, 255, 255);
  border: 1px #aaa solid;
  border-radius: 10px;
  z-index: 9999;
  display: none;
  transform: translate(0, -112%);
  overflow: hidden;
  animation: owoIn 0.3s cubic-bezier(0.42, 0, 0.3, 1.11);
}
#owo-big img {
  width: 100%;
}

.tk-expand {
  width: 100%;
  cursor: pointer;
  padding: 0.75em;
  text-align: center;
  transition: all 0.5s;
  border: var(--style-border);
  box-shadow: 0 8px 16px -4px #2c2d300c;
  border-radius: 50px;
  letter-spacing: 5px;
  background-color: var(--twikoo-card-bg);
}

#twikoo .tk-comments > .tk-submit {
  overflow: visible !important;
}
#twikoo .tk-comments .OwO .OwO-body {
  border: var(--style-border-always) !important;
  border-radius: 8px !important;
  overflow: hidden;
  background-color: var(--twikoo-maskbg) !important;
  backdrop-filter: saturate(180%) blur(10px);
  cursor: auto;
  top: 2.1em !important;
  transform: translateZ(0);
  animation: 0.3s ease 0.1s 1 normal both running donate_effcet;
}
#twikoo .tk-comments .OwO .OwO-body .OwO-items-show {
  margin: 12px 8px;
}
#twikoo
  .tk-comments
  button.el-button.tk-cancel.el-button--default.el-button--small {
  background: var(--twikoo-secondbg);
  border-radius: 8px;
  color: var(--twikoo-fontcolor);
}
#twikoo
  .tk-comments
  button.el-button.tk-cancel.el-button--default.el-button--small:hover {
  background: var(--twikoo-lighttext);
  color: var(--twikoo-white);
}
#twikoo .tk-comments a.tk-submit-action-icon.__markdown {
  display: none;
}
#twikoo .tk-comments > div.tk-submit > div.tk-row.actions > a {
  display: none;
}
#twikoo .tk-comments .el-button.tk-preview {
  display: none;
}
#twikoo .tk-comments .el-button--primary.is-disabled,
#twikoo .tk-comments .el-button--primary.is-disabled:active,
#twikoo .tk-comments .el-button--primary.is-disabled:focus,
#twikoo .tk-comments .el-button--primary.is-disabled:hover {
  opacity: 0.2;
}
#twikoo .tk-comments .el-button--primary {
  border-color: var(--twikoo-fontcolor);
  color: var(--twikoo-card-bg);
  border-radius: 12px;
  box-shadow: var(--twikoo-shadow-black);
  transition: 0.3s;
  width: 6.25rem;
  position: absolute;
  top: -43px;
  right: 0;
  margin-left: 0.5rem !important;
  height: 32px;
}
#twikoo .tk-comments .tk-input .el-textarea__inner {
  min-height: 130px !important;
  border-radius: 15px;
  display: block;
  resize: vertical;
  padding: 16px 16px 40px 16px;
  line-height: 1.5;
  box-sizing: border-box;
  width: 100%;
  font-size: inherit;
  color: var(--twikoo-fontcolor);
  background-color: var(--twikoo-secondbg);
  border: var(--style-border-always);
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
}

#twikoo .tk-comments .el-input__inner {
  background: var(--twikoo-secondbg) !important;
  border: none !important;
  color: var(--twikoo-fontcolor) !important;
  padding-left: 8px;
}
#twikoo .tk-comments .el-input__inner:focus {
  border: none;
}
#twikoo .tk-comments .el-input-group__append,
#twikoo .tk-comments .el-input-group__prepend {
  background-color: var(--twikoo-card-bg);
  color: var(--twikoo-fontcolor);
  border-color: var(--twikoo-card-border);
  border: none;
  font-weight: 700;
}
#twikoo .tk-comments .el-input-group--prepend .el-input__inner,
#twikoo .tk-comments .el-input-group__append {
  border-radius: 0 10px 10px 0;
}
#twikoo .tk-comments .el-input--small .el-input__inner {
  padding: 8px;
  padding-left: 16px;
}
#twikoo .tk-comments .el-input-group--prepend .el-input__inner,
#twikoo .tk-comments .el-input-group__append {
  border-left-width: 0 !important;
}
#twikoo .tk-comments .tk-meta-input {
  position: relative;
  margin-top: 8px;
  width: calc(100% - 6.875rem);
}
#twikoo
  .tk-comments
  .tk-meta-input
  .el-input.el-input--small.el-input-group.el-input-group--prepend {
  border-radius: 12px;
  background: var(--twikoo-secondbg);
  border: var(--style-border-always);
}
#twikoo .tk-comments .tk-meta-input .el-input .el-input-group__prepend {
  user-select: none;
  border-radius: 12px 0 0 12px;
}
#twikoo
  .tk-comments
  .tk-meta-input
  .el-input--small.el-input-group.el-input-group--prepend:focus-within {
  border: var(--style-border-hover);
}
#twikoo .tk-comments .tk-row .tk-avatar {
  display: none;
}
#twikoo .tk-comments .tk-row .tk-col {
  flex-direction: column-reverse;
}
#twikoo .tk-comments .tk-row.actions {
  margin-bottom: 0;
  margin-left: 0;
  margin-top: 0;
  justify-content: space-around;
}
#twikoo .tk-comments .tk-admin {
  backdrop-filter: blur(5px);
}
#twikoo .tk-comments .el-button {
  background-color: var(--twikoo-fontcolor);
  border: 0 solid var(--twikoo-main);
  color: var(--twikoo-background);
}
#twikoo .tk-comments .tk-tag-green {
  background-color: var(--twikoo-main);
  border: none;
  border-radius: 4px;
  color: var(--twikoo-white);
}
#twikoo .tk-comments .tk-action-icon {
  color: var(--twikoo-main);
  cursor: pointer;
}
#twikoo .tk-comments .tk-icon.__comments {
  color: var(--twikoo-main);
}
#twikoo .tk-comments .tk-actions a {
  cursor: pointer;
}
#twikoo .tk-comments .tk-nick {
  line-height: 40px;
}
#twikoo .tk-comments .tk-extras {
  margin-top: 0.5rem;
  padding-bottom: 0.5rem;
}
#twikoo .tk-comments .tk-expand:hover {
  color: #fff;
  background-color: var(--twikoo-main);
  border: var(--style-border-none);
}

#twikoo .tk-comments .tk-content p {
  margin: 0;
}
#twikoo .tk-comments .tk-admin-config-input .el-input__inner {
  background: transparent !important;
}
#twikoo pre code {
  background: none;
}
#twikoo code {
  padding: 2px 4px;
  background: var(--twikoo-secondbg);
  color: #f47466;
}
#twikoo .tk-comment .tk-submit .tk-avatar,
#twikoo .tk-replies .tk-avatar {
  height: 2.5rem !important;
  width: 2.5rem !important;
}
#twikoo .tk-comment pre {
  background: #272822;
  padding: 1em;
  margin: 0.5em 0;
  overflow: auto;
  border-radius: 0.3em;
}

@media screen and (max-width: 768px) {
  #twikoo .tk-comments-container .tk-comment {
    padding: 1rem;
    border: var(--style-border-always);
    box-shadow: var(--twikoo-shadow-border);
    background: var(--twikoo-card-bg);
  }
  #twikoo .tk-replies .tk-comment {
    border: none;
  }
}

#twikoo .tk-avatar {
  border-radius: 50px;
}
#twikoo .tk-avatar .tk-avatar-img {
  height: 2.5rem !important;
}

#twikoo .tk-replies {
  max-height: 10rem !important;
}
#twikoo .tk-replies.tk-replies-expand {
  max-height: none !important;
}
#twikoo .tk-replies .tk-comment {
  border-top: var(--style-border-dashed);
  border-radius: 12px;
  padding: 1rem 0px 0px;
  margin-top: 0;
  transition: all 0.3s ease 0s;
}
#twikoo .tk-replies .tk-content span:first-child:not(.token) {
  font-size: 0.75rem;
  color: var(--twikoo-secondtext);
}

[data-theme="dark"] #owo-big {
  background-color: #4a4a4a;
}
.tk-comments-container .tk-submit {
  opacity: 1;
  height: auto;
  overflow: visible;
}
/* 输入提示 */
/* 设置文字内容 :nth-child(1)的作用是选择第几个 */
.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(
    1
  ):before {
  content: "输入QQ号会自动获取昵称和头像🐧";
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(
    2
  ):before {
  content: "收到回复将会发送到您的邮箱📧";
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(
    3
  ):before {
  content: "可以通过昵称访问您的网站🔗";
}

/* 当用户点击输入框时显示 */
.el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::before {
  display: block;
  animation: commonTipsIn 0.3s;
  z-index: 2;
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::after {
  display: block;
  animation: commonTriangleIn 0.3s;
}

/* 主内容区 */
.el-input.el-input--small.el-input-group.el-input-group--prepend::before {
  display: none;
  position: absolute;
  top: -60px;
  white-space: nowrap;
  border-radius: 10px;
  left: 50%;
  transform: translate(-50%);
  padding: 14px 18px;
  background: #444;
  color: #fff;
  z-index: 100;
}

/* 小角标 */
.el-input.el-input--small.el-input-group.el-input-group--prepend::after {
  display: none;
  content: "";
  position: absolute;
  border: 12px solid transparent;
  border-top-color: #444;
  left: 50%;
  transform: translate(-50%, -46px);
}

/* 评论框 */
.vwrap {
  box-shadow: 2px 2px 5px #bbb;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 8px;
  padding: 30px;
  margin: 30px 0px 30px 0px;
}

/* 设置评论框 */
.vcard {
  box-shadow: 2px 2px 5px #bbb;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 8px;
  padding: 30px;
  margin: 30px 0px 0px 0px;
}

#twikoo .tk-extra {
  background: var(--twikoo-card-bg);
  border: var(--style-border-always);
  padding: 4px 8px;
  border-radius: 8px;
  margin-right: 4px;
  color: var(--twikoo-secondtext);
  margin-top: 6px;
  font-size: 0.8rem;
}
#twikoo .tk-extra-text {
  font-size: 0.75rem;
}
#twikoo .tk-replies .tk-content {
  font-size: 0.9rem;
}
#twikoo .tk-content {
  margin-top: 0;
}
.tk-content span a:not([data-fancybox="gallery"]) {
  font-weight: 500;
  border-bottom: solid 2px var(--twikoo-lighttext);
  color: var(--twikoo-fontcolor);
  padding: 0 0.2em;
  text-decoration: none;
}
.tk-content span a:not([data-fancybox="gallery"]):hover {
  color: var(--twikoo-white);
  background-color: var(--twikoo-theme);
  border-radius: 4px;
}
.tk-main .tk-content span > a {
  border-bottom: none;
}
#post-comment .comment-head {
  font-size: 0.8em !important;
  margin-bottom: 0.5rem;
}

@keyframes commonTipsIn {
  0% {
    top: -50px;
    opacity: 0;
  }
  100% {
    top: -60px;
    opacity: 1;
  }
}

@keyframes commonTriangleIn {
  0% {
    transform: translate(-50%, -36px);
    opacity: 0;
  }
  100% {
    transform: translate(-50%, -46px);
    opacity: 1;
  }
}
@keyframes donate_effcet {
  0% {
    opacity: 0;
    transform: translateY(-20px);
  }
  100% {
    opacity: 1;
    filter: none;
    transform: translateY(0);
  }
}

#body-wrap.page .el-input__inner {
  background: var(--twikoo-card-bg);
  box-shadow: var(--twikoo-shadow-border);
  color: var(--twikoo-fontcolor);
}
#body-wrap.page .tk-admin-config .el-input__inner {
  color: currentColor;
}

#twikoo.twikoo .el-input__inner:focus,
#twikoo.twikoo .el-textarea__inner:focus {
  /* border-color: var(--twikoo-main); */
}

.tk-comments-container > .tk-comment {
  margin-top: 0 !important;
  margin-bottom: 1rem !important;
  transition: 0.3s;
  border-radius: 12px;
  padding: 0;
  padding-top: 1rem;
  border: none;
  border-top: var(--style-border-dashed);
}

#post-comment .comment-tips {
  background-color: rgba(103, 194, 58, 0.13);
  border: var(--style-border-always);
  border-color: var(--twikoo-green);
  color: var(--twikoo-green);
  border-radius: 8px;
  padding: 8px 12px;
  margin-top: 0.5rem;
  display: none;
  width: 100%;
}

#post-comment .comment-tips.show {
  display: flex;
}

#page .tk-comments-container > .tk-comment {
  background: var(--twikoo-card-bg);
  padding: 1rem;
  padding-bottom: 1rem;
  border: var(--style-border);
  border-top: var(--style-border);
  box-shadow: var(--twikoo-shadow-border);
}
@media (prefers-reduced-motion: no-preference) {
  #page .tk-comments-container > .tk-comment {
    animation: animate-in-and-out 1s linear forwards;
    animation-timeline: view();
  }
  #page .tk-comments-container > .tk-comment:has(.OwO-open) {
    z-index: 1;
  }
}

.tk-content {
  margin-top: 0.5rem;
  overflow: auto;
  max-height: 500px;
}

.tk-comments .tk-row-actions-start {
  position: absolute;
  top: -84px;
  left: 17px;
}

@media screen and (max-width: 768px) {
  .OwO .OwO-body {
    min-width: 260px;
  }
  .tk-comments .tk-row-actions-start {
    top: -176px;
  }
  #twikoo .tk-comments .tk-submit .el-button--primary {
    height: 122px;
    top: -126px;
  }
  #twikoo .el-textarea__inner {
    background: var(--twikoo-card-bg) !important;
    overflow: hidden;
    resize: none !important;
  }

  .tk-comments button.el-button.tk-preview.el-button--default.el-button--small {
    display: none;
  }
  .tk-comments .tk-main .tk-submit .tk-row.actions {
    justify-content: center;
  }
  .tk-comments button.el-button.tk-send,
  .tk-comments button.el-button.tk-cancel {
    width: 100%;
  }
  .tk-comments .tk-row-actions-start {
    position: absolute;
  }
}

.OwO .OwO-body .OwO-items .OwO-item:hover {
  box-shadow: var(--twikoo-shadow-lightblack) !important;
  border-radius: 8px;
}

三、使用组件(前端部署)

Twikoo 支持的博客主题:https://twikoo.js.org/frontend.html

如果你的博客不支持 Twikoo 则使用 CDN 引入,反之查看你博客对应的官方文档

<div id="tcomment"></div>
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.6.39/dist/twikoo.all.min.js"></script>
<script>
  twikoo.init({
    envId: "您的环境id", // 腾讯云环境填 envId;Vercel 环境填地址(https://xxx.vercel.app)
    el: "#tcomment", // 容器元素
    // region: 'ap-guangzhou', // 环境地域,默认为 ap-shanghai,腾讯云环境填 ap-shanghai 或 ap-guangzhou;Vercel 环境不填
    // path: location.pathname, // 用于区分不同文章的自定义 js 路径,如果您的文章路径不是 location.pathname,需传此参数
    // lang: 'zh-CN', // 用于手动设定评论区语言,支持的语言列表 https://github.com/twikoojs/twikoo/blob/main/src/client/utils/i18n/index.js
  });
</script>