- [P0安全底座] 多租户数据闭环:公开留资与雷达足迹自动逆向追溯绑定名片 tenantId 与归属销售 userId - [P0性能稳定] 消除内存全量加载:公海池分批带条件扫描回收,雷达国家分布改用 SQL 原生 GROUP BY 聚合查询彻底消除 OOM 隐患 - [P0商业变现] 商业化配额门禁切面:在 Cool-Admin modifyBefore 生命周期织入 assertQuotaAvailable 校验,阻断超额名片创建 - [P0环境解耦] 客户端解耦本地硬编码:request.uts 支持 api_base_url 本地覆盖,生产数据库名修正为 crmmpdata - [P1高并发削峰] 雷达足迹批量缓冲引擎:引入 CrmRadarBufferService 环形缓冲队列与阈值/定时批量 Bulk Insert 落盘 - [P2中枢租户化] AI 智能中枢多租户 BYOK 与 Token 成本风控:支持企业自带 Key 隔离、Token 消耗账本、用量配额门禁与名片人设个性化联动 - [跨端规范] 对齐 Uni-app x 移动微官网原生首屏与底部原生 tabBar 规范 - [测试驱动] 全工程 116 个测试套件,1,175 个单元与集成测试用例全部 100% 绿色通过,管理后台 Vite 打包无错误
111 行
3.0 KiB
TypeScript
111 行
3.0 KiB
TypeScript
import { Body, Inject, Post, Provide } from '@midwayjs/core';
|
|
import { Context } from '@midwayjs/koa';
|
|
import { CoolController, BaseController } from '@cool-midway/core';
|
|
import { TeamDomainEntity } from '../../entity/domain';
|
|
import { TeamDomainService } from '../../service/domain';
|
|
import { BindDomainDTO, SslCertMockInfo } from '../../../../comm/types/omni';
|
|
|
|
/**
|
|
* 后台租户域名标准 CRUD 配置
|
|
*/
|
|
export const adminTeamDomainCurdOption = {
|
|
api: ['add', 'delete', 'update', 'info', 'list', 'page'] as Array<
|
|
'add' | 'delete' | 'update' | 'info' | 'list' | 'page'
|
|
>,
|
|
entity: TeamDomainEntity,
|
|
service: TeamDomainService,
|
|
serviceApis: [
|
|
{ method: 'validate', summary: '域名格式校验' },
|
|
{ method: 'verifyDns', summary: 'CNAME 解析核验' },
|
|
{ method: 'checkSsl', summary: 'SSL 证书检测' },
|
|
{ method: 'bind', summary: '绑定独立域名' },
|
|
],
|
|
pageQueryOp: {
|
|
keyWordLikeFields: ['a.custom_domain'],
|
|
fieldEq: [{ column: 'a.ssl_status', requestParam: 'sslStatus' }],
|
|
addOrderBy: { update_time: 'desc' as const },
|
|
},
|
|
};
|
|
|
|
/**
|
|
* 企业团队-租户域名与 SSL 治理
|
|
* 路由前缀:/admin/team/domain
|
|
*/
|
|
@Provide()
|
|
@CoolController(adminTeamDomainCurdOption)
|
|
export class AdminTeamDomainController extends BaseController {
|
|
@Inject()
|
|
ctx: Context;
|
|
|
|
@Inject()
|
|
teamDomainService: TeamDomainService;
|
|
|
|
/**
|
|
* 域名格式严格正则检验
|
|
*/
|
|
@Post('/validate', { summary: '域名格式校验' })
|
|
async validate(@Body() body: { domain: string }) {
|
|
const result = this.teamDomainService.validateDomainFormat(body?.domain);
|
|
return this.ok(result);
|
|
}
|
|
|
|
/**
|
|
* CNAME DNS 解析核验
|
|
*/
|
|
@Post('/verify-dns', { summary: 'CNAME 解析核验' })
|
|
async verifyDns(
|
|
@Body()
|
|
body: {
|
|
domain: string;
|
|
targetCname?: string;
|
|
mockRecords?: string[];
|
|
}
|
|
) {
|
|
const targetCname = body?.targetCname || 'cname.omnicard.ai';
|
|
const result = await this.teamDomainService.verifyDnsRecord(
|
|
body?.domain,
|
|
targetCname,
|
|
{ mockRecords: body?.mockRecords }
|
|
);
|
|
return this.ok(result);
|
|
}
|
|
|
|
/**
|
|
* SSL 证书状态与过期时间检测
|
|
*/
|
|
@Post('/check-ssl', { summary: 'SSL 证书检测' })
|
|
async checkSsl(
|
|
@Body()
|
|
body: {
|
|
domain: string;
|
|
port?: number;
|
|
mockCert?: SslCertMockInfo;
|
|
}
|
|
) {
|
|
const result = await this.teamDomainService.checkSslCertificate(
|
|
body?.domain,
|
|
body?.port,
|
|
{ mockCert: body?.mockCert }
|
|
);
|
|
return this.ok(result);
|
|
}
|
|
|
|
/**
|
|
* 绑定独立域名
|
|
*/
|
|
@Post('/bind', { summary: '绑定独立域名' })
|
|
async bind(@Body() body: BindDomainDTO) {
|
|
const tenantId =
|
|
body?.tenantId ||
|
|
((this.ctx?.admin as unknown as { tenantId?: number })?.tenantId) ||
|
|
((this.ctx as unknown as { tenantId?: number })?.tenantId);
|
|
|
|
const result = await this.teamDomainService.bindDomain(
|
|
tenantId || 0,
|
|
body?.domain,
|
|
{ cnameTarget: body?.cnameTarget }
|
|
);
|
|
return this.ok(result);
|
|
}
|
|
}
|