From b938fcb12ccd38c0d8bbde0035ef68aca136891a Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Thu, 2 Feb 2023 17:36:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(server):=20=E5=A2=9E=E5=8A=A0=E9=9D=A2?= =?UTF-8?q?=E6=9D=BFfeature=E5=AE=9A=E4=B9=89=EF=BC=8C=E5=A2=9E=E5=8A=A0su?= =?UTF-8?q?bscribe=E7=94=A8=E4=BA=8E=E7=BB=99=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E5=A2=9E=E5=8A=A0=E8=AE=A2=E9=98=85=E5=8A=9F?= =?UTF-8?q?=E8=83=BD(=E4=B9=8B=E5=89=8D=E5=86=99=E6=AD=BB=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E9=9D=A2=E6=9D=BF=E4=BC=9A=E6=9C=89=E8=BF=99=E4=B8=AA?= =?UTF-8?q?=E6=95=88=E6=9E=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/packages/sdk/src/index.ts | 1 + server/packages/sdk/src/services/base.ts | 27 ++++++++++- server/packages/sdk/src/services/types.ts | 5 ++ .../services/topic.service.ts | 10 +++- server/services/core/config.service.ts | 9 ++-- server/services/core/group/group.service.ts | 47 +++++++++++++++++-- 6 files changed, 84 insertions(+), 15 deletions(-) diff --git a/server/packages/sdk/src/index.ts b/server/packages/sdk/src/index.ts index 80a8ea92..2644f67d 100644 --- a/server/packages/sdk/src/index.ts +++ b/server/packages/sdk/src/index.ts @@ -9,6 +9,7 @@ export type { GroupBaseInfo, PureServiceSchema, PureService, + PanelFeature, } from './services/types'; export { parseLanguageFromHead } from './services/lib/i18n/parser'; export { t } from './services/lib/i18n'; diff --git a/server/packages/sdk/src/services/base.ts b/server/packages/sdk/src/services/base.ts index deb2bf17..443d0570 100644 --- a/server/packages/sdk/src/services/base.ts +++ b/server/packages/sdk/src/services/base.ts @@ -13,7 +13,7 @@ import { } from 'moleculer'; import { once } from 'lodash'; import { TcDbService } from './mixins/db.mixin'; -import type { PureContext, TcPureContext } from './types'; +import type { PanelFeature, PureContext, TcPureContext } from './types'; import type { TFunction } from 'i18next'; import { t } from './lib/i18n'; import type { ValidationRuleObject } from 'fastest-validator'; @@ -309,6 +309,29 @@ export abstract class TcService extends Service { }); } + /** + * 注册面板功能特性,用于在服务端基础设施开放部分能力 + * @param panelFeature 面板功能 + */ + async setPanelFeature(panelName: string, panelFeatures: PanelFeature[]) { + await this.setGlobalConfig(`panelFeature.${panelName}`, panelFeatures); + } + + /** + * 获取拥有某些特性的面板列表 + * @param panelFeature 面板功能 + */ + getPanelNamesWithFeature(panelFeature: PanelFeature) { + const map = + this.getGlobalConfig>('panelFeature'); + + const matched = Object.entries(map).filter(([panelName, panelFeatures]) => + panelFeatures.includes(panelFeature) + ); + + return matched.map((m) => m[0]); + } + /** * 等待微服务启动 * @param serviceNames @@ -334,7 +357,7 @@ export abstract class TcService extends Service { return super.waitForServices(serviceNames, timeout, interval, logger); } - getGlobalConfig(key: string): any { + getGlobalConfig(key: string): T { return _.get(this.globalConfig, key); } diff --git a/server/packages/sdk/src/services/types.ts b/server/packages/sdk/src/services/types.ts index b3aab062..7b7a927a 100644 --- a/server/packages/sdk/src/services/types.ts +++ b/server/packages/sdk/src/services/types.ts @@ -53,3 +53,8 @@ export type TcContext

= TcPureContext< export type GroupBaseInfo = Pick & { memberCount: number; }; + +/** + * 面板能力 + */ +export type PanelFeature = 'subscribe'; // 订阅变更,即用户登录时自动加入面板的房间 diff --git a/server/plugins/com.msgbyte.topic/services/topic.service.ts b/server/plugins/com.msgbyte.topic/services/topic.service.ts index de274788..b0ad81a4 100644 --- a/server/plugins/com.msgbyte.topic/services/topic.service.ts +++ b/server/plugins/com.msgbyte.topic/services/topic.service.ts @@ -43,6 +43,10 @@ class GroupTopicService extends TcService { }); } + protected onInited(): void { + this.setPanelFeature('com.msgbyte.topic/grouppanel', ['subscribe']); + } + /** * 获取所有Topic */ @@ -121,7 +125,7 @@ class GroupTopicService extends TcService { const json = await this.transformDocuments(ctx, {}, topic); - this.roomcastNotify(ctx, groupId, 'create', json); + this.roomcastNotify(ctx, panelId, 'create', json); return json; } @@ -175,7 +179,9 @@ class GroupTopicService extends TcService { const json = await this.transformDocuments(ctx, {}, topic); - this.roomcastNotify(ctx, groupId, 'createComment', json); + // TODO: 回复需要添加到收件箱 + + this.roomcastNotify(ctx, panelId, 'createComment', json); return true; } diff --git a/server/services/core/config.service.ts b/server/services/core/config.service.ts index acdd5143..587d06c5 100644 --- a/server/services/core/config.service.ts +++ b/server/services/core/config.service.ts @@ -12,11 +12,6 @@ class ConfigService extends TcService { } onInit(): void { - /** - * 全局配置 - * - * 用于提供给前端使用 - */ this.registerAction('client', this.client); this.registerAction('all', this.all, { visibility: 'public', @@ -48,7 +43,9 @@ class ConfigService extends TcService { /** * 全局配置 * - * 用于提供给前端使用d + * 用于提供给前端使用 + * + * NOTICE: 返回内容比较简单,因此不建议增加缓存 */ async client(ctx: TcPureContext) { return { diff --git a/server/services/core/group/group.service.ts b/server/services/core/group/group.service.ts index 10179af2..62ac1d36 100644 --- a/server/services/core/group/group.service.ts +++ b/server/services/core/group/group.service.ts @@ -19,6 +19,7 @@ import { NoPermissionError, PERMISSION, GroupPanelType, + PanelFeature, } from 'tailchat-server-sdk'; import moment from 'moment'; @@ -210,6 +211,21 @@ class GroupService extends TcService { }); } + /** + * 获取会被订阅的群组面板id列表 + * + * 订阅即加入socket房间 + */ + private getSubscribedGroupPanelIds(group: Group): string[] { + const textPanelIds = this.getGroupTextPanelIds(group); + const subscribeFeaturePanelIds = this.getGroupPanelIdsWithFeature( + group, + 'subscribe' + ); + + return _.uniq([...textPanelIds, ...subscribeFeaturePanelIds]); + } + /** * 获取群组所有的文字面板id列表 * 用于加入房间 @@ -223,6 +239,22 @@ class GroupService extends TcService { return textPanelIds; } + /** + * 获取群组中拥有某些特性的面板 + * @param group + */ + private getGroupPanelIdsWithFeature( + group: Group, + feature: PanelFeature + ): string[] { + const featureAllPanelNames = this.getPanelNamesWithFeature(feature); + const matchedPanels = group.panels.filter((p) => + featureAllPanelNames.includes(p.pluginPanelName) + ); + + return matchedPanels.map((p) => p.id); + } + /** * 创建群组 */ @@ -242,7 +274,7 @@ class GroupService extends TcService { owner: userId, }); - const textPanelIds = this.getGroupTextPanelIds(group); + const textPanelIds = this.getSubscribedGroupPanelIds(group); await call(ctx).joinSocketIORoom( [String(group._id), ...textPanelIds], @@ -268,7 +300,9 @@ class GroupService extends TcService { panelIds: string[]; }> { const groups = await this.getUserGroups(ctx); // TODO: 应该使用call而不是直接调用,为了获取tracer和caching支持。目前moleculer的文档没有显式的声明类似localCall的行为,可以花时间看一下 - const panelIds = _.flatten(groups.map((g) => this.getGroupTextPanelIds(g))); + const panelIds = _.flatten( + groups.map((g) => this.getSubscribedGroupPanelIds(g)) + ); return { groupIds: groups.map((g) => String(g._id)), @@ -460,7 +494,7 @@ class GroupService extends TcService { this.notifyGroupInfoUpdate(ctx, group); // 推送变更 this.unicastNotify(ctx, userId, 'add', group); - const textPanelIds = this.getGroupTextPanelIds(group); + const textPanelIds = this.getSubscribedGroupPanelIds(group); await call(ctx).joinSocketIORoom( [String(group._id), ...textPanelIds], @@ -658,9 +692,12 @@ class GroupService extends TcService { ) .exec(); - if (type === 0) { + if ( + type === GroupPanelType.TEXT || + this.getPanelNamesWithFeature('subscribe').includes(name) + ) { /** - * 如果为文本面板 + * 如果为订阅的面板 * 则所有群组成员加入房间 */ const groupInfo = await call(ctx).getGroupInfo(groupId);