feat(round-16): AI意图情绪分析/展会名片双向互换/雷达爬虫清洗/离线多媒体缓存 (103套件1101测试全绿)
这个提交包含在:
@@ -0,0 +1,127 @@
|
||||
import { Provide } from '@midwayjs/core';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
|
||||
export type MutualExchangeStatus = 'REQUESTED' | 'ACCEPTED' | 'REJECTED' | 'EXPIRED';
|
||||
|
||||
export interface MutualExchangeInvitation {
|
||||
id: string;
|
||||
senderCardId: number;
|
||||
recipientCardId: number;
|
||||
status: MutualExchangeStatus;
|
||||
exchangeCode: string;
|
||||
notes?: string;
|
||||
createdAt: number;
|
||||
acceptedAt?: number;
|
||||
}
|
||||
|
||||
export interface MutualExchangeSyncAction {
|
||||
targetCardId: number;
|
||||
sourceCardId: number;
|
||||
action: 'CREATE_CRM_LEAD';
|
||||
}
|
||||
|
||||
export interface AcceptExchangeResult {
|
||||
invitation: MutualExchangeInvitation;
|
||||
syncActions: MutualExchangeSyncAction[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起名片双向互换邀约
|
||||
*/
|
||||
export function createMutualExchangeInvitation(
|
||||
senderCardId: number,
|
||||
recipientCardId: number,
|
||||
notes?: string
|
||||
): MutualExchangeInvitation {
|
||||
if (senderCardId === recipientCardId) {
|
||||
throw new Error('不能与自己互换名片');
|
||||
}
|
||||
|
||||
const exchangeCode = String(Math.floor(100000 + Math.random() * 900000));
|
||||
const id = `xchg_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
||||
|
||||
return {
|
||||
id,
|
||||
senderCardId,
|
||||
recipientCardId,
|
||||
status: 'REQUESTED',
|
||||
exchangeCode,
|
||||
notes,
|
||||
createdAt: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收方确认互换名片
|
||||
*/
|
||||
export function acceptMutualExchangeInvitation(
|
||||
invitation: MutualExchangeInvitation,
|
||||
actingCardId: number
|
||||
): AcceptExchangeResult {
|
||||
if (invitation.recipientCardId !== actingCardId) {
|
||||
throw new Error('无权操作此名片互换邀约');
|
||||
}
|
||||
|
||||
if (invitation.status !== 'REQUESTED') {
|
||||
throw new Error(`当前互换邀约状态为 ${invitation.status},不可重复确认`);
|
||||
}
|
||||
|
||||
invitation.status = 'ACCEPTED';
|
||||
invitation.acceptedAt = Date.now();
|
||||
|
||||
const syncActions: MutualExchangeSyncAction[] = [
|
||||
{
|
||||
targetCardId: invitation.senderCardId,
|
||||
sourceCardId: invitation.recipientCardId,
|
||||
action: 'CREATE_CRM_LEAD',
|
||||
},
|
||||
{
|
||||
targetCardId: invitation.recipientCardId,
|
||||
sourceCardId: invitation.senderCardId,
|
||||
action: 'CREATE_CRM_LEAD',
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
invitation,
|
||||
syncActions,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 展会名片双向互换服务
|
||||
*/
|
||||
@Provide()
|
||||
export class CardMutualExchangeService extends BaseService {
|
||||
private readonly invitations = new Map<string, MutualExchangeInvitation>();
|
||||
|
||||
async initiateExchange(params: {
|
||||
senderCardId: number;
|
||||
recipientCardId: number;
|
||||
notes?: string;
|
||||
}): Promise<MutualExchangeInvitation> {
|
||||
const invite = createMutualExchangeInvitation(
|
||||
params.senderCardId,
|
||||
params.recipientCardId,
|
||||
params.notes
|
||||
);
|
||||
this.invitations.set(invite.id, invite);
|
||||
return invite;
|
||||
}
|
||||
|
||||
async confirmExchange(
|
||||
invitationId: string,
|
||||
actingCardId: number
|
||||
): Promise<{ status: MutualExchangeStatus; isDualSynced: boolean }> {
|
||||
const invite = this.invitations.get(invitationId);
|
||||
if (!invite) {
|
||||
throw new Error('未找到该名片互换邀约');
|
||||
}
|
||||
|
||||
const res = acceptMutualExchangeInvitation(invite, actingCardId);
|
||||
return {
|
||||
status: res.invitation.status,
|
||||
isDualSynced: res.syncActions.length === 2,
|
||||
};
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户