koc.controller.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /**
  2. * 拉群、KOC 与意向客户模块 — 控制器层
  3. *
  4. * 对应规范文档 §十「模块 7:拉群、KOC 与意向客户模块」
  5. */
  6. import type { Request, Response } from 'express';
  7. import { sendSuccess, sendError } from '../../../../shared/http/response.js';
  8. import {
  9. createChannel, listChannels, updateChannel, deleteChannel,
  10. syncContacts, listContacts, getContact,
  11. findKocCandidates, labelKoc,
  12. detectIntent, listLeads, updateLead, listTasks,
  13. } from '../services/koc.service.js';
  14. // ============================================================
  15. // 渠道管理
  16. // ============================================================
  17. export async function createCh(req: Request, res: Response): Promise<void> {
  18. try {
  19. const { name, code, type } = req.body;
  20. if (!name || !code || !type) {
  21. sendError(res, 400, 'VALIDATION_ERROR', '缺少必填参数:name, code, type');
  22. return;
  23. }
  24. const ch = createChannel({ name, code, type, remark: req.body.remark || '' });
  25. sendSuccess(res, ch, 201);
  26. } catch (error) { throw error; }
  27. }
  28. export async function listCh(_req: Request, res: Response): Promise<void> {
  29. try { sendSuccess(res, listChannels()); } catch (error) { throw error; }
  30. }
  31. export async function updateCh(req: Request, res: Response): Promise<void> {
  32. try {
  33. const id = Number(req.params.id);
  34. sendSuccess(res, updateChannel(id, req.body));
  35. } catch (error) { throw error; }
  36. }
  37. export async function deleteCh(req: Request, res: Response): Promise<void> {
  38. try {
  39. deleteChannel(Number(req.params.id));
  40. sendSuccess(res, { deleted: true });
  41. } catch (error) { throw error; }
  42. }
  43. // ============================================================
  44. // 外部联系人
  45. // ============================================================
  46. export async function syncCt(req: Request, res: Response): Promise<void> {
  47. try {
  48. const { guid, currentSeq, limit } = req.body;
  49. if (!guid) { sendError(res, 400, 'VALIDATION_ERROR', '缺少 guid 参数'); return; }
  50. const result = await syncContacts(guid, currentSeq || 0, limit || 50);
  51. sendSuccess(res, result);
  52. } catch (error) { throw error; }
  53. }
  54. export async function listCt(_req: Request, res: Response): Promise<void> {
  55. try { sendSuccess(res, listContacts()); } catch (error) { throw error; }
  56. }
  57. export async function getCt(req: Request, res: Response): Promise<void> {
  58. try { sendSuccess(res, getContact(String(req.params.userId))); } catch (error) { throw error; }
  59. }
  60. // ============================================================
  61. // KOC
  62. // ============================================================
  63. export async function kocCandidates(_req: Request, res: Response): Promise<void> {
  64. try { sendSuccess(res, findKocCandidates()); } catch (error) { throw error; }
  65. }
  66. export async function labelKocUser(req: Request, res: Response): Promise<void> {
  67. try {
  68. const { userId, guid, labelId } = req.body;
  69. if (!userId || !guid || !labelId) {
  70. sendError(res, 400, 'VALIDATION_ERROR', '缺少必填参数:userId, guid, labelId');
  71. return;
  72. }
  73. const result = await labelKoc(userId, guid, labelId);
  74. sendSuccess(res, result);
  75. } catch (error) { throw error; }
  76. }
  77. // ============================================================
  78. // 意向客户
  79. // ============================================================
  80. export async function detectIntentMsg(req: Request, res: Response): Promise<void> {
  81. try {
  82. const { userId, roomId, content } = req.body;
  83. if (!userId || !roomId || !content) {
  84. sendError(res, 400, 'VALIDATION_ERROR', '缺少必填参数:userId, roomId, content');
  85. return;
  86. }
  87. const lead = detectIntent(userId, roomId, content);
  88. if (!lead) {
  89. sendSuccess(res, { matched: false, lead: null });
  90. return;
  91. }
  92. sendSuccess(res, { matched: true, lead });
  93. } catch (error) { throw error; }
  94. }
  95. export async function listLd(req: Request, res: Response): Promise<void> {
  96. try {
  97. const { intentLevel, status } = req.query;
  98. sendSuccess(res, listLeads(
  99. typeof intentLevel === 'string' ? intentLevel : undefined,
  100. typeof status === 'string' ? status : undefined,
  101. ));
  102. } catch (error) { throw error; }
  103. }
  104. export async function updateLd(req: Request, res: Response): Promise<void> {
  105. try {
  106. sendSuccess(res, updateLead(Number(req.params.id), req.body));
  107. } catch (error) { throw error; }
  108. }
  109. export async function listTk(req: Request, res: Response): Promise<void> {
  110. try {
  111. const { assigneeId } = req.query;
  112. sendSuccess(res, listTasks(typeof assigneeId === 'string' ? Number(assigneeId) : undefined));
  113. } catch (error) { throw error; }
  114. }