/** * 拉群、KOC 与意向客户模块 — 控制器层 * * 对应规范文档 §十「模块 7:拉群、KOC 与意向客户模块」 */ import type { Request, Response } from 'express'; import { sendSuccess, sendError } from '../../../../shared/http/response.js'; import { createChannel, listChannels, updateChannel, deleteChannel, syncContacts, listContacts, getContact, findKocCandidates, labelKoc, detectIntent, listLeads, updateLead, listTasks, } from '../services/koc.service.js'; // ============================================================ // 渠道管理 // ============================================================ export async function createCh(req: Request, res: Response): Promise { try { const { name, code, type } = req.body; if (!name || !code || !type) { sendError(res, 400, 'VALIDATION_ERROR', '缺少必填参数:name, code, type'); return; } const ch = createChannel({ name, code, type, remark: req.body.remark || '' }); sendSuccess(res, ch, 201); } catch (error) { throw error; } } export async function listCh(_req: Request, res: Response): Promise { try { sendSuccess(res, listChannels()); } catch (error) { throw error; } } export async function updateCh(req: Request, res: Response): Promise { try { const id = Number(req.params.id); sendSuccess(res, updateChannel(id, req.body)); } catch (error) { throw error; } } export async function deleteCh(req: Request, res: Response): Promise { try { deleteChannel(Number(req.params.id)); sendSuccess(res, { deleted: true }); } catch (error) { throw error; } } // ============================================================ // 外部联系人 // ============================================================ export async function syncCt(req: Request, res: Response): Promise { try { const { guid, currentSeq, limit } = req.body; if (!guid) { sendError(res, 400, 'VALIDATION_ERROR', '缺少 guid 参数'); return; } const result = await syncContacts(guid, currentSeq || 0, limit || 50); sendSuccess(res, result); } catch (error) { throw error; } } export async function listCt(_req: Request, res: Response): Promise { try { sendSuccess(res, listContacts()); } catch (error) { throw error; } } export async function getCt(req: Request, res: Response): Promise { try { sendSuccess(res, getContact(String(req.params.userId))); } catch (error) { throw error; } } // ============================================================ // KOC // ============================================================ export async function kocCandidates(_req: Request, res: Response): Promise { try { sendSuccess(res, findKocCandidates()); } catch (error) { throw error; } } export async function labelKocUser(req: Request, res: Response): Promise { try { const { userId, guid, labelId } = req.body; if (!userId || !guid || !labelId) { sendError(res, 400, 'VALIDATION_ERROR', '缺少必填参数:userId, guid, labelId'); return; } const result = await labelKoc(userId, guid, labelId); sendSuccess(res, result); } catch (error) { throw error; } } // ============================================================ // 意向客户 // ============================================================ export async function detectIntentMsg(req: Request, res: Response): Promise { try { const { userId, roomId, content } = req.body; if (!userId || !roomId || !content) { sendError(res, 400, 'VALIDATION_ERROR', '缺少必填参数:userId, roomId, content'); return; } const lead = detectIntent(userId, roomId, content); if (!lead) { sendSuccess(res, { matched: false, lead: null }); return; } sendSuccess(res, { matched: true, lead }); } catch (error) { throw error; } } export async function listLd(req: Request, res: Response): Promise { try { const { intentLevel, status } = req.query; sendSuccess(res, listLeads( typeof intentLevel === 'string' ? intentLevel : undefined, typeof status === 'string' ? status : undefined, )); } catch (error) { throw error; } } export async function updateLd(req: Request, res: Response): Promise { try { sendSuccess(res, updateLead(Number(req.params.id), req.body)); } catch (error) { throw error; } } export async function listTk(req: Request, res: Response): Promise { try { const { assigneeId } = req.query; sendSuccess(res, listTasks(typeof assigneeId === 'string' ? Number(assigneeId) : undefined)); } catch (error) { throw error; } }