package com.crm.lead.controller; import com.crm.base.domain.result.PageResult; import com.crm.base.domain.result.Result; import com.crm.base.domain.result.BatchResult; import com.crm.lead.domain.dto.LeadDTO; import com.crm.lead.domain.dto.LeadBatchFailItem; import com.crm.lead.domain.dto.LeadFeedbackDTO; import com.crm.lead.domain.dto.LeadHistoryDTO; import com.crm.lead.domain.dto.LeadStatsDTO; import com.crm.lead.domain.param.ConvertOpportunityParam; import com.crm.lead.domain.param.LeadPageParam; import com.crm.lead.service.ILeadService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * 线索管理接口(薄适配层) *

权限策略:不种子化 button 权限点(用户决策),ApiPermissionInterceptor 对未注册 URL fail-open。 * 数据隔离由 {@code @DataScope(module="lead", ownerColumn="owner_user_id", deptColumn="dept_id")} 自动注入。

*/ @Tag(name = "线索管理") @RestController @RequestMapping("/api/lead") @RequiredArgsConstructor public class LeadController { private final ILeadService leadService; // ==================== 查询 ==================== @Operation(summary = "线索分页(四视图:PUBLIC_POOL/MY_LEAD/MY_FOLLOW/MANAGE)") @PostMapping("/page") public Result> page(LeadPageParam param) { return Result.success(leadService.pageLeads(param)); } @Operation(summary = "线索详情") @GetMapping("/detail") public Result detail(@RequestParam("id") Long id) { return Result.success(leadService.getLeadDetail(id)); } @Operation(summary = "历史记录(只展示 5 种:领取/释放/反馈/转商机/编辑)") @GetMapping("/history") public Result> history(@RequestParam("leadId") Long leadId) { return Result.success(leadService.listHistory(leadId)); } // ==================== 创建/编辑/删除 ==================== @Operation(summary = "新建线索(claimOnCreate=true 销售新增即领取)") @PostMapping("/create") public Result create(LeadDTO dto, @RequestParam(value = "claimOnCreate", defaultValue = "false") boolean claimOnCreate) { return Result.success(leadService.createLead(dto, claimOnCreate)); } @Operation(summary = "编辑线索(非终态可编辑)") @PostMapping("/edit") public Result edit(LeadDTO dto) { leadService.editLead(dto); return Result.success(); } @Operation(summary = "删除线索(已转商机禁止删除)") @PostMapping("/delete") public Result delete(@RequestParam("id") Long id) { leadService.deleteLead(id); return Result.success(); } // ==================== 流转操作 ==================== @Operation(summary = "领取线索(待领取→已领取)") @PostMapping("/claim") public Result claim(@RequestParam("id") Long id) { leadService.claimLead(id); return Result.success(); } @Operation(summary = "分配线索到池(未分发→待领取)") @PostMapping("/assign-pool") public Result assignToPool(@RequestParam("id") Long id, @RequestParam("poolId") Long poolId) { leadService.assignToPool(id, poolId); return Result.success(); } @Operation(summary = "分配线索到销售(未分发/待领取→已领取 or 作废自环)") @PostMapping("/assign-user") public Result assignToUser(@RequestParam("id") Long id, @RequestParam("userId") Long userId) { leadService.assignToUser(id, userId); return Result.success(); } @Operation(summary = "保存反馈草稿(不改状态机)") @PostMapping("/feedback-draft") public Result feedbackDraft(LeadFeedbackDTO dto) { leadService.saveFeedbackDraft(dto); return Result.success(); } @Operation(summary = "提交反馈(已领取→跟进中 or →作废)") @PostMapping("/feedback-submit") public Result feedbackSubmit(LeadFeedbackDTO dto) { leadService.submitFeedback(dto); return Result.success(); } @Operation(summary = "转商机(已领取/跟进中→已转商机)") @PostMapping("/convert") public Result convert(@RequestParam("id") Long id, ConvertOpportunityParam param) { leadService.convertToOpportunity(id, param); return Result.success(); } @Operation(summary = "释放线索(已领取/跟进中→待领取)") @PostMapping("/release") public Result release(@RequestParam("id") Long id) { leadService.releaseLead(id); return Result.success(); } @Operation(summary = "激活线索(过期失效→恢复失效前态)") @PostMapping("/activate") public Result activate(@RequestParam("id") Long id) { leadService.activateLead(id); return Result.success(); } // ==================== 关注 ==================== @Operation(summary = "关注线索") @PostMapping("/follow") public Result follow(@RequestParam("id") Long id) { leadService.followLead(id); return Result.success(); } @Operation(summary = "取消关注") @PostMapping("/unfollow") public Result unfollow(@RequestParam("id") Long id) { leadService.unfollowLead(id); return Result.success(); } @Operation(summary = "视图统计卡片(与 /page 同套筛选口径,口径随视图)") @PostMapping("/stats") public Result stats(LeadPageParam param) { return Result.success(leadService.countStats(param)); } // ==================== 批量操作(非原子、逐条 CAS、部分成功,ADR-0023) ==================== @Operation(summary = "批量领取") @PostMapping("/claim-batch") public Result> claimBatch(@RequestParam("ids") List ids) { return Result.success(leadService.claimBatch(ids)); } @Operation(summary = "批量分配到池(未分发→待领取)") @PostMapping("/assign-pool-batch") public Result> assignToPoolBatch(@RequestParam("ids") List ids, @RequestParam("poolId") Long poolId) { return Result.success(leadService.assignToPoolBatch(ids, poolId)); } @Operation(summary = "批量分配到销售(统一分配给同一销售)") @PostMapping("/assign-user-batch") public Result> assignToUserBatch(@RequestParam("ids") List ids, @RequestParam("userId") Long userId) { return Result.success(leadService.assignToUserBatch(ids, userId)); } @Operation(summary = "批量释放(已领取/跟进中→待领取)") @PostMapping("/release-batch") public Result> releaseBatch(@RequestParam("ids") List ids) { return Result.success(leadService.releaseBatch(ids)); } @Operation(summary = "批量激活(过期失效→恢复失效前态)") @PostMapping("/activate-batch") public Result> activateBatch(@RequestParam("ids") List ids) { return Result.success(leadService.activateBatch(ids)); } @Operation(summary = "批量删除(已转商机禁止删除,记失败)") @PostMapping("/delete-batch") public Result> deleteBatch(@RequestParam("ids") List ids) { return Result.success(leadService.deleteBatch(ids)); } }