feat: add VitePress docs-site with full SDK integration guides
- Add docs-site workspace (VitePress 1.5.0) with Android/iOS/RN/Vue3/HarmonyOS/Server docs - Update Dockerfile to build and serve docs under /docs/ - Add /docs/ location block to Nginx config - Add docs-site to yarn workspaces Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
946ed35813
当前提交
dadedbc4df
@ -5,6 +5,7 @@ COPY package.json ./package.json
|
||||
COPY yarn.lock ./yarn.lock
|
||||
COPY tenant-platform ./tenant-platform
|
||||
COPY ops-platform ./ops-platform
|
||||
COPY docs-site ./docs-site
|
||||
|
||||
RUN yarn install --frozen-lockfile
|
||||
|
||||
@ -19,7 +20,10 @@ RUN cd tenant-platform && \
|
||||
RUN cd ops-platform && \
|
||||
VITE_APP_BASE=${OPS_APP_BASE} VITE_API_BASE_URL=${OPS_API_BASE_URL} yarn build
|
||||
|
||||
RUN cd docs-site && yarn build
|
||||
|
||||
FROM nginx:1.27-alpine
|
||||
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /workspace/tenant-platform/dist /usr/share/nginx/html/tenant
|
||||
COPY --from=build /workspace/ops-platform/dist /usr/share/nginx/html/ops
|
||||
COPY --from=build /workspace/docs-site/docs/.vitepress/dist /usr/share/nginx/html/docs
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
import { defineConfig } from 'vitepress'
|
||||
|
||||
export default defineConfig({
|
||||
title: 'XuqmGroup 开发者文档',
|
||||
description: 'XuqmGroup 多端 SDK 接入指南',
|
||||
base: '/docs/',
|
||||
lang: 'zh-CN',
|
||||
|
||||
themeConfig: {
|
||||
logo: '/logo.svg',
|
||||
siteTitle: 'XuqmGroup Dev Docs',
|
||||
|
||||
nav: [
|
||||
{ text: '快速开始', link: '/guide/quickstart' },
|
||||
{
|
||||
text: 'SDK',
|
||||
items: [
|
||||
{ text: 'Android', link: '/android/' },
|
||||
{ text: 'iOS', link: '/ios/' },
|
||||
{ text: 'React Native', link: '/rn/' },
|
||||
{ text: 'Vue3', link: '/vue3/' },
|
||||
{ text: 'HarmonyOS', link: '/harmony/' },
|
||||
],
|
||||
},
|
||||
{ text: 'API 速查', link: '/server/api' },
|
||||
{ text: '平台控制台', link: 'https://sentry.xuqinmin.com', target: '_blank' },
|
||||
],
|
||||
|
||||
sidebar: {
|
||||
'/guide/': [
|
||||
{ text: '快速开始', link: '/guide/quickstart' },
|
||||
{ text: '平台概念', link: '/guide/concepts' },
|
||||
{ text: '接入流程', link: '/guide/flow' },
|
||||
],
|
||||
'/android/': [
|
||||
{ text: '概览', link: '/android/' },
|
||||
{ text: '安装配置', link: '/android/setup' },
|
||||
{ text: 'IM 接入', link: '/android/im' },
|
||||
{ text: '推送接入', link: '/android/push' },
|
||||
{ text: '版本管理', link: '/android/update' },
|
||||
{ text: 'API Reference', link: '/android/api' },
|
||||
],
|
||||
'/ios/': [
|
||||
{ text: '概览', link: '/ios/' },
|
||||
{ text: '安装配置', link: '/ios/setup' },
|
||||
{ text: 'IM 接入', link: '/ios/im' },
|
||||
{ text: '推送接入', link: '/ios/push' },
|
||||
{ text: '版本管理', link: '/ios/update' },
|
||||
{ text: 'API Reference', link: '/ios/api' },
|
||||
],
|
||||
'/rn/': [
|
||||
{ text: '概览', link: '/rn/' },
|
||||
{ text: '安装配置', link: '/rn/setup' },
|
||||
{ text: 'IM 接入', link: '/rn/im' },
|
||||
{ text: '群聊', link: '/rn/group' },
|
||||
{ text: '版本管理', link: '/rn/update' },
|
||||
{ text: 'API Reference', link: '/rn/api' },
|
||||
],
|
||||
'/vue3/': [
|
||||
{ text: '概览', link: '/vue3/' },
|
||||
{ text: '安装配置', link: '/vue3/setup' },
|
||||
{ text: 'IM 接入', link: '/vue3/im' },
|
||||
{ text: 'API Reference', link: '/vue3/api' },
|
||||
],
|
||||
'/harmony/': [
|
||||
{ text: '概览', link: '/harmony/' },
|
||||
{ text: '安装配置', link: '/harmony/setup' },
|
||||
{ text: 'IM 接入', link: '/harmony/im' },
|
||||
],
|
||||
'/server/': [
|
||||
{ text: 'API 速查', link: '/server/api' },
|
||||
{ text: 'WebSocket', link: '/server/websocket' },
|
||||
{ text: '错误码', link: '/server/errors' },
|
||||
],
|
||||
},
|
||||
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://xuqinmin.com/xuqinmin12' },
|
||||
],
|
||||
|
||||
footer: {
|
||||
message: 'XuqmGroup 开放平台',
|
||||
copyright: 'Copyright © 2026 XuqmGroup',
|
||||
},
|
||||
|
||||
search: { provider: 'local' },
|
||||
},
|
||||
})
|
||||
80
docs-site/docs/android/index.md
普通文件
80
docs-site/docs/android/index.md
普通文件
@ -0,0 +1,80 @@
|
||||
# Android SDK 概览
|
||||
|
||||
**版本**:0.1.0 · **最低 Android 版本**:API 24 (Android 7.0) · **语言**:Kotlin
|
||||
|
||||
## 功能模块
|
||||
|
||||
| 模块 | Artifact | 功能 |
|
||||
|------|----------|------|
|
||||
| sdk-core | `com.xuqm:sdk-core` | 初始化、网络、鉴权、设备信息 |
|
||||
| sdk-im | `com.xuqm:sdk-im` | 单聊、群聊、消息收发 |
|
||||
| sdk-push | `com.xuqm:sdk-push` | 设备 Token 注册、离线推送 |
|
||||
| sdk-update | `com.xuqm:sdk-update` | App 更新检查、RN 热更新 |
|
||||
|
||||
## 快速接入
|
||||
|
||||
### 1. 添加依赖
|
||||
|
||||
```kotlin
|
||||
// settings.gradle.kts
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
maven("https://nexus.xuqinmin.com/repository/android/")
|
||||
google(); mavenCentral()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```kotlin
|
||||
// app/build.gradle.kts
|
||||
dependencies {
|
||||
implementation("com.xuqm:sdk-core:0.1.0")
|
||||
implementation("com.xuqm:sdk-im:0.1.0") // 按需
|
||||
implementation("com.xuqm:sdk-update:0.1.0") // 按需
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 初始化
|
||||
|
||||
```kotlin
|
||||
// Application.onCreate()
|
||||
XuqmSDK.init(
|
||||
context = this,
|
||||
appKey = "your_app_id",
|
||||
appSecret = "your_app_secret", // 建议由服务端签发临时凭证
|
||||
apiBaseUrl = "https://sentry.xuqinmin.com",
|
||||
imBaseUrl = "wss://sentry.xuqinmin.com/ws/im",
|
||||
debug = BuildConfig.DEBUG
|
||||
)
|
||||
```
|
||||
|
||||
### 3. IM 登录与收消息
|
||||
|
||||
```kotlin
|
||||
// 先从你的服务端换取 IM Token,再登录
|
||||
ImSDK.login(
|
||||
appId = "your_app_id",
|
||||
userId = "user_001",
|
||||
nickname = "张三"
|
||||
)
|
||||
|
||||
// 监听事件
|
||||
ImSDK.addListener(object : ImEventListener {
|
||||
override fun onConnected() { /* WebSocket 已连接 */ }
|
||||
override fun onMessage(msg: ImMessage) { /* 处理收到的消息 */ }
|
||||
override fun onDisconnected(reason: String?) { /* 断线处理 */ }
|
||||
})
|
||||
```
|
||||
|
||||
### 4. 发送消息
|
||||
|
||||
```kotlin
|
||||
ImSDK.sendMessage(
|
||||
toId = "user_002",
|
||||
chatType = ChatType.SINGLE,
|
||||
msgType = MsgType.TEXT,
|
||||
content = "Hello!"
|
||||
)
|
||||
```
|
||||
|
||||
[→ 完整安装配置](./setup) · [→ IM 接入详解](./im) · [→ API Reference](./api)
|
||||
@ -0,0 +1,46 @@
|
||||
# 快速开始
|
||||
|
||||
5 分钟接入 XuqmGroup IM,实现消息收发。
|
||||
|
||||
## 1. 注册账号与创建应用
|
||||
|
||||
1. 访问 [XuqmGroup 控制台](https://sentry.xuqinmin.com)
|
||||
2. 注册租户账号,创建应用
|
||||
3. 记录 `appId`(即 `appKey`)
|
||||
|
||||
## 2. 选择你的平台
|
||||
|
||||
| 平台 | 推荐接入方式 |
|
||||
|------|------------|
|
||||
| Android | [Android SDK →](/android/) |
|
||||
| iOS | [iOS SDK →](/ios/) |
|
||||
| React Native | [RN SDK →](/rn/) |
|
||||
| Vue3 / Web | [Vue3 SDK →](/vue3/) |
|
||||
| HarmonyOS | [HarmonyOS SDK →](/harmony/) |
|
||||
|
||||
## 3. 演示环境
|
||||
|
||||
所有 SDK 均可直接连接演示环境验证功能:
|
||||
|
||||
```
|
||||
API 地址:https://sentry.xuqinmin.com
|
||||
WS 地址:wss://sentry.xuqinmin.com/ws/im
|
||||
演示 AppId:ak_demo_chat
|
||||
演示用户:demo_alice / demo_bob
|
||||
```
|
||||
|
||||
## 4. 接入流程
|
||||
|
||||
```
|
||||
你的业务服务端
|
||||
→ 持有 appId/appSecret
|
||||
→ 调用 POST /api/im/auth/login?appId=&userId=&nickname= 换取 IM Token
|
||||
→ 返回 Token 给客户端
|
||||
|
||||
客户端 SDK
|
||||
→ 使用 Token 初始化 IM 连接
|
||||
→ 建立 WebSocket 长连接
|
||||
→ 开始收发消息
|
||||
```
|
||||
|
||||
> **安全提示**:appSecret 应仅在你的服务端持有,不应下发给客户端。
|
||||
170
docs-site/docs/harmony/index.md
普通文件
170
docs-site/docs/harmony/index.md
普通文件
@ -0,0 +1,170 @@
|
||||
# HarmonyOS SDK 概览
|
||||
|
||||
**包名**:`@xuqm/harmony-sdk` · **版本**:0.1.0 · **支持**:HarmonyOS NEXT(API 12+)、ArkTS
|
||||
|
||||
## 功能模块
|
||||
|
||||
| 模块 | 功能 |
|
||||
|------|------|
|
||||
| `XuqmSDK` | 全局初始化 |
|
||||
| `ImSDK` | 单聊、群聊、消息收发 |
|
||||
| `UpdateSDK` | App 版本检查、RN Bundle 热更新 |
|
||||
|
||||
## 安装
|
||||
|
||||
在 `oh-package.json5` 中添加:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@xuqm/harmony-sdk": "0.1.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
配置私有仓库(`.ohpmrc`):
|
||||
|
||||
```
|
||||
registry=https://nexus.xuqinmin.com/repository/ohpm-hosted/
|
||||
```
|
||||
|
||||
执行安装:
|
||||
|
||||
```bash
|
||||
ohpm install
|
||||
```
|
||||
|
||||
## 快速接入
|
||||
|
||||
### 1. 初始化(EntryAbility.onCreate)
|
||||
|
||||
```typescript
|
||||
import { XuqmSDK } from '@xuqm/harmony-sdk'
|
||||
|
||||
export default class EntryAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
|
||||
XuqmSDK.init({
|
||||
appId: 'your_app_id',
|
||||
appKey: 'your_app_id',
|
||||
appSecret: 'your_app_secret',
|
||||
apiBaseUrl: 'https://sentry.xuqinmin.com',
|
||||
imWsUrl: 'wss://sentry.xuqinmin.com/ws/im',
|
||||
debug: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. IM 登录
|
||||
|
||||
```typescript
|
||||
import { ImSDK } from '@xuqm/harmony-sdk'
|
||||
|
||||
await ImSDK.login('user_001', '张三')
|
||||
```
|
||||
|
||||
### 3. 监听消息
|
||||
|
||||
```typescript
|
||||
ImSDK.addListener({
|
||||
onConnected(): void { console.log('WS connected') },
|
||||
onDisconnected(reason: string | null): void { },
|
||||
onMessage(msg: ImMessage): void { /* 处理消息 */ },
|
||||
onError(err: string): void { },
|
||||
})
|
||||
```
|
||||
|
||||
### 4. 发送消息
|
||||
|
||||
```typescript
|
||||
// 文本消息
|
||||
const sent = await ImSDK.sendMessage({
|
||||
toId: 'user_002',
|
||||
chatType: 'SINGLE',
|
||||
msgType: 'TEXT',
|
||||
content: 'Hello from HarmonyOS!',
|
||||
})
|
||||
|
||||
// 图片消息
|
||||
const sent = await ImSDK.sendMessage({
|
||||
toId: 'user_002', chatType: 'SINGLE',
|
||||
msgType: 'IMAGE',
|
||||
content: JSON.stringify({ url: 'https://cdn.example.com/img.jpg', width: 800, height: 600 }),
|
||||
})
|
||||
```
|
||||
|
||||
### 5. 撤回消息
|
||||
|
||||
```typescript
|
||||
const revoked = await ImSDK.revokeMessage(msg.id)
|
||||
```
|
||||
|
||||
### 6. 群聊
|
||||
|
||||
```typescript
|
||||
const group = await ImSDK.createGroup('鸿蒙群', ['user_001', 'user_002'])
|
||||
ImSDK.subscribeGroup(group.id)
|
||||
const sent = await ImSDK.sendMessage({ toId: group.id, chatType: 'GROUP', msgType: 'TEXT', content: '大家好' })
|
||||
```
|
||||
|
||||
### 7. 检查更新
|
||||
|
||||
```typescript
|
||||
import { UpdateSDK } from '@xuqm/harmony-sdk'
|
||||
|
||||
const appInfo = await UpdateSDK.checkAppUpdate(1)
|
||||
if (appInfo?.forceUpdate) {
|
||||
// 跳转应用市场
|
||||
}
|
||||
|
||||
const bundle = await UpdateSDK.checkRNUpdate('home', '1.0.0')
|
||||
if (bundle) {
|
||||
const content = await UpdateSDK.downloadBundle(bundle.downloadUrl)
|
||||
// 缓存至本地,由 BundleRuntime 加载
|
||||
}
|
||||
```
|
||||
|
||||
## ArkUI 示例
|
||||
|
||||
```typescript
|
||||
@Component
|
||||
struct ChatView {
|
||||
@State messages: ImMessage[] = []
|
||||
|
||||
aboutToAppear() {
|
||||
ImSDK.addListener({
|
||||
onMessage: (msg) => { this.messages = [...this.messages, msg] },
|
||||
onConnected: () => {},
|
||||
onDisconnected: () => {},
|
||||
onError: () => {},
|
||||
})
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
List() {
|
||||
ForEach(this.messages, (msg: ImMessage) => {
|
||||
ListItem() {
|
||||
Text(`${msg.fromUserId}: ${msg.content}`)
|
||||
.fontSize(16)
|
||||
.padding(8)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 权限配置
|
||||
|
||||
在 `module.json5` 中添加必要权限:
|
||||
|
||||
```json
|
||||
{
|
||||
"requestPermissions": [
|
||||
{ "name": "ohos.permission.INTERNET" },
|
||||
{ "name": "ohos.permission.GET_NETWORK_INFO" }
|
||||
]
|
||||
}
|
||||
```
|
||||
40
docs-site/docs/index.md
普通文件
40
docs-site/docs/index.md
普通文件
@ -0,0 +1,40 @@
|
||||
---
|
||||
layout: home
|
||||
hero:
|
||||
name: XuqmGroup
|
||||
text: 开发者文档
|
||||
tagline: 多端 SDK 一站式接入指南 · IM · 推送 · 版本管理
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 快速开始
|
||||
link: /guide/quickstart
|
||||
- theme: alt
|
||||
text: 平台控制台
|
||||
link: https://sentry.xuqinmin.com
|
||||
|
||||
features:
|
||||
- icon: 🤖
|
||||
title: Android SDK
|
||||
details: Kotlin 优先,支持 IM 单聊/群聊、离线推送、整包/热更新
|
||||
link: /android/
|
||||
- icon: 🍎
|
||||
title: iOS SDK
|
||||
details: Swift async/await,支持 IM、APNs 推送、版本管理
|
||||
link: /ios/
|
||||
- icon: ⚛️
|
||||
title: React Native SDK
|
||||
details: TypeScript,支持全 12 种消息类型、群聊、热更新
|
||||
link: /rn/
|
||||
- icon: 💚
|
||||
title: Vue3 SDK
|
||||
details: Composable API,useIm() 开箱即用
|
||||
link: /vue3/
|
||||
- icon: 🎵
|
||||
title: HarmonyOS SDK
|
||||
details: ArkTS,支持 IM 和基础推送能力
|
||||
link: /harmony/
|
||||
- icon: 🔌
|
||||
title: 服务端 API
|
||||
details: 完整 REST API 速查,WebSocket STOMP 协议说明
|
||||
link: /server/api
|
||||
---
|
||||
159
docs-site/docs/ios/index.md
普通文件
159
docs-site/docs/ios/index.md
普通文件
@ -0,0 +1,159 @@
|
||||
# iOS SDK 概览
|
||||
|
||||
**版本**:0.1.0 · **最低 iOS 版本**:iOS 14 · **语言**:Swift 5.9+
|
||||
|
||||
## 功能模块
|
||||
|
||||
| 模块 | 功能 |
|
||||
|------|------|
|
||||
| XuqmCore | 初始化、网络、鉴权 |
|
||||
| XuqmIM | 单聊、群聊、消息收发(13 种类型)|
|
||||
| XuqmPush | APNs 设备 Token 注册、通知处理 |
|
||||
| XuqmUpdate | App 版本检查、RN Bundle 热更新 |
|
||||
|
||||
## 安装
|
||||
|
||||
### Swift Package Manager(推荐)
|
||||
|
||||
在 Xcode → File → Add Package Dependencies 中输入:
|
||||
|
||||
```
|
||||
https://github.com/xuqm/XuqmGroup-iOSSDK
|
||||
```
|
||||
|
||||
或在 `Package.swift` 中添加:
|
||||
|
||||
```swift
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/xuqm/XuqmGroup-iOSSDK", from: "0.1.0")
|
||||
]
|
||||
```
|
||||
|
||||
按需引入所需模块:
|
||||
|
||||
```swift
|
||||
.target(
|
||||
name: "MyApp",
|
||||
dependencies: [
|
||||
.product(name: "XuqmCore", package: "XuqmGroup-iOSSDK"),
|
||||
.product(name: "XuqmIM", package: "XuqmGroup-iOSSDK"),
|
||||
.product(name: "XuqmUpdate", package: "XuqmGroup-iOSSDK"),
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
## 快速接入
|
||||
|
||||
### 1. 初始化
|
||||
|
||||
在 `AppDelegate.application(_:didFinishLaunchingWithOptions:)` 中:
|
||||
|
||||
```swift
|
||||
import XuqmCore
|
||||
|
||||
XuqmSDK.shared.initialize(
|
||||
appKey: "your_app_id",
|
||||
appSecret: "your_app_secret",
|
||||
apiBaseUrl: "https://sentry.xuqinmin.com",
|
||||
imWsUrl: "wss://sentry.xuqinmin.com/ws/im",
|
||||
debug: false
|
||||
)
|
||||
```
|
||||
|
||||
### 2. IM 登录与监听消息
|
||||
|
||||
```swift
|
||||
import XuqmIM
|
||||
|
||||
// 登录(appId 已在 init 时指定)
|
||||
try await ImSDK.shared.login(userId: "user_001", nickname: "张三")
|
||||
|
||||
// 监听事件
|
||||
ImSDK.shared.addListener(self)
|
||||
|
||||
extension ViewController: ImEventListener {
|
||||
func onConnected() { print("WS connected") }
|
||||
func onMessage(_ msg: ImMessage) { /* 处理消息 */ }
|
||||
func onDisconnected(reason: String?) { /* 断线 */ }
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 发送消息
|
||||
|
||||
```swift
|
||||
// 发文本
|
||||
let sent = try await ImSDK.shared.sendMessage(
|
||||
toId: "user_002",
|
||||
chatType: .single,
|
||||
msgType: .text,
|
||||
content: "Hello!"
|
||||
)
|
||||
|
||||
// 发图片(content 为 JSON 字符串)
|
||||
let imgContent = try JSONSerialization.data(withJSONObject: [
|
||||
"url": "https://cdn.example.com/img.jpg",
|
||||
"width": 800, "height": 600
|
||||
])
|
||||
let sent = try await ImSDK.shared.sendMessage(
|
||||
toId: "user_002", chatType: .single,
|
||||
msgType: .image, content: String(data: imgContent, encoding: .utf8)!
|
||||
)
|
||||
```
|
||||
|
||||
### 4. 撤回消息
|
||||
|
||||
```swift
|
||||
let revoked = try await ImSDK.shared.revokeMessage(messageId: msg.id)
|
||||
```
|
||||
|
||||
### 5. 群聊
|
||||
|
||||
```swift
|
||||
// 创建群组
|
||||
let group = try await ImSDK.shared.createGroup(name: "我的群", memberIds: ["user_001", "user_002"])
|
||||
|
||||
// 订阅群消息
|
||||
ImSDK.shared.subscribeGroup(groupId: group.id)
|
||||
|
||||
// 发送群消息
|
||||
try await ImSDK.shared.sendMessage(
|
||||
toId: group.id, chatType: .group, msgType: .text, content: "大家好"
|
||||
)
|
||||
```
|
||||
|
||||
### 6. 检查更新
|
||||
|
||||
```swift
|
||||
import XuqmUpdate
|
||||
|
||||
// App 整包更新
|
||||
let appInfo = try await UpdateSDK.shared.checkAppUpdate(currentVersionCode: 1)
|
||||
if let info = appInfo, info.forceUpdate {
|
||||
// 强制更新:跳转 App Store 或下载链接
|
||||
UIApplication.shared.open(URL(string: info.downloadUrl ?? info.appStoreUrl!)!)
|
||||
}
|
||||
|
||||
// RN Bundle 热更新
|
||||
let bundle = try await UpdateSDK.shared.checkRNUpdate(moduleId: "home", currentVersion: "1.0.0")
|
||||
if let bundle = bundle {
|
||||
let data = try await UpdateSDK.shared.downloadBundle(url: bundle.downloadUrl)
|
||||
// 缓存至本地,下次启动时由 BundleRuntime 加载
|
||||
}
|
||||
```
|
||||
|
||||
## 消息类型
|
||||
|
||||
| MsgType | 说明 | content 结构 |
|
||||
|---------|------|-------------|
|
||||
| `.text` | 纯文本 | `String` |
|
||||
| `.image` | 图片 | `{url, width, height, thumbnailUrl?}` |
|
||||
| `.video` | 视频 | `{url, duration, thumbnailUrl, size}` |
|
||||
| `.audio` | 语音 | `{url, duration, size}` |
|
||||
| `.file` | 文件 | `{url, name, size, mimeType}` |
|
||||
| `.location` | 位置 | `{lat, lng, address, title}` |
|
||||
| `.custom` | 自定义 | 任意 JSON |
|
||||
| `.notify` | 系统通知 | `{title, content, level}` |
|
||||
| `.richText` | 富文本 | `{html}` |
|
||||
| `.callAudio` | 语音通话信令 | `{callId, action, callerName}` |
|
||||
| `.callVideo` | 视频通话信令 | `{callId, action, callerName}` |
|
||||
| `.forward` | 转发 | `{originalMsgId, originalContent, originalSender}` |
|
||||
209
docs-site/docs/rn/index.md
普通文件
209
docs-site/docs/rn/index.md
普通文件
@ -0,0 +1,209 @@
|
||||
# React Native SDK 概览
|
||||
|
||||
**包名**:`@xuqm/rn-sdk` · **版本**:0.1.0 · **支持**:React Native 0.73+、Expo 50+
|
||||
|
||||
## 功能模块
|
||||
|
||||
| 导出 | 功能 |
|
||||
|------|------|
|
||||
| `XuqmSDK` | 全局初始化 |
|
||||
| `ImSDK` | 单聊、群聊、消息收发、历史记录 |
|
||||
| `UpdateSDK` | App 版本检查、RN Bundle 热更新 |
|
||||
| `PushSDK` | 设备 Token 上报 |
|
||||
|
||||
## 安装
|
||||
|
||||
### 从 Nexus 私有仓库安装
|
||||
|
||||
在项目根目录创建 `.npmrc`:
|
||||
|
||||
```
|
||||
@xuqm:registry=https://nexus.xuqinmin.com/repository/npm-hosted/
|
||||
```
|
||||
|
||||
然后安装:
|
||||
|
||||
```bash
|
||||
npm install @xuqm/rn-sdk
|
||||
# 或
|
||||
yarn add @xuqm/rn-sdk
|
||||
```
|
||||
|
||||
## 快速接入
|
||||
|
||||
### 1. 初始化(一次即可,在 App 启动时调用)
|
||||
|
||||
```ts
|
||||
import { XuqmSDK } from '@xuqm/rn-sdk'
|
||||
|
||||
XuqmSDK.init({
|
||||
appId: 'your_app_id',
|
||||
appKey: 'your_app_id',
|
||||
appSecret: 'your_app_secret',
|
||||
apiBaseUrl: 'https://sentry.xuqinmin.com',
|
||||
imWsUrl: 'wss://sentry.xuqinmin.com/ws/im',
|
||||
debug: __DEV__,
|
||||
})
|
||||
```
|
||||
|
||||
### 2. IM 登录
|
||||
|
||||
```ts
|
||||
import { ImSDK } from '@xuqm/rn-sdk'
|
||||
|
||||
await ImSDK.login('user_001', '张三')
|
||||
```
|
||||
|
||||
### 3. 监听消息与连接事件
|
||||
|
||||
```ts
|
||||
import type { ImEventListener } from '@xuqm/rn-sdk'
|
||||
|
||||
const listener: ImEventListener = {
|
||||
onConnected() { console.log('WS connected') },
|
||||
onDisconnected(reason) { console.log('WS disconnected:', reason) },
|
||||
onMessage(msg) { /* 单聊/群聊消息 */ },
|
||||
onGroupMessage(msg) { /* 群消息(独立回调) */ },
|
||||
onError(err) { console.error(err) },
|
||||
}
|
||||
|
||||
ImSDK.addListener(listener)
|
||||
|
||||
// 组件卸载时移除
|
||||
return () => {
|
||||
ImSDK.removeListener(listener)
|
||||
ImSDK.disconnect()
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 发送消息
|
||||
|
||||
```ts
|
||||
// 文本
|
||||
const sent = await ImSDK.sendMessage('user_002', 'SINGLE', 'TEXT', 'Hello!')
|
||||
|
||||
// 图片(content 为 JSON 字符串)
|
||||
const sent = await ImSDK.sendMessage('user_002', 'SINGLE', 'IMAGE', JSON.stringify({
|
||||
url: 'https://cdn.example.com/img.jpg',
|
||||
width: 800, height: 600,
|
||||
}))
|
||||
```
|
||||
|
||||
### 5. 撤回消息
|
||||
|
||||
```ts
|
||||
const revoked = await ImSDK.revokeMessage(msg.id)
|
||||
```
|
||||
|
||||
### 6. 拉取历史
|
||||
|
||||
```ts
|
||||
// 单聊历史(page=0, size=50)
|
||||
const history = await ImSDK.fetchHistory('user_002', 0, 50)
|
||||
|
||||
// 群历史
|
||||
const gHistory = await ImSDK.fetchGroupHistory(groupId, 0, 50)
|
||||
```
|
||||
|
||||
### 7. 群聊
|
||||
|
||||
```ts
|
||||
// 创建群(自动将自己加入成员列表)
|
||||
const group = await ImSDK.createGroup('开发讨论组', ['user_001', 'user_002'])
|
||||
|
||||
// 订阅群 WebSocket topic
|
||||
ImSDK.subscribeGroup(group.id)
|
||||
|
||||
// 列出所有群
|
||||
const groups = await ImSDK.listGroups()
|
||||
|
||||
// 发群消息
|
||||
const sent = await ImSDK.sendMessage(group.id, 'GROUP', 'TEXT', '大家好')
|
||||
```
|
||||
|
||||
### 8. 检查 App 更新
|
||||
|
||||
```ts
|
||||
import { UpdateSDK } from '@xuqm/rn-sdk'
|
||||
|
||||
const info = await UpdateSDK.checkAppUpdate(1 /* 当前 versionCode */)
|
||||
if (info) {
|
||||
console.log(info.versionName, info.forceUpdate, info.downloadUrl)
|
||||
}
|
||||
```
|
||||
|
||||
### 9. RN Bundle 热更新(三步流程)
|
||||
|
||||
```ts
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
||||
|
||||
// Step 1: 检查是否有新版本
|
||||
const bundle = await UpdateSDK.checkRNUpdate('home', '1.0.0')
|
||||
if (!bundle) return // 已是最新
|
||||
|
||||
// Step 2: 下载 bundle
|
||||
const content = await UpdateSDK.downloadBundle(bundle.downloadUrl)
|
||||
|
||||
// Step 3: 缓存,下次启动由 BundleRuntime 加载
|
||||
await AsyncStorage.setItem('rn_bundle_home', JSON.stringify({
|
||||
version: bundle.version,
|
||||
md5: bundle.md5,
|
||||
content,
|
||||
cachedAt: new Date().toISOString(),
|
||||
}))
|
||||
```
|
||||
|
||||
> **提示**:运行时替换(热加载)需对接原生 `BundleRuntime`,参考 `ProjectFrameReactNative` 架构文档。
|
||||
|
||||
## 完整消息类型
|
||||
|
||||
```ts
|
||||
type MsgType =
|
||||
| 'TEXT' | 'IMAGE' | 'VIDEO' | 'AUDIO' | 'FILE'
|
||||
| 'CUSTOM' | 'LOCATION' | 'NOTIFY' | 'RICH_TEXT'
|
||||
| 'CALL_AUDIO' | 'CALL_VIDEO' | 'FORWARD' | 'REVOKED'
|
||||
```
|
||||
|
||||
每种类型的 `content` 格式:
|
||||
|
||||
| MsgType | content |
|
||||
|---------|---------|
|
||||
| `TEXT` | 纯文本字符串 |
|
||||
| `IMAGE` | `{"url":"...","width":800,"height":600,"thumbnailUrl":"..."}` |
|
||||
| `VIDEO` | `{"url":"...","duration":30,"thumbnailUrl":"...","size":1048576}` |
|
||||
| `AUDIO` | `{"url":"...","duration":12,"size":204800}` |
|
||||
| `FILE` | `{"url":"...","name":"report.pdf","size":512000,"mimeType":"application/pdf"}` |
|
||||
| `LOCATION` | `{"lat":39.9042,"lng":116.4074,"address":"北京市东城区","title":"天安门"}` |
|
||||
| `CUSTOM` | 任意 JSON 字符串 |
|
||||
| `NOTIFY` | `{"title":"系统通知","content":"服务器维护","level":"INFO"}` |
|
||||
| `RICH_TEXT` | `{"html":"<b>加粗</b>内容"}` |
|
||||
| `CALL_AUDIO` | `{"callId":"uuid","action":"INVITE","callerName":"张三"}` |
|
||||
| `CALL_VIDEO` | `{"callId":"uuid","action":"INVITE","callerName":"张三"}` |
|
||||
| `FORWARD` | `{"originalMsgId":"...","originalContent":"原始内容","originalSender":"张三"}` |
|
||||
| `REVOKED` | 服务端下发,客户端只读 |
|
||||
|
||||
## TypeScript 类型定义
|
||||
|
||||
```ts
|
||||
interface ImMessage {
|
||||
id: string
|
||||
appId: string
|
||||
fromUserId: string
|
||||
toId: string
|
||||
chatType: 'SINGLE' | 'GROUP'
|
||||
msgType: MsgType
|
||||
content: string
|
||||
status: 'SENT' | 'REVOKED'
|
||||
createdAt: string // ISO 8601
|
||||
}
|
||||
|
||||
interface ImGroup {
|
||||
id: string
|
||||
appId: string
|
||||
name: string
|
||||
creatorId: string
|
||||
memberIds: string[]
|
||||
adminIds: string[]
|
||||
createdAt: string
|
||||
}
|
||||
```
|
||||
267
docs-site/docs/server/api.md
普通文件
267
docs-site/docs/server/api.md
普通文件
@ -0,0 +1,267 @@
|
||||
# Server API 参考
|
||||
|
||||
**Base URL**:`https://sentry.xuqinmin.com`
|
||||
|
||||
所有 API 通过 Nginx 反代,无需区分内部端口。
|
||||
|
||||
## 认证
|
||||
|
||||
除 `/api/im/auth/login` 外,所有 IM 接口需在请求头携带 JWT Token:
|
||||
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
Token 由 `/api/im/auth/login` 接口签发。
|
||||
|
||||
---
|
||||
|
||||
## IM 服务(/api/im/)
|
||||
|
||||
### 登录 · 获取 Token
|
||||
|
||||
```
|
||||
POST /api/im/auth/login
|
||||
```
|
||||
|
||||
**Query 参数**
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `appId` | 是 | 应用 ID |
|
||||
| `userId` | 是 | 用户 ID |
|
||||
| `nickname` | 是 | 昵称 |
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{ "token": "eyJ..." }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### WebSocket 连接
|
||||
|
||||
```
|
||||
WSS /ws/im?token=<token>&appId=<appId>
|
||||
```
|
||||
|
||||
- 协议:STOMP over WebSocket
|
||||
- 单聊订阅:`/user/{userId}/queue/messages`
|
||||
- 群聊订阅:`/topic/group/{groupId}`
|
||||
|
||||
---
|
||||
|
||||
### 发送消息
|
||||
|
||||
```
|
||||
POST /api/im/messages
|
||||
Authorization: Bearer <token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**请求体**
|
||||
|
||||
```json
|
||||
{
|
||||
"toId": "user_002",
|
||||
"chatType": "SINGLE",
|
||||
"msgType": "TEXT",
|
||||
"content": "Hello!"
|
||||
}
|
||||
```
|
||||
|
||||
`chatType`:`SINGLE` | `GROUP`
|
||||
|
||||
`msgType`:`TEXT` | `IMAGE` | `VIDEO` | `AUDIO` | `FILE` | `CUSTOM` | `LOCATION` | `NOTIFY` | `RICH_TEXT` | `CALL_AUDIO` | `CALL_VIDEO` | `FORWARD`
|
||||
|
||||
**响应**:`ImMessage` 对象
|
||||
|
||||
---
|
||||
|
||||
### 撤回消息
|
||||
|
||||
```
|
||||
PUT /api/im/messages/{messageId}/revoke
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**响应**:更新后的 `ImMessage`(`status: "REVOKED"`,`msgType: "REVOKED"`)
|
||||
|
||||
---
|
||||
|
||||
### 消息历史(单聊)
|
||||
|
||||
```
|
||||
GET /api/im/messages/history?appId=&userId=&toId=&page=0&size=50
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**响应**:分页 `ImMessage` 列表
|
||||
|
||||
---
|
||||
|
||||
### 创建群组
|
||||
|
||||
```
|
||||
POST /api/im/groups
|
||||
Authorization: Bearer <token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"appId": "ak_demo_chat",
|
||||
"name": "开发群",
|
||||
"memberIds": ["user_001", "user_002"]
|
||||
}
|
||||
```
|
||||
|
||||
**响应**:`ImGroup` 对象
|
||||
|
||||
---
|
||||
|
||||
### 获取群列表
|
||||
|
||||
```
|
||||
GET /api/im/groups?appId=ak_demo_chat
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 添加群成员
|
||||
|
||||
```
|
||||
POST /api/im/groups/{groupId}/members
|
||||
Authorization: Bearer <token>
|
||||
Content-Type: application/json
|
||||
|
||||
{ "userId": "user_003" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 移除群成员
|
||||
|
||||
```
|
||||
DELETE /api/im/groups/{groupId}/members/{targetUserId}
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 版本管理服务(/api/v1/updates/ 和 /api/v1/rn/)
|
||||
|
||||
### 检查 App 更新
|
||||
|
||||
```
|
||||
GET /api/v1/updates/check?appId=&platform=ANDROID&versionCode=1
|
||||
```
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"hasUpdate": true,
|
||||
"versionCode": 2,
|
||||
"versionName": "1.0.1",
|
||||
"forceUpdate": false,
|
||||
"downloadUrl": "https://cdn.example.com/app.apk",
|
||||
"appStoreUrl": null,
|
||||
"releaseNotes": "修复若干问题"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 检查 RN Bundle 热更新
|
||||
|
||||
```
|
||||
GET /api/v1/rn/check?appId=&moduleId=home&version=1.0.0&platform=ANDROID
|
||||
```
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"hasUpdate": true,
|
||||
"version": "1.0.1",
|
||||
"downloadUrl": "https://cdn.example.com/bundles/home_1.0.1.bundle",
|
||||
"md5": "a1b2c3d4...",
|
||||
"size": 204800
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 下载 Bundle
|
||||
|
||||
`downloadUrl` 返回的 URL 可直接 `GET` 下载,响应体为 bundle 二进制内容。
|
||||
|
||||
---
|
||||
|
||||
## 租户服务(/api/)
|
||||
|
||||
### 创建应用(租户管理后台调用)
|
||||
|
||||
```
|
||||
POST /api/apps
|
||||
Authorization: Bearer <tenant_token>
|
||||
Content-Type: application/json
|
||||
|
||||
{ "name": "我的 App", "platform": "ANDROID" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据模型
|
||||
|
||||
### ImMessage
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"appId": "ak_demo_chat",
|
||||
"fromUserId": "user_001",
|
||||
"toId": "user_002",
|
||||
"chatType": "SINGLE",
|
||||
"msgType": "TEXT",
|
||||
"content": "Hello!",
|
||||
"status": "SENT",
|
||||
"mentionedUserIds": [],
|
||||
"createdAt": "2026-04-24T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
### ImGroup
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "group_uuid",
|
||||
"appId": "ak_demo_chat",
|
||||
"name": "开发群",
|
||||
"creatorId": "user_001",
|
||||
"memberIds": ["user_001", "user_002"],
|
||||
"adminIds": ["user_001"],
|
||||
"createdAt": "2026-04-24T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 错误码
|
||||
|
||||
| HTTP 状态 | code | 说明 |
|
||||
|-----------|------|------|
|
||||
| 400 | 400 | 请求参数错误 |
|
||||
| 401 | 401 | Token 无效或过期 |
|
||||
| 403 | 403 | 无权限操作(如撤回他人消息)|
|
||||
| 404 | 404 | 资源不存在 |
|
||||
| 500 | 500 | 服务器内部错误 |
|
||||
|
||||
错误响应格式:
|
||||
|
||||
```json
|
||||
{ "code": 403, "message": "只能撤回自己发送的消息" }
|
||||
```
|
||||
149
docs-site/docs/vue3/index.md
普通文件
149
docs-site/docs/vue3/index.md
普通文件
@ -0,0 +1,149 @@
|
||||
# Vue3 SDK 概览
|
||||
|
||||
**包名**:`@xuqm/vue3-sdk` · **版本**:0.1.0 · **支持**:Vue 3.4+、Vite 5+
|
||||
|
||||
## 功能模块
|
||||
|
||||
| 导出 | 功能 |
|
||||
|------|------|
|
||||
| `useXuqm()` | 全局初始化 Composable |
|
||||
| `useIm()` | IM 单聊/群聊响应式状态 |
|
||||
| `useUpdate()` | 版本检查与热更新 |
|
||||
| `XuqmProvider` | 可选根组件(自动初始化)|
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
npm install @xuqm/vue3-sdk
|
||||
```
|
||||
|
||||
从私有 Nexus 安装时,在 `.npmrc` 中添加:
|
||||
|
||||
```
|
||||
@xuqm:registry=https://nexus.xuqinmin.com/repository/npm-hosted/
|
||||
```
|
||||
|
||||
## 快速接入
|
||||
|
||||
### 1. 全局初始化(main.ts)
|
||||
|
||||
```ts
|
||||
import { createApp } from 'vue'
|
||||
import { createXuqm } from '@xuqm/vue3-sdk'
|
||||
import App from './App.vue'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(createXuqm({
|
||||
appId: 'your_app_id',
|
||||
appKey: 'your_app_id',
|
||||
appSecret: 'your_app_secret',
|
||||
apiBaseUrl: 'https://sentry.xuqinmin.com',
|
||||
imWsUrl: 'wss://sentry.xuqinmin.com/ws/im',
|
||||
debug: import.meta.env.DEV,
|
||||
}))
|
||||
|
||||
app.mount('#app')
|
||||
```
|
||||
|
||||
### 2. IM 登录与消息监听
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import { useIm } from '@xuqm/vue3-sdk'
|
||||
|
||||
const { messages, connected, login, sendMessage, revokeMessage } = useIm()
|
||||
|
||||
onMounted(() => login('user_001', '张三'))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<span :class="connected ? 'green' : 'gray'">
|
||||
{{ connected ? '已连接' : '未连接' }}
|
||||
</span>
|
||||
<div v-for="msg in messages" :key="msg.id">
|
||||
<b>{{ msg.fromUserId }}</b>: {{ msg.content }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 3. 发送消息
|
||||
|
||||
```ts
|
||||
// 文本
|
||||
await sendMessage('user_002', 'SINGLE', 'TEXT', 'Hello!')
|
||||
|
||||
// 图片
|
||||
await sendMessage('user_002', 'SINGLE', 'IMAGE', JSON.stringify({
|
||||
url: 'https://cdn.example.com/img.jpg',
|
||||
width: 1200, height: 800,
|
||||
}))
|
||||
```
|
||||
|
||||
### 4. 撤回消息
|
||||
|
||||
```ts
|
||||
const revoked = await revokeMessage(msg.id)
|
||||
```
|
||||
|
||||
### 5. 群聊
|
||||
|
||||
```ts
|
||||
const { createGroup, listGroups, subscribeGroup, groupMessages } = useIm()
|
||||
|
||||
// 创建群
|
||||
const group = await createGroup('开发群', ['user_001', 'user_002'])
|
||||
|
||||
// 订阅群消息
|
||||
subscribeGroup(group.id)
|
||||
|
||||
// 发群消息
|
||||
await sendMessage(group.id, 'GROUP', 'TEXT', '大家好')
|
||||
```
|
||||
|
||||
### 6. 检查 App/RN 更新
|
||||
|
||||
```ts
|
||||
import { useUpdate } from '@xuqm/vue3-sdk'
|
||||
|
||||
const { checkAppUpdate, checkRNUpdate } = useUpdate()
|
||||
|
||||
const appInfo = await checkAppUpdate(1) // 当前 versionCode
|
||||
const rnBundle = await checkRNUpdate('home', '1.0.0')
|
||||
```
|
||||
|
||||
## 响应式状态
|
||||
|
||||
`useIm()` 返回的响应式 ref:
|
||||
|
||||
```ts
|
||||
const {
|
||||
messages, // Ref<ImMessage[]> 单聊消息列表
|
||||
groupMessages, // Ref<ImMessage[]> 当前群消息列表
|
||||
connected, // Ref<boolean> WS 连接状态
|
||||
currentUser, // Ref<string | null> 当前登录用户
|
||||
} = useIm()
|
||||
```
|
||||
|
||||
## 消息气泡组件(内置)
|
||||
|
||||
SDK 内置基础气泡组件,开箱即用:
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { ImMessageBubble } from '@xuqm/vue3-sdk'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ImMessageBubble
|
||||
v-for="msg in messages"
|
||||
:key="msg.id"
|
||||
:message="msg"
|
||||
:is-own="msg.fromUserId === currentUser"
|
||||
@revoke="revokeMessage(msg.id)"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
13
docs-site/package.json
普通文件
13
docs-site/package.json
普通文件
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "@xuqm/docs-site",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vitepress dev docs",
|
||||
"build": "vitepress build docs",
|
||||
"preview": "vitepress preview docs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vitepress": "^1.5.0"
|
||||
}
|
||||
}
|
||||
@ -13,4 +13,9 @@ server {
|
||||
alias /usr/share/nginx/html/ops/;
|
||||
try_files $uri $uri/ /ops/index.html;
|
||||
}
|
||||
|
||||
location /docs/ {
|
||||
alias /usr/share/nginx/html/docs/;
|
||||
try_files $uri $uri/ /docs/index.html;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,13 @@
|
||||
"packageManager": "yarn@1.22.22",
|
||||
"workspaces": [
|
||||
"tenant-platform",
|
||||
"ops-platform"
|
||||
"ops-platform",
|
||||
"docs-site"
|
||||
],
|
||||
"scripts": {
|
||||
"dev:tenant": "yarn workspace tenant-platform dev",
|
||||
"dev:ops": "yarn workspace ops-platform dev",
|
||||
"dev:docs": "yarn workspace docs-site dev",
|
||||
"build": "yarn workspaces run build"
|
||||
}
|
||||
}
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户