From 669d4b91c03c42a08d7aa7ff134b723c995d1dfe Mon Sep 17 00:00:00 2001 From: wikiboss Date: Mon, 21 Sep 2026 11:23:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(crm):=20=E6=96=B0=E5=A2=9EGDPR=E5=90=88?= =?UTF-8?q?=E8=A7=84=E6=93=A6=E9=99=A4=E6=8E=A7=E5=88=B6=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/controller/admin/compliance.ts | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 backend/src/modules/crm/controller/admin/compliance.ts diff --git a/backend/src/modules/crm/controller/admin/compliance.ts b/backend/src/modules/crm/controller/admin/compliance.ts new file mode 100644 index 0000000..c7a2c22 --- /dev/null +++ b/backend/src/modules/crm/controller/admin/compliance.ts @@ -0,0 +1,53 @@ +import { Body, Inject, Post, Provide } from '@midwayjs/core'; +import { BaseController, CoolController, CoolCommException } from '@cool-midway/core'; +import { ComplianceGdprService } from '../../service/compliance'; + +/** + * 管理后台 - 海外数据隐私与合规治理 (GDPR / CCPA) + * 路由前缀: /admin/crm/compliance + */ +@Provide() +@CoolController({ + api: [], + service: ComplianceGdprService, + serviceApis: [ + { method: 'exportPersonalDataBundle', summary: '导出个人便携数据包 (GDPR Art. 20)' }, + { method: 'executeRightToBeForgotten', summary: '签发被遗忘权销毁证书 (GDPR Art. 17)' }, + ], +}) +export class AdminCrmComplianceController extends BaseController { + @Inject() + complianceGdprService: ComplianceGdprService; + + /** + * 执行数据擦除与被遗忘权 (GDPR Article 17) + */ + @Post('/erasure', { summary: '执行被遗忘权数据抹除' }) + async erasure( + @Body() body: { email?: string; leadId?: number | string; visitorId?: string } + ) { + if (!body?.email && !body?.leadId && !body?.visitorId) { + throw new CoolCommException('缺少数据主体标识 (email / leadId / visitorId)'); + } + + const receipt = await this.complianceGdprService.purgeVisitorPersonalData(body); + return this.ok(receipt); + } + + /** + * 导出数据主体全量便携数据 (GDPR Article 20) + */ + @Post('/export', { summary: '导出数据主体便携数据包' }) + async export( + @Body() body: { subjectId: string; dataPayload: Record } + ) { + if (!body?.subjectId) { + throw new CoolCommException('缺少数据主体标识 subjectId'); + } + const bundle = await this.complianceGdprService.exportPersonalDataBundle( + body.subjectId, + body.dataPayload || {} + ); + return this.ok(bundle); + } +}