diff --git a/server/packages/sdk/src/index.ts b/server/packages/sdk/src/index.ts index 80a8ea92349..2644f67d60a 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 deb2bf17b9f..443d0570015 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 b3aab06259b..7b7a927a82d 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 de274788ed7..b0ad81a4f1d 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 acdd5143df4..587d06c57c9 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 10179af2873..62ac1d36cae 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);