chore: move tailchat-website into tailchat
@ -0,0 +1,53 @@
|
||||
name: "Deployment Website"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- "./website/**"
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
defaults:
|
||||
run:
|
||||
working-directory: website
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Cache pnpm modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.pnpm-store
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-
|
||||
- uses: pnpm/action-setup@v2.0.1
|
||||
with:
|
||||
version: 6.0.2
|
||||
run_install: true
|
||||
- name: Install Packages
|
||||
run: pnpm install
|
||||
- name: Build page
|
||||
run: pnpm build
|
||||
# - name: Deploy to gh-pages
|
||||
# uses: peaceiris/actions-gh-pages@v3
|
||||
# with:
|
||||
# github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# publish_dir: ./website/build
|
||||
- name: Deploy to Vercel
|
||||
uses: amondnet/vercel-action@master
|
||||
env:
|
||||
VERSION: ${{ env.GITHUB_SHA }}
|
||||
with:
|
||||
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
||||
vercel-org-id: ${{ secrets.ORG_ID}}
|
||||
vercel-project-id: ${{ secrets.PROJECT_ID}}
|
||||
working-directory: ./
|
||||
vercel-args: '--prod'
|
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="zh-CN" />
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<style>
|
||||
body {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.video-container {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.video-iframe {
|
||||
width: 640px;
|
||||
height: 360px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 966px) {
|
||||
.video-iframe {
|
||||
width: 360px;
|
||||
height: 240px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>
|
||||
Tailchat Nightly
|
||||
</h1>
|
||||
|
||||
<h3>
|
||||
Tailchat 演示环境
|
||||
</h3>
|
||||
|
||||
<p>如果有任何反馈欢迎直接在本群组 @moonrailgun 或者发送邮件到 <a href="mailto:moonrailgun@gmail.com">moonrailgun@gmail.com</a></p>
|
||||
|
||||
<p>
|
||||
官方文档: <a href="https://tailchat.msgbyte.com/">https://tailchat.msgbyte.com/</a>
|
||||
</p>
|
||||
<p>
|
||||
开源地址: <a href="https://github.com/msgbyte/tailchat">https://github.com/msgbyte/tailchat</a>
|
||||
</p>
|
||||
|
||||
<div class="video-container">
|
||||
<h2>演示视频</h2>
|
||||
<iframe class="video-iframe" src="https://player.bilibili.com/player.html?aid=340398093&bvid=BV1394y1Z76n&cid=568332564&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,20 @@
|
||||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
@ -0,0 +1,2 @@
|
||||
# https://npmmirror.com/
|
||||
registry = https://registry.npmmirror.com
|
@ -0,0 +1,3 @@
|
||||
# Tailchat Document
|
||||
|
||||
一个开放的即时通讯聊天应用
|
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
@ -0,0 +1,6 @@
|
||||
moonrailgun:
|
||||
name: moonrailgun
|
||||
title: Tailchat 开发者
|
||||
url: https://github.com/moonrailgun
|
||||
image_url: https://avatars.githubusercontent.com/u/6964737?v=4
|
||||
email: moonrailgun@gmail.com
|
@ -0,0 +1,12 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: 架构
|
||||
---
|
||||
|
||||
## 服务端架构
|
||||
|
||||

|
||||
|
||||
## 插件机制架构
|
||||
|
||||

|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "命令行终端",
|
||||
"position": 30
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: 命令行工具 tailchat-cli
|
||||
---
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
npm install -g tailchat-cli@latest # 安装与更新同一命令
|
||||
```
|
||||
|
||||
安装成功后输入`tailchat` 后返回如下
|
||||
|
||||
```bash
|
||||
tailchat <command>
|
||||
|
||||
Commands:
|
||||
tailchat create [template] 创建 Tailchat 项目代码
|
||||
tailchat connect 连接到 Tailchat 节点网络
|
||||
tailchat declaration [source] Tailchat 插件类型声明
|
||||
|
||||
Options:
|
||||
--version Show version number [boolean]
|
||||
-h, --help Show help [boolean]
|
||||
```
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
sidebar_position: 100
|
||||
title: 演示群组
|
||||
---
|
||||
|
||||
这里有一些用于演示Tailchat功能的群组
|
||||
|
||||
- [Tailchat Nightly](https://nightly.paw.msgbyte.com/invite/8Jfm1dWb)
|
||||
- [原神](https://nightly.paw.msgbyte.com/invite/GFFzfD5H)
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "部署",
|
||||
"position": 10
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: 安装docker环境
|
||||
---
|
||||
|
||||
> 因为 `Tailchat` 的环境对于初学者来说有一些些复杂,因此提供了 `docker` 为主的一键环境搭建配置。但是对于`docker`不熟的同学来说可能`docker`本身也是一种复杂度。
|
||||
|
||||
> 因此为了方便大家可以快速搭建 `Tailchat`,提供了本文作为引导。对于 `docker` 有一定了解的同学可以跳过本篇
|
||||
|
||||
> 本文以 `linux centos` 为例,目标是方便大家直接在服务器上部署。对于想要在其他系统(`windows`, `mac`) 使用的同学可以参考官方文档进行`docker`的安装
|
||||
|
||||
## 安装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 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 # 该行命令返回版本号则成功安装
|
||||
```
|
@ -0,0 +1,75 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: 概述
|
||||
---
|
||||
|
||||
`Tailchat` 是一款插件化易拓展的开源 IM 应用。可拓展架构赋予 `Tailchat` 无限可能性。
|
||||
|
||||
前端微内核架构 + 后端微服务架构 使得 `Tailchat` 能够驾驭任何定制化/私有化的场景
|
||||
|
||||
## 特性
|
||||
|
||||
- 完整的即时通讯基础能力
|
||||
- 插件化架构的赋予的自由拓展能力
|
||||
- 微服务架构赋予的水平拓展能力
|
||||
|
||||
## 技术栈
|
||||
|
||||
- 前端
|
||||
- `React`
|
||||
- `Redux`
|
||||
- `MiniStar`
|
||||
- `tailwindcss`
|
||||
- `iconify`
|
||||
- 后端
|
||||
- `Nodejs`
|
||||
- `Socket.io`
|
||||
- `koa`
|
||||
- `moleculer`
|
||||
|
||||
## 功能列表
|
||||
|
||||
- 用户管理
|
||||
- 基于4位数字标识(战网like)的用户名系统
|
||||
- 好友管理
|
||||
- 聊天系统
|
||||
- 私聊
|
||||
- 群聊
|
||||
- 富文本消息
|
||||
- 图片
|
||||
- 链接
|
||||
- 提及(@)
|
||||
- 代码
|
||||
- 插件系统
|
||||
- 前端插件系统(基于`ministar`的微内核架构)
|
||||
- 自定义主题
|
||||
- 自定义面板
|
||||
- 自定义操作
|
||||
- 消息内容转换
|
||||
- ...
|
||||
- 后端插件系统(基于`moleculer`的微服务架构)
|
||||
- 开放平台
|
||||
- Connect ID
|
||||
- *(其他正在开发中)*
|
||||
- 快速跳转
|
||||
|
||||
|
||||
## 截图
|
||||
|
||||
#### 插件中心
|
||||
|
||||

|
||||
|
||||
#### 各类主题
|
||||
|
||||

|
||||
|
||||
#### Github订阅机器人
|
||||
|
||||

|
||||
|
||||
## 开源协议
|
||||
|
||||
开源协议请主要参考以下文档:
|
||||
|
||||
[GNU General Public License 3.0](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "视频会议",
|
||||
"position": 60
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: 概述
|
||||
---
|
||||
|
||||
## 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 协议)的实现可以看一下这两个项目
|
||||
:::
|
||||
|
||||
|
||||
### 项目架构
|
||||
|
||||

|
@ -0,0 +1,6 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: 插件部署
|
||||
---
|
||||
|
||||
TODO
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
title: SDK
|
||||
---
|
||||
|
||||
TODO
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "插件列表",
|
||||
"position": 20
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: 纯前端插件
|
||||
---
|
||||
|
||||
### com.msgbyte.bbcode
|
||||
|
||||
`默认安装`
|
||||
|
||||
一个用于支持bbcode语法解释富文本消息的插件
|
||||
|
||||
### com.msgbyte.intro
|
||||
|
||||
`默认安装`
|
||||
|
||||
新人引导插件
|
||||
|
||||
### com.msgbyte.notify
|
||||
|
||||
`默认安装`
|
||||
|
||||
消息通知插件
|
||||
|
||||
### com.msgbyte.webview
|
||||
|
||||
`默认安装`
|
||||
|
||||
增加用户添加群组网页面板的能力。
|
||||
|
||||
### com.msgbyte.draw
|
||||
|
||||
允许用户发送自定义绘图
|
||||
|
||||
### com.msgbyte.genshin
|
||||
|
||||
原神工具箱
|
||||
|
||||
### com.msgbyte.miaolang
|
||||
|
||||
允许发送喵语,安装插件后的双方加密对话,未安装插件的人看到的是 "喵"
|
||||
|
||||
### com.msgbyte.openapi
|
||||
|
||||
`WIP`
|
||||
|
||||
开放平台管理插件
|
@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: 自定义主题
|
||||
---
|
||||
|
||||
### com.msgbyte.theme.genshin
|
||||
|
||||
原神主题
|
||||
|
||||
包含主题如下:
|
||||
- 原神-胡桃
|
||||
- 原神-琴
|
||||
- 原神-安柏
|
||||
- 原神-莫娜
|
||||
- 原神-罗莎莉亚
|
||||
|
||||
### com.msgbyte.theme.miku
|
||||
|
||||
初音未来主题,支持亮色与暗色
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "开发插件",
|
||||
"position": 99
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "API 接口",
|
||||
"position": 99
|
||||
}
|
@ -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,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,58 @@
|
||||
---
|
||||
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
|
||||
{
|
||||
"label": "网页面板插件",
|
||||
"name": "com.msgbyte.webview",
|
||||
"url": "/plugins/com.msgbyte.webview/index.js",
|
||||
"version": "0.0.0",
|
||||
"author": "msgbyte",
|
||||
"description": "为群组提供创建网页面板的功能",
|
||||
"requireRestart": false
|
||||
}
|
||||
```
|
||||
|
||||
## 其他有用的资源
|
||||
|
||||
- 来自基础项目提供的API: [API 文档](./api/common)
|
||||
- 导出接口源码
|
||||
- [@capital/common](https://github.com/msgbyte/tailchat/blob/master/web/src/plugin/common/index.ts)
|
||||
- [@capital/component](https://github.com/msgbyte/tailchat/blob/master/web/src/plugin/component/index.tsx)
|
@ -0,0 +1,118 @@
|
||||
const lightCodeTheme = require('prism-react-renderer/themes/github');
|
||||
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
|
||||
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
const themeConfig = {
|
||||
navbar: {
|
||||
title: 'Tailchat',
|
||||
logo: {
|
||||
alt: 'Tailchat Logo',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
docId: 'intro',
|
||||
position: 'left',
|
||||
label: '文档',
|
||||
},
|
||||
{ to: '/blog', label: '博客', position: 'left' },
|
||||
{
|
||||
href: 'https://github.com/msgbyte/tailchat',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
// links: [
|
||||
// {
|
||||
// title: 'Docs',
|
||||
// items: [
|
||||
// {
|
||||
// label: 'Tutorial',
|
||||
// to: '/docs/intro',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// title: 'Community',
|
||||
// items: [
|
||||
// {
|
||||
// label: 'Stack Overflow',
|
||||
// href: 'https://stackoverflow.com/questions/tagged/docusaurus',
|
||||
// },
|
||||
// {
|
||||
// label: 'Discord',
|
||||
// href: 'https://discordapp.com/invite/docusaurus',
|
||||
// },
|
||||
// {
|
||||
// label: 'Twitter',
|
||||
// href: 'https://twitter.com/docusaurus',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// title: 'More',
|
||||
// items: [
|
||||
// {
|
||||
// label: 'Blog',
|
||||
// to: '/blog',
|
||||
// },
|
||||
// {
|
||||
// label: 'GitHub',
|
||||
// href: 'https://github.com/facebook/docusaurus',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
copyright: `Copyright © ${new Date().getFullYear()} MsgByte, Inc. Built with Docusaurus and ❤.`,
|
||||
},
|
||||
prism: {
|
||||
theme: lightCodeTheme,
|
||||
darkTheme: darkCodeTheme,
|
||||
},
|
||||
zoom: {
|
||||
selector: '.markdown img',
|
||||
config: {
|
||||
// options you can specify via https://github.com/francoischalifour/medium-zoom#usage
|
||||
background: {
|
||||
light: 'rgb(255, 255, 255)',
|
||||
dark: 'rgb(50, 50, 50)',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
const presetClassicOptions = {
|
||||
docs: {
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
// Please change this to your repo.
|
||||
editUrl: 'https://github.com/msgbyte/tailchat-website/edit/master/website/',
|
||||
},
|
||||
blog: {
|
||||
postsPerPage: 5,
|
||||
},
|
||||
// blog: false,
|
||||
theme: {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
},
|
||||
};
|
||||
|
||||
/** @type {import('@docusaurus/types').DocusaurusConfig} */
|
||||
module.exports = {
|
||||
title: 'Tailchat',
|
||||
tagline: '一个插件化易拓展的开源 IM 应用',
|
||||
url: 'https://tailchat.msgbyte.com', // TODO: 待修改成文档主页
|
||||
baseUrl: '/',
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
favicon: 'img/logo.svg',
|
||||
organizationName: 'msgbyte', // Usually your GitHub org/user name.
|
||||
projectName: 'tailchat', // Usually your repo name.
|
||||
themeConfig,
|
||||
presets: [['@docusaurus/preset-classic', presetClassicOptions]],
|
||||
plugins: [require.resolve('docusaurus-plugin-image-zoom')],
|
||||
};
|
@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "website",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start -p 11033",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle --typescript",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "2.0.0-beta.18",
|
||||
"@docusaurus/preset-classic": "2.0.0-beta.18",
|
||||
"@mdx-js/react": "^1.6.21",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"clsx": "^1.1.1",
|
||||
"docusaurus-plugin-image-zoom": "^0.0.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"prism-react-renderer": "^1.2.1",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"url-loader": "^4.1.1"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^2.0.0-beta.18",
|
||||
"@tsconfig/docusaurus": "^1.0.5",
|
||||
"@types/react": "^17.0.26",
|
||||
"@types/react-helmet": "^6.1.2",
|
||||
"@types/react-router-dom": "^5.3.0",
|
||||
"typescript": "^4.4.3"
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// By default, Docusaurus generates a sidebar from the docs folder structure
|
||||
tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }],
|
||||
|
||||
// But you can create a sidebar manually
|
||||
/*
|
||||
tutorialSidebar: [
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorial',
|
||||
items: ['hello'],
|
||||
},
|
||||
],
|
||||
*/
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
/* stylelint-disable docusaurus/copyright-header */
|
||||
|
||||
.features {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.featureSvg {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/* stylelint-disable docusaurus/copyright-header */
|
||||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
--ifm-color-primary: #25c2a0;
|
||||
--ifm-color-primary-dark: rgb(33, 175, 144);
|
||||
--ifm-color-primary-darker: rgb(31, 165, 136);
|
||||
--ifm-color-primary-darkest: rgb(26, 136, 112);
|
||||
--ifm-color-primary-light: rgb(70, 203, 174);
|
||||
--ifm-color-primary-lighter: rgb(102, 212, 189);
|
||||
--ifm-color-primary-lightest: rgb(146, 224, 208);
|
||||
--ifm-code-font-size: 95%;
|
||||
}
|
||||
|
||||
.docusaurus-highlight-code-line {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
display: block;
|
||||
margin: 0 calc(-1 * var(--ifm-pre-padding));
|
||||
padding: 0 var(--ifm-pre-padding);
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .docusaurus-highlight-code-line {
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.medium-zoom-image--opened {
|
||||
z-index: var(--ifm-z-index-fixed);
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/* stylelint-disable docusaurus/copyright-header */
|
||||
|
||||
/**
|
||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
||||
* and scoped locally.
|
||||
*/
|
||||
|
||||
.heroBanner {
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 966px) {
|
||||
.heroBanner {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.videoContainer {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.videoIframe {
|
||||
width: 640px;
|
||||
height: 360px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 966px) {
|
||||
.videoIframe {
|
||||
width: 360px;
|
||||
height: 240px;
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import styles from './index.module.css';
|
||||
import HomepageFeatures from '../components/HomepageFeatures';
|
||||
|
||||
function HomepageHeader() {
|
||||
const { siteConfig } = useDocusaurusContext();
|
||||
return (
|
||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<h1 className="hero__title">{siteConfig.title}</h1>
|
||||
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link
|
||||
className="button button--secondary button--lg"
|
||||
to="https://nightly.paw.msgbyte.com/"
|
||||
>
|
||||
进入网页 Nightly 版
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
function HomepageVideo() {
|
||||
return (
|
||||
<div className={styles.videoContainer}>
|
||||
<iframe
|
||||
className={styles.videoIframe}
|
||||
src="//player.bilibili.com/player.html?aid=340398093&bvid=BV1394y1Z76n&cid=568332564&page=1"
|
||||
scrolling="no"
|
||||
border="0"
|
||||
frameBorder="no"
|
||||
framespacing="0"
|
||||
allowFullScreen="true"
|
||||
>
|
||||
{' '}
|
||||
</iframe>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
const { siteConfig } = useDocusaurusContext();
|
||||
return (
|
||||
<Layout
|
||||
title={`Hello from ${siteConfig.title}`}
|
||||
description="Description will go into a meta tag in <head />"
|
||||
>
|
||||
<HomepageHeader />
|
||||
<main>
|
||||
<HomepageVideo />
|
||||
|
||||
<HomepageFeatures />
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Markdown page example
|
||||
---
|
||||
|
||||
# Markdown page example
|
||||
|
||||
You don't need React to write simple standalone pages.
|
@ -0,0 +1 @@
|
||||
tailchat.msgbyte.com
|
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 485 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 482 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 498 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 419 KiB |
After Width: | Height: | Size: 324 KiB |
After Width: | Height: | Size: 114 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
||||
"include": ["src/"]
|
||||
}
|