feat: 完成全系统30个功能点开发与E2E全链路验收 (8轮调度32个子代理闭环)
- 模块一: 出海案例作品集、博客动态发布、人名发音语音条、RTL阿语多语言切换 - 模块二: AI顾问人设配置、行业术语库润色、RAG切片沙盒调试、流式会话与意向留资卡片 - 模块三: 全球访客雷达大屏、多维加权意向算分、外部CRM对接推送、团队公海池流转 - 模块四: 移动端NFC安全挂失、NFC动态路由规则配置、动态防伪验签、展会制卡Zip批量导出 - 模块五: 组织架构与名片分配、移动端个人中心设置、离职交接与历史线索迁移、安全审计日志 - 模块六: Stripe国际信用卡订阅Webhook、独立二级域名与SSL检测、坐席配额预警、多币种发票 - 模块七: 纸质名片OCR解析入库、国际商务日程RFC 5545 ICS日历、微官网离线SWR预加载、展会实时排行榜大屏 - 模块八: 全球出海SEO OpenGraph元标签注入与社交爬虫探测、30点端到端全链路业务流集成测试套件
这个提交包含在:
@@ -0,0 +1,110 @@
|
||||
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.customDomain'],
|
||||
fieldEq: ['a.sslStatus'],
|
||||
addOrderBy: { updateTime: '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);
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户