复制项目
This commit is contained in:
208
docs/使用Ex字段区分群类型方案.md
Normal file
208
docs/使用Ex字段区分群类型方案.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# 使用 Ex 字段区分群类型方案
|
||||
|
||||
## 一、方案概述
|
||||
|
||||
使用群组的 `Ex` 扩展字段来区分不同类型的群,在客户端根据 `Ex` 字段控制功能展示,服务端保持统一的验证逻辑。
|
||||
|
||||
## 二、Ex 字段格式建议
|
||||
|
||||
### 2.1 JSON 格式
|
||||
|
||||
```json
|
||||
{
|
||||
"groupCategory": "super", // 群类型:super(超级群)、normal(普通群)、work(工作群)
|
||||
"features": {
|
||||
"allowLink": true, // 是否允许发送链接
|
||||
"allowQRCode": true, // 是否允许发送二维码
|
||||
"showMemberList": true, // 是否显示成员列表
|
||||
"showAdminPanel": false // 是否显示管理面板
|
||||
},
|
||||
"custom": {} // 其他自定义字段
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 简化格式(如果只需要区分类型)
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "super" // super, normal, work
|
||||
}
|
||||
```
|
||||
|
||||
## 三、实现方式
|
||||
|
||||
### 3.1 创建群组时设置 Ex
|
||||
|
||||
**创建群组时**,在 `GroupInfo.Ex` 中设置群类型:
|
||||
|
||||
```go
|
||||
// 创建超级群
|
||||
groupInfo := &sdkws.GroupInfo{
|
||||
GroupName: "超级群",
|
||||
Ex: `{"type":"super"}`,
|
||||
// ... 其他字段
|
||||
}
|
||||
|
||||
// 创建普通群
|
||||
groupInfo := &sdkws.GroupInfo{
|
||||
GroupName: "普通群",
|
||||
Ex: `{"type":"normal"}`,
|
||||
// ... 其他字段
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 客户端解析 Ex 字段
|
||||
|
||||
**客户端获取群信息后**,解析 `Ex` 字段:
|
||||
|
||||
```javascript
|
||||
// 示例:JavaScript/TypeScript
|
||||
function getGroupType(groupInfo) {
|
||||
try {
|
||||
const ex = JSON.parse(groupInfo.Ex || '{}');
|
||||
return ex.type || 'normal'; // 默认为普通群
|
||||
} catch (e) {
|
||||
return 'normal';
|
||||
}
|
||||
}
|
||||
|
||||
// 根据群类型控制功能显示
|
||||
function shouldShowFeature(groupInfo, feature) {
|
||||
const type = getGroupType(groupInfo);
|
||||
|
||||
switch (feature) {
|
||||
case 'memberList':
|
||||
// 超级群可能不显示成员列表
|
||||
return type !== 'super';
|
||||
case 'adminPanel':
|
||||
// 只有工作群显示管理面板
|
||||
return type === 'work';
|
||||
case 'linkMessage':
|
||||
// 根据类型决定是否允许发送链接
|
||||
return type !== 'super'; // 超级群不允许发送链接
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 更新群信息时保持 Ex 字段
|
||||
|
||||
**使用 `SetGroupInfoEx` 接口更新群信息时**,可以更新 `Ex` 字段:
|
||||
|
||||
```go
|
||||
// 更新群扩展信息
|
||||
req := &pbgroup.SetGroupInfoExReq{
|
||||
GroupID: groupID,
|
||||
Ex: &wrapperspb.StringValue{
|
||||
Value: `{"type":"super","features":{"allowLink":false}}`,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 四、优势
|
||||
|
||||
### 4.1 服务端优势
|
||||
|
||||
1. **统一验证逻辑**:所有群组都使用 `WorkingGroup` 的完整验证,安全可靠
|
||||
2. **无需修改代码**:不需要修改服务端的验证、推送等逻辑
|
||||
3. **向后兼容**:不影响现有群组,新群组通过 Ex 字段区分
|
||||
4. **灵活扩展**:Ex 字段可以存储任意 JSON 数据,便于后续扩展
|
||||
|
||||
### 4.2 客户端优势
|
||||
|
||||
1. **完全可控**:客户端可以根据业务需求灵活控制功能展示
|
||||
2. **易于实现**:只需要解析 JSON 并做条件判断
|
||||
3. **不影响现有功能**:对没有 Ex 字段或 Ex 字段格式不正确的群组,可以设置默认行为
|
||||
|
||||
## 五、注意事项
|
||||
|
||||
### 5.1 Ex 字段格式
|
||||
|
||||
- **建议使用 JSON 格式**:便于解析和扩展
|
||||
- **字段命名规范**:使用小驼峰或下划线命名
|
||||
- **版本兼容**:如果后续需要修改格式,考虑版本号字段
|
||||
|
||||
### 5.2 默认值处理
|
||||
|
||||
- **客户端**:如果 Ex 字段为空或解析失败,应设置合理的默认值
|
||||
- **服务端**:创建群组时,如果没有设置 Ex,可以设置默认值
|
||||
|
||||
### 5.3 数据一致性
|
||||
|
||||
- **更新 Ex 字段时**:确保 JSON 格式正确
|
||||
- **验证**:客户端解析 Ex 字段时,应该处理 JSON 解析错误
|
||||
|
||||
## 六、示例代码
|
||||
|
||||
### 6.1 Go 服务端示例
|
||||
|
||||
```go
|
||||
// 创建群组时设置 Ex
|
||||
func createSuperGroup(req *pbgroup.CreateGroupReq) {
|
||||
req.GroupInfo.Ex = `{"type":"super","features":{"allowLink":false}}`
|
||||
// ... 创建群组
|
||||
}
|
||||
|
||||
// 解析 Ex 字段(如果需要)
|
||||
func parseGroupEx(ex string) map[string]interface{} {
|
||||
var result map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(ex), &result); err != nil {
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 客户端示例(React/TypeScript)
|
||||
|
||||
```typescript
|
||||
interface GroupEx {
|
||||
type?: 'super' | 'normal' | 'work';
|
||||
features?: {
|
||||
allowLink?: boolean;
|
||||
allowQRCode?: boolean;
|
||||
showMemberList?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
function parseGroupEx(ex: string): GroupEx {
|
||||
try {
|
||||
return JSON.parse(ex || '{}') as GroupEx;
|
||||
} catch {
|
||||
return { type: 'normal' };
|
||||
}
|
||||
}
|
||||
|
||||
function useGroupFeatures(groupInfo: GroupInfo) {
|
||||
const ex = parseGroupEx(groupInfo.Ex);
|
||||
|
||||
return {
|
||||
canSendLink: ex.features?.allowLink !== false,
|
||||
canSendQRCode: ex.features?.allowQRCode !== false,
|
||||
showMemberList: ex.features?.showMemberList !== false,
|
||||
isSuperGroup: ex.type === 'super',
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 七、总结
|
||||
|
||||
使用 `Ex` 字段区分群类型是一个**保守、安全、灵活**的方案:
|
||||
|
||||
- ✅ **服务端**:保持统一逻辑,无需修改验证和推送代码
|
||||
- ✅ **客户端**:完全可控,根据业务需求灵活展示功能
|
||||
- ✅ **扩展性**:Ex 字段可以存储任意扩展信息
|
||||
- ✅ **兼容性**:不影响现有群组和功能
|
||||
|
||||
这个方案避免了修改服务端核心逻辑带来的风险,同时提供了足够的灵活性来满足不同的业务需求。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user