feat: 新增vitepress文档

This commit is contained in:
wanglihui 2023-06-26 21:34:27 +08:00
parent df322c1eac
commit bf34ddf376
98 changed files with 2474 additions and 21262 deletions

View File

@ -1,6 +0,0 @@
import Prism from 'prism-react-renderer/prism';
(typeof global !== 'undefined' ? global : window).Prism = Prism;
require('prismjs/components/prism-kotlin');
require('prismjs/components/prism-java');

View File

@ -1,145 +0,0 @@
import React, { useRef } from 'react';
import './style.scss';
import { usePrefersColor } from 'dumi/dist/client/theme-api/usePrefersColor';
const Home: any = () => {
const ref = useRef<HTMLDivElement>(null);
const [color] = usePrefersColor();
// mount
React.useEffect(() => {
document.title = '悟空IM';
const element = document.getElementById('root')
element?.setAttribute('home', 'true')
const logoElement = document.querySelector('.dumi-default-logo img');
logoElement?.setAttribute('src', '/logo_white.png')
return () => {
const element = document.getElementById('root')
element?.removeAttribute('home')
logoElement?.setAttribute('src', '/logo.png')
};
}, []);
var isPhone = true
if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
isPhone = true
} else {
isPhone = false
}
var item1 = {
icon: './././imgs/ic_no_dependency.png',
title: '零依赖',
desc: '没有依赖任何第三方组件,部署简单,一条命令即可启动'
}
var item2 = {
icon: './././imgs/ic_self_developed.png',
title: '完全自研',
desc: '自研消息数据库,消息分区永久存储,自研二进制协议,支持自定义协议'
}
var item3 = {
icon: './././imgs/ic_secure.png',
title: '安全',
desc: '消息通道和消息内容全程加密,防中间人攻击和串改消息内容'
}
var item4 = {
icon: './././imgs/ic_function.png',
title: '功能强劲',
desc: 'MAC 笔记本单机测试 16w 多/秒的消息(包含存储)吞吐量,频道支持万人同时订阅'
}
var item5 = {
icon: './././imgs/ic_extend.png',
title: '扩展性强',
desc: '采用频道设计理念,目前支持群组频道,点对点频道,后续可以根据自己业务自定义频道可实现机器人频道,客服频道等等'
}
var item6 = {
icon: './././imgs/ic_compatibility.png',
title: '兼容性强',
desc: '同时无差别支持 tcpwebsocket'
}
var list1 = []
var list2 = []
var list3 = []
list1.push(item1)
list1.push(item2)
if (!isPhone) {
list1.push(item3)
list2.push(item4)
list2.push(item5)
list2.push(item6)
} else {
list2.push(item3)
list2.push(item4)
list3.push(item5)
list3.push(item6)
}
return (
<section className="home-page">
<div className="banner">
<div className={`content ${color}`} style={{ backgroundImage: 'url(./././imgs/ic_bg.png)' }}>
<label className="center-title">IM</label>
<label className="center-small-text"></label>
<div className={`btn-view ${color}`}>
<a href="/guide/guide" className="btn"></a>
<a style={{ marginLeft: '30px' }} target="_blank" href="https://github.com/WuKongIM/WuKongIM"
className="btn">Github</a>
</div>
<p className="content-text">IM是高性能通用即时通讯服务AI </p>
</div>
<div className="des">
<div className={`card ${color}`}>
<div className='bg'>
<label className="big-font"></label>
<div style={{ marginTop: '37px', display: 'flex' }}>
{
list1.map((item: any) =>
<div className='card-item' style={{ width: isPhone ? '50%' : '33.3%' }}>
<img className="img" src={item.icon} />
<label className="characteristic-title">{item.title}</label>
<label className="characteristic-content">{item.desc}</label>
</div>
)
}
</div>
<div style={{ display: 'flex' }}>
{
list2.map((item: any) =>
<div className='card-item' style={{ width: isPhone ? '50%' : '33.3%' }}>
<img className="img" src={item.icon} />
<label className="characteristic-title">{item.title}</label>
<label className="characteristic-content">{item.desc}</label>
</div>
)
}
</div>
<div style={{ display: 'flex' }} >
{
list3.map((item: any) =>
<div className='card-item' style={{ width: isPhone ? '50%' : '33.3%' }}>
<img className="img" src={item.icon} />
<label className="characteristic-title">{item.title}</label>
<label className="characteristic-content">{item.desc}</label>
</div>
)
}
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default Home;

View File

@ -1,212 +0,0 @@
[home="true"] {
.dumi-default-doc-layout>main {
padding: 0px;
max-width: 100% !important;
}
.dumi-default-header {
background-color: transparent !important;
}
.dumi-default-navbar li a {
color: white !important;
}
.dumi-default-logo {
color: white;
}
.dumi-default-search-bar input {
background-color: white !important;
border: 1px solid #d9d9d9 !important;
}
.dumi-default-search-shortcut {
border: 1px solid #d9d9d9 !important;
}
.dumi-default-search-bar input::placeholder {
color: #bbb;
}
.dumi-default-color-switch svg {
color: white;
}
.dumi-default-color-switch svg path{
fill: white;
}
.dumi-default-icon svg {
color: white;
}
.dumi-default-icon svg path{
fill: white;
}
}
.home-page {
font-size: 14px;
margin-top: -76px;
color: white;
.banner {
margin-right: auto;
margin-left: auto;
// position: absolute;
// top: 0px;
// right: 0px;
// width: 100%;
a {
text-decoration: none;
list-style: none;
background-color: transparent;
outline: none;
cursor: pointer;
}
.center-title {
font-weight: bold;
font-size: 100px;
margin-top: 8rem;
display: block;
align-content: center;
color: white;
}
.center-small-text {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
}
.des {
margin-top: -5rem;
position: inherit;
text-align: center;
margin-left: 10%;
width: 80%;
}
.content {
display: flow-root;
text-align: center;
width: 100%;
height: 100vh;
background-repeat: repeat;
background-position: 50%;
.content-text {
font-size: 14px;
margin-top: 5rem;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
line-height: 20px;
margin-left: 30%;
color: white;
margin-right: 30%;
}
}
}
.btn-view {
margin-top: 50px;
.btn {
cursor: pointer;
text-decoration: none;
-moz-border-radius: 4px;
/*Gecko(Firefox内核)浏览器圆角样式*/
-webkit-border-radius: 30px;
/*webkit(Chrome内核)浏览器圆角样式*/
border-radius: 30px;
/*Trident(IE内核)浏览器圆角样式*/
color: #df5d2a !important;
background: #fff;
padding: 8px 18px 8px 18px !important;
border: 1px solid #df5d2a;
}
// &.dark {
// .btn {
// color: #9f4522 !important;
// background: #141414;
// border: 1px solid #9f4522;
// }
// }
}
.card {
.bg {
background: #fff !important;
box-shadow: 0px 0px 100px 1PX #f8f8f7;
}
.card-item {
display: inline-block;
text-align: center;
width: 33.33%;
margin-right: 1rem;
margin-bottom: 1rem;
margin-left: 1rem;
}
.img {
width: 4rem;
height: 4rem;
}
.big-font {
display: block;
padding-top: 40px;
font-size: 30px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #000000;
line-height: 42px;
}
.characteristic-title {
font-size: 14px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
margin-top: 10px;
color: #333333;
display: block;
line-height: 20px;
}
.characteristic-content {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 17px;
margin-top: 5px;
}
&.dark {
.bg {
background: #0a0909 !important;
box-shadow: 0px 0px 100px 1PX #282828;
}
.big-font {
color: #fff;
}
.characteristic-title {
color: #d1d0d0;
}
.characteristic-content {
color: #8590a0;
}
}
}
}

View File

@ -1,14 +0,0 @@
import { defineConfig } from 'dumi';
export default defineConfig({
themeConfig: {
logo: '/logo.png',
name: '悟空IM',
hd: { rules: [] },
socialLinks: {
github: 'https://github.com/WuKongIM/WuKongIM',
},
footer: "Copyright © 2023 | Powered by 悟空IM | <a href='https://beian.miit.gov.cn/' style='color:gray'>ICP备案号沪ICP备2021032718号-2</a>",
},
headScripts: ["https://hm.baidu.com/hm.js?219604efa41d5fcab346766087ead60a"] // 百度统计
});

View File

@ -1,13 +1,15 @@
# http://editorconfig.org
# @see: http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
end_of_line = lf # 控制换行类型(lf | cr | crlf)
insert_final_newline = true # 始终在文件末尾插入一个新行
indent_style = tab # 缩进风格tab | space
indent_size = 2 # 缩进大小
max_line_length = 130 # 最大行长度
[*.md]
trim_trailing_whitespace = false
[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off # 关闭最大行长度限制
trim_trailing_whitespace = false # 关闭末尾空格修剪

29
.gitignore vendored
View File

@ -1,5 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
/dist
.dumi/tmp
.dumi/tmp-production
dist
dist-ssr
stats.html
*.local
docs/.vitepress/cache
.vitepress/cache
# Editor directories and files
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx commitlint --edit "${1}"

View File

@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged

View File

@ -1,3 +0,0 @@
.dumi/tmp
.dumi/tmp-production
*.yaml

View File

@ -1,14 +0,0 @@
module.exports = {
printWidth: 80,
proseWrap: 'never',
singleQuote: true,
trailingComma: 'all',
overrides: [
{
files: '*.md',
options: {
proseWrap: 'preserve',
},
},
],
};

71
.vitepress/config.ts Normal file
View File

@ -0,0 +1,71 @@
import { defineConfig } from "vitepress";
import mdItCustomAttrs from "markdown-it-custom-attrs";
import UnoCSS from "unocss/vite";
import { navbar } from "./navbar";
import { sidebar } from "./sidebar";
export default defineConfig({
title: "悟空IM",
description: "IM",
lang: "zh-CN",
head: [
["meta", { name: "keywords", content: "IM" }],
["link", { rel: "icon", type: "image/x-icon", href: "/favicon.ico" }],
["link", { rel: "stylesheet", href: "/css/fancybox.css" }],
["script", { src: "/js/fancybox.umd.js" }],
["script", { src: "https://hm.baidu.com/hm.js?219604efa41d5fcab346766087ead60a" }], // 百度统计
],
markdown: {
theme: {
light: "vitesse-light",
dark: "vitesse-dark",
},
config: (md) => md.use(mdItCustomAttrs, "image", { "data-fancybox": "gallery" }),
},
lastUpdated: true,
srcDir: "./src",
themeConfig: {
logo: "/logo.png",
siteTitle: "悟空IM",
nav: navbar,
sidebar: sidebar,
lastUpdatedText: "上次更新",
outlineTitle: "目录",
outline: [2, 6],
docFooter: {
prev: "上一篇",
next: "下一篇",
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/WuKongIM/WuKongIM' }
],
footer: {
message: `本文档内容版权属于 悟空IM 作者,保留所有权利`,
copyright: "Copyright © 2023 | Powered by 悟空IM | ICP备案号沪ICP备2021032718号-2",
},
search: {
provider: "local",
options: {
translations: {
button: { buttonText: "搜索文档", buttonAriaLabel: "搜索文档" },
modal: {
noResultsText: "无法找到相关结果",
resetButtonTitle: "清除查询条件",
footer: { selectText: "选择", navigateText: "切换", closeText: "关闭" },
},
},
},
},
},
vite: {
optimizeDeps: {
exclude: ["vitepress"],
},
server: {
host: "0.0.0.0",
},
plugins: [UnoCSS()],
},
});

27
.vitepress/navbar.ts Normal file
View File

@ -0,0 +1,27 @@
import { DefaultTheme } from "vitepress/types/default-theme";
export const navbar: DefaultTheme.NavItem[] = [
{
text: " 指南",
link: "/guide/guide",
activeMatch: "^/guide",
},
{
text: "API文档",
link: "/api/",
activeMatch: "^/api",
},
{
text: "SDK文档",
link: "/sdk/",
activeMatch: "^/sdk",
},
{
text: "相关链接",
activeMatch: "^/im",
items: [
{ text: "Go", link: "https://pkg.go.dev/" },
{ text: "Node", link: "https://nodejs.org/" },
],
},
];

61
.vitepress/sidebar.ts Normal file
View File

@ -0,0 +1,61 @@
import { DefaultTheme } from "vitepress";
export const sidebar: DefaultTheme.Sidebar = {
"/guide": [
{
text: "介绍",
collapsed: false,
items: [
{ text: "文档阅读引导", link: "/guide/guide" },
{ text: "什么是悟空 IM", link: "/guide/" },
{ text: "基础概念", link: "/guide/initialize" },
{ text: "适用场景", link: "/guide/scene" },
{ text: "Demo 演示", link: "/guide/demo" },
],
},
{
text: "快速开始",
collapsed: false,
items: [
{ text: "部署", link: "/guide/quickstart" },
{ text: "集成到自己系统", link: "/guide/integration" },
],
},
{
text: "进阶",
collapsed: false,
items: [
{ text: "配置说明", link: "/guide/fullconfig" },
{ text: "WSS 配置", link: "/guide/wss" },
{ text: "命令行工具", link: "/guide/cli" },
{ text: "测试", link: "/guide/stress" },
{ text: "悟空 IM 协议", link: "/guide/proto" },
],
},
{
text: "其他",
collapsed: false,
items: [
{ text: "常见问题", link: "/guide/others" },
],
}
],
"/api": [
{ text: "基础", link: "/api/" },
{ text: "用户", link: "/api/user" },
{ text: "频道", link: "/api/channel" },
{ text: "消息", link: "/api/message" },
{ text: "最近会话", link: "/api/conversation" },
{ text: "Webhook", link: "/api/webhook" },
{ text: "Datasource", link: "/api/datasource" },
],
"/sdk": [
{ text: "概述", link: "/sdk/" },
{ text: "IOS", link: "/sdk/ios" },
{ text: "Android", link: "/sdk/android" },
{ text: "Javascript", link: "/sdk/javascript" },
{ text: "Uniapp", link: "/sdk/uniapp" },
{ text: "Flutter", link: "/sdk/flutter" },
{ text: "c", link: "/sdk/c" },
]
};

View File

@ -0,0 +1,89 @@
<template>
<div class="home-preview-block">
<div class="home-preview">
<h2>截图预览</h2>
<div class="items">
<div class="item">
<img data-fancybox="gallery" src="/imgs/screen1.png" />
</div>
<div class="item">
<img data-fancybox="gallery" src="/imgs/screen2.png" />
</div>
<div class="item">
<img data-fancybox="gallery" src="/imgs/screen3.png" />
</div>
<div class="item">
<img data-fancybox="gallery" src="/imgs/screen4.png" />
</div>
<div class="item">
<img data-fancybox="gallery" src="/imgs/screen5.png" />
</div>
</div>
</div>
</div>
</template>
<style scoped>
.home-preview-block {
padding: 0 24px;
}
.home-preview {
max-width: 1152px;
margin: 50px auto 0;
}
.home-preview h2 {
font-size: 24px;
font-weight: bold;
margin-bottom: 20px;
text-align: center;
}
.home-preview .items {
display: flex;
flex-wrap: wrap;
margin: -8px;
}
.home-preview .items .item {
width: 100%;
padding: 8px;
}
.home-preview .items .item img{
width: 100%;
height: 100%;
cursor: pointer;
}
.home-preview .items .item p {
padding: 24px;
border-radius: 12px;
background-color: var(--vp-c-bg-soft);
}
.home-preview .items .item p :deep(img) {
border: 1px solid var(--vp-c-divider);
}
@media (min-width: 640px) {
.home-preview-block {
padding: 0 48px;
}
.home-preview .items .item {
width: calc(100% / 2);
}
}
@media (min-width: 960px) {
.home-preview-block {
padding: 0 64px;
}
.home-preview .items .item {
width: calc(100% / 3);
}
}
</style>

16
.vitepress/theme/index.ts Normal file
View File

@ -0,0 +1,16 @@
import { h } from "vue";
import Theme from "vitepress/theme";
import "./styles/var.css";
import "./styles/custom.css";
import 'uno.css';
import HomePreview from "./components/HomePreview.vue";
export default {
...Theme,
Layout() {
return h(Theme.Layout, null, {
"home-features-after": () => h(HomePreview),
});
},
};

View File

@ -0,0 +1,10 @@
.docs-cn-github-release-tag {
font-size: 14px;
font-weight: bold;
padding: 4px 6px;
margin-left: 6px;
background: var(--vp-button-brand-bg);
color: white;
border-radius: 6px;
vertical-align: middle;
}

View File

@ -0,0 +1,112 @@
/**
* Colors
* -------------------------------------------------------------------------- */
:root {
--vp-c-brand: #df5d2a;
--vp-c-brand-light: #df5d2a;
--vp-c-brand-lighter: #ff9a2e;
--vp-c-brand-lightest: #ff7d00;
--vp-c-brand-dark: #483838;
--vp-c-brand-darker: #3a2d2d;
--vp-c-brand-dimm: rgba(100, 108, 255, 0.08);
}
/**
* Component: Button
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: var(--vp-c-brand-light);
--vp-button-brand-text: var(--vp-c-text-dark-1);
--vp-button-brand-bg: var(--vp-c-brand);
--vp-button-brand-hover-border: var(--vp-c-brand-light);
--vp-button-brand-hover-text: var(--vp-c-text-dark-1);
--vp-button-brand-hover-bg: var(--vp-c-brand-light);
--vp-button-brand-active-border: var(--vp-c-brand-light);
--vp-button-brand-active-text: var(--vp-c-text-dark-1);
--vp-button-brand-active-bg: var(--vp-button-brand-bg);
}
/**
* Component: Home
* -------------------------------------------------------------------------- */
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #ffcf8b 10%, var(--vp-c-brand-lightest));
--vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-lightest) 90%, #ffcf8b 10%);
--vp-home-hero-image-filter: blur(40px);
}
@media (min-width: 640px) {
:root {
--vp-home-hero-image-filter: blur(56px);
}
}
@media (min-width: 960px) {
:root {
--vp-home-hero-image-filter: blur(72px);
}
}
/**
* Component: Custom Block
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-tip-border: var(--vp-c-brand);
--vp-custom-block-tip-text: var(--vp-c-brand-darker);
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
}
.dark {
--vp-custom-block-tip-border: var(--vp-c-brand);
--vp-custom-block-tip-text: var(--vp-c-brand-lightest);
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
}
/**
* Component: Algolia
* -------------------------------------------------------------------------- */
.DocSearch {
--docsearch-primary-color: var(--vp-c-brand-light) !important;
}
/**
* VitePress: Custom fix
* -------------------------------------------------------------------------- */
/*
Use lighter colors for links in dark mode for a11y.
Also specify some classes twice to have higher specificity
over scoped class data attribute.
*/
.dark .vp-doc a,
.dark .vp-doc a > code,
.dark .VPNavBarMenuLink.VPNavBarMenuLink:hover,
.dark .VPNavBarMenuLink.VPNavBarMenuLink.active,
.dark .link.link:hover,
.dark .link.link.active,
.dark .edit-link-button.edit-link-button,
.dark .pager-link .title {
color: var(--vp-c-brand-lighter);
}
.dark .vp-doc a:hover,
.dark .vp-doc a > code:hover {
color: var(--vp-c-brand-lightest);
opacity: 1;
}
/* Transition by color instead of opacity */
.dark .vp-doc .custom-block a {
transition: color 0.25s;
}
body {
cursor: url('/blue.cur'), auto;
}

View File

@ -0,0 +1,8 @@
export function fetchReleaseTag() {
const releaseTag = "1.0.0";
const tagLineParagragh = document.querySelector("div.VPHero.has-image.VPHomeHero > div > div.main > p.tagline");
const docsReleaseTagSpan = document.createElement("samp");
docsReleaseTagSpan.classList.add("docs-cn-github-release-tag");
docsReleaseTagSpan.innerText = releaseTag;
tagLineParagragh?.appendChild(docsReleaseTagSpan);
}

View File

@ -1,18 +0,0 @@
FROM node:18.0.0 as builder
WORKDIR /app
RUN curl -o- -L https://yarnpkg.com/install.sh | bash
COPY package.json .
COPY yarn.lock .
# https://registry.npmjs.org/ https://registry.npm.taobao.org
# RUN yarn config set registry https://registry.npm.taobao.org -g
# RUN yarn config set disturl https://npm.taobao.org/dist
RUN yarn install
COPY . .
RUN yarn build
FROM nginx:latest
COPY --from=builder /app/docker-entrypoint.sh /docker-entrypoint2.sh
COPY --from=builder /app/nginx.conf.template /
COPY --from=builder /app/dist /usr/share/nginx/html
ENTRYPOINT ["sh", "/docker-entrypoint2.sh"]
CMD ["nginx","-g","daemon off;"]

View File

@ -1,6 +0,0 @@
build:
docker build -t wukongimdocs .
deploy:
docker build -t wukongimdocs .
docker tag wukongimdocs wukongim/wukongimdocs:latest
docker push wukongim/wukongimdocs:latest

View File

@ -1,20 +1,19 @@
# WuKongIMDocs
# 悟空IM
A static site base on [dumi](https://d.umijs.org).
## 本地开发
## Development
```bash
# install dependencies
$ yarn install
# start dev server
$ yarn start
# build docs
$ yarn run build
``` sh
pnpm run dev
```
## LICENSE
## 编译
MIT
``` sh
pnpm run build
```
## 预览
``` sh
pnpm run serve
```

Binary file not shown.

Binary file not shown.

View File

@ -1,8 +0,0 @@
#!/usr/bin/env sh
set -eu
envsubst '${API_URL}' < /nginx.conf.template > /etc/nginx/conf.d/default.conf
exec "$@"

View File

@ -1,26 +0,0 @@
<!-- ---
title: 悟空IM
hero:
title: 悟空IM
description: 让信息传递更简单
actions:
- text: 立即上手
link: /guide/guide
- text: Github
link: https://github.com/WuKongIM/WuKongIM
# features:
# - title: Hello
# emoji: 💎
# description: Put hello description here
# - title: World
# emoji: 🌈
# description: Put world description here
# - title: '!'
# emoji: 🚀
# description: Put ! description here
# - title: 'zz'
# emoji: 🚀
# description: Put ! description here
footer: Open-source Apache 2.0 Licensed | Copyright © 2020<br />Powered by 上海信必达网络科技
--- -->
<!-- <embed src="./index.html"></embed> -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 KiB

View File

@ -1,10 +0,0 @@
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}

View File

@ -1,36 +1,43 @@
{
"name": "WuKongIMDocs",
"version": "0.0.1",
"description": "Docs For WuKongIM",
"license": "MIT",
"name": "wukongim-doc",
"version": "1.0.0",
"description": "wukongim文档",
"keywords": [
"悟空IM",
"IM"
],
"scripts": {
"build": "dumi build",
"dev": "dumi dev",
"prepare": "husky install && dumi setup",
"start": "npm run dev"
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"lint-staged": {
"*.{md,json}": [
"prettier --write --no-error-on-unmatched-pattern"
]
"dev": "vitepress dev",
"build": "vitepress build",
"serve": "vitepress serve"
},
"dependencies": {
"prism-react-renderer": "^2.0.5"
"@iconify-json/carbon": "^1.1.18",
"@iconify-json/logos": "^1.1.33",
"@iconify-json/mdi": "^1.1.52",
"@iconify-json/ph": "^1.1.5",
"@iconify-json/twemoji": "^1.1.11",
"@iconify-json/vscode-icons": "^1.1.25",
"vitepress": "1.0.0-beta.3",
"vue": "^3.3.4"
},
"devDependencies": {
"@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.1.0",
"dumi": "^2.1.22",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1"
"@types/node": "^18.15.13",
"markdown-it-custom-attrs": "^1.0.2",
"typescript": "^5.0.4",
"unocss": "^0.53.3",
"vite": "^4.3.9"
},
"authors": [
"tt@gmail.com"
]
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"@algolia/client-search"
]
}
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"packageManager": "pnpm@7.9.5",
"license": "ISC"
}

1704
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,11 +1,3 @@
---
group:
title: 进阶
order: 300
order: 300
title: 命令行工具
---
# 命令行工具
## 安装命令行工具

View File

@ -1,11 +1,3 @@
---
group:
title: 介绍
order: -1
order: 300
title: Demo演示
---
# Demo 演示
## 前端聊天 Demo

View File

@ -1,11 +1,3 @@
---
title: 配置说明
group:
title: 进阶
order: 100
order: 200
---
# 配置说明
## 配置文件

View File

@ -1,9 +1,6 @@
---
group:
title: 介绍
order: -1
order: -1
title: 文档阅读引导
title: 介绍
---
# 文档阅读引导

View File

@ -1,14 +1,3 @@
---
group:
title: 介绍
order: -1
order: 1
title: 什么是悟空IM
nav:
title: 指南
order: -1
---
# 什么是悟空 IM
高性能通用即时通讯服务支持聊天应用消息推送物联网通讯音视频信令直播弹幕客服系统AI 通讯,即时社区等场景。

View File

@ -1,11 +1,3 @@
---
group:
title: 介绍
order: -1
order: 1
title: 基础概念
---
# 基础概念
### 频道

View File

@ -1,11 +1,3 @@
---
group:
title: 快速开始
order: -1
order: 200
title: 集成到自己系统
---
# 集成到自己系统
`所有悟空IM的接口不要直接给APP端调用应该前端先调用自己的业务API业务API再调用悟空IM的API并且悟空IM的API不要暴露给外网这样可以保证数据的安全性。`

View File

@ -1,11 +1,3 @@
---
title: 常见问题
group:
title: 其他
order: 100
order: 100
---
# 常见问题
#### iOS 打包失败 file not found: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a

View File

@ -1,11 +1,3 @@
---
group:
title: 进阶
order: 300
order: 700
title: 悟空IM协议
---
# 悟空 IM 协议
## 控制报文结构

View File

@ -1,11 +1,3 @@
---
title: 部署
group:
title: 快速开始
order: -1
order: 100
---
# 部署
## 一键部署(推荐)

View File

@ -1,12 +1,6 @@
---
group:
title: 介绍
order: -1
order: 1
title: 适用场景
---
# 适用场景
### 即时通讯
## 即时通讯
- 群频道支持
- 个人频道支持
@ -14,13 +8,13 @@ title: 适用场景
- 离线消息推送支持
- 最近会话维护
### 消息推送/站内消息
## 消息推送/站内消息
- 群频道支持
- 个人频道支持
- 离线消息推送支持
### 客服系统
## 客服系统
- 客服频道支持
@ -28,17 +22,17 @@ title: 适用场景
- 第三方服务器可决定分配指定的订阅者成组投递
### 游戏聊天室
## 游戏聊天室
- 大群频道支持
<!-- 把联机的用户建立一个频道内当A打了敌人后A将数据告诉你们自己的业务服务器业务服务器处理后调用悟空IM的发送消息接口发送消息的频道参数指定为这个建立的频道这样这个频道内所有人都能收到包括A -->
### 音视频信令服务器
## 音视频信令服务器
- 支持临时指令消息投递
### 直播弹幕
## 直播弹幕
- 临时消息投递
@ -46,16 +40,16 @@ title: 适用场景
一个直播一个频道,用户进入直播就是用户订阅频道,用户退出直播就是用户取消订阅频道,直播结束就是频道销毁。
### 实时 AI 反馈
## 实时 AI 反馈
- 支持客户端发的消息推送给第三方服务器,第三方服务器反馈给 AI 后返回的结果再推送给客户端
### 即时社区
## 即时社区
- 社区频道支持
- 支持 topic 模式的消息投递
### 物联网通讯
## 物联网通讯
- mqtt 协议支持(待开发)
- 支持发布与订阅

View File

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 213 KiB

View File

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

View File

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 242 KiB

View File

Before

Width:  |  Height:  |  Size: 463 KiB

After

Width:  |  Height:  |  Size: 463 KiB

View File

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 211 KiB

View File

Before

Width:  |  Height:  |  Size: 406 KiB

After

Width:  |  Height:  |  Size: 406 KiB

View File

Before

Width:  |  Height:  |  Size: 578 KiB

After

Width:  |  Height:  |  Size: 578 KiB

View File

Before

Width:  |  Height:  |  Size: 563 KiB

After

Width:  |  Height:  |  Size: 563 KiB

View File

@ -1,11 +1,3 @@
---
group:
title: 进阶
order: 300
order: 600
title: 测试
---
# 测试
## 性能测试

View File

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 182 KiB

View File

@ -1,10 +1,3 @@
---
group:
title: 进阶
order: 290
title: WSS配置
---
# WSS 配置
```yaml

View File

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 195 KiB

50
src/index.md Normal file
View File

@ -0,0 +1,50 @@
---
layout: home
title: 悟空IM
titleTemplate: 悟空IM
hero:
name: 悟空IM
text: 让信息传递更简单
tagline: 悟空IM是高性能通用即时通讯服务支持聊天应用消息推送物联网通讯音视频信令直播弹幕客服系统AI 通讯,即时社区等场景
image:
src: /logo_white.png
alt: logo
actions:
- theme: brand
text: 马上开始
link: /guide/guide
- theme: alt
text: 介绍
link: /guide/
features:
- icon: <span class="i-carbon:ibm-cloud-pak-integration"></span>
title: 零依赖
details: 没有依赖任何第三方组件,部署简单,一条命令即可启动
- icon: <span class="i-carbon:plug"></span>
title: 完全自研
details: 自研消息数据库,消息分区永久存储,自研二进制协议,支持自定义协议
- icon: <span class="i-carbon:ibm-cloud-hyper-protect-crypto-services"></span>
title: 安全
details: 消息通道和消息内容全程加密,防中间人攻击和串改消息内容
- icon: <span class="i-carbon:ibm-cloud-pak-manta-automated-data-lineage"></span>
title: 功能强劲
details: MAC 笔记本单机测试 16w 多/秒的消息(包含存储)吞吐量,频道支持万人同时订阅
- icon: <span class="i-carbon:deployment-pattern"></span>
title: 扩展性强
details: 采用频道设计理念,目前支持群组频道,点对点频道,后续可以根据自己业务自定义频道可实现机器人频道,客服频道等等
- icon: <span class="i-carbon:api"></span>
title: 兼容性强
details: 同时无差别支持 tcpwebsocket
---
<script setup>
import { onMounted } from 'vue'
import { fetchReleaseTag } from '../.vitepress/utils/fetchReleaseTag.js'
onMounted(() => {
fetchReleaseTag()
})
</script>

BIN
src/public/blue.cur Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
src/public/imgs/screen1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 KiB

BIN
src/public/imgs/screen2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

BIN
src/public/imgs/screen3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

BIN
src/public/imgs/screen4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

BIN
src/public/imgs/screen5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 KiB

View File

Before

Width:  |  Height:  |  Size: 382 KiB

After

Width:  |  Height:  |  Size: 382 KiB

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
src/public/logo_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -2,6 +2,7 @@
title: Android
order: 200
---
# Android
## 设计理念

View File

@ -8,13 +8,13 @@ nav:
# 文档阅读引导
[iOS SDK](./iOS/index.md)<br/>
[iOS SDK](./ios.md)<br/>
[Android SDK](./Android/index.md) <br/>
[Android SDK](./android.md) <br/>
[JavaScript SDK](./Javascript/index.md) <br/>
[JavaScript SDK](./javascript.md) <br/>
[Uniapp SDK](./uniapp/index.md) <br/>
[Uniapp SDK](./uniapp.md) <br/>
Flutter SDK (待开发)

View File

@ -1,20 +1,10 @@
---
order: 1
title: iOS
nav:
title: SDK文档
order: 1
---
# iOS
## 介绍
### 设计理念
## 设计理念
像设计书的目录一样设计 api, 通过 WKSDK.shared.xxxManager 我们可以访问到所有需要的功能,例如发送消息 `[WKSDK.shared.chatManager sendMessage:xxx]`
### 结构说明
## 结构说明
![sdk结构图](./wksdk.png)
@ -81,7 +71,6 @@ sdk 与已有 APP 交互的整体流程就是 已有 APP 调用 SDK 对应的方
}
```
## 集成
### 通过 CocoaPods 集成
@ -89,7 +78,6 @@ sdk 与已有 APP 交互的整体流程就是 已有 APP 调用 SDK 对应的方
```objc
pod 'WuKongIMSDK'
```
### 通过二进制集成
(后续完善)
@ -109,12 +97,11 @@ pod 'WuKongIMSDK'
};
```
更多配置请查看 `[WKSDK shared].options`
## 连接与断开
#### 数据操作
### 数据操作
```objc
// 开始连接
@ -125,7 +112,7 @@ pod 'WuKongIMSDK'
```
#### 数据监听
### 数据监听
```objc
[WKSDK.shared.connectManager addDelegate:self]; // WKConnectionManagerDelegate
@ -148,7 +135,7 @@ pod 'WuKongIMSDK'
## 在线消息收发
#### 数据操作
### 数据操作
发送消息
@ -173,7 +160,7 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
[[WKSDK shared].chatManager sendMessage:content channel:channel];
```
#### 数据监听
### 数据监听
```objc
[WKSDK.shared.chatManager addDelegate:self]; // WKChatManagerDelegate
@ -229,8 +216,6 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
...
@end
```
消息正文核心属性
@ -243,13 +228,14 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
你自定义的消息类型,在各个平台上需要保持一致
@return 正文类型
*/
+(NSInteger) contentType;
(NSInteger) contentType;
// 上层无需实现encode 实现此方法即可
-(NSDictionary*) encodeWithJSON;
(NSDictionary*) encodeWithJSON;
// 上层无序实现decode 实现此方法即可
-(void) decodeWithJSON:(NSDictionary*)contentDic;
(void) decodeWithJSON:(NSDictionary*)contentDic;
// 消息中的@提醒信息
@property (nonatomic, strong) WKMentionedInfo *mentionedInfo;
@ -260,8 +246,6 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
...
@end
```
## 离线消息接收
@ -270,9 +254,9 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
而是采用拉取这 10 个会话的信息和对应的最新 20 条消息,也就是实际只拉取了 200 条消息 相对 100 万条消息来说大大提高了离线拉取速度。用户点进对应的会话才会去按需拉取这个会话的消息。
这些机制 SDK 内部都已做好了封装,使用者其实不需要关心。使用者只需要关心最近会话的变化
最近会话的变化可以通过 WKConversationManager 进行监听
最近会话的变化可以通过 **WKConversationManager** 进行监听
#### 数据操作
### 数据操作
```objc
@ -311,7 +295,7 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
```
#### 数据监听
### 数据监听
```objc
// 添加委托
@ -326,7 +310,7 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
@param conversation 最近会话对象
@param left 会话剩余数量 UI层可以判断left == 0 的时候才刷新 避免频繁刷新UI导致卡顿
*/
- (void)onConversationAdd:(WKConversation*)conversation left:(NSInteger)left;
(void)onConversationAdd:(WKConversation*)conversation left:(NSInteger)left;
/**
@ -335,7 +319,7 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
@param conversation 最近会话对象
@param left 会话剩余数量 UI层可以判断left == 0 的时候才刷新 避免频繁刷新UI导致卡顿
*/
- (void)onConversationUpdate:(WKConversation*)conversation left:(NSInteger)left;
(void)onConversationUpdate:(WKConversation*)conversation left:(NSInteger)left;
/**
最近会话未读数发送改变
@ -343,15 +327,15 @@ WKTextContent *content = [[WKTextContent alloc] initWithContent:@"hello"];
@param channel 频道
@param unreadCount 未读数量
*/
- (void)onConversationUnreadCountUpdate:(WKChannel*)channel unreadCount:(NSInteger)unreadCount;
(void)onConversationUnreadCountUpdate:(WKChannel*)channel unreadCount:(NSInteger)unreadCount;
...
```
WKConversation 类的核心属性
**WKConversation** 类的核心属性
```objc
``` objc
/**
频道
@ -384,11 +368,11 @@ WKConversation 类的核心属性
@property(nonatomic,copy) NSString *content;
@end
```
## 图片消息
```objc
@interface WKImageContent : WKMediaMessageContent
@ -404,7 +388,7 @@ WKConversation 类的核心属性
@param image 原始图片
@return 图片消息对象
*/
+ (instancetype)initWithImage:(UIImage *)image;
(instancetype)initWithImage:(UIImage *)image;
@ -412,7 +396,7 @@ WKConversation 类的核心属性
/// @param data 图片数据
/// @param width 图片宽度
/// @param height 图片高度
+ (instancetype)initWithData:(NSData *)data width:(CGFloat)width height:(CGFloat)height;
(instancetype)initWithData:(NSData *)data width:(CGFloat)width height:(CGFloat)height;
/// 初始化
@ -420,7 +404,7 @@ WKConversation 类的核心属性
/// @param width 原图宽度
/// @param height 原图高度
/// @param thumbData 缩略图data 如果传了缩略图的data数据sdk将不再生成缩略图数据
+ (instancetype)initWithData:(NSData *)data width:(CGFloat)width height:(CGFloat)height thumbData:( nullable NSData*)thumbData;
(instancetype)initWithData:(NSData *)data width:(CGFloat)width height:(CGFloat)height thumbData:( nullable NSData*)thumbData;
/*!
@ -430,7 +414,6 @@ WKConversation 类的核心属性
*/
@property (nonatomic, getter=isFull) BOOL full;
@end
```
@ -449,7 +432,7 @@ WKConversation 类的核心属性
@param waveform 音频波浪数据 (可选参数)
@return <#return value description#>
*/
+ (instancetype)initWithData:(NSData *)voiceData second:(int)second waveform:(NSData*)waveform;
(instancetype)initWithData:(NSData *)voiceData second:(int)second waveform:(NSData*)waveform;
// 音频数据
@ -460,7 +443,6 @@ WKConversation 类的核心属性
// 音频波浪数据 (可选参数)
@property(nonatomic,strong) NSData *waveform;
@end
```
@ -475,7 +457,7 @@ WKConversation 类的核心属性
/// @param title 位置标题
/// @param address 位置地址
/// @param image 地图图片
+(WKLocationContent*) locationContent:(CGFloat)lng lat:(CGFloat)lat title:(NSString*)title address:(NSString*)address img:(UIImage*)image;
(WKLocationContent*) locationContent:(CGFloat)lng lat:(CGFloat)lat title:(NSString*)title address:(NSString*)address img:(UIImage*)image;
@ -489,12 +471,7 @@ WKConversation 类的核心属性
/// 地图图片
@property(nonatomic,strong,readonly) UIImage *mapImage;
@end
```
## CMD 消息
cmd 消息由服务端下发客户端解析。
@ -518,7 +495,6 @@ cmd 消息由服务端下发客户端解析。
@end
```
## 最近会话
最近会话用于表示会话列表页的数据模型。当用户发送,收取及删除消息时,都会同时去修改最近会话。
@ -566,7 +542,7 @@ cmd 消息由服务端下发客户端解析。
```
#### 数据操作
### 数据操作
```objc
@ -585,15 +561,13 @@ cmd 消息由服务端下发客户端解析。
```
#### 数据监听
### 数据监听
```objc
[[WKSDK shared].conversationManager addDelegate:self] // WKConversationManagerDelegate
```
```objc
// ---------- WKConversationManagerDelegate ----------
/**
@ -602,7 +576,7 @@ cmd 消息由服务端下发客户端解析。
@param conversation 最近会话对象
@param left 会话剩余数量 UI层可以判断left == 0 的时候才刷新 避免频繁刷新UI导致卡顿
*/
- (void)onConversationAdd:(WKConversation*)conversation left:(NSInteger)left;
(void)onConversationAdd:(WKConversation*)conversation left:(NSInteger)left;
/**
@ -611,7 +585,7 @@ cmd 消息由服务端下发客户端解析。
@param conversation 最近会话对象
@param left 会话剩余数量 UI层可以判断left == 0 的时候才刷新 避免频繁刷新UI导致卡顿
*/
- (void)onConversationUpdate:(WKConversation*)conversation left:(NSInteger)left;
(void)onConversationUpdate:(WKConversation*)conversation left:(NSInteger)left;
/**
最近会话未读数发送改变
@ -619,7 +593,7 @@ cmd 消息由服务端下发客户端解析。
@param channel 频道
@param unreadCount 未读数量
*/
- (void)onConversationUnreadCountUpdate:(WKChannel*)channel unreadCount:(NSInteger)unreadCount;
(void)onConversationUnreadCountUpdate:(WKChannel*)channel unreadCount:(NSInteger)unreadCount;
...
@ -693,7 +667,7 @@ cmd 消息由服务端下发客户端解析。
```
#### 数据操作
### 数据操作
```objc
@ -746,15 +720,15 @@ cmd 消息由服务端下发客户端解析。
// 实现四个方法 initWithMessage resume cancel suspend
@implementation WKFileUploadTask
- (instancetype)initWithMessage:(WKMessage *)message {
self = [super initWithMessage:message];
if(self) {
[self initTask];
}
return self;
(instancetype)initWithMessage:(WKMessage *)message {
self = [super initWithMessage:message];
if(self) {
[self initTask];
}
return self;
}
-(void) initTask {
(void) initTask {
WKMediaContent *mediaContent = (WKMediaContent*)self.message.content;
NSString *fileLocalPath = mediaContent.localPath; // 附件本地路径
@ -776,18 +750,18 @@ cmd 消息由服务端下发客户端解析。
}
// 任务恢复
-(void) resume {
[self.task resume];
(void) resume {
[self.task resume];
}
// 任务取消
-(void) cancel {
[self.task cancel];
(void) cancel {
[self.task cancel];
}
// 任务挂起
- (void)suspend {
[self.task suspend];
(void)suspend {
[self.task suspend];
}
@end
@ -822,15 +796,15 @@ cmd 消息由服务端下发客户端解析。
// 实现四个方法 initWithMessage resume cancel suspend
@implementation WKFileDownloadTask
- (instancetype)initWithMessage:(WKMessage *)message {
self = [super initWithMessage:message];
if(self) {
[self initTask];
}
return self;
(instancetype)initWithMessage:(WKMessage *)message {
self = [super initWithMessage:message];
if(self) {
[self initTask];
}
return self;
}
-(void) initTask {
(void) initTask {
WKMediaContent *mediaContent = (WKMediaContent*)self.message.content;
NSString *downloadURL = mediaContent.remoteUrl; // 附件下载地址
@ -852,17 +826,17 @@ cmd 消息由服务端下发客户端解析。
}
// 任务恢复
-(void) resume {
[self.task resume];
(void) resume {
[self.task resume];
}
// 任务取消
-(void) cancel {
[self.task cancel];
(void) cancel {
[self.task cancel];
}
// 任务挂起
- (void)suspend {
(void)suspend {
[self.task suspend];
}
@ -899,37 +873,35 @@ cmd 消息由服务端下发客户端解析。
```
#### 第二步 编码解码
```objc
最终传递的消息内容为 {"type":3,"url":"xxxx","width":xxx,"height":xxx}
// 最终传递的消息内容为 {"type":3,"url":"xxxx","width":xxx,"height":xxx}
@implementation WKGIFContent
// 定义消息正文类型
+(NSInteger) contentType {
(NSInteger) contentType {
return 3;
}
// 发送消息时对消息内容编码
- (NSDictionary *)encodeWithJSON {
NSMutableDictionary *dataDict = [NSMutableDictionary dictionary];
[dataDict setObject:self.url?:@"" forKey:@"url"];
[dataDict setObject:@(self.width) forKey:@"width"];
[dataDict setObject:@(self.height) forKey:@"height"];
return dataDict;
(NSDictionary *)encodeWithJSON {
NSMutableDictionary *dataDict = [NSMutableDictionary dictionary];
[dataDict setObject:self.url?:@"" forKey:@"url"];
[dataDict setObject:@(self.width) forKey:@"width"];
[dataDict setObject:@(self.height) forKey:@"height"];
return dataDict;
}
// 收到消息时对消息内容解码
- (void)decodeWithJSON:(NSDictionary *)contentDic {
self.url = contentDic[@"url"];
self.width = contentDic[@"width"]?[contentDic[@"width"] integerValue]:100;
self.height = contentDic[@"height"]?[contentDic[@"height"] integerValue]:100;
(void)decodeWithJSON:(NSDictionary *)contentDic {
self.url = contentDic[@"url"];
self.width = contentDic[@"width"]?[contentDic[@"width"] integerValue]:100;
self.height = contentDic[@"height"]?[contentDic[@"height"] integerValue]:100;
}
// 最近会话显示的内容
- (NSString *)conversationDigest {
(NSString *)conversationDigest {
return @"[gif表情]"
}
@ -952,7 +924,7 @@ cmd 消息由服务端下发客户端解析。
注意这里时继承 WKMediaMessageContent 不是 WKMessageContent
最终传递的消息内容为 {"type":4,"url":"xxxx","width":xxx,"height":xxx}
最终传递的消息内容为 ```{"type":4,"url":"xxxx","width":xxx,"height":xxx}```
```objc
@ -967,36 +939,35 @@ cmd 消息由服务端下发客户端解析。
@end
```
#### 第二步编码解码和将需要上传的数据写入本地路径
```objc
@implementation WKImageContent
// 定义消息正文类型
+(NSInteger) contentType {
return 4;
(NSInteger) contentType {
return 4;
}
// 将图片数据写入到本地路径,这样后面的上传任务会将此路径的附件上传到服务器
- (void) writeDataToLocalPath {
[super writeDataToLocalPath];
[self.imageData writeToFile:self.localPath atomically:YES];
(void) writeDataToLocalPath {
[super writeDataToLocalPath];
[self.imageData writeToFile:self.localPath atomically:YES];
}
// 附件消息当附件上传成功后 会获取到上传后的self.remoteUrl下载地址我们只需要将此下载地址编码到json里附件的上传任务进度管理请查看 [WKSDK shared].mediaManager
- (NSDictionary *)encodeWithJSON {
NSMutableDictionary *dataDict = [NSMutableDictionary dictionary];
[dataDict setObject:self.remoteUrl?:@"" forKey:@"url"];
[dataDict setObject:@(self.width) forKey:@"width"];
[dataDict setObject:@(self.height) forKey:@"height"];
return dataDict;
(NSDictionary *)encodeWithJSON {
NSMutableDictionary *dataDict = [NSMutableDictionary dictionary];
[dataDict setObject:self.remoteUrl?:@"" forKey:@"url"];
[dataDict setObject:@(self.width) forKey:@"width"];
[dataDict setObject:@(self.height) forKey:@"height"];
return dataDict;
}
// 当收到消息需要解码这时候我们只需要将下载地址url 赋值给self.remoteUrl后 下载任务会通过self.remoteUrl的下载地址进行下载附件 附件的下载任务进度管理请查看 [WKSDK shared].mediaManager
- (void)decodeWithJSON:(NSDictionary *)contentDic {
self.remoteUrl = contentDic[@"url"];
self.width = contentDic[@"width"]?[contentDic[@"width"] floatValue]:0;
self.height = contentDic[@"height"]?[contentDic[@"height"] floatValue]:0;
(void)decodeWithJSON:(NSDictionary *)contentDic {
self.remoteUrl = contentDic[@"url"];
self.width = contentDic[@"width"]?[contentDic[@"width"] floatValue]:0;
self.height = contentDic[@"height"]?[contentDic[@"height"] floatValue]:0;
}
@ -1101,17 +1072,17 @@ cmd 消息由服务端下发客户端解析。
```objc
// 提交编辑内容。
[[[WKSDK shared] chatManager] setMessageEditProvider:^(WKMessageExtra * _Nonnull extra, WKMessageEditCallback _Nonnull callback) {
// 提交编辑内容。
[[[WKSDK shared] chatManager] setMessageEditProvider:^(WKMessageExtra * _Nonnull extra, WKMessageEditCallback _Nonnull callback) {
NSData *editContentData = extra.contentEditData; // 编辑后的正文数据
NSData *editContentData = extra.contentEditData; // 编辑后的正文数据
// 请求自己的app服务端
....
// 请求自己的app服务端
....
// 结果回调
callback(result);
}];
// 结果回调
callback(result);
}];
```
@ -1134,7 +1105,7 @@ WKMessage *messageEditAfter = [[WKSDK shared].chatManager editMessage:(WKMessage
// ---------- WKChatManagerDelegate ----------
-(void) onMessageUpdate:(WKMessage*) message left:(NSInteger)left {
(void) onMessageUpdate:(WKMessage*) message left:(NSInteger)left {
WKMessageContent *orgContent = message.content; // 原始正文
WKMessageContent *editContent = message.remoteExtra.contentEdit; // 编辑后的正文
}
@ -1175,7 +1146,7 @@ WKMessage *messageEditAfter = [[WKSDK shared].chatManager editMessage:(WKMessage
// ---------- WKReactionManagerDelegate ----------
-(void) reactionManagerChange:(WKReactionManager*)reactionManager reactions:(NSArray<WKReaction*>*)reactions channel:(WKChannel*)channel {
(void) reactionManagerChange:(WKReactionManager*)reactionManager reactions:(NSArray<WKReaction*>*)reactions channel:(WKChannel*)channel {
}
@ -1207,7 +1178,6 @@ setting.receiptEnabled = true // 开启端消息回执
}];
```
#### 数据操作
```objc
@ -1227,10 +1197,10 @@ setting.receiptEnabled = true // 开启端消息回执
@param message <#message description#>
@param left 消息剩余数量 可当left为0时再刷新UI
*/
-(void) onMessageUpdate:(WKMessage*) message left:(NSInteger)left {
if(message.remoteExtra.readed) {
NSLog(@"消息已读");
}
(void) onMessageUpdate:(WKMessage*) message left:(NSInteger)left {
if(message.remoteExtra.readed) {
NSLog(@"消息已读");
}
}
```
@ -1282,6 +1252,16 @@ setting.signal = true // 开启端对端加密 (目前只有个人频道才有
[[WKSDK shared].reminderManager done:(NSArray<NSNumber*>*)ids];
```
#### 数据操作
```objc
// 同步提醒
[[WKSDK shared].reminderManager sync];
// 提醒项已处理完成
[[WKSDK shared].reminderManager done:(NSArray<NSNumber*>*)ids];
```
#### 数据监听
```objc
@ -1289,7 +1269,7 @@ setting.signal = true // 开启端对端加密 (目前只有个人频道才有
// ---------- WKReminderManagerDelegate ----------
// 某个频道的reminders发生变化
-(void) reminderManager:(WKReminderManager*)manager didChange:(WKChannel*)channel reminders:(NSArray<WKReminder*>*) reminders {
(void) reminderManager:(WKReminderManager*)manager didChange:(WKChannel*)channel reminders:(NSArray<WKReminder*>*) reminders {
}

View File

@ -1,21 +1,13 @@
---
title: Javascript
order: 300
---
# Javascript
## 介绍
## 设计理念
像设计书的目录一样设计 api, 通过 WKSDK.shared().xxxManager 我们可以访问到所有需要的功能,例如发送消息 WKSDK.shared().chatManager.send(xxx)
### 设计理念
像设计书的目录一样设计 api, 通过 WKSDK.shared().xxxManager 我们可以访问到所有需要的功能,例如发送消息 `WKSDK.shared().chatManager.send(xxx)`
### 结构说明
## 结构说明
![sdk结构图](./wksdk.png)
```ts
``` js
// 聊天管理者
// 负责消息相关的增删改查操作 比如发送消息,删除消息,撤回消息,聊天消息的监听等等
WKSDK.shared().chatManager;
@ -36,28 +28,36 @@ WKSDK.shared().conversationManager;
// 负责最近会话的提醒事项维护
WKSDK.shared().reminderManager;
```
## 集成
### npm 或 yarn 引入
### 安装
```
$ npm i wukongimjssdk
::: code-group
``` sh [npm]
npm i wukongimjssdk
```
或者
``` sh [yarn]
yarn add wukongimjssdk
```
``` sh [pnpm]
pnpm add wukongimjssdk
```
$ yarn add wukongimjssdk
```
:::
### 引入
``` js
import { WKSDK } from "wukongimjssdk/lib/sdk"
```
### 初始化
```ts
``` js
// 集群模式通过此方法获取连接地址
// WKSDK.shared().config.provider.connectAddrCallback = async (callback: ConnectAddrCallback) => {
// const addr = await xxxx // addr 格式为 ip:port
@ -76,7 +76,7 @@ WKSDK.shared().config;
## 连接与断开
```ts
``` js
// 连接
WKSDK.shared().connectManager.connect();
@ -94,12 +94,10 @@ WKSDK.shared().connectManager.addConnectStatusListener(
},
);
```
## 在线消息收发
### 数据操作
#### 数据操作
```ts
``` js
/**
* 发送消息
* @param content 消息内容
@ -115,10 +113,9 @@ const text = new MessageText("hello")
WKSDK.shared().chatManager.send(text,new Channel("A",ChannelTypePerson))
```
### 数据监听
#### 数据监听
```ts
``` js
// 消息发送状态监听
WKSDK.shared().chatManager.addMessageStatusListener((packet: SendackPacket) => {
console.log('消息clientSeq->', packet.clientSeq); // 客户端序号用来匹配对应的发送的消息
@ -132,14 +129,11 @@ WKSDK.shared().chatManager.addMessageStatusListener((packet: SendackPacket) => {
// 消息监听
WKSDK.shared().chatManager.addMessageListener((message: Message) => {});
```
## 离线消息接收
在悟空 **IM**中为了应付海量离线消息,采用了按需拉取的机制,比如 10 个会话一个会话 10 万条消息,**悟空 IM** 不会把这个 **1010** 万=100 万条消息都拉取到本地。 而是采用拉取这 10 个会话的信息和对应的最新 20 条消息,也就是实际只拉取了 200 条消息 相对 100 万条消息来说大大提高了离线拉取速度。用户点进对应的会话才会去按需拉取这个会话的消息。 这些机制 SDK 内部都已做好了封装,使用者其实不需要关心。使用者只需要关心最近会话的变化
### 数据源设置
在**悟空 IM**中为了应付海量离线消息,采用了按需拉取的机制,比如 10 个会话一个会话 10 万条消息,\**悟空 IM 不会把这个 10*10 万=100 万条消息都拉取到本地。 而是采用拉取这 10 个会话的信息和对应的最新 20 条消息,也就是实际只拉取了 200 条消息 相对 100 万条消息来说大大提高了离线拉取速度。用户点进对应的会话才会去按需拉取这个会话的消息。 这些机制 SDK 内部都已做好了封装,使用者其实不需要关心。使用者只需要关心最近会话的变化
#### 数据源设置
```ts
``` js
// 提供最近会话同步的数据源
WKSDK.shared().config.provider.syncConversationsCallback = async (): Promise<Array<Conversation>> => {
@ -160,20 +154,18 @@ WKSDK.shared().config.provider.syncMessagesCallback = async(channel:Channel,opts
}
```
### 数据操作
##### 数据操作
```ts
``` js
// 同步最近会话会触发WKSDK.shared().config.provider.syncConversationsCallback
const conversations = await WKSDK.shared().conversationManager.sync({});
// 同步频道的消息会触发WKSDK.shared().config.provider.syncMessagesCallback
const messages = WKSDK.shared().chatManager.syncMessages(channel, opts);
```
### 数据监听
##### 数据监听
```ts
``` js
// 监听最近会话数据
WKSDK.shared().conversationManager.addConversationListener(
(conversation: Conversation, action: ConversationAction) => {
@ -182,10 +174,9 @@ WKSDK.shared().conversationManager.addConversationListener(
},
);
```
## 文本消息
```ts
``` ts
class MessageText extends MessageContent {
text?: string;
}
@ -193,7 +184,7 @@ class MessageText extends MessageContent {
## 图片消息
```ts
``` ts
class ImageContent extends MediaMessageContent {
width!: number; // 图片宽度
height!: number; // 图片高度
@ -208,22 +199,19 @@ class ImageContent extends MediaMessageContent {
```
## 语音消息
web 语音消息暂只支持收不支持发送
```ts
``` ts
class VoiceContent extends MediaMessageContent {
url!: string; // 语音文件下载地址
timeTrad!: number; // 语音秒长
waveform!: string; // 语音波纹 base64编码
}
```
## 小视频消息
web 语小视频消息暂只支持收不支持发送
```ts
``` ts
class VideoContent extends MessageContent {
url!: string; // 小视频下载地址
cover!: string; // 小视频封面图片下载地址
@ -233,10 +221,9 @@ class VideoContent extends MessageContent {
second!: number; // 小视频秒长
}
```
## 名片消息
```ts
``` ts
class Card extends MessageContent {
name!: string; // 好友名字
uid!: string; // 好友uid
@ -246,7 +233,7 @@ class Card extends MessageContent {
## 位置消息
```ts
``` ts
class LocationContent extends MessageContent {
lng: number = 0; // 纬度
lat: number = 0; // 经度
@ -257,26 +244,22 @@ class LocationContent extends MessageContent {
```
## CMD 消息
cmd 消息由服务端下发客户端解析执行。
```ts
``` ts
class CMDContent extends MessageContent {
cmd!: string; // cmd的指令
param: any; // 指令对应的参数
}
```
## 最近会话
最近会话用于表示会话列表页的数据模型。当用户发送,收取及删除消息时,都会同时去修改最近会话。
当收到或者一条消息时,会自动生成这个消息对应的最近会话。但值得注意的是最近会话和会话并不是一一对应的关系,删除最近会话并不影响会话
当收到或者一条消息时,会自动生成这个消息对应的最近会话。但值得注意的是最近会话和会话并不是一一对应的关系,删除最近会话并不影响会话
最近会话主要属性
```ts
``` ts
class Conversation {
channel!: Channel; // 频道
unread!: number; // 未读消息
@ -286,9 +269,7 @@ class Conversation {
reminders = new Array<Reminder>() // 提醒项
...
}
```
## 频道管理(置顶,免打扰等等)
[什么是频道](/guide/initialize#频道)
@ -318,10 +299,9 @@ class ChannelInfo {
orgData: any; // 频道原始数据由第三方自定义
}
```
### 数据源设置
#### 数据源设置
```ts
``` ts
// 频道详情获取数据源提供
WKSDK.shared().config.provider.channelInfoCallback = async function (channel: Channel): Promise<ChannelInfo> {
let channelInfo:ChannelInfo
@ -337,10 +317,9 @@ class ChannelInfo {
}
```
### 数据操作
#### 数据操作
```ts
``` ts
// 获取频道详情(不会触发数据源的远程获取)
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(channel);
@ -353,10 +332,9 @@ WKSDK.shared().channelManager.fetchChannelInfo(channel);
// 从远程提取频道列表(会触发数据源的远程获取和订阅者的监听,是异步过程)
WKSDK.shared().channelManager.syncSubscribes(channel);
```
### 数据监听
#### 数据监听
```ts
``` ts
// 监听频道详情
WKSDK.shared().channelManager.addListener((channelInfo: ChannelInfo) => {});
```
@ -364,73 +342,69 @@ WKSDK.shared().channelManager.addListener((channelInfo: ChannelInfo) => {});
## 进阶使用
### 消息附件上传设置
所有带附件的消息的上传都会通过此任务上传
伪代码如下:
```ts
``` ts
// 实现四个方法 initWithMessage resume cancel suspend
class MediaMessageUploadTask extends MessageTask {
- (instancetype)initWithMessage:(WKMessage *)message {
self = [super initWithMessage:message];
if(self) {
[self initTask];
}
- (instancetype)initWithMessage:(WKMessage *)message {
self = [super initWithMessage:message];
if(self) {
[self initTask];
}
return self;
}
}
async start(): Promise<void> {
const mediaContent = this.message.content as MediaMessageContent
const param = new FormData();
param.append("file", mediaContent.file);
const resp = await axios.post(uploadURL,param,{
headers: { "Content-Type": "multipart/form-data" },
cancelToken: new axios.CancelToken((c: Canceler) => {
this.canceler = c
}),
onUploadProgress: e => {
// 更新任务进度
var completeProgress = ((e.loaded / e.total) | 0);
this._progress = completeProgress
this.update()
}
}).catch(error => {
// 更新任务错误
console.log('文件上传失败!->', error);
this.status = TaskStatus.fail
this.update()
async start(): Promise<void> {
const mediaContent = this.message.content as MediaMessageContent
const param = new FormData();
param.append("file", mediaContent.file);
const resp = await axios.post(uploadURL,param,{
headers: { "Content-Type": "multipart/form-data" },
cancelToken: new axios.CancelToken((c: Canceler) => {
this.canceler = c
}),
onUploadProgress: e => {
// 更新任务进度
var completeProgress = ((e.loaded / e.total) | 0);
this._progress = completeProgress
this.update()
}
}).catch(error => {
// 更新任务错误
console.log('文件上传失败!->', error);
this.status = TaskStatus.fail
this.update()
})
if(resp) {
if(resp.data.path) {
// 更新任务成功
const mediaContent = this.message.content as MediaMessageContent
mediaContent.remoteUrl = resp.data.path
this.status = TaskStatus.success
this.update()
}
if(resp.data.path) {
// 更新任务成功
const mediaContent = this.message.content as MediaMessageContent
mediaContent.remoteUrl = resp.data.path
this.status = TaskStatus.success
this.update()
}
}
}
}
// 任务取消
cancel(): void {
this.status = TaskStatus.cancel
if(this.canceler) {
this.canceler()
}
this.update()
// 任务取消
cancel(): void {
this.status = TaskStatus.cancel
if(this.canceler) {
this.canceler()
}
this.update()
}
// 任务进度
progress(): number {
return this._progress??0
}
}
// 任务进度
progress(): number {
return this._progress??0
}
@end
```
注册上传任务
@ -442,11 +416,9 @@ WKSDK.shared().config.provider.messageUploadTaskCallback = (
return new MediaMessageUploadTask(message);
};
```
### 自定义普通消息
我们以自定义一个 gif 消息为例。
#### 第一步继承 MessageContent 和定义 gif 消息的正文结构
```ts
@ -461,7 +433,7 @@ class GifContent extends MessageContent {
```ts
最终传递的消息内容为 {"type":3,"url":"xxxx","width":xxx,"height":xxx}
// 最终传递的消息内容为 {"type":3,"url":"xxxx","width":xxx,"height":xxx}
class GifContent extends MessageContent {
width!: number // gif宽度
@ -482,7 +454,6 @@ class GifContent extends MessageContent {
}
```
#### 第三步 注册
```ts
@ -497,7 +468,7 @@ WKSDK.shared().register(MessageContentTypeConst.gif, () => new GifContent()); //
注意这里是继承 MediaMessageContent 不是 MessageContent当发送附件消息的时候sdk 会调用[上传任务](/web/onlysdk.html#消息附件上传设置),将本地的文件上传到服务器,然后再进行消息的编码和发送
最终传递的消息内容为 {"type":4,"url":"xxxx","width":xxx,"height":xxx}
最终传递的消息内容为 ```{"type":4,"url":"xxxx","width":xxx,"height":xxx}```
```ts
@ -507,7 +478,6 @@ class ImageContent : MediaMessageContent {
url!: string // gif远程下载地址
}
```
#### 第二步编码解码
```ts
@ -571,12 +541,12 @@ web 不支持端对端加密
会话提醒目前只支持服务端下发指令,客户端同步提醒然后显示提醒,会话提醒由 WKSDK.shared().reminderManager 管理
```ts
``` ts
class Reminder {
channel!: Channel;
reminderID!: number; // 提醒ID
messageID!: string;
messageSeq!: number;
channel: Channel;
reminderID: number; // 提醒ID
messageID: string;
messageSeq: number;
reminderType!: ReminderType; // 提醒类型
text?: string; // 文本提示
data?: any; // 提醒包含的自定义数据
@ -602,7 +572,6 @@ class Reminder {
}
```
###### 数据操作
```ts
@ -623,3 +592,4 @@ WKSDK.shared().conversationManager.addConversationListener(
},
);
```

View File

Before

Width:  |  Height:  |  Size: 591 KiB

After

Width:  |  Height:  |  Size: 591 KiB

View File

Before

Width:  |  Height:  |  Size: 335 KiB

After

Width:  |  Height:  |  Size: 335 KiB

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

BIN
src/sdk/wksdk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

View File

@ -1,14 +0,0 @@
{
"compilerOptions": {
"jsx": "react",
"jsx": "react",
"strict": true,
"skipLibCheck": true,
"esModuleInterop": true,
"baseUrl": "./",
"paths": {
"@@/*": [".dumi/tmp/*"]
}
},
"include": [".dumi/**/*", ".dumirc.ts"]
}

7
uno.config.ts Normal file
View File

@ -0,0 +1,7 @@
// eslint-disable-next-line no-restricted-imports
import { defineConfig, presetAttributify, presetIcons, presetUno, transformerDirectives } from "unocss";
export default defineConfig({
presets: [presetUno(), presetIcons(), presetAttributify()],
transformers: [transformerDirectives()],
});

File diff suppressed because it is too large Load Diff

10148
yarn.lock

File diff suppressed because it is too large Load Diff