feat(ops): 总部可按百分比限制接口放行并开关企微通知

线上需要按账户、用户和功能控制登录与加载成功率,同时单独停发订单、核销和账单通知。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-26 12:04:16 +08:00
parent 674b6ac31b
commit cb63d382ad
29 changed files with 1888 additions and 18 deletions
@@ -20,7 +20,9 @@ import {
type WecomPushTemplateDto,
type WecomTemplateEventKey,
} from '@dukang/shared-types';
import type { ApiAccessSubject } from '@dukang/domain';
import { PrismaService } from '../../common/prisma/prisma.module';
import { ApiAccessService } from '../../common/api-access/api-access.service';
import { applyWecomAtMentionInContent } from '../../modules/dev-plan/dev-plan-wecom-mention.util';
import {
WECOM_PUSH_TEMPLATE_DEFAULTS,
@@ -62,7 +64,10 @@ type TemplateRow = {
export class WecomMessagePushService implements OnModuleInit {
private readonly logger = new Logger(WecomMessagePushService.name);
constructor(private readonly prisma: PrismaService) {}
constructor(
private readonly prisma: PrismaService,
private readonly apiAccess: ApiAccessService,
) {}
async onModuleInit(): Promise<void> {
try {
@@ -248,12 +253,13 @@ export class WecomMessagePushService implements OnModuleInit {
async dispatchEvent(
eventKey: WecomTemplateEventKey,
vars: Record<string, string | number | null | undefined>,
options?: { applyMention?: boolean; handlePath?: string },
options?: { applyMention?: boolean; handlePath?: string; accessSubject?: ApiAccessSubject },
): Promise<number> {
try {
const content = await this.renderEventContent(eventKey, vars, options?.handlePath);
return await this.dispatchMarkdown(eventKey, content, {
applyMention: options?.applyMention ?? false,
accessSubject: options?.accessSubject,
});
} catch (e) {
this.logger.warn(
@@ -297,8 +303,13 @@ export class WecomMessagePushService implements OnModuleInit {
async dispatchMarkdown(
eventKey: WecomPushCondition,
content: string,
options?: { applyMention?: boolean },
options?: { applyMention?: boolean; accessSubject?: ApiAccessSubject },
): Promise<number> {
const gate = await this.apiAccess.gateWecom(eventKey, options?.accessSubject);
if (gate !== 'allow') {
this.logger.log(`skip wecom ${eventKey}: ${gate}`);
return 0;
}
const pushes = await this.listMatchingPushes(eventKey);
if (!pushes.length) return 0;
@@ -456,6 +467,9 @@ export class WecomMessagePushService implements OnModuleInit {
sample.vars,
sample.handlePath,
);
if (await this.apiAccess.isNotifySwitchOff(eventKey)) {
return { ok: false, message: '接口访问已关闭该通知', preview };
}
const sent = await this.dispatchMarkdown(eventKey, preview, { applyMention: false });
if (sent === 0) {
return {