增加了部分功能 #14

Merged
zzx-coder merged 6 commits from zhouzexin_branch into master 2026-05-13 21:59:47 +08:00
24 changed files with 475 additions and 135 deletions

View File

@ -0,0 +1,22 @@
{
"permissions": {
"allow": [
"Bash(npm run:*)",
"Bash(npm install:*)",
"Bash(netstat -ano)",
"Bash(powershell -Command \"Get-NetTCPConnection -LocalPort 3000 -ErrorAction SilentlyContinue | Select-Object LocalPort, State\")",
"Bash(findstr \":3000\")",
"Bash(findstr \"LISTENING\")",
"Bash(git config:*)",
"Bash(git fetch:*)",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)",
"Bash(start:*)",
"Bash(git remote:*)",
"Bash(ssh-keygen:*)",
"Bash(ssh -T git@gitlink.org.cn)",
"Bash(git branch:*)"
]
}
}

View File

@ -1,43 +1,10 @@
FROM crpi-1x701qgqjia2gdeu.cn-chengdu.personal.cr.aliyuncs.com/gitlink-help-center/gitlink-help-center:node-20-alpine
FROM node:18-alpine
LABEL maintainer="yuankaifneg <2894340009@qq.com>"
# 设置为root用户以安装系统依赖
USER root
WORKDIR /gitlink_help_center
# 安装必要的系统依赖
RUN yum install -y \
git \
python3 \
make \
gcc-c++ \
bash && \
yum clean all
COPY ./ /gitlink_help_center/
# 设置工作目录
WORKDIR /app
# 优先复制package.json和package-lock.json以利用Docker缓存
COPY package.json package-lock.json ./
# 安装依赖忽略peer依赖冲突
RUN npm install --legacy-peer-deps
# 复制项目文件
COPY . .
# 构建应用
RUN npm run build
# 暴露端口
EXPOSE 3000
# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
# 启动应用
RUN yarn install
RUN npm run build -- --locale zh-cn
CMD ["npm", "run", "serve"]

View File

@ -32,7 +32,7 @@ GitLink确实开源是CCF官方指定的开源创新服务平台旨在
<article class="col col--6 margin-bottom--lg">
<a class="card padding--lg cardContainer" href="/代码库管理/仓库创建">
<h2 class="text--truncate cardTitle" title="代码库管理">代码库管理</h2>
<p>代码库使用及设置[8个文档]</p>
<p>代码库使用及设置[9个文档]</p>
</a></article>
<article class="col col--6 margin-bottom--lg">
<a class="card padding--lg cardContainer" href="/组织管理/组织简介">
@ -60,9 +60,9 @@ GitLink确实开源是CCF官方指定的开源创新服务平台旨在
<p>维基(Wiki)使用及设置[2个文档]</p>
</a></article>
<article class="col col--6 margin-bottom--lg">
<a class="card padding--lg cardContainer" href="/Bot市场/bot安装">
<h2 class="text--truncate cardTitle" title="Bot市场">Bot市场</h2>
<p>Bot市场使用及设置[4个文档]</p>
<a class="card padding--lg cardContainer" href="/bot市场/bot安装">
<h2 class="text--truncate cardTitle" title="bot市场">bot市场</h2>
<p>bot市场使用及设置[3个文档]</p>
</a></article>
<article class="col col--6 margin-bottom--lg">
<a class="card padding--lg cardContainer" href="/第三方服务/跨平台代码同步">

View File

@ -8,39 +8,39 @@ sidebar_position: 1
![img](../../static/img/建站工具/1.png)
点击左面板中 个人建站 - 我的站点
点击左面板中 个人建站 - 我的站点
![img](../../static/img/建站工具/3.png)
### 创建站点
我的站点界面点击 新建站点 按钮,进入新建站点界面
**我的站点**界面点击**新建站点**按钮,进入新建站点界面
在新建站点界面输入站点名称,此名称将在我的站点列表中展示
在新建站点界面输入站点名称,此名称将在**我的站点**的**站点列表**中展示
并且选择对应的建站工具与主题我们为您提供了3种不同的工具每个工具10种主题一共30种供您挑选
![img](../../static/img/建站工具/4.png)
填写完毕后,点击页面下方蓝色按钮 创建站点
填写完毕后,点击页面下方蓝色按钮**创建站点**
![img](../../static/img/建站工具/5.png)
这样您就拥有了一个网站,并且有了一个代码仓库。
在仓库的 服务 一栏中 个人建站服务的操作界面,这里您可以查看一些您的站点状态、站点名称、网站地址、建站工具、建站时间
在仓库的**服务**一栏中**个人建站**服务的操作界面,这里您可以查看一些您的站点状态、站点名称、网站地址、建站工具、建站时间
### 部署站点
![img](../../static/img/建站工具/6.png)
点击去部署按钮,选择想要部署的分支后点击确定
点击**去部署**按钮,选择想要部署的分支后点击**确定**
![img](../../static/img/建站工具/7.png)
等待程序运行一会儿后,会返回一些服务器部署信息给您
等待程序运行一会儿后,会返回一些服务器部署信息给您,部署成功后您就可以访问站点了。
部署成功后您就可以访问站点了。点击网站地址就可以跳转
点击网站地址就可以跳转
![img](../../static/img/建站工具/8.png)

View File

@ -3,15 +3,15 @@ sidebar_label: '成员管理'
sidebar_position: 7
---
### **1. 成员管理入口**
在仓库主页,点击“仓库设置”按键,再点击”成员管理“按键,即可进入成员管理模块,如下图所示。
在仓库主页,点击**仓库设置**按键,再点击**成员管理**按键,即可进入成员管理模块,如下图所示。
![](../../static/img/代码库管理/成员管理/成员管理入口.png)<br/>
### **2. 筛选、搜索项目成员**
进入成员管理模块后,可以通过”角色筛选“按键来筛选项目成员类型,通过”搜索“按键可以检索具体的项目成员,如下图所示。
进入成员管理模块后,可以通过**角色筛选**按键来筛选项目成员类型,通过**搜索**按键可以检索具体的项目成员,如下图所示。
![](../../static/img/代码库管理/成员管理/筛选、搜索项目成员.png)<br/>
### **3. 筛选、搜索项目成员**
进入成员管理模块后,可以通过”添加成员“按键来添加项目成员,左侧搜索框检索到具体用户并选中后,单击”添加成员“按键即可成功添加项目成员。
### **3. 添加成员**
进入成员管理模块后,可以通过**添加成员**按键来添加项目成员,左侧搜索框检索到具体用户并选中后,单击**添加成员**按键即可成功添加项目成员。
![](../../static/img/代码库管理/成员管理/添加成员.png)<br/>
### **4. 项目成员权限管理**
@ -19,5 +19,5 @@ sidebar_position: 7
![](../../static/img/代码库管理/成员管理/项目成员权限管理.png)<br/>
### **5. 删除项目成员**
进入成员管理模块后,单击项目成员右侧的”删除“按键,可以删除改名项目成员,如下图所示。
进入成员管理模块后,单击项目成员右侧的**删除**按键,可以删除改名项目成员,如下图所示。
![](../../static/img/代码库管理/成员管理/删除项目成员.png)<br/>

View File

@ -3,4 +3,6 @@ sidebar_label: '合并请求关联疑修'
sidebar_position: 5
---
# 合并请求关联疑修
# 合并请求关联疑修
该功能还在开发完善中,敬请期待......

View File

@ -1,4 +1,12 @@
---
sidebar_label: '平台公告'
sidebar_position: 1
---
---
# 平台公告
GitLink帮助中心致力于帮助开发者快速熟悉平台功能掌握开源协作的正确方法。在这里您可以找到从账号注册到项目管理的完整指南也可以通过实际使用中发现平台存在的问题并提出改进建议。我们希望通过文档与社区的共同努力让GitLink成为更好的开源创新服务平台。如果您在使用过程中遇到任何问题欢迎在平台中提交疑修Issue获得帮助。
帮助中心项目地址是https://gitlink.org.cn/Gitlink/gitlink_help_center/
开发者可以先复刻帮助中心项目,然后在本地进行开发。

View File

@ -33,7 +33,7 @@ Gitee配置方式为个人头像→设置→私人令牌→生成新令牌→
![5.配置webhook](../../static/img/reposyncer/5.配置webhook.jpg)
②访问点击前往按钮前往目标仓库webhook页新建一个webhook以github为例
②访问点击前往按钮前往目标仓库webhook页新建一个webhook以github为例
![6.webhook示例](../../static/img/reposyncer/6.webhook示例.png)

View File

@ -2,13 +2,13 @@
sidebar_label: '组织创建及设置'
sidebar_position: 2
---
# 组织创建Organization Creation
# 组织创建
*https://www.gitlink.org.cn* 页面点击顶部导航栏的“+”符号可以进行组织新建操作。
在 https://www.gitlink.org.cn 页面点击顶部导航栏的“+”符号可以进行组织新建操作。
![](/img/Org/imageOrg1.png)
在新建页面中输入**组织账号****组织名称****组织描述****所在地区****可见性**以及**组织头像**等信息后,点击**创建组织**按钮完成组织的创建。
在新建页面中输入组织账号、组织名称、组织描述、所在地区、可见性以及组织头像等信息后,点击**创建组织**按钮完成组织的创建。
![](/img/Org/imageOrg2.png)

View File

@ -7,7 +7,7 @@ sidebar_position: 3
## 创建组织团队
点击组织信息页面中的“新建团队”按钮可以创建属于该组织的团队平台默认创建“Owners”团队成员为组织的创建者
在团队新建页面,输入团队标识、团队名称、团队描述、项目权限以及版本库权限等信息后,点击“新建团队”完成团队的创建。
在团队新建页面,输入团队标识、团队名称、团队描述、项目权限以及版本库权限等信息后,点击 **新建团队** 按钮完成团队的创建。
![](/img/Org/imageOrg9.png)
@ -19,7 +19,7 @@ sidebar_position: 3
## 管理组织团队
点击团队信息页面中的“团队设置”按钮可以对团队进行管理
点击团队信息页面中的 **团队设置** 按钮可以对团队进行管理。
- 基本设置:修改项目的基本信息,如名称和描述等。
![](/img/Org/imageOrg10.png)

View File

@ -2,9 +2,9 @@
sidebar_label: '组织成员管理'
sidebar_position: 4
---
# 成员管理Members Management
# 成员管理
个人所管理的项目当中的**仓库设置**当中的**成员管理**可以进入成员管理界面
在个人所管理的项目当中的**仓库设置**当中的**成员管理**可以进入成员管理界面
![](/img/Org/imageOrg14.png)

View File

@ -3,9 +3,7 @@ sidebar_label: '模板导入及导出'
sidebar_position: 2
---
# 确实开源帮助中心
## 模板的导入及导出管理
# 模板导入及导出
#### 1.模板导入
通过点击wiki界面的**导入模板**按钮即可导入本地的txtmarkdown等格式文件进行Wiki文档的创建当前平台此项功能尚在开发测试环节
[](/img/wiki/img4.png)

View File

@ -4,20 +4,21 @@ sidebar_position: 1
---
# 确实开源帮助中心
# 维基页面管理
## 维基界面管理
#### 1.维基界面
GitLink项目安排了专门的**维基(Wiki)界面**来展示项目的一些情况
[](/img/wiki/img1.png)
GitLink项目安排了专门的**维基(Wiki)界面**来展示项目的一些情况
![](/img/wiki/img1.png)
#### 2.创建维基内容
在初始化的维基界面当中点击**创建Wiki文档**或者**导入模板**即可进行Wiki文档的编辑
在初始化的维基界面当中点击**创建Wiki文档**或者**导入模板**即可进行Wiki文档的编辑
<br/>
![](/img/wiki/img4.png)
#### 3.进行Wiki文档的编辑
点击**创建Wiki文档**后即跳转到编辑界面,初始内容为空白的文档
[](/img/wiki/img3.png)
也可以通过勾选*添加模板*来进行模板的导入,平台提供的模板包括*周报*和*月报*的格式
[](/img/wiki/img2.png)
完成编辑后点击左下角的的保存即可
![](/img/wiki/img3.png)
也可以通过勾选**添加模板**来进行模板的导入,平台提供的模板包括*周报*和*月报*的格式
![](/img/wiki/img2.png)
完成编辑后点击左下角的的**保存**即可

View File

@ -3,9 +3,8 @@ sidebar_label: '通知简介'
sidebar_position: 1
---
# 确实开源帮助中心
# 通知简介
## 通知简介
#### 1.通知类型
GitLink将通知分为“系统通知”和“@我”的两种类型:
* 系统通知包括“我的状态”、“我创建的或负责的”、“我管理的仓库”三种类型的通知:
@ -25,5 +24,5 @@ GitLink将通知分为“系统通知”和“@我”的两种类型:
<br/>
点击通知按钮可以进入消息通知界面,“我的通知”界面可以进行“进查看未读消息”和“所有消息一键已读”的选择。
点击通知按钮可以进入消息通知界面,“我的通知”界面可以进行“仅看未读消息”和“所有系统通知一键已读”的选择。
![](/img/notice/my_notice2.png)

View File

@ -3,19 +3,16 @@ sidebar_label: '通知设置'
sidebar_position: 2
---
# 确实开源帮助中心
## 通知设置
# 通知设置
#### 1.进入通知设置界面
通过点击首页的通知按钮进入通知设置界面
通过点击首页的通知按钮进入通知设置界面
![](/img/notice/home_notice.png)
<br/>
或在头像下拉列表中选择设置可以进入消息通知设置界面
或在头像下拉列表中选择设置可以进入消息通知设置界面
![](/img/notice/into_notice.png)
#### 2.进行通知设置
通过“通知管理”可以对接受通知的方式进行设置,默认所有通知都是通过站内信的方式接受,可以通过勾选为重要的通知类型增加邮件接受方式。
通过**通知管理**可以对接受通知的方式进行设置,默认所有通知都是通过站内信的方式接受,可以通过勾选为重要的通知类型增加邮件接受方式。
![](/img/notice/notice_set.png)

View File

@ -185,23 +185,22 @@ module.exports = {
],
themes: [
// ... Your other themes.
// Local search plugin temporarily disabled due to compatibility issues with Docusaurus 3.9.2
// [
// require.resolve("@easyops-cn/docusaurus-search-local"),
// {
// // ... Your options.
// // `hashed` is recommended as long-term-cache of index file is possible.
// hashed: true,
// language: ["en", "zh"],
// highlightSearchTermsOnTargetPage: true,
// blogRouteBasePath: "/",
// explicitSearchResultPath: true,
// // For Docs using Chinese, The `language` is recommended to set to:
// // ```
// // language: ["en", "zh"],
// // ```
// },
// ],
[
require.resolve("@easyops-cn/docusaurus-search-local"),
{
// ... Your options.
// `hashed` is recommended as long-term-cache of index file is possible.
hashed: true,
language: ["en", "zh"],
highlightSearchTermsOnTargetPage: true,
blogRouteBasePath: "/",
explicitSearchResultPath: true,
// For Docs using Chinese, The `language` is recommended to set to:
// ```
// language: ["en", "zh"],
// ```
},
],
],
i18n: {
defaultLocale: 'zh-cn',

1
gitlink_help_center Submodule

@ -0,0 +1 @@
Subproject commit 293675001acfe7c74caa0bcf78765ec29034c715

27
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "docusaurus",
"version": "0.0.0",
"version": "3.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "docusaurus",
"version": "0.0.0",
"version": "3.0.0",
"dependencies": {
"@cmfcmf/docusaurus-search-local": "1.1.0",
"@docusaurus/core": "3.9.2",
@ -26,7 +26,7 @@
"react-modal": "3.16.1"
},
"engines": {
"node": ">=14.18.1 <=18.x"
"node": ">=18.x"
}
},
"node_modules/@algolia/abtesting": {
@ -19901,13 +19901,6 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/search-insights": {
"version": "2.17.3",
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz",
"integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==",
"license": "MIT",
"peer": true
},
"node_modules/section-matter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
@ -20994,20 +20987,6 @@
"is-typedarray": "^1.0.0"
}
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici": {
"version": "7.22.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz",

View File

@ -1,9 +1,8 @@
module.exports = {
DocsSidebar: [
docs: [
{
type: 'doc',
id: 'index',
label: 'Docs',
}
type: 'autogenerated',
dirName: '.', // 自动生成 docs/ 下所有文档的侧边栏
},
],
};
};

View File

@ -0,0 +1,151 @@
import { useState, useEffect } from 'react';
const GITEE_API = 'https://gitee.com/api/v5/repos/camelliamc/gitlink-feedback';
const TOKEN = 'f8433b20f2a07a28cf95aa0e17edfac4';
const getDocTitle = (path) => {
const cleanPath = path.replace(/^\//, '');
return `Vote_${cleanPath.replace(/\//g, '_')}`;
};
export default function VoteButtons() {
const [upvotes, setUpvotes] = useState(0);
const [downvotes, setDownvotes] = useState(0);
const [userVote, setUserVote] = useState(null); // null | 'up' | 'down'
const [docPath, setDocPath] = useState('');
const [loading, setLoading] = useState(false);
useEffect(() => {
const path = window.location.pathname;
setDocPath(path);
const stored = localStorage.getItem(`vote_${path}`);
if (stored === 'up' || stored === 'down') {
setUserVote(stored);
}
fetchVotes(path);
}, []);
const fetchVotes = async (path) => {
try {
const res = await fetch(`${GITEE_API}/issues?access_token=${TOKEN}&state=open&labels=vote`);
const data = await res.json();
const title = getDocTitle(path);
const issue = data.find(i => i.title === title);
if (issue) {
const labels = issue.labels || [];
const upLabel = labels.find(l => l.name.startsWith('up:'));
const downLabel = labels.find(l => l.name.startsWith('down:'));
if (upLabel) setUpvotes(parseInt(upLabel.name.split(':')[1]) || 0);
if (downLabel) setDownvotes(parseInt(downLabel.name.split(':')[1]) || 0);
}
} catch (e) {
console.error('获取投票失败:', e);
}
};
const updateGiteeIssue = async (newUp, newDown) => {
const title = getDocTitle(docPath);
const res = await fetch(`${GITEE_API}/issues?access_token=${TOKEN}&state=open&labels=vote`);
const data = await res.json();
const existingIssue = data.find(i => i.title === title);
const labels = [`vote`, `up:${newUp}`, `down:${newDown}`];
if (existingIssue) {
await fetch(`${GITEE_API}/issues/${existingIssue.number}?access_token=${TOKEN}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ labels })
});
} else {
await fetch(`${GITEE_API}/issues?access_token=${TOKEN}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title,
body: `文档投票 - ${docPath}`,
labels
})
});
}
};
const handleVote = async (type) => {
if (loading || !docPath) return;
setLoading(true);
try {
let newUp = upvotes;
let newDown = downvotes;
let newVote = null;
if (userVote === null) {
// 未投票 → 投票
if (type === 'up') {
newUp = upvotes + 1;
} else {
newDown = downvotes + 1;
}
newVote = type;
} else if (userVote === type) {
// 点击已选中的 → 取消投票
if (type === 'up') {
newUp = Math.max(0, upvotes - 1);
} else {
newDown = Math.max(0, downvotes - 1);
}
newVote = null;
} else {
// 切换投票
if (type === 'up') {
newUp = upvotes + 1;
newDown = Math.max(0, downvotes - 1);
} else {
newDown = downvotes + 1;
newUp = Math.max(0, upvotes - 1);
}
newVote = type;
}
await updateGiteeIssue(newUp, newDown);
setUpvotes(newUp);
setDownvotes(newDown);
setUserVote(newVote);
if (newVote) {
localStorage.setItem(`vote_${docPath}`, newVote);
} else {
localStorage.removeItem(`vote_${docPath}`);
}
} catch (e) {
console.error('投票失败:', e);
} finally {
setLoading(false);
}
};
return (
<div className="vote-container">
<span className="vote-label">这篇文档有帮助吗</span>
<div className="vote-buttons">
<button
onClick={() => handleVote('up')}
className={`vote-btn vote-btn-up ${userVote === 'up' ? 'vote-btn-active-up' : ''}`}
title={userVote === 'up' ? '取消投票' : '有帮助'}
>
<span className="vote-emoji">👍</span>
<span className="vote-count">{upvotes}</span>
</button>
<button
onClick={() => handleVote('down')}
className={`vote-btn vote-btn-down ${userVote === 'down' ? 'vote-btn-active-down' : ''}`}
title={userVote === 'down' ? '取消投票' : '没帮助'}
>
<span className="vote-emoji">👎</span>
<span className="vote-count">{downvotes}</span>
</button>
</div>
</div>
);
}

View File

@ -148,4 +148,143 @@ html[data-theme='dark'] .docusaurus-highlight-code-line {
.widget{
display: none!important;
opacity: 0;
}
}
/* 帮助文档卡片背景 */
.cardContainer {
background-color: #e6f0ff !important;
border-radius: 12px;
transition: all 0.3s ease;
}
.cardContainer:hover {
background-color: #cce0ff !important;
box-shadow: 0 4px 12px rgba(70, 106, 255, 0.15);
}
/* ===== 文档投票组件样式 ===== */
.vote-container {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 1.2rem;
padding: 1.5rem 0 0.5rem 0;
margin-top: 1.5rem;
border-top: 1px solid var(--ifm-toc-border-color);
}
.vote-label {
font-weight: 500;
color: var(--ifm-color-emphasis-600);
font-size: 0.95rem;
white-space: nowrap;
}
.vote-buttons {
display: flex;
align-items: center;
gap: 0.6rem;
}
.vote-btn {
display: flex;
align-items: center;
gap: 0.35rem;
padding: 0.4rem 0.85rem;
border: none;
border-radius: 20px;
background: var(--ifm-color-emphasis-100);
cursor: pointer;
font-size: 1rem;
transition: all 0.2s ease;
user-select: none;
outline: none;
}
.vote-btn:hover {
background: var(--ifm-color-emphasis-200);
transform: scale(1.05);
}
.vote-btn:active {
transform: scale(0.97);
}
.vote-emoji {
font-size: 1.25rem;
line-height: 1;
}
.vote-count {
color: var(--ifm-color-emphasis-700);
font-weight: 600;
font-size: 0.95rem;
min-width: 1ch;
text-align: center;
}
/* 👍 高亮状态 */
.vote-btn-active-up {
background: #e6f0ff;
box-shadow: 0 0 0 2px rgba(70, 106, 255, 0.25);
}
.vote-btn-active-up:hover {
background: #d6e4ff;
}
.vote-btn-active-up .vote-count {
color: #466aff;
}
/* 👎 高亮状态 */
.vote-btn-active-down {
background: #fff0e6;
box-shadow: 0 0 0 2px rgba(255, 102, 0, 0.25);
}
.vote-btn-active-down:hover {
background: #ffe4d0;
}
.vote-btn-active-down .vote-count {
color: #ff6600;
}
/* 暗色模式适配 */
html[data-theme='dark'] .vote-btn {
background: var(--ifm-color-emphasis-200);
}
html[data-theme='dark'] .vote-btn:hover {
background: var(--ifm-color-emphasis-300);
}
html[data-theme='dark'] .vote-count {
color: var(--ifm-color-emphasis-600);
}
html[data-theme='dark'] .vote-btn-active-up {
background: rgba(70, 106, 255, 0.2);
box-shadow: 0 0 0 2px rgba(70, 106, 255, 0.35);
}
html[data-theme='dark'] .vote-btn-active-up:hover {
background: rgba(70, 106, 255, 0.3);
}
html[data-theme='dark'] .vote-btn-active-up .vote-count {
color: #8aa3ff;
}
html[data-theme='dark'] .vote-btn-active-down {
background: rgba(255, 102, 0, 0.15);
box-shadow: 0 0 0 2px rgba(255, 102, 0, 0.3);
}
html[data-theme='dark'] .vote-btn-active-down:hover {
background: rgba(255, 102, 0, 0.25);
}
html[data-theme='dark'] .vote-btn-active-down .vote-count {
color: #ff9944;
}

View File

@ -0,0 +1,57 @@
import React from 'react';
import clsx from 'clsx';
import {useWindowSize} from '@docusaurus/theme-common';
import {useDoc} from '@docusaurus/plugin-content-docs/client';
import DocItemPaginator from '@theme/DocItem/Paginator';
import DocVersionBanner from '@theme/DocVersionBanner';
import DocVersionBadge from '@theme/DocVersionBadge';
import DocItemFooter from '@theme/DocItem/Footer';
import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile';
import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop';
import DocItemContent from '@theme/DocItem/Content';
import DocBreadcrumbs from '@theme/DocBreadcrumbs';
import ContentVisibility from '@theme/ContentVisibility';
import VoteButtons from '@site/src/components/VoteButtons';
import styles from './styles.module.css';
function useDocTOC() {
const {frontMatter, toc} = useDoc();
const windowSize = useWindowSize();
const hidden = frontMatter.hide_table_of_contents;
const canRender = !hidden && toc.length > 0;
const mobile = canRender ? <DocItemTOCMobile /> : undefined;
const desktop =
canRender && (windowSize === 'desktop' || windowSize === 'ssr') ? (
<DocItemTOCDesktop />
) : undefined;
return {
hidden,
mobile,
desktop,
};
}
export default function DocItemLayout({children}) {
const docTOC = useDocTOC();
const {metadata} = useDoc();
return (
<div className="row">
<div className={clsx('col', !docTOC.hidden && styles.docItemCol)}>
<ContentVisibility metadata={metadata} />
<DocVersionBanner />
<div className={styles.docItemContainer}>
<article>
<DocBreadcrumbs />
<DocVersionBadge />
{docTOC.mobile}
<DocItemContent>{children}</DocItemContent>
<DocItemFooter />
<VoteButtons />
</article>
<DocItemPaginator />
</div>
</div>
{docTOC.desktop && <div className="col col--3">{docTOC.desktop}</div>}
</div>
);
}

View File

@ -0,0 +1,10 @@
.docItemContainer header + *,
.docItemContainer article > *:first-child {
margin-top: 0;
}
@media (min-width: 997px) {
.docItemCol {
max-width: 75% !important;
}
}

View File

@ -0,0 +1,11 @@
import OriginalFooter from '@docusaurus/theme-classic/lib/theme/Footer/Layout';
import VoteButtons from '@site/src/components/VoteButtons';
export default function Layout(props) {
return (
<>
<OriginalFooter {...props} />
<VoteButtons />
</>
);
}