feat: ops租户筛选 + 服务去平台化 + 补全Flutter/H5/小程序文档
- AppListView: 添加租户模糊搜索筛选,显示租户名称 - AppDetailView: 功能服务表去掉平台列,按服务类型展示 - ops.ts: listApps 支持 tenantId 参数,AppItem 添加 tenantName - 新增 Flutter/H5/小程序 setup.md 和 im.md 文档 - config.ts: sidebar 添加 Flutter/H5/小程序子页面 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
这个提交包含在:
父节点
ceb22c6286
当前提交
65914b0ec2
@ -69,6 +69,8 @@ export default defineConfig({
|
|||||||
],
|
],
|
||||||
'/flutter/': [
|
'/flutter/': [
|
||||||
{ text: '概览', link: '/flutter/' },
|
{ text: '概览', link: '/flutter/' },
|
||||||
|
{ text: '安装配置', link: '/flutter/setup' },
|
||||||
|
{ text: 'IM 接入', link: '/flutter/im' },
|
||||||
],
|
],
|
||||||
'/harmony/': [
|
'/harmony/': [
|
||||||
{ text: '概览', link: '/harmony/' },
|
{ text: '概览', link: '/harmony/' },
|
||||||
@ -79,9 +81,13 @@ export default defineConfig({
|
|||||||
],
|
],
|
||||||
'/miniprogram/': [
|
'/miniprogram/': [
|
||||||
{ text: '概览', link: '/miniprogram/' },
|
{ text: '概览', link: '/miniprogram/' },
|
||||||
|
{ text: '安装配置', link: '/miniprogram/setup' },
|
||||||
|
{ text: 'IM 接入', link: '/miniprogram/im' },
|
||||||
],
|
],
|
||||||
'/h5/': [
|
'/h5/': [
|
||||||
{ text: '概览', link: '/h5/' },
|
{ text: '概览', link: '/h5/' },
|
||||||
|
{ text: '安装配置', link: '/h5/setup' },
|
||||||
|
{ text: 'IM 接入', link: '/h5/im' },
|
||||||
],
|
],
|
||||||
'/server/': [
|
'/server/': [
|
||||||
{ text: 'API 速查', link: '/server/api' },
|
{ text: 'API 速查', link: '/server/api' },
|
||||||
|
|||||||
183
docs-site/docs/flutter/im.md
普通文件
183
docs-site/docs/flutter/im.md
普通文件
@ -0,0 +1,183 @@
|
|||||||
|
# Flutter IM 接入
|
||||||
|
|
||||||
|
**模块**:`xuqm_flutter_im` · **最低版本**:Dart 3.0+
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 登录
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:xuqm_flutter_sdk/xuqm_flutter_sdk.dart';
|
||||||
|
|
||||||
|
await XuqmImSdk().login('user_001', 'your_user_sig_jwt');
|
||||||
|
```
|
||||||
|
|
||||||
|
登录成功后会自动建立 IM 实时连接。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 监听消息
|
||||||
|
|
||||||
|
```dart
|
||||||
|
final im = XuqmImSdk();
|
||||||
|
|
||||||
|
im.ws.onConnected = () {
|
||||||
|
print('IM 已连接');
|
||||||
|
};
|
||||||
|
|
||||||
|
im.ws.onMessage = (XuqmImMessage msg) {
|
||||||
|
print('收到消息: ${msg.msgType} - ${msg.content}');
|
||||||
|
};
|
||||||
|
|
||||||
|
im.ws.onDisconnected = (String? reason) {
|
||||||
|
print('IM 断开: $reason');
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 发送消息
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// 发送文本消息
|
||||||
|
final msg = await im.sendTextMessage(
|
||||||
|
'user_002',
|
||||||
|
'SINGLE',
|
||||||
|
'Hello from Flutter!',
|
||||||
|
);
|
||||||
|
|
||||||
|
// 发送图片消息
|
||||||
|
final imgMsg = await im.sendMessage(
|
||||||
|
'user_002',
|
||||||
|
'SINGLE',
|
||||||
|
'IMAGE',
|
||||||
|
jsonEncode({'url': 'https://cdn.example.com/img.jpg', 'width': 800, 'height': 600}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 撤回消息
|
||||||
|
await im.revokeMessage(msg.id);
|
||||||
|
|
||||||
|
// 编辑消息
|
||||||
|
await im.editMessage(msg.id, '新内容');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 会话管理
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// 会话列表
|
||||||
|
final conversations = await im.listConversations();
|
||||||
|
|
||||||
|
// 置顶会话
|
||||||
|
await im.setConversationPinned('user_002', 'SINGLE', true);
|
||||||
|
|
||||||
|
// 免打扰
|
||||||
|
await im.setConversationMuted('group_xxx', 'GROUP', true);
|
||||||
|
|
||||||
|
// 标记已读
|
||||||
|
await im.markRead('user_002');
|
||||||
|
|
||||||
|
// 设置草稿
|
||||||
|
await im.setDraft('user_002', 'SINGLE', '未完成的消息');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 好友与群组
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// 好友列表
|
||||||
|
final friends = await im.listFriends();
|
||||||
|
|
||||||
|
// 添加好友
|
||||||
|
await im.addFriend('user_002');
|
||||||
|
|
||||||
|
// 移除好友
|
||||||
|
await im.removeFriend('user_002');
|
||||||
|
|
||||||
|
// 创建群组
|
||||||
|
final group = await im.createGroup('Flutter 群', ['user_001', 'user_002']);
|
||||||
|
|
||||||
|
// 群组列表
|
||||||
|
final groups = await im.listGroups();
|
||||||
|
|
||||||
|
// 添加群成员
|
||||||
|
await im.addGroupMember(group.id, 'user_003');
|
||||||
|
|
||||||
|
// 退出群聊
|
||||||
|
await im.leaveGroup(group.id);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 历史消息
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// 单聊历史
|
||||||
|
final history = await im.fetchHistory('user_002', page: 0, size: 20);
|
||||||
|
|
||||||
|
// 群聊历史
|
||||||
|
final groupHistory = await im.fetchGroupHistory('group_xxx', page: 0, size: 50);
|
||||||
|
|
||||||
|
// 定位消息所在页
|
||||||
|
final page = await im.locateHistoryPage(
|
||||||
|
'user_002',
|
||||||
|
messageId: 'msg_xxx',
|
||||||
|
pageSize: 20,
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 完整示例
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:xuqm_flutter_sdk/xuqm_flutter_sdk.dart';
|
||||||
|
|
||||||
|
class ChatPage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ChatPageState createState() => _ChatPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChatPageState extends State<ChatPage> {
|
||||||
|
final im = XuqmImSdk();
|
||||||
|
final List<XuqmImMessage> messages = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _init() async {
|
||||||
|
await XuqmSDK.initialize(XuqmInitOptions(appKey: 'your_app_key'));
|
||||||
|
await im.login('user_001', 'your_user_sig_jwt');
|
||||||
|
|
||||||
|
im.ws.onMessage = (msg) {
|
||||||
|
setState(() => messages.add(msg));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _send(String text) async {
|
||||||
|
final msg = await im.sendTextMessage('user_002', 'SINGLE', text);
|
||||||
|
setState(() => messages.add(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: Text('Flutter IM')),
|
||||||
|
body: ListView.builder(
|
||||||
|
itemCount: messages.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final msg = messages[index];
|
||||||
|
return ListTile(title: Text('${msg.fromId}: ${msg.content}'));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
68
docs-site/docs/flutter/setup.md
普通文件
68
docs-site/docs/flutter/setup.md
普通文件
@ -0,0 +1,68 @@
|
|||||||
|
# Flutter 安装配置
|
||||||
|
|
||||||
|
**包名**:`xuqm_flutter_sdk` · **版本**:0.2.x · **语言**:Dart
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
SDK 通过 Gitea Git 仓库发布,在 `pubspec.yaml` 中配置:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
dependencies:
|
||||||
|
xuqm_flutter_sdk:
|
||||||
|
git:
|
||||||
|
url: https://xuqinmin.com/xuqinmin12/XuqmGroup-FlutterSDK.git
|
||||||
|
ref: v0.2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
> Gitea Package Registry 暂不支持 Dart/Flutter 包格式,因此通过 Git Tag 方式发布。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 模块说明
|
||||||
|
|
||||||
|
| 模块 | 包 | 功能 |
|
||||||
|
|------|-----|------|
|
||||||
|
| `xuqm_flutter_common` | `packages/common` | 初始化、网络、配置管理 |
|
||||||
|
| `xuqm_flutter_im` | `packages/im` | 单聊、群聊、消息收发、会话、好友、群组 |
|
||||||
|
| `xuqm_flutter_push` | `packages/push` | 设备 Token 注册、厂商检测(Android)/ APNs(iOS)|
|
||||||
|
| `xuqm_flutter_update` | `packages/update` | App 版本检查、商店跳转、APK 下载(Android)|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 初始化
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:xuqm_flutter_sdk/xuqm_flutter_sdk.dart';
|
||||||
|
|
||||||
|
await XuqmSDK.initialize(XuqmInitOptions(
|
||||||
|
appKey: 'your_app_key',
|
||||||
|
debug: true,
|
||||||
|
));
|
||||||
|
```
|
||||||
|
|
||||||
|
初始化时会自动向服务端请求远程配置(IM API 地址等),若网络异常则回退到内置默认值。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 多模块统一登录
|
||||||
|
|
||||||
|
无论集成了哪些模块(IM、Push、Update),**初始化和登录永远只做一次**:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// 初始化
|
||||||
|
await XuqmSDK.initialize(XuqmInitOptions(appKey: 'your_app_key'));
|
||||||
|
|
||||||
|
// 登录(业务登录成功后调用一次)
|
||||||
|
await XuqmImSdk().login('user_001', 'your_user_sig_jwt');
|
||||||
|
|
||||||
|
// 登出
|
||||||
|
await XuqmImSdk().logout();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
- [Flutter IM 接入 →](./im)
|
||||||
156
docs-site/docs/h5/im.md
普通文件
156
docs-site/docs/h5/im.md
普通文件
@ -0,0 +1,156 @@
|
|||||||
|
# H5 IM 接入
|
||||||
|
|
||||||
|
**模块**:`@xuqm/h5-sdk` · **功能范围**:消息收发、会话管理、好友、群组
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## IM 管理器
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ImManager } from '@xuqm/h5-sdk'
|
||||||
|
|
||||||
|
const im = new ImManager()
|
||||||
|
|
||||||
|
// 监听连接状态
|
||||||
|
im.on('connected', () => console.log('IM 已连接'))
|
||||||
|
im.on('disconnected', () => console.log('IM 已断开'))
|
||||||
|
|
||||||
|
// 监听实时消息
|
||||||
|
im.on('messages', (msgs) => {
|
||||||
|
console.log('收到消息', msgs)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听会话列表变化
|
||||||
|
im.on('conversations', (convs) => {
|
||||||
|
console.log('会话列表更新', convs)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 开始连接
|
||||||
|
im.connect()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 发送消息
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 发送文本
|
||||||
|
im.send({
|
||||||
|
toId: 'user_002',
|
||||||
|
chatType: 'SINGLE',
|
||||||
|
msgType: 'TEXT',
|
||||||
|
content: 'Hello H5!',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发送文件消息(自动上传)
|
||||||
|
|
||||||
|
SDK 内部自动上传文件到文件服务器,无需调用方手动上传。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { sendImageMessage, sendFileMessage } from '@xuqm/h5-sdk'
|
||||||
|
|
||||||
|
// 发送图片(从 input 元素获取)
|
||||||
|
const file = document.querySelector('input[type="file"]').files[0]
|
||||||
|
await sendImageMessage('user_002', 'SINGLE', file, 800, 600)
|
||||||
|
|
||||||
|
// 发送文件
|
||||||
|
await sendFileMessage('user_002', 'SINGLE', file)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 核心 API
|
||||||
|
|
||||||
|
### 事件订阅
|
||||||
|
|
||||||
|
| 事件 | 回调签名 | 说明 |
|
||||||
|
|------|---------|------|
|
||||||
|
| `connected` | `() => void` | IM 实时连接已建立 |
|
||||||
|
| `disconnected` | `() => void` | IM 实时连接已断开 |
|
||||||
|
| `messages` | `(msgs: ImMessage[]) => void` | 收到新消息 |
|
||||||
|
| `conversations` | `(convs: ConversationData[]) => void` | 会话列表变化 |
|
||||||
|
| `error` | `(err: Error) => void` | 发生错误 |
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
im.on('conversations', (convs) => {
|
||||||
|
// 更新 UI
|
||||||
|
})
|
||||||
|
im.off('conversations', handler) // 取消订阅
|
||||||
|
```
|
||||||
|
|
||||||
|
### 状态属性
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
im.connected // boolean,是否已连接
|
||||||
|
im.messages // ImMessage[],当前消息列表
|
||||||
|
im.conversations // ConversationData[],当前会话列表
|
||||||
|
im.error // Error | null,最近错误
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP API
|
||||||
|
|
||||||
|
所有 IM 功能均通过纯函数暴露:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {
|
||||||
|
sendMessage,
|
||||||
|
sendTextMessage,
|
||||||
|
sendImageMessage,
|
||||||
|
sendVideoMessage,
|
||||||
|
sendFileMessage,
|
||||||
|
sendAudioMessage,
|
||||||
|
fetchHistory,
|
||||||
|
fetchGroupHistory,
|
||||||
|
listConversations,
|
||||||
|
markRead,
|
||||||
|
listFriends,
|
||||||
|
addFriend,
|
||||||
|
listGroups,
|
||||||
|
createGroup,
|
||||||
|
// ...
|
||||||
|
} from '@xuqm/h5-sdk'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 与框架集成
|
||||||
|
|
||||||
|
### React
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { ImManager } from '@xuqm/h5-sdk'
|
||||||
|
|
||||||
|
function useIm() {
|
||||||
|
const [im] = useState(() => new ImManager())
|
||||||
|
const [messages, setMessages] = useState([])
|
||||||
|
const [conversations, setConversations] = useState([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
im.on('messages', setMessages)
|
||||||
|
im.on('conversations', setConversations)
|
||||||
|
im.connect()
|
||||||
|
return () => {
|
||||||
|
im.off('messages', setMessages)
|
||||||
|
im.off('conversations', setConversations)
|
||||||
|
im.disconnect()
|
||||||
|
}
|
||||||
|
}, [im])
|
||||||
|
|
||||||
|
return { im, messages, conversations }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 纯 HTML/JS
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="https://dev.xuqinmin.com/docs/h5-sdk/index.umd.js"></script>
|
||||||
|
<script>
|
||||||
|
XuqmH5SDK.init({ appKey: 'your_app_key' })
|
||||||
|
XuqmH5SDK.login('user_001', 'userSig')
|
||||||
|
const im = new XuqmH5SDK.ImManager()
|
||||||
|
im.on('messages', function(msgs) { console.log(msgs) })
|
||||||
|
im.connect()
|
||||||
|
</script>
|
||||||
|
```
|
||||||
54
docs-site/docs/h5/setup.md
普通文件
54
docs-site/docs/h5/setup.md
普通文件
@ -0,0 +1,54 @@
|
|||||||
|
# H5 安装配置
|
||||||
|
|
||||||
|
**包名**:`@xuqm/h5-sdk` · **语言**:TypeScript / JavaScript · **格式**:ESM + UMD
|
||||||
|
|
||||||
|
`@xuqm/h5-sdk` 是从 Vue3 SDK 提取的纯 JavaScript/TypeScript 核心库,**不依赖任何前端框架**(Vue/React/Angular 均可使用),可在任何支持 ES6 的浏览器或 H5 环境中运行。
|
||||||
|
|
||||||
|
> **功能范围**:仅包含 **IM** 功能(消息收发、会话管理、好友、群组),**不包含 Push 和 Update**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @xuqm/h5-sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
或 CDN 引入:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="https://dev.xuqinmin.com/docs/h5-sdk/index.umd.js"></script>
|
||||||
|
<script>
|
||||||
|
const { init, ImManager, login } = XuqmH5SDK
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 初始化
|
||||||
|
|
||||||
|
只需传入 `appKey`,服务器地址由 SDK 内置。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { init } from '@xuqm/h5-sdk'
|
||||||
|
|
||||||
|
init({
|
||||||
|
appKey: 'your_app_key', // 在租户平台创建应用后获得
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 登录
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { login } from '@xuqm/h5-sdk'
|
||||||
|
|
||||||
|
await login('user_001', 'your_user_sig_jwt')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
- [H5 IM 接入 →](./im)
|
||||||
137
docs-site/docs/miniprogram/im.md
普通文件
137
docs-site/docs/miniprogram/im.md
普通文件
@ -0,0 +1,137 @@
|
|||||||
|
# 微信小程序 IM 接入
|
||||||
|
|
||||||
|
**模块**:`xuqm-group-wechat-mini-program-sdk`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 登录
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { XuqmMiniProgramSDK } from 'xuqm-group-wechat-mini-program-sdk'
|
||||||
|
|
||||||
|
const sdk = new XuqmMiniProgramSDK()
|
||||||
|
sdk.init({ appKey: 'your_app_key' })
|
||||||
|
|
||||||
|
// 使用 UserSig 登录
|
||||||
|
await sdk.login('user_001', 'your_user_sig_jwt')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 监听消息
|
||||||
|
|
||||||
|
```ts
|
||||||
|
sdk.on('connected', () => {
|
||||||
|
console.log('IM 已连接')
|
||||||
|
})
|
||||||
|
|
||||||
|
sdk.on('message', (msg) => {
|
||||||
|
console.log('收到消息:', msg.msgType, msg.content)
|
||||||
|
})
|
||||||
|
|
||||||
|
sdk.on('read', (msg) => {
|
||||||
|
console.log('已读回执:', msg.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
sdk.on('revoke', (data) => {
|
||||||
|
console.log('消息被撤回:', data.msgId)
|
||||||
|
})
|
||||||
|
|
||||||
|
sdk.on('disconnected', (reason) => {
|
||||||
|
console.log('断开连接:', reason)
|
||||||
|
})
|
||||||
|
|
||||||
|
sdk.on('error', (error) => {
|
||||||
|
console.error('IM 错误:', error)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 发送消息
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const msg = await sdk.send({
|
||||||
|
toId: 'user_002',
|
||||||
|
chatType: 'SINGLE',
|
||||||
|
msgType: 'TEXT',
|
||||||
|
content: 'Hello!',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发送文本消息(快捷方法)
|
||||||
|
|
||||||
|
```ts
|
||||||
|
await sdk.sendTextMessage('user_002', 'SINGLE', 'Hello!')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 历史消息
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const history = await sdk.fetchHistory('user_002')
|
||||||
|
const groupHistory = await sdk.fetchGroupHistory('group_xxx')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 会话列表
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const conversations = await sdk.listConversations()
|
||||||
|
await sdk.markRead('user_002')
|
||||||
|
await sdk.setConversationPinned('user_002', 'SINGLE', true)
|
||||||
|
await sdk.setConversationMuted('user_002', 'SINGLE', true)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 群聊
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const groups = await sdk.listGroups()
|
||||||
|
const group = await sdk.getGroupInfo('group_xxx')
|
||||||
|
const members = await sdk.listGroupMembers('group_xxx')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 好友管理
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const friends = await sdk.listFriends()
|
||||||
|
await sdk.addFriend('user_002')
|
||||||
|
await sdk.removeFriend('user_002')
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 离线消息同步
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const count = await sdk.offlineMessageCount()
|
||||||
|
const messages = await sdk.syncOfflineMessages()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 消息类型
|
||||||
|
|
||||||
|
| MsgType | 说明 |
|
||||||
|
|---------|------|
|
||||||
|
| `TEXT` | 纯文本 |
|
||||||
|
| `IMAGE` | 图片 |
|
||||||
|
| `VIDEO` | 视频 |
|
||||||
|
| `AUDIO` | 语音 |
|
||||||
|
| `FILE` | 文件 |
|
||||||
|
| `LOCATION` | 位置 |
|
||||||
|
| `CUSTOM` | 自定义 |
|
||||||
|
| `NOTIFY` | 系统通知 |
|
||||||
|
| `RICH_TEXT` | 富文本 |
|
||||||
|
| `CALL_AUDIO` | 语音通话信令 |
|
||||||
|
| `CALL_VIDEO` | 视频通话信令 |
|
||||||
|
| `QUOTE` | 引用 |
|
||||||
|
| `MERGE` | 合并转发 |
|
||||||
|
| `FORWARD` | 转发 |
|
||||||
|
| `REVOKED` | 撤回 |
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
# 微信小程序安装配置
|
||||||
|
|
||||||
|
**包名**:`xuqm-group-wechat-mini-program-sdk` · **版本**:0.1.0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## npm 安装
|
||||||
|
|
||||||
|
在项目根目录创建 `.npmrc`:
|
||||||
|
|
||||||
|
```
|
||||||
|
registry=https://nexus.xuqinmin.com/repository/npm/
|
||||||
|
```
|
||||||
|
|
||||||
|
然后安装:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install xuqm-group-wechat-mini-program-sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
或在微信开发者工具中:
|
||||||
|
|
||||||
|
1. 打开「工具」→「构建 npm」
|
||||||
|
2. 在小程序 `package.json` 中添加上述依赖
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 初始化
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { XuqmMiniProgramSDK } from 'xuqm-group-wechat-mini-program-sdk'
|
||||||
|
|
||||||
|
const sdk = new XuqmMiniProgramSDK()
|
||||||
|
|
||||||
|
sdk.init({
|
||||||
|
appKey: 'your_app_key',
|
||||||
|
debug: true, // 可选
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
- [小程序 IM 接入 →](./im)
|
||||||
@ -91,6 +91,7 @@ export interface AppItem {
|
|||||||
name: string
|
name: string
|
||||||
packageName: string
|
packageName: string
|
||||||
tenantId: string
|
tenantId: string
|
||||||
|
tenantName?: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,8 +242,8 @@ export const opsApi = {
|
|||||||
rejectRequest: (requestId: string, reviewNote = '') =>
|
rejectRequest: (requestId: string, reviewNote = '') =>
|
||||||
client.post<{ data: ServiceRequest }>(`/ops/service-requests/${requestId}/reject`, { reviewNote }),
|
client.post<{ data: ServiceRequest }>(`/ops/service-requests/${requestId}/reject`, { reviewNote }),
|
||||||
|
|
||||||
listApps: (keyword = '', page = 0, size = 20) =>
|
listApps: (keyword = '', tenantId = '', page = 0, size = 20) =>
|
||||||
client.get<{ data: AppPage }>('/ops/apps', { params: { keyword, page, size } }),
|
client.get<{ data: AppPage }>('/ops/apps', { params: { keyword, tenantId, page, size } }),
|
||||||
|
|
||||||
getApp: (id: string) =>
|
getApp: (id: string) =>
|
||||||
client.get<{ data: AppDetail }>(`/ops/apps/${id}`),
|
client.get<{ data: AppDetail }>(`/ops/apps/${id}`),
|
||||||
|
|||||||
@ -34,7 +34,6 @@
|
|||||||
<el-card style="margin-bottom: 16px">
|
<el-card style="margin-bottom: 16px">
|
||||||
<template #header>功能服务</template>
|
<template #header>功能服务</template>
|
||||||
<el-table :data="detail.services" border stripe>
|
<el-table :data="detail.services" border stripe>
|
||||||
<el-table-column prop="platform" label="平台" width="120" />
|
|
||||||
<el-table-column prop="serviceType" label="服务类型" width="140" />
|
<el-table-column prop="serviceType" label="服务类型" width="140" />
|
||||||
<el-table-column label="状态" width="120">
|
<el-table-column label="状态" width="120">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
|
|||||||
@ -2,16 +2,38 @@
|
|||||||
<div>
|
<div>
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px">
|
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px">
|
||||||
<h2>应用管理</h2>
|
<h2>应用管理</h2>
|
||||||
<el-input v-model="search" placeholder="搜索应用名称 / AppKey" style="width:280px" clearable @clear="loadApps" @keyup.enter="loadApps">
|
<div style="display:flex;gap:12px;align-items:center">
|
||||||
<template #prefix><el-icon><Search /></el-icon></template>
|
<el-select
|
||||||
</el-input>
|
v-model="tenantFilter"
|
||||||
|
filterable
|
||||||
|
remote
|
||||||
|
clearable
|
||||||
|
placeholder="筛选租户"
|
||||||
|
:remote-method="searchTenants"
|
||||||
|
:loading="tenantLoading"
|
||||||
|
style="width:200px"
|
||||||
|
@change="onTenantChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="t in tenantOptions"
|
||||||
|
:key="t.id"
|
||||||
|
:label="t.nickname || t.username"
|
||||||
|
:value="t.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-input v-model="search" placeholder="搜索应用名称 / AppKey" style="width:280px" clearable @clear="loadApps" @keyup.enter="loadApps">
|
||||||
|
<template #prefix><el-icon><Search /></el-icon></template>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table :data="apps" v-loading="loading" border stripe>
|
<el-table :data="apps" v-loading="loading" border stripe>
|
||||||
<el-table-column prop="appKey" label="AppKey" width="220" />
|
<el-table-column prop="appKey" label="AppKey" width="220" />
|
||||||
<el-table-column prop="name" label="应用名称" min-width="160" />
|
<el-table-column prop="name" label="应用名称" min-width="160" />
|
||||||
<el-table-column prop="packageName" label="包名" min-width="160" />
|
<el-table-column prop="packageName" label="包名" min-width="160" />
|
||||||
<el-table-column prop="tenantId" label="租户ID" width="220" show-overflow-tooltip />
|
<el-table-column label="租户" width="180" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">{{ row.tenantName || row.tenantId }}</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="createdAt" label="创建时间" width="180">
|
<el-table-column prop="createdAt" label="创建时间" width="180">
|
||||||
<template #default="{ row }">{{ new Date(row.createdAt).toLocaleString('zh-CN') }}</template>
|
<template #default="{ row }">{{ new Date(row.createdAt).toLocaleString('zh-CN') }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -33,19 +55,41 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { Search } from '@element-plus/icons-vue'
|
import { Search } from '@element-plus/icons-vue'
|
||||||
import { opsApi, type AppItem } from '@/api/ops'
|
import { opsApi, type AppItem, type TenantItem } from '@/api/ops'
|
||||||
|
|
||||||
const apps = ref<AppItem[]>([])
|
const apps = ref<AppItem[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const search = ref('')
|
const search = ref('')
|
||||||
|
const tenantFilter = ref('')
|
||||||
const page = ref(0)
|
const page = ref(0)
|
||||||
const size = ref(20)
|
const size = ref(20)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
|
||||||
|
const tenantOptions = ref<TenantItem[]>([])
|
||||||
|
const tenantLoading = ref(false)
|
||||||
|
|
||||||
|
async function searchTenants(keyword: string) {
|
||||||
|
if (!keyword) { tenantOptions.value = []; return }
|
||||||
|
tenantLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await opsApi.listTenants(keyword, 0, 20)
|
||||||
|
tenantOptions.value = res.data.data.content
|
||||||
|
} catch {
|
||||||
|
tenantOptions.value = []
|
||||||
|
} finally {
|
||||||
|
tenantLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTenantChange() {
|
||||||
|
page.value = 0
|
||||||
|
loadApps()
|
||||||
|
}
|
||||||
|
|
||||||
async function loadApps() {
|
async function loadApps() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await opsApi.listApps(search.value, page.value, size.value)
|
const res = await opsApi.listApps(search.value, tenantFilter.value, page.value, size.value)
|
||||||
apps.value = res.data.data.content
|
apps.value = res.data.data.content
|
||||||
total.value = res.data.data.total
|
total.value = res.data.data.total
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户