docs: add chinese docs

pull/90/head
moonrailgun 2 years ago
parent 51c2fb2032
commit 47c0491e75

@ -14,9 +14,13 @@ const themeConfig = {
type: 'doc',
docId: 'intro',
position: 'left',
label: '文档',
label: 'Docs',
},
{ to: '/blog', label: 'Blog', position: 'left' },
{
type: 'localeDropdown',
position: 'right',
},
{ to: '/blog', label: '博客', position: 'left' },
{
href: 'https://github.com/msgbyte/tailchat',
label: 'GitHub',
@ -104,7 +108,7 @@ const presetClassicOptions = {
/** @type {import('@docusaurus/types').DocusaurusConfig} */
module.exports = {
title: 'Tailchat',
tagline: '一个插件化易拓展的开源 IM 应用',
tagline: 'A pluginify opensource IM Application',
url: 'https://tailchat.msgbyte.com', // TODO: 待修改成文档主页
baseUrl: '/',
onBrokenLinks: 'throw',
@ -113,6 +117,10 @@ module.exports = {
organizationName: 'msgbyte', // Usually your GitHub org/user name.
projectName: 'tailchat', // Usually your repo name.
themeConfig,
i18n: {
defaultLocale: 'en',
locales: ['en', 'zh-Hans'],
},
presets: [['@docusaurus/preset-classic', presetClassicOptions]],
plugins: [require.resolve('docusaurus-plugin-image-zoom')],
};

@ -0,0 +1,269 @@
{
"Easy to use": {
"message": "易于使用"
},
"Easy to expand": {
"message": "易于拓展"
},
"Open source": {
"message": "面向开源"
},
"Try in Nightly version": {
"message": "进入 Nightly 版"
},
"theme.ErrorPageContent.title": {
"message": "页面已崩溃。",
"description": "The title of the fallback page when the page crashed"
},
"theme.ErrorPageContent.tryAgain": {
"message": "重试",
"description": "The label of the button to try again when the page crashed"
},
"theme.NotFound.title": {
"message": "找不到页面",
"description": "The title of the 404 page"
},
"theme.NotFound.p1": {
"message": "我们找不到您要找的页面。",
"description": "The first paragraph of the 404 page"
},
"theme.NotFound.p2": {
"message": "请联系原始链接来源网站的所有者,并告知他们链接已损坏。",
"description": "The 2nd paragraph of the 404 page"
},
"theme.admonition.note": {
"message": "备注",
"description": "The default label used for the Note admonition (:::note)"
},
"theme.admonition.tip": {
"message": "提示",
"description": "The default label used for the Tip admonition (:::tip)"
},
"theme.admonition.danger": {
"message": "危险",
"description": "The default label used for the Danger admonition (:::danger)"
},
"theme.admonition.info": {
"message": "信息",
"description": "The default label used for the Info admonition (:::info)"
},
"theme.admonition.caution": {
"message": "警告",
"description": "The default label used for the Caution admonition (:::caution)"
},
"theme.BackToTopButton.buttonAriaLabel": {
"message": "回到顶部",
"description": "The ARIA label for the back to top button"
},
"theme.blog.archive.title": {
"message": "历史博文",
"description": "The page & hero title of the blog archive page"
},
"theme.blog.archive.description": {
"message": "历史博文",
"description": "The page & hero description of the blog archive page"
},
"theme.blog.paginator.navAriaLabel": {
"message": "博文列表分页导航",
"description": "The ARIA label for the blog pagination"
},
"theme.blog.paginator.newerEntries": {
"message": "较新的博文",
"description": "The label used to navigate to the newer blog posts page (previous page)"
},
"theme.blog.paginator.olderEntries": {
"message": "较旧的博文",
"description": "The label used to navigate to the older blog posts page (next page)"
},
"theme.blog.post.paginator.navAriaLabel": {
"message": "博文分页导航",
"description": "The ARIA label for the blog posts pagination"
},
"theme.blog.post.paginator.newerPost": {
"message": "较新一篇",
"description": "The blog post button label to navigate to the newer/previous post"
},
"theme.blog.post.paginator.olderPost": {
"message": "较旧一篇",
"description": "The blog post button label to navigate to the older/next post"
},
"theme.blog.post.plurals": {
"message": "{count} 篇博文",
"description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.blog.tagTitle": {
"message": "{nPosts} 含有标签「{tagName}」",
"description": "The title of the page for a blog tag"
},
"theme.tags.tagsPageLink": {
"message": "查看所有标签",
"description": "The label of the link targeting the tag list page"
},
"theme.colorToggle.ariaLabel": {
"message": "切换浅色/暗黑模式(当前为{mode}",
"description": "The ARIA label for the navbar color mode toggle"
},
"theme.colorToggle.ariaLabel.mode.dark": {
"message": "暗黑模式",
"description": "The name for the dark color mode"
},
"theme.colorToggle.ariaLabel.mode.light": {
"message": "浅色模式",
"description": "The name for the light color mode"
},
"theme.docs.breadcrumbs.home": {
"message": "主页面",
"description": "The ARIA label for the home page in the breadcrumbs"
},
"theme.docs.breadcrumbs.navAriaLabel": {
"message": "页面路径",
"description": "The ARIA label for the breadcrumbs"
},
"theme.docs.DocCard.categoryDescription": {
"message": "{count} 个项目",
"description": "The default description for a category card in the generated index about how many items this category includes"
},
"theme.docs.paginator.navAriaLabel": {
"message": "文档分页导航",
"description": "The ARIA label for the docs pagination"
},
"theme.docs.paginator.previous": {
"message": "上一页",
"description": "The label used to navigate to the previous doc"
},
"theme.docs.paginator.next": {
"message": "下一页",
"description": "The label used to navigate to the next doc"
},
"theme.docs.tagDocListPageTitle.nDocsTagged": {
"message": "{count} 篇文档带有标签",
"description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.tagDocListPageTitle": {
"message": "{nDocsTagged}「{tagName}」",
"description": "The title of the page for a docs tag"
},
"theme.docs.versionBadge.label": {
"message": "版本:{versionLabel}"
},
"theme.docs.versions.unreleasedVersionLabel": {
"message": "此为 {siteTitle} {versionLabel} 版尚未发行的文档。",
"description": "The label used to tell the user that he's browsing an unreleased doc version"
},
"theme.docs.versions.unmaintainedVersionLabel": {
"message": "此为 {siteTitle} {versionLabel} 版的文档,现已不再积极维护。",
"description": "The label used to tell the user that he's browsing an unmaintained doc version"
},
"theme.docs.versions.latestVersionSuggestionLabel": {
"message": "最新的文档请参阅 {latestVersionLink} ({versionLabel})。",
"description": "The label used to tell the user to check the latest version"
},
"theme.docs.versions.latestVersionLinkLabel": {
"message": "最新版本",
"description": "The label used for the latest version suggestion link label"
},
"theme.common.editThisPage": {
"message": "编辑此页",
"description": "The link label to edit the current page"
},
"theme.common.headingLinkTitle": {
"message": "标题的直接链接",
"description": "Title for link to heading"
},
"theme.lastUpdated.atDate": {
"message": "于 {date} ",
"description": "The words used to describe on which date a page has been last updated"
},
"theme.lastUpdated.byUser": {
"message": "由 {user} ",
"description": "The words used to describe by who the page has been last updated"
},
"theme.lastUpdated.lastUpdatedAtBy": {
"message": "最后{byUser}{atDate}更新",
"description": "The sentence used to display when a page has been last updated, and by who"
},
"theme.navbar.mobileVersionsDropdown.label": {
"message": "选择版本",
"description": "The label for the navbar versions dropdown on mobile view"
},
"theme.common.skipToMainContent": {
"message": "跳到主要内容",
"description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation"
},
"theme.tags.tagsListLabel": {
"message": "标签:",
"description": "The label alongside a tag list"
},
"theme.AnnouncementBar.closeButtonAriaLabel": {
"message": "关闭",
"description": "The ARIA label for close button of announcement bar"
},
"theme.blog.sidebar.navAriaLabel": {
"message": "最近博文导航",
"description": "The ARIA label for recent posts in the blog sidebar"
},
"theme.CodeBlock.copied": {
"message": "复制成功",
"description": "The copied button label on code blocks"
},
"theme.CodeBlock.copyButtonAriaLabel": {
"message": "复制代码到剪贴板",
"description": "The ARIA label for copy code blocks button"
},
"theme.CodeBlock.copy": {
"message": "复制",
"description": "The copy button label on code blocks"
},
"theme.CodeBlock.wordWrapToggle": {
"message": "切换自动换行",
"description": "The title attribute for toggle word wrapping button of code block lines"
},
"theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel": {
"message": "打开/收起侧边栏菜单「{label}」",
"description": "The ARIA label to toggle the collapsible sidebar category"
},
"theme.navbar.mobileLanguageDropdown.label": {
"message": "选择语言",
"description": "The label for the mobile language switcher dropdown"
},
"theme.TOCCollapsible.toggleButtonLabel": {
"message": "本页总览",
"description": "The label used by the button on the collapsible TOC component"
},
"theme.blog.post.readMore": {
"message": "阅读更多",
"description": "The label used in blog post item excerpts to link to full blog posts"
},
"theme.blog.post.readMoreLabel": {
"message": "阅读 {title} 的全文",
"description": "The ARIA label for the link to full blog posts from excerpts"
},
"theme.blog.post.readingTime.plurals": {
"message": "阅读需 {readingTime} 分钟",
"description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.sidebar.collapseButtonTitle": {
"message": "收起侧边栏",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.collapseButtonAriaLabel": {
"message": "收起侧边栏",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": {
"message": "← 回到主菜单",
"description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"
},
"theme.docs.sidebar.expandButtonTitle": {
"message": "展开侧边栏",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.docs.sidebar.expandButtonAriaLabel": {
"message": "展开侧边栏",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.tags.tagsPageTitle": {
"message": "标签",
"description": "The title of the tag list page"
}
}

@ -0,0 +1,14 @@
{
"title": {
"message": "Blog",
"description": "The title for the blog used in SEO"
},
"description": {
"message": "Blog",
"description": "The description for the blog used in SEO"
},
"sidebar.title": {
"message": "Recent posts",
"description": "The label for the left sidebar"
}
}

@ -0,0 +1,46 @@
{
"version.label": {
"message": "Next",
"description": "The label for version current"
},
"sidebar.tutorialSidebar.category.应用部署": {
"message": "应用部署",
"description": "The label for category 应用部署 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.运维操作": {
"message": "运维操作",
"description": "The label for category 运维操作 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.插件列表": {
"message": "插件列表",
"description": "The label for category 插件列表 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.进阶使用": {
"message": "进阶使用",
"description": "The label for category 进阶使用 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.命令行终端": {
"message": "命令行终端",
"description": "The label for category 命令行终端 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.视频会议": {
"message": "视频会议",
"description": "The label for category 视频会议 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.开发插件": {
"message": "开发插件",
"description": "The label for category 开发插件 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.API 接口": {
"message": "API 接口",
"description": "The label for category API 接口 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.项目贡献": {
"message": "项目贡献",
"description": "The label for category 项目贡献 in sidebar tutorialSidebar"
},
"sidebar.tutorialSidebar.category.开发文档": {
"message": "开发文档",
"description": "The label for category 开发文档 in sidebar tutorialSidebar"
}
}

@ -0,0 +1,52 @@
---
sidebar_position: 2
title: Github 集成
---
![](./assets/github-integration.excalidraw.png)
## 普通用户使用
### 在项目安装应用
地址: https://github.com/apps/tailchat
安装到项目仓库中。
### 在项目中进行配置
在根目录创建`.tailchat/topic.json` 文件:
```json
{
"groupId": "<your-notify-group-id>",
"panelId": "<your-topic-panel-id>"
}
```
## 自部署配置
应用启动前需要在github中注册一个应用:
![](./assets/github-new-app.png)
部署时需要配置以下环境变量:
- `APP_ID`: 来自github 应用设置
- `WEBHOOK_SECRET`: 来自github 应用设置
- `PRIVATE_KEY`: 来自github 应用设置
- `TAILCHAT_APP_ID`: Tailchat 开放平台的id
- `TAILCHAT_APP_SECRET`: Tailchat 开放平台的秘钥
- `TAILCHAT_API_URL`: Tailchat 后台地址
为获取 `TAILCHAT_APP_ID``TAILCHAT_APP_SECRET` 需要在 Tailchat 开放平台中创建一个开放平台应用
同时开启机器人权限,并设置消息回调地址: `https://<your_app_url>/message/webhook`
### 部署开放平台应用
> 源码: [https://github.com/msgbyte/tailchat/tree/master/apps/github-app](https://github.com/msgbyte/tailchat/tree/master/apps/github-app)
拉取源码后部署到可供访问的线上,提供两种方式:
- 独立应用: `npm run build` 后执行 `node lib/index.js`运行应用
- Vercel: 直接推送到Vercel即可

@ -0,0 +1,34 @@
---
sidebar_position: 1
title: 富文本语法
---
## 对于普通用户
Tailchat 内置了 `com.msgbyte.bbcode` 插件用于对富文本消息做支持(且是默认安装的)。
以下是目前 `bbcode` 插件支持的语法列表:
| 关键字 | 描述 | 用法示例 | 预览 |
| ------ | ----- | ------ | ----- |
| b | 文本加粗 | `[b]foo[/b]` | <b>foo</b> |
| i | 文本倾斜 | `[i]foo[/i]` | <i>foo</i> |
| u | 文本下划线 | `[u]foo[/u]` | <ins>foo</ins> |
| s | 文本删除线 | `[s]foo[/s]` | <del>foo</del> |
| url | 超链接 | <div style={{width: 400}}>`[url]https://tailchat.msgbyte.com[/url]` / `[url=https://tailchat.msgbyte.com]官网[/url]`</div> | <a>https://tailchat.msgbyte.com</a> / <a href="https://tailchat.msgbyte.com">官网</a> |
| img | 图片 | `[img]https://tailchat.msgbyte.com/img/logo.svg[/img]` | <div style={{width: 60}}><img src="https://tailchat.msgbyte.com/img/logo.svg" /></div> |
| at | 提及 | `[at=<hereisuserid>]moonrailgun[/at]` | - |
| emoji | 表情 | `[emoji]smile[/emoji]` | - |
| markdown / md | markdown语法支持 | `[markdown]## Heading[/markdown]` | - |
## 对于插件开发者
如果你的插件需要使用统一的富文本支持,请在你的渲染函数中这样实现:
```jsx
import { getMessageRender } from '@capital/common';
const Component = (text: string) => {
return <div>{getMessageRender(text)}</div>
}
```

@ -0,0 +1,12 @@
---
sidebar_position: 3
title: 系统架构
---
## 服务端架构
![](/img/architecture/backend.excalidraw.svg)
## 插件机制架构
![](/img/architecture/plugin.excalidraw.svg)

@ -0,0 +1,33 @@
---
sidebar_position: 1
title: 命令行工具 tailchat-cli
---
## 安装
```bash
npm install -g tailchat-cli@latest # 安装与更新同一命令
```
或直接使用
```bash
npx tailchat-cli <command>
```
安装成功后输入`tailchat` 后返回如下
```bash
tailchat <command>
Commands:
tailchat create [template] 创建 Tailchat 项目代码
tailchat connect 连接到 Tailchat 节点网络
tailchat app Tailchat cli 版本(WIP)
tailchat bench 压力测试
tailchat declaration <source> Tailchat 插件类型声明
tailchat docker Tailchat 镜像管理
Options:
--version Show version number [boolean]
-h, --help Show help [boolean]
```

@ -0,0 +1,24 @@
---
sidebar_position: 99
title: 生态与社区
---
`Tailchat` 是一个非常开放的平台,欢迎来自所有人的以任何形式的贡献。在这里收录一些`Tailchat`相关的第三方资源
欢迎提交 `pr/issue` 来提交你对`Tailchat`的贡献,让我们能够以下列表中收录:
## 交流社区
<img width="360" src="/img/wechat.jpg" />
## 代码
*(empty)*
## 视频
- [【好玩儿的Docker项目】激情畅聊十分钟搭建一个插件化易拓展的开源即时聊天IM应用——Tailchat](https://www.bilibili.com/video/BV1aG411u7M8/)
## 文章
- [【好玩儿的Docker项目】激情畅聊十分钟搭建一个插件化易拓展的开源即时聊天IM应用——Tailchat](https://blog.laoda.de/archives/docker-compose-install-tailchat)

@ -0,0 +1,73 @@
---
sidebar_position: 1
title: 身份组与权限
---
身份组是在群组管理中划分用户权限点的形式(RBAC)。
身份组是由一系列权限点的开关组合而成的而一个用户可能是由多个身份组组合而成的比如身份组A拥有A权限身份组B拥有B权限那么作为同时拥有身份组A和身份组B的用户C则拥有权限A和权限B。为了简化权限的设计权限点则是通过简单的`true/false`实现的
更多关于 `RBAC` 可以查看相关wiki: https://en.wikipedia.org/wiki/Role-based_access_control 在此不做赘述。
下面主要讲讲在 `Tailchat` 是如何增加/修改权限点的
## 内置权限
权限点需要同时在前端和后端均做一次声明,前端负责前端的显示,后端负责做兜底的权限校验。如果没有权限的话处理接口应当直接范围一个报错。
### 前端管理
前端的权限点列表维护在 `client/shared/utils/role-helper.ts` 中, 包含权限点的权限点位, 如:
```tsx
export const PERMISSION = {
/**
* 非插件的权限点都叫core
*/
core: {
message: 'core.message',
},
};
```
以及权限点的在管理页面中的显示:
```tsx
export const getPermissionList = (): PermissionItemType[] => [
{
key: PERMISSION.core.message,
title: t('发送消息'),
desc: t('允许成员在文字频道发送消息'),
default: true,
}
];
```
使用方式则是通过hooks获取维护在群组下的权限点:
```tsx
const [allowSendMessage] = useHasGroupPermission(groupId, [
PERMISSION.core.message,
]);
```
使用数组的方式便于一些业务逻辑需要拥有多个权限点。
### 后端
后端的权限声明则是在 `server/packages/sdk/src/services/lib/role.ts` 中维护,使用方式也非常简单。如下:
```ts
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
userId,
[PERMISSION.core.message]
);
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
```
## 插件权限
TODO

@ -0,0 +1,54 @@
---
sidebar_position: 1
title: 贡献指南
---
`Tailchat` 是一个非常开放的项目,欢迎来自各种不同背景、任何形式的贡献。其插件的形式意味着允许`Tailchat` 可以承载任何想法的实现。
我们期望 `Tailchat` 不仅仅是一个简单的聊天应用,更是一个连接不同工具、不同想法的空间。
Github 地址: https://github.com/msgbyte/tailchat
-----------
目前 `Tailchat` 所急需要贡献者角色:
### 前端插件开发者
- 熟悉 React 的使用
- 拥有一定的抽象化思维
- 有基本的审美能力
- 对开源项目抱有热情
### 后端插件开发者
- 熟悉 Nodejs 的使用
- 对微服务有基本的认知
- 对开源项目抱有热情
### electron 应用开发者
- 了解跨平台的开发
- 熟悉代码注入,能够实现 render 进程与 main 进行数据交互
- 对开源项目抱有热情
### uniapp w2a 应用开发者
- 熟悉uniapp应用的开发
- 熟悉unipush2的开发
- 对开源项目抱有热情
### 运营同学
- 了解基本的运营能力,有当过大群群主的经验
- 了解开源项目的宣传渠道与方式
- 沟通能力强
### 其他
更多的一切可能性...
:::info
联系方式: 发送邮件到`moonrailgun@gmail.com` 或 [加入TailchatNightly频道](https://nightly.paw.msgbyte.com/invite/8Jfm1dWb)
:::

@ -0,0 +1,34 @@
---
sidebar_position: 9
title: 部署管理后台(可选)
---
:::info
管理后台的功能还在不断迭代中,目前正处于前期体验版
后续会不断丰富内部的内容
:::
从`github`获取最新的管理后台配置:
```bash
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/admin.yml
```
在环境变量 `docker-compose.env` 中设置管理后台的账号和密码:
```ini
ADMIN_USER=tailchat
ADMIN_PASS=<这里写入独立的后台密码, 不要告知其他人>
```
然后使用[多文件方式](https://docs.docker.com/compose/extends/#understanding-multiple-compose-files)启动应用:
```bash
docker compose -f docker-compose.yml -f admin.yml up -d
```
*注意先后顺序,因为`admin.yml`依赖`docker-compose.yml`所以要放在后面*
此时访问后台地址后面追加`/admin/`即可访问:
```
https://tailchat.example.com/admin/
```
*注意不要忘记在最后有一个`/`*

@ -0,0 +1,38 @@
---
sidebar_position: 99
title: 开发环境
---
对于开发环境的搭建tailchat 提供了非常简单快捷的方式:
## 使用Docker快速搭建依赖环境
**mongodb**
```bash
docker run -d --name mongo -p 27017:27017 mongo:4
```
**redis**
```bash
docker run -d --name redis -p 6379:6379 redis
```
**minio**
```bash
docker run -d \
-p 19000:9000 \
-p 19001:9001 \
--name minio \
-e "MINIO_ROOT_USER=tailchat" \
-e "MINIO_ROOT_PASSWORD=com.msgbyte.tailchat" \
minio/minio server /data --console-address ":9001"
```
### 启动开发服务器
```bash
pnpm install
pnpm dev
```
可以编辑`.env`的配置为自己相关的上下文

@ -0,0 +1,90 @@
---
sidebar_position: 104
title: Docker Compose 部署服务端(Deprecated)
---
:::caution 弃用警告
该文档已弃用。建议访问最新版的部署文档以获得最新的支持, [点击此处跳转](./docker-compose.mdx)
我们保留本篇文档是为了希望安装 `1.x` 版本之前的用户准备的
:::
## 安装环境
### Docker / Docker Compose
首先需要确保有 `Docker / Docker Compose` 环境
安装方式如下:
- [Docker](https://docs.docker.com/engine/install/)
- [Docker Compose](https://docs.docker.com/compose/install/)
### node 环境
- 从[官网下载](https://nodejs.org/en/download/)
- 或者使用[nvm](https://github.com/nvm-sh/nvm)
#### 安装pnpm
`pnpm` 是一个`nodejs`的包管理工具, 是`npm`的替代品, 为了确保能有与开发者一样依赖环境强烈建议你使用pnpm作为后续的包管理工具
```bash
npm install -g pnpm
```
## Clone 项目
将项目从远程下载到本地:
```bash
mkdir msgbyte && cd msgbyte
git clone https://github.com/msgbyte/tailchat.git # clone 客户端
git clone https://github.com/msgbyte/tailchat-server.git # clone 服务端
```
## 编译项目
#### 前端项目
```bash
cd tailchat/web
pnpm install # 安装依赖
export SERVICE_URL=http://127.0.0.1:11000 # 配置服务端地址这里的127.0.0.1 可以替换为任何网页可以访问到的服务端地址
pnpm build # 构建项目
```
构建完毕后会生成一个`tailchat/web/dist`目录,将该目录托管到任意网页托管服务器即可(如使用`http-server`进行静态代理或者直接上传到`oss`)
> NOTICE: 因为webpack编译需要比较大的内存资源占用在服务器资源不足的场合建议使用本地编译完毕以后上传到服务端
#### 使用docker-compose构建服务端
> 在启动前需要检查代码环境变量
修改 `docker-compose.env` 文件的配置,以下内容推荐修改:
- `API_URL` 对外可访问的url地址用于文件服务访问
- `SECRET` 服务端加密秘钥用于生成Token. 默认为 `tailchat`
```bash
cd tailchat-server
docker-compose build
docker-compose up -d
```
*在`docker-compose.env`文件中提供了部分环境变量可供配置。*
`tailchat` 的`docker-compose.yml`配置默认提供了如下配置:
- `mongodb`: 持久化数据库
- `redis`: KV数据库与消息中转服务
- `minio`: 分布式文件服务
其中持久化文件(数据库, 文件存储)通过 `docker volume` 统一管理:
```
docker volume ls | grep "tailchat-server"
```

@ -0,0 +1,184 @@
---
sidebar_position: 4
title: Docker Compose 部署
---
## 建议配置
建议最低配置 **1核2G**
> 如果只有 **1核1G**? 请参阅我的博客: [Linux 小资源服务器使用经验总结](http://moonrailgun.com/posts/6769ba51/) 通过交换内存来拓展内存空间
>
> 可供参考的内存用量:
> ![](/img/misc/memory-usage.png)
## 前置环境
### Docker / Docker Compose
首先需要确保有 `Docker / Docker Compose` 环境
安装方式可参考: [安装 Docker 环境](./install-docker.md)
## 拉取镜像
你可以通过从**公共镜像拉取已经编译好的镜像**或者**通过源码手动编译**
> 使用已经编译好的镜像可以无需花费足够的计算机资源进行编译,对小资源配置的服务器会十分友好。另外相对于源码编译,公共镜像的代码更加稳定。
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs groupId="build">
<TabItem value="cli" label="使用cli一键安装" default>
> 使用 `cli` 请确保在你的服务器上已经拥有了node环境(建议node版本 16+)
> 如果对node不了解可以使用`从公共镜像中手动安装`方式
使用 命令行工具 tailchat-cli 一键拉取/更新镜像:
```bash
npx tailchat-cli docker update
```
</TabItem>
<TabItem value="public-image" label="从公共镜像中手动安装" default>
使用Docker原生命令手动安装:
```bash
docker pull moonrailgun/tailchat # 从公共镜像库拉取 tailchat镜像
docker tag moonrailgun/tailchat tailchat # 将下载的镜像改名为tailchat(和源码编译保持一致,如果不改的话会走源码编译流程)
```
:::info
可以从 [Docker Hub](https://hub.docker.com/r/moonrailgun/tailchat/tags) 查看历史支持的镜像版本
:::
</TabItem>
<TabItem value="source-code" label="从源码中编译">
*本节内容适用于高级玩家用于获取最新的tailchat实现请确保你有足够的 docker, nodejs, git 的使用常识*
#### 编译环境 node 环境
- 从 [官网下载](https://nodejs.org/en/download/)
- 或者使用 [nvm](https://github.com/nvm-sh/nvm)
#### 安装pnpm
`pnpm` 是一个`nodejs`的包管理工具, 是`npm`的替代品, 为了确保能有与开发者一样依赖环境强烈建议你使用pnpm作为后续的包管理工具
```bash
npm install -g pnpm
```
#### Clone 项目
将项目从远程下载到本地:
```bash
mkdir msgbyte && cd msgbyte
git clone https://github.com/msgbyte/tailchat.git # 克隆项目到本地
```
#### 编译项目
```bash
cd tailchat && docker compose build
```
*编译对服务器配置有一定要求2核4G编译约10分钟供参考*
编译完毕后可以通过 `docker images` 查看编译完毕的镜像。
</TabItem>
</Tabs>
## 启动项目
<Tabs groupId="build">
<TabItem value="cli" label="使用cli一键安装" default>
```bash
npx tailchat-cli docker init
```
执行该命令会以交互式的方式向你询问一些配置相关的问题(如下图),填写完毕后即可自动生成配置文件
![](./assets/docker-init.png)
</TabItem>
<TabItem value="public-image" label="从公共镜像中手动安装">
> 启动之前需要下载配置文件以告知 `docker-compose` 要如何启动镜像
> 从仓库下载配置文件与配置环境变量:
> - [docker-compose.yml](https://raw.githubusercontent.com/msgbyte/tailchat/master/docker-compose.yml)
> - [docker-compose.env](https://raw.githubusercontent.com/msgbyte/tailchat/master/docker-compose.env)
```bash
mkdir tailchat && cd tailchat
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker-compose.yml
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker-compose.env
```
在启动之前需要修改一下配置
修改 `docker-compose.env` 文件的配置,以下字段推荐修改:
- `API_URL` 对外可访问的url地址用于文件服务访问, 可以是域名也可以是ip **如果出现发送图片不能正常显示就是这个变量没有设置**
- `SECRET` 服务端加密秘钥用于生成Token. 默认为 `tailchat`
</TabItem>
<TabItem value="source-code" label="从源码中编译">
在启动之前需要修改一下配置
修改 `docker-compose.env` 文件的配置,以下字段推荐修改:
- `API_URL` 对外可访问的url地址用于文件服务访问, 可以是域名也可以是ip
- `SECRET` 服务端加密秘钥用于生成Token. 默认为 `tailchat`
</TabItem>
</Tabs>
完成配置后使用`docker-compose` 一键启动 `Tailchat` 应用:
```bash
# 确保配置文件(docker-compose.yml和docker-compose.env)在当前目录下
# 执行以下命令一键启动
docker compose up -d
```
访问: `http://<server ip>:11000` 即可打开tailchat
注意部分云服务可能需要手动开放防火墙端口。
*在`docker-compose.env`文件中提供了部分环境变量可供配置。*
`tailchat` 的`docker-compose.yml`配置默认提供了如下配置:
- `mongodb`: 持久化数据库
- `redis`: KV数据库与消息中转服务
- `minio`: 分布式文件服务
其中持久化文件(数据库, 文件存储)通过 `docker volume` 统一管理:
```
docker volume ls | grep "tailchat-server"
```
:::info
完整的环境变量可以查询 [环境变量](./environment.md)
:::
## 更多部署相关文档
- [搭建 https 网关(可选)](./https-gateway.md)
- [部署管理后台(可选)](./admin.md)

@ -0,0 +1,35 @@
---
sidebar_position: 7
title: 环境变量
---
## 环境变量
| 变量名 | 默认值 | 描述 |
| ----- | ------ | --- |
| PORT | 11000 | 网关服务端口号 |
| SECRET | tailchat | 加密秘钥, 用于JWT |
| API_URL | http://127.0.0.1:11000 | 对外可访问的url地址用于文件服务访问 |
| MONGO_URL | - | 数据库服务地址 |
| REDIS_URL | - | Redis服务地址 |
| MINIO_URL | - | 文件服务地址(minio) |
| MINIO_USER | - | 文件服务用户名 |
| MINIO_PASS | - | 文件服务密码 |
| MINIO_BUCKET_NAME | tailchat | 文件服务存储桶名 |
| SMTP_SENDER | - | 邮件服务发件人(示例: `"Tailchat" example@163.com`) |
| SMTP_URI | - | 邮件服务连接地址(示例: `smtp://username:password@smtp.example.com/?pool=true`) |
| FILE_LIMIT | 1048576 | 文件/图片上传的大小限制默认为1m请输入数字 |
| EMAIL_VERIFY | - | 是否开启邮箱校验, 如果为 "1" 或者 "true" 则在注册时增加邮箱校验控制 |
| DISABLE_LOGGER | - | 是否禁用日志输出, 如果为 "1" 或者 "true" 则在运行中关闭日志 |
> 部分环境变量示例可见: https://github.com/msgbyte/tailchat/blob/master/server/.env.example
### 使用文件进行配置环境变量
- 如果是本地方式启动,请复制 `.env.example``.env` 然后进行编辑
```bash
mv .env.example .env
vi .env
```
- 如果是 `docker-compose` 启动,可以直接编辑 `docker-compose.env`, 改动后直接使用 `docker compose up -d` 即可生效

@ -0,0 +1,45 @@
---
sidebar_position: 8
title: 搭建 https 网关(可选)
---
`Tailchat` 中,有一些服务是强依赖 `https` 的,比如音视频通话、嵌入外部的 `https` 媒体资源与网页等。
同时为了用户的安全性,我们非常建议将 `Tailchat` 对外以 `https` 服务的形式提供。
![](/img/architecture/https-gateway.excalidraw.svg)
如果你没有相关的经验,且在同一台机器上只部署了 `Tailchat` 服务(没有占用 **80**/**443** 端口),那么我们推荐从 `Tailchat` 自带的 `swag` 配置开始。
:::info
你可以在 [Github](https://github.com/msgbyte/tailchat/tree/master/docker) 看到原始的配置内容
:::
通过以下命令直接拉取所需要的配置文件
```bash
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/swag.yml
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/swag.env.example -O swag.env
mkdir config
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/config/nginx.conf -O ./config/nginx.conf
```
完成后应该会在在当前目录看到以下三个文件:
- `swag.yml`
- `swag.env`
- `config/nginx.conf`
修改`swag.env`的内容,将 `URL` 的值改为域名, 如: `URL=tailchat.example.com`
:::info
`https`协议是依赖域名做证书校验的,因此需要提前分配一个域名指向目标服务器
:::
域名的地址需要在购买域名的管理后台创建一条A指向记录。
在分配好域名后我们就可以启动服务了。
```bash
docker compose -f ./swag.yml up -d
```
如果一切顺利的话,此时`swag`服务已经自动为你申请了一个证书并启动了反向代理服务,此时在浏览器访问 `https://tailchat.example.com` 的话可以看到熟悉的界面已经出现了。

@ -0,0 +1,79 @@
---
sidebar_position: 2
title: 安装docker环境
---
> 因为 `Tailchat` 的环境对于初学者来说有一些些复杂,因此提供了 `docker` 为主的一键环境搭建配置。但是对于`docker`不熟的同学来说可能`docker`本身也是一种复杂度。
> 因此为了方便大家可以快速搭建 `Tailchat`,提供了本文作为引导。对于 `docker` 有一定了解的同学可以跳过本篇
> 本文以 `linux centos` 为例,目标是方便大家直接在服务器上部署。对于想要在其他系统(`windows`, `mac`) 使用的同学可以参考官方文档进行`docker`的安装
## 一键安装 docker
官方维护的一键安装 `Docker` 脚本, 适合不喜欢研究细节的同学
在服务器终端按照以下操作依次执行即可
```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
如果安装成功的话就可以跳过后续内容了。
## 手动安装docker与docker compose
官方文档: [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
```bash
# 如果之前有安装过docker可以执行以下命令删除旧的
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
```
```bash
sudo yum install -y yum-utils # yum-utils 提供了 yum-config-manager 命令
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
```
<!-- 安装docker 与 docker-compose 插件 -->
```bash
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
```
*PS: `docker-compose-plugin`提供了`docker compose`命令,用法同`docker-compose`*
> 如果`docker ps`显示守护进程没有启动(Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?)的话可以执行以下命令启动: `sudo systemctl start docker`
## 单独安装 docker-compose
如果购买的服务器已经预装了docker, 想要单独安装docker-compose的话可以看本节内容:
官方文档: [https://docs.docker.com/compose/install/](https://docs.docker.com/compose/install/)
```bash
curl -SL https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose # 下载二进制文件
sudo chmod +x /usr/local/bin/docker-compose # 给予执行权限
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 软链接到path, 可以直接调用
docker-compose --version # 该行命令返回版本号则成功安装
```
## NOTICE
因为历史原因,`docker compose` 拥有`docker`插件版本与 `docker compose` 独立版本。一般意义上可以认为 `docker compose xxx``docker-compose xxx` 是等价的
## 参考文档
- [Docker](https://docs.docker.com/engine/install/)
- [Docker Compose](https://docs.docker.com/compose/install/)

@ -0,0 +1,20 @@
---
sidebar_position: 1
title: 快速开始
---
## 演示环境
演示环境会持续部署最新前端代码和不定期更新后端代码
[https://nightly.paw.msgbyte.com/](https://nightly.paw.msgbyte.com/)
## 部署方式
强烈推荐使用 `docker-compose` 部署 `tailchat`
教程请翻阅: [Docker Compose 部署](./docker-compose.mdx)
## 系统架构
见 [系统架构](../architecture.md)

@ -0,0 +1,59 @@
---
sidebar_position: 10
title: 常见问题
---
## 服务端相关
### Websocket 连接访问不正确,表现形式是可以注册但是无法打开主界面
如果使用了 nginx 进行反向代理。请确保nginx的配置支持websocket一个参考的配置如下:
```
server {
server_name demo.example.com;
listen 443 ssl;
access_log /var/log/nginx/host.access.log main;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_pass http://127.0.0.1:11000/;
}
}
```
### 内网可以访问外网无法访问?
可以启动一个简单的http服务看下是不是docker-proxy层的问题。*该问题可能会出现在腾讯轻量云的docker-ce镜像机器上, 可以选择使用centos7镜像重装*
```bash
docker run --rm --name nginx-test -p 8080:80 nginx
```
## 开放平台相关
如果开放平台部署在代理之后,如果出现访问 `/open/.well-known/openid-configuration` 结果的json中endpoint不正确的情况请尝试修改代理的配置。
如nginx:
```
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:11000;
proxy_redirect off;
}
```

@ -0,0 +1,22 @@
---
sidebar_position: 1
title: 数据库管理
---
`tailchat` 使用 mongodb 作为主要数据库存储用户信息
在`docker`中,常见的运维命令如下:
```bash
# 备份
docker exec -i <IMAGE_NAME> mongodump -d tailchat --archive > ./backup.archive
# 还原
docker exec -i <IMAGE_NAME> mongorestore -d tailchat --archive < ./backup.archive
```
其中`<IMAGE_NAME>` 表示mongodb镜像名而`-d tailchat` 表示使用的数据库的名字,默认启动的数据库名为`tailchat`, 你可以通过环境变量`MONGO_URL`进行修改
:::info
为了用户数据安全,建议创建定时任务定期备份数据库文件
:::

@ -0,0 +1,82 @@
---
sidebar_position: 1
title: 概述
---
`Tailchat` 是一款插件化易拓展的开源 IM 应用。可拓展架构赋予 `Tailchat` 无限可能性。
前端微内核架构 + 后端微服务架构 使得 `Tailchat` 能够驾驭任何定制化/私有化的场景
面向企业与私域用户打造,高度自由的群组管理与定制化的面板展示可以让私域主能够更好的展示自己的作品,管理用户,打造自己的品牌与圈子。
## 特性
- 完整的即时通讯基础能力
- 插件化架构的赋予的自由拓展能力
- 微服务架构赋予的水平拓展能力
## 亮点
- 基于[mini-star](https://ministar.moonrailgun.com/)的前端微内核架构与基于[moleculer](https://moleculer.services/)的后端微服务架构可以适应各种用户用量,便于拓展
- 完整的聊天系统支持提及、面板跳转、富文本、markdown、url链接等各种语法
- 消息reaction机制让你通过表情表达自己
- 文件分享与图片发送
- 支持语音通话与视频通话
- 完善的身份组管理,权限控制颗粒化
- 用户管理与用户禁言
- 邮箱认证与密码找回
- 多种面板: 网页嵌入, 自定义html, 话题面板
- 简易消息推送与github通知订阅
- 后台管理平台,可以
- 开放平台
- 机器人
- OAuth
- 插件带来的更多奇妙化学反应
- 自定义主题
- 在线听音乐
- 消息加密
- url获取元数据
- 隔空投送
- 任务管理
- 在线绘图
- 字体放大
- 工具箱
- ...
## 技术栈
- 前端
- `React`
- `Redux`
- `mini-star`
- `tailwindcss`
- `iconify`
- 后端
- `Nodejs`
- `Socket.io`
- `koa`
- `moleculer`
## 截图
#### 插件中心
![](/img/intro/plugins.png)
#### 各类主题
![](/img/intro/theme.png)
#### Github订阅机器人
![](/img/intro/github-bot.png)
#### Admin 后台管理
![](/img/intro/admin-network.png)
## 开源协议
开源协议请主要参考以下文档:
[Apache 2.0](https://github.com/msgbyte/tailchat/blob/master/LICENSE)

@ -0,0 +1,93 @@
---
sidebar_position: 10
title: 声网插件部署指南
---
:::info
声网插件需要确保您的 `tailchat` 镜像版本在 1.4.0+
:::
## 在声网平台申请项目
Tailchat 声网集成是依赖声网服务实现的音视频通话功能,因此在使用前需要在声网平台上注册。
声网官方: [https://www.agora.io/](https://www.agora.io/)
### 获取配置参数
注册完毕后/登录后会自动跳转到控制台。在控制台中可以进行项目配置
![](./images/1.png)
如果没有创建项目则需要先创建项目。如下图所示
![](./images/2.png)
建议使用安全模式以避免被其他人盗用。
接下来我们需要获取一些配置项用于配置`Tailchat`的声网插件。
![](./images/3.png)
在项目配置中我们可以获取 `appid` 和`app cert`。这两个分别是我们之后要用到的环境变量 `AGORA_APP_ID``AGORA_APP_CERT`
### 获取客户凭证
另外我们还需要在右上角的 `RESTful API` 处获得客户的权限,
操作如图所示:
![](./images/4.png)
![](./images/5.png)
这样我们就拿到了另外两个环境变量: `AGORA_CUSTOMER_KEY``AGORA_CUSTOMER_SECRET`
我们初步的准备工作就完成了
## 安装插件
目前声网插件的服务端插件已经被默认安装,您无需做任何事情。但是为了正常使用需要配置环境变量
### 配置环境变量
配置环境变量请见 [环境变量](../deployment/environment.md)
声网插件需要环境变量如下:
- `AGORA_APP_ID`: 声网项目应用id
- `AGORA_APP_CERT`: 声网项目证书
- `AGORA_CUSTOMER_KEY`: 声网客户id
- `AGORA_CUSTOMER_SECRET`: 声网客户秘钥
这些环境变量都可以在上面的教程中获取。
配置环境变量完毕后即可
## 申请服务状态回调
为了使通话状态能够同步给`Tailchat`, 需要在声网中申请服务端回调。
在项目配置中,我们需要在`服务配置` 中启用`消息通知服务`
![](./images/6.png)
需要订阅以下事件:
- channel create=101
- channel destroy=102
- broadcaster join channel=103
- broadcaster leave channel=104
接收服务器 URL 一般为: `https://<YOUR SERVER DOMAIN>/api/plugin:com.msgbyte.agora/webhook`, 其中`<YOUR SERVER DOMAIN>` 换成你的 `Tailchat` 域名。
:::info
声网的服务会对服务器做连通性检查,因此需要配置好环境变量启动服务后再执行本次步骤。
另外声网需要配置`https` 且 `webrtc`服务也依赖`https`, 因此需要确保服务器网关支持`https`协议
:::
配置完成后你会看到如下提示。等待声网工作人员确认完毕后即可生效。
![](./images/7.png)

@ -0,0 +1,96 @@
---
sidebar_position: 2
title: 部署视频会议
---
视频会议服务 `Tailchat Meeting` 可以作为一个独立应用单品存在。在本节中将会讲述如何独立部署 `Tailchat Meeting`
以下内容均基于`docker`环境,请确保服务端有 `docker` 最基本程度的环境。
如果还没有安装 `docker` + `docker-compose` 可以查看文档 [安装docker环境](../deployment/install-docker.md)
## 快速部署
```bash
git clone https://github.com/msgbyte/tailchat-meeting --depth=1
```
> NOTE: 接下来会使用docker 的 host 模式进行安装。即`docker-compose` 会自动绑定主机端口
需要服务器预留端口如下:
- swag(服务器网关, nginx 强化版, 端口可通过配置文件 tailchat-meeting/compose/nginx.conf 修改)
- 80
- 443
- tailchat-meeting
- 13001
- 40000-49999(用于RTC服务, 动态占用)
- redis
- 6379
**以上端口均会在宿主机上暴露为了服务器安全着想建议配置合适的防火墙策略仅暴露必要的端口443和40000-49999**
```bash
cd tailchat-meeting/compose
cp docker-compose.env.example docker-compose.env
vi docker-compose.env
```
修改环境变量。
环境变量如下:
```
# 内网IP
MEDIASOUP_IP=
# 公网IP
MEDIASOUP_ANNOUNCED_IP=
# swag相关
URL=
SUBDOMAINS=
TZ=Asia/Shanghai
```
其中
- 如果仅单机部署的话`MEDIASOUP_IP`和`MEDIASOUP_ANNOUNCED_IP`可以均填写服务器公网ip, **但是对于弹性部署网络的服务商(如国内的腾讯云,阿里云等)必须严格按照注释分别填写内网IP和公网IP**(因为该类服务商提供的外网IP并不是绑定在网卡上的)
- `tailchat-meeting` 基于 webrtc 服务,因此强依赖 https/wss 协议。swag服务可以为您自动申请https证书但是必须得分配一个有效的域名并确保dns指向已经指向到服务器上。
- 更多相关的文档可以查看 [README](https://github.com/linuxserver/docker-letsencrypt/blob/master/README.md)
- 示例配置:
```bash
URL=meeting.example.com # 这里请填入
SUBDOMAINS= # 该参数用于多域名证书申请,可留空
```
修改完毕以后可以直接执行以下命令
```bash
docker compose up -d
```
`docker compose` 会自动从网络下载镜像并构建`tailchat-meeting`
构建可能需要花费一定时间和资源。特别是构建前端代码,如果使用的小配置的服务器的话请耐心一点等待。
> 实际测试中使用1核2g的小资源服务器耗时参考如下:
> - 下载依赖包: 3分钟
> - 编译前端代码: 5分钟
访问 `https://meeting.example.com` 即可看到`tailchat-meeting`的页面
## 组合使用
对于傻瓜式部署来说只需要一键就可以执行。如果已经有现成的网关服务(比如nginx, caddy等)以及redis实例可以有选择的启动服务。
如:
```bash
docker compose up tailchat-meeting -d # 仅运行 tailchat-meeting 实例
```
## 使用host模式的原因
`tailchat-meeting` 核心的RTC服务需要在运行时申请端口但是对于docker来说并不能实现这个功能。而预先申请一定范围的端口绑定即会造成无意义端口的浪费也会在启动时瞬间占据大量资源并把系统打死。
**需要注意的是请不要把redis所在的6379端口暴露出去这可能会产生安全隐患。**

@ -0,0 +1,9 @@
---
sidebar_position: 99
title: SDK设计文档
draft: true
---
## 基本路径
用户基本操作路径是: 加入房间 —— 监听变更/推送本地媒体流 —— 离开房间这样完整的生命周期。

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@ -0,0 +1,36 @@
---
sidebar_position: 1
title: 概述
---
`Tailchat` 提供两套方案用于视频语音通话,可以根据实际情况自行选择:
- `tailchat-meeting` 自部署视频会议(WIP)
- `agora` 声网集成, 详细说明见: [声网插件部署指南](./agora.md)
## Tailchat Meeting
视频会议模块是 `Tailchat` 系列的一套重要组成部分。提供能力如下:
- 语音通信
- 视频会话
- 屏幕共享
- 虚拟背景
- 文件传输
- 聊天记录
同时 `tailchat-meeting` 还可以作为独立单品存在,无需登录即可快速发起/加入会议
### 项目仓库
- 开源地址: [https://github.com/msgbyte/tailchat-meeting](https://github.com/msgbyte/tailchat-meeting)
- 开源协议: GPL-3.0
:::info 开源声明
本项目基于 [edumeet](https://github.com/edumeet/edumeet) 和 [mediasoup](https://github.com/versatica/mediasoup) 进行二次开发而来。
在此基础上进行了功能追加与SDK实现以及代码优化。如果想要找到开源协议更加宽松(MIT + ISC 协议)的实现可以看一下这两个项目
:::
### 项目架构
![](/img/architecture/meeting.excalidraw.svg)

@ -0,0 +1,6 @@
---
sidebar_position: 3
title: 插件部署
---
TODO

@ -0,0 +1,11 @@
---
sidebar_position: 100
title: 演示环境与群组
---
演示环境为体现在低配置服务器下 `Tailchat` 的表现(更少的资源占用是Tailchat的重点要求)。测试环境的服务器为 1C2G1M(一个cpu核心2g内存空间1mb带宽限制)。
另外, 这里有一些用于演示Tailchat功能的群组:
- [Tailchat Nightly](https://nightly.paw.msgbyte.com/invite/8Jfm1dWb)
- [原神](https://nightly.paw.msgbyte.com/invite/GFFzfD5H)

@ -0,0 +1,180 @@
---
sidebar_position: 1
title: 纯前端插件 (22)
---
### com.msgbyte.bbcode BBCode 消息解释器
一个用于支持bbcode语法解释富文本消息的插件
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.bbcode)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.bbcode/manifest.json)
### com.msgbyte.biggerfont 字号放大
为Tailchat增加放大字号的功能,方便不同用户群体
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.biggerfont)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.biggerfont/manifest.json)
### com.msgbyte.draw 绘图插件
允许发送自定义绘图
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.draw)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.draw/manifest.json)
### com.msgbyte.env.rn ReactNative支持
在Tailchat添加对ReactNative环境的支持
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.env.rn)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.env.rn/manifest.json)
### com.msgbyte.filepizza file.pizza
在聊天输入框快捷打开 filepizza 以支持p2p传输文件
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.filepizza)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.filepizza/manifest.json)
### com.msgbyte.filesend filesend
在聊天输入框快捷打开 Filesend 以支持传输文件
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.filesend)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.filesend/manifest.json)
### com.msgbyte.filesfm files.fm
在聊天输入框快捷打开 files.fm 以支持传输文件
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.filesfm)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.filesfm/manifest.json)
### com.msgbyte.genshin 原神工具箱
为Tailchat增加原神相关的娱乐能力
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.genshin)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.genshin/manifest.json)
### com.msgbyte.integration 第三方集成
用于在群组中集成第三方应用
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.integration)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.integration/manifest.json)
### com.msgbyte.intro 初始引导插件
为应用首次打开介绍应用的能力
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.intro)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.intro/manifest.json)
### com.msgbyte.miaolang 喵语言
允许发送喵语,安装插件后的双方加密对话,未安装插件的人看到的是 '喵'
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.miaolang)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.miaolang/manifest.json)
### com.msgbyte.music 在线听音乐
提供在线听音乐服务,内容来自网络
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.music)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.music/manifest.json)
### com.msgbyte.notify 消息通知插件
为应用增加通知的能力
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.notify)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.notify/manifest.json)
### com.msgbyte.openapi 开放平台插件
为应用提供开放平台的操作能力
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.openapi)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.openapi/manifest.json)
### com.msgbyte.posthog Posthog
Posthog 数据统计
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.posthog)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.posthog/manifest.json)
### com.msgbyte.sentry Sentry
Sentry 错误处理
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.sentry)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.sentry/manifest.json)
### com.msgbyte.snapdrop 隔空投送
隔空投送 —— 在同一网络发送文件与消息
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.snapdrop)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.snapdrop/manifest.json)
### com.msgbyte.toolwa 工具哇!
工具哇 —— 在线小工具
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.toolwa)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.toolwa/manifest.json)
### com.msgbyte.user.location 用户地理位置
为用户信息增加地理位置记录
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.user.location)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.user.location/manifest.json)
### com.msgbyte.webview 网页面板插件
为群组提供创建网页面板的功能
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.webview)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.webview/manifest.json)
### com.msgbyte.wenshushu wenshushu
在聊天输入框快捷打开 文叔叔 以支持传输文件
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.wenshushu)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.wenshushu/manifest.json)
### com.msgbyte.wormhole wormhole
在聊天输入框快捷打开 wormhole 以支持传输文件
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.wormhole)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.wormhole/manifest.json)

@ -0,0 +1,60 @@
---
sidebar_position: 3
title: 前后端插件 (7)
---
### com.msgbyte.agora 声网音视频
为Tailchat增加声网音视频通信功能
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/manifest.json)
### com.msgbyte.github Github 订阅
订阅Github项目动态到群组
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.github/web/plugins/com.msgbyte.github)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.github/web/plugins/com.msgbyte.github/manifest.json)
### com.msgbyte.linkmeta Url元数据展示
解析并获取在聊天信息中的url信息概述如标题/概述/缩略图, 支持媒体路径,直接显示媒体播放器(特殊支持bilibili自动加载b站iframe播放器)
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.linkmeta/web/plugins/com.msgbyte.linkmeta)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.linkmeta/web/plugins/com.msgbyte.linkmeta/manifest.json)
### com.msgbyte.meeting 音视频服务(WIP)
为Tailchat提供音视频通讯的服务
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.meeting/web/plugins/com.msgbyte.meeting)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.meeting/web/plugins/com.msgbyte.meeting/manifest.json)
### com.msgbyte.simplenotify 简易机器人
一个简单的通用通知机器人, 用于直接向群组发送消息
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.simplenotify/web/plugins/com.msgbyte.simplenotify)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.simplenotify/web/plugins/com.msgbyte.simplenotify/manifest.json)
### com.msgbyte.tasks 任务管理
任务管理插件在个人面板中增加TODO面板用于个人待办事项的管理
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.tasks/web/plugins/com.msgbyte.tasks)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.tasks/web/plugins/com.msgbyte.tasks/manifest.json)
### com.msgbyte.topic 群组话题
为群组提供话题功能
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.topic/web/plugins/com.msgbyte.topic)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/server/plugins/com.msgbyte.topic/web/plugins/com.msgbyte.topic/manifest.json)

@ -0,0 +1,20 @@
---
sidebar_position: 2
title: 自定义主题 (2)
---
### com.msgbyte.theme.genshin 原神主题
原神主题
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.theme.genshin)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.theme.genshin/manifest.json)
### com.msgbyte.theme.miku Miku初音未来主题
初音未来主题,支持亮色与暗色
- [插件源码](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.theme.miku)
- [manifest.json](https://github.com/msgbyte/tailchat/blob/master/client/web/plugins/com.msgbyte.theme.miku/manifest.json)

@ -0,0 +1,249 @@
---
sidebar_position: 1
title: "@capital/common"
---
## 注册
### regGroupPanel
注册群组面板
```typescript
regGroupPanel({
name: `com.msgbyte.webview/grouppanel`,
label: '网页面板',
provider: PLUGIN_NAME,
extraFormMeta: [{ type: 'text', name: 'url', label: '网址' }],
render: GroupWebPanelRender,
});
```
参数类型: [PluginGroupPanel](#plugingrouppanel)
### regMessageInterpreter
注册消息解释器
```typescript
regMessageInterpreter({
name: '喵语翻译',
explainMessage(message: string) {
// 喵语 -> 人话
if (!isMiao(message)) {
return null;
}
return decode(message);
},
});
```
参数类型: [PluginMessageInterpreter](#pluginmessageinterpreter)
### regMessageRender
*注册多个仅生效最后一个*
注册消息渲染器, 输入消息文本返回渲染内容
```typescript
regMessageRender((message) => {
return <BBCode plainText={message} />;
});
```
### regChatInputAction
注册聊天输入框操作
```typescript
regChatInputAction({
label: '喵言喵语',
onClick: (actions) => {
openModal(createElement(SendMiaoModal, { actions }));
},
});
```
参数类型: [ChatInputAction](#chatinputaction)
### regPluginColorScheme
注册插件配色方案/主题
```typescript
regPluginColorScheme({
label: 'Miku 葱',
name: 'light+miku',
});
```
## 工具函数
### useGroupPanelParams
在`hooks`中获取用户面板相关信息
```typescript
import { useGroupPanelParams } from '@capital/common';
const { groupId, panelId } = useGroupPanelParams();
```
### openModal
打开一个模态框
```typescript
openModal(
content: React.ReactNode,
props?: Pick<ModalProps, 'closable' | 'maskClosable'>
)
```
类型:
- [ModalProps](#modalprops)
### ModalWrapper
模态框包装器
```jsx
<ModalWrapper>
<div></div>
</ModalWrapper>
```
### useModalContext
获取模态框上下文
```typescript
const { closeModal } = useModalContext();
```
### getGlobalState
获取全局 `Redux` 状态上下文
```typescript
const state = getGlobalState();
```
### getCachedUserInfo
获取用户信息, 缓存版本
```typescript
const info = getCachedUserInfo(userId);
```
### getCachedConverseInfo
获取会话信息
```typescript
const info = getCachedConverseInfo(converseId);
```
## 类型
### PluginGroupPanel
```typescript
interface PluginGroupPanel {
/**
* 面板唯一标识
* @example com.msgbyte.webview/grouppanel
*/
name: string;
/**
* 面板显示名
*/
label: string;
/**
* 插件提供者, 用于引导没有安装插件的用户安装插件
*/
provider: string;
/**
* 额外的表单数据, 用于创建面板时使用
*/
extraFormMeta: FastFormFieldMeta[];
/**
* 该面板如何渲染
*/
render: React.ComponentType;
}
```
### PluginMessageInterpreter
插件消息解释器
```typescript
interface PluginMessageInterpreter {
name?: string;
explainMessage: (message: string) => React.ReactNode;
}
```
### ChatInputAction
消息输入框操作对象
```typescript
interface ChatInputAction {
label: string;
onClick: (actions: ChatInputActionContextProps) => void;
}
```
### GroupPanel
```typescript
interface GroupPanel {
id: string; // 在群组中唯一
name: string;
parentId?: string;
type: GroupPanelType;
provider?: string; // 面板提供者
pluginPanelName?: string; // 插件面板名
meta?: Record<string, unknown>;
}
```
### ModalProps
```typescript
interface ModalProps {
visible?: boolean;
onChangeVisible?: (visible: boolean) => void;
/**
* 是否显示右上角的关闭按钮
* @default false
*/
closable?: boolean;
/**
* 遮罩层是否可关闭
*/
maskClosable?: boolean;
}
```

@ -0,0 +1,22 @@
---
sidebar_position: 2
title: "@capital/component"
---
### Button
组件来自 [antd](https://ant.design/)
组件文档: [Button](https://ant.design/components/button-cn/)
### TextArea
组件来自 [antd](https://ant.design/)
组件文档: [TextArea](https://ant.design/components/input-cn/#components-input-demo-textarea)
### Image
组件来自 [antd](https://ant.design/)
组件文档: [Image](https://ant.design/components/image-cn/)

@ -0,0 +1,9 @@
---
sidebar_position: 3
title: 全局CSS变量
---
- `--tc-primary-color`: 主色调
- `--tc-background-image`: 背景图片
- `--tc-content-background-image`: 内容页背景图片
- `--tc-content-background-image-opacity`: 内容页背景图片透明度,默认 **0.15**

@ -0,0 +1,19 @@
---
sidebar_position: 4
title: "data-tc-role"
---
`Tailchat Role` 是一种通过`data-*`方式来标识DOM的一种方式表明该节点在`Tailchat`中的角色, 开发者可以通过这来找到对应角色的DOM节点
例如: `[data-tc-role=navbar]`
- `navbar`: 导航栏
- `navbar-personal`: 导航栏中的个人主页
- `navbar-groups`: 导航栏中的群组
- `navbar-settings`: 导航栏中的设置
- `sidebar-personal`: 个人主页中的侧边栏
- `sidebar-group`: 群组中的侧边栏
- `content-personal`: 个人主页中的内容
- `content-group`: 群组页面中的内容
- `modal`: 模态框
- `modal-mask`: 模态框的遮罩层

@ -0,0 +1,20 @@
---
sidebar_position: 2
title: Icon 图标
---
```ts
import { Icon } from '@capital/component';
```
`tailchat` 的 icon 解决方案来自 `iconify`
使用方法很简单:
- 在下述网站中选择想要的图标: [https://icon-sets.iconify.design/](https://icon-sets.iconify.design/)
- 复制选中的key。传给 `Icon` 组件, 示例:
```tsx
<Icon icon="mdi:account" />
```
推荐使用`mdi`来统一化图标视觉设计:
[https://icon-sets.iconify.design/mdi/](https://icon-sets.iconify.design/mdi/)

@ -0,0 +1,59 @@
---
sidebar_position: 1
title: 开始开发插件
---
## 认识 MiniStar
`MiniStar` 是一套完整的微内核架构开发工具链,`tailchat`的插件架构就是基于 `MiniStar` 进行开发。
关于更多的 `MiniStar` 相关问题可以查看 `MiniStar` 的官方文档: [https://ministar.moonrailgun.com/](https://ministar.moonrailgun.com/)
## 创建一个基础项目
首先创建一个基本的 npm 项目, 并全局安装 `MiniStar`
```bash
npm install --global mini-star
```
在项目中执行: `ministar createPlugin` 来创建一个基本的插件
在项目中执行: `ministar buildPlugin` 来编译插件
> 值得一提的是, 虽然 `Tailchat` 并没有强制规定插件命名规范,但是还是推荐使用 `反域名` 的命名方式(类似于java中的包命名), 然后对插件中的部件,使用 `/` 进行分割
>
> 如:
> 插件名: `com.msgbyte.webview`
>
> 注册内容: `com.msgbyte.webview/grouppanel`
## 安装插件
### 手动安装插件
在不经过任何预设的情况下,一个通用的办法是自己构造一个 `manifest` 配置, 然后在 `tailchat` 提供手动安装插件 Tab 中将配置文件粘贴进去安装。
插件的url路径可以通过 `oss对象存储服务` / `static-server` 等办法代理
一个作为示例的`manifest.json`配置如下:
```json
{
"label": "网页面板插件",
"name": "com.msgbyte.webview",
"url": "/plugins/com.msgbyte.webview/index.js",
"version": "0.0.0",
"author": "msgbyte",
"description": "为群组提供创建网页面板的功能",
"requireRestart": false
}
```
## 其他有用的资源
- 插件化架构内核依赖库 [MiniStar](https://ministar.moonrailgun.com/)
- 来自基础项目提供的API: [API 文档](./api/common)
- 导出接口源码
- [@capital/common](https://github.com/msgbyte/tailchat/blob/master/client/web/src/plugin/common/index.ts)
- [@capital/component](https://github.com/msgbyte/tailchat/blob/master/client/web/src/plugin/component/index.tsx)

@ -0,0 +1,26 @@
---
sidebar_position: 2
title: 使用场景
---
Tailchat 的设计之处就是以插件化的架构来满足不同人群对于不同需求的实现。
## 对于个人用户
- 如果希望和朋友一起玩
- 创建一个群组
- 通过多个频道分割不同的话题
- 使用网页面板来分享喜欢的网页
- 如果希望聚集自己的粉丝圈
- 使用机器人来订阅自己的信息并转发到聊天面板
- 让自己的粉丝集中在一起不需要创建无数个qq群/微信群
- 多个频道让多个话题能够一起产生
- 如果对于自己的隐私非常看中
- 自己部署让一切都能掌控在手中
## 对于企业用户
- 面板化设计满足企业自定义化设计需求
- 插件化架构可以方便基于核心进行二次开发
- 自部署的实现可以让企业价值得到保护,让企业安心
- 开源代码方便审查

@ -0,0 +1,6 @@
{
"copyright": {
"message": "Copyright © 2023 MsgByte, Inc. Built with Docusaurus and ❤.",
"description": "The footer copyright"
}
}

@ -0,0 +1,18 @@
{
"title": {
"message": "Tailchat",
"description": "The title in the navbar"
},
"item.label.Docs": {
"message": "文档",
"description": "Navbar item with label Docs"
},
"item.label.Blog": {
"message": "博客",
"description": "Navbar item with label Blog"
},
"item.label.GitHub": {
"message": "GitHub",
"description": "Navbar item with label GitHub"
}
}

@ -5,12 +5,14 @@
"scripts": {
"docusaurus": "docusaurus",
"dev": "docusaurus start -p 11033",
"dev:zh": "docusaurus start -p 11033 --locale zh-Hans",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle --typescript",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-translations:zh": "docusaurus write-translations --locale zh-Hans",
"write-heading-ids": "docusaurus write-heading-ids",
"gen:plugin-doc": "ts-node ./scripts/generate-plugin-list.ts"
},

@ -1,36 +1,41 @@
import React from 'react';
import clsx from 'clsx';
import styles from './HomepageFeatures.module.css';
import { translate } from '@docusaurus/Translate';
const FeatureList = [
{
title: '易于使用',
title: translate({ message: 'Easy to use' }),
Svg: require('../../static/img/undraw_Website_setup_re_d4y9.svg').default,
description: (
<>
<code>Tailchat</code> <code>discord</code>, {' '}
<code>discord</code> , <code>Tailchat</code>{' '}
使
The basic design of <code>Tailchat</code> is borrowed from{' '}
<code>Discord</code>, but with <code>Discord</code> is different,{' '}
<code>Tailchat</code> Use the concept of panels instead of channels.
This makes groups capable of more than just chatting.
</>
),
},
{
title: '易于拓展',
title: translate({ message: 'Easy to expand' }),
Svg: require('../../static/img/undraw_design_components_9vy6.svg').default,
description: (
<>
<code>Tailchat</code>{' '}
+
<code>Tailchat</code> is based on the microkernel + microservice
architecture, and has carefully designed a unique plug-in system, which
is easy to expand in terms of business and scale, and is sufficient to
support business and needs of any size
</>
),
},
{
title: '面向开源',
title: translate({ message: 'Open source' }),
Svg: require('../../static/img/undraw_open_source_1qxw.svg').default,
description: (
<>
<code>Tailchat</code>{' '}
Tailchat
<code>Tailchat</code> is an open source software, anyone can submit the
ability they want to Tailchat. We always believe that the power of open
source can make an application better
</>
),
},

@ -5,6 +5,7 @@ import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import styles from './index.module.css';
import HomepageFeatures from '../components/HomepageFeatures';
import Translate from '@docusaurus/Translate';
function HomepageHeader() {
const { siteConfig } = useDocusaurusContext();
@ -18,7 +19,7 @@ function HomepageHeader() {
className="button button--secondary button--lg"
to="https://nightly.paw.msgbyte.com/"
>
Nightly
<Translate>Try in Nightly version</Translate>
</Link>
</div>
</div>

Loading…
Cancel
Save