diff --git a/klp-admin/pom.xml b/klp-admin/pom.xml
index acca9260..b55a60ea 100644
--- a/klp-admin/pom.xml
+++ b/klp-admin/pom.xml
@@ -112,13 +112,17 @@
com.klp
klp-hrm
-
+
+ com.klp
+ klp-crm
+
com.klp
klp-reader
+
org.springframework.boot
spring-boot-starter-test
diff --git a/klp-crm/pom.xml b/klp-crm/pom.xml
new file mode 100644
index 00000000..18c99afe
--- /dev/null
+++ b/klp-crm/pom.xml
@@ -0,0 +1,47 @@
+
+ 4.0.0
+
+ com.klp
+ klp-oa
+ 0.8.3
+
+ klp-crm
+
+ 8
+ 8
+ UTF-8
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+ com.baomidou
+ mybatis-plus-annotation
+ 3.5.9
+ compile
+
+
+ com.klp
+ klp-common
+
+
+ com.alibaba
+ fastjson
+ 1.2.83
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ 2.0.35
+
+
+ com.klp
+ klp-wms
+
+
+
diff --git a/klp-crm/src/main/java/com/klp/crm/controller/CrmCustomerController.java b/klp-crm/src/main/java/com/klp/crm/controller/CrmCustomerController.java
new file mode 100644
index 00000000..32faadce
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/controller/CrmCustomerController.java
@@ -0,0 +1,99 @@
+package com.klp.crm.controller;
+
+import java.util.List;
+import java.util.Arrays;
+
+import lombok.RequiredArgsConstructor;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.*;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import com.klp.common.annotation.RepeatSubmit;
+import com.klp.common.annotation.Log;
+import com.klp.common.core.controller.BaseController;
+import com.klp.common.core.domain.PageQuery;
+import com.klp.common.core.domain.R;
+import com.klp.common.core.validate.AddGroup;
+import com.klp.common.core.validate.EditGroup;
+import com.klp.common.enums.BusinessType;
+import com.klp.common.utils.poi.ExcelUtil;
+import com.klp.crm.domain.vo.CrmCustomerVo;
+import com.klp.crm.domain.bo.CrmCustomerBo;
+import com.klp.crm.service.ICrmCustomerService;
+import com.klp.common.core.page.TableDataInfo;
+
+/**
+ * 客户信息
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/crm/customer")
+public class CrmCustomerController extends BaseController {
+
+ private final ICrmCustomerService iCrmCustomerService;
+
+ /**
+ * 查询客户信息列表
+ */
+ @GetMapping("/list")
+ public TableDataInfo list(CrmCustomerBo bo, PageQuery pageQuery) {
+ return iCrmCustomerService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出客户信息列表
+ */
+ @Log(title = "客户信息", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(CrmCustomerBo bo, HttpServletResponse response) {
+ List list = iCrmCustomerService.queryList(bo);
+ ExcelUtil.exportExcel(list, "客户信息", CrmCustomerVo.class, response);
+ }
+
+ /**
+ * 获取客户信息详细信息
+ *
+ * @param customerId 主键
+ */
+ @GetMapping("/{customerId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable String customerId) {
+ return R.ok(iCrmCustomerService.queryById(customerId));
+ }
+
+ /**
+ * 新增客户信息
+ */
+ @Log(title = "客户信息", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody CrmCustomerBo bo) {
+ return toAjax(iCrmCustomerService.insertByBo(bo));
+ }
+
+ /**
+ * 修改客户信息
+ */
+ @Log(title = "客户信息", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody CrmCustomerBo bo) {
+ return toAjax(iCrmCustomerService.updateByBo(bo));
+ }
+
+ /**
+ * 删除客户信息
+ *
+ * @param customerIds 主键串
+ */
+ @Log(title = "客户信息", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{customerIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable String[] customerIds) {
+ return toAjax(iCrmCustomerService.deleteWithValidByIds(Arrays.asList(customerIds), true));
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderController.java b/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderController.java
new file mode 100644
index 00000000..bdc2d625
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderController.java
@@ -0,0 +1,99 @@
+package com.klp.crm.controller;
+
+import java.util.List;
+import java.util.Arrays;
+
+import lombok.RequiredArgsConstructor;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.*;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import com.klp.common.annotation.RepeatSubmit;
+import com.klp.common.annotation.Log;
+import com.klp.common.core.controller.BaseController;
+import com.klp.common.core.domain.PageQuery;
+import com.klp.common.core.domain.R;
+import com.klp.common.core.validate.AddGroup;
+import com.klp.common.core.validate.EditGroup;
+import com.klp.common.enums.BusinessType;
+import com.klp.common.utils.poi.ExcelUtil;
+import com.klp.crm.domain.vo.CrmOrderVo;
+import com.klp.crm.domain.bo.CrmOrderBo;
+import com.klp.crm.service.ICrmOrderService;
+import com.klp.common.core.page.TableDataInfo;
+
+/**
+ * 正式订单主
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/crm/order")
+public class CrmOrderController extends BaseController {
+
+ private final ICrmOrderService iCrmOrderService;
+
+ /**
+ * 查询正式订单主列表
+ */
+ @GetMapping("/list")
+ public TableDataInfo list(CrmOrderBo bo, PageQuery pageQuery) {
+ return iCrmOrderService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出正式订单主列表
+ */
+ @Log(title = "正式订单主", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(CrmOrderBo bo, HttpServletResponse response) {
+ List list = iCrmOrderService.queryList(bo);
+ ExcelUtil.exportExcel(list, "正式订单主", CrmOrderVo.class, response);
+ }
+
+ /**
+ * 获取正式订单主详细信息
+ *
+ * @param orderId 主键
+ */
+ @GetMapping("/{orderId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable String orderId) {
+ return R.ok(iCrmOrderService.queryById(orderId));
+ }
+
+ /**
+ * 新增正式订单主
+ */
+ @Log(title = "正式订单主", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody CrmOrderBo bo) {
+ return toAjax(iCrmOrderService.insertByBo(bo));
+ }
+
+ /**
+ * 修改正式订单主
+ */
+ @Log(title = "正式订单主", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody CrmOrderBo bo) {
+ return toAjax(iCrmOrderService.updateByBo(bo));
+ }
+
+ /**
+ * 删除正式订单主
+ *
+ * @param orderIds 主键串
+ */
+ @Log(title = "正式订单主", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{orderIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable String[] orderIds) {
+ return toAjax(iCrmOrderService.deleteWithValidByIds(Arrays.asList(orderIds), true));
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderItemController.java b/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderItemController.java
new file mode 100644
index 00000000..b8ae9206
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderItemController.java
@@ -0,0 +1,99 @@
+package com.klp.crm.controller;
+
+import java.util.List;
+import java.util.Arrays;
+
+import lombok.RequiredArgsConstructor;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.*;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import com.klp.common.annotation.RepeatSubmit;
+import com.klp.common.annotation.Log;
+import com.klp.common.core.controller.BaseController;
+import com.klp.common.core.domain.PageQuery;
+import com.klp.common.core.domain.R;
+import com.klp.common.core.validate.AddGroup;
+import com.klp.common.core.validate.EditGroup;
+import com.klp.common.enums.BusinessType;
+import com.klp.common.utils.poi.ExcelUtil;
+import com.klp.crm.domain.vo.CrmOrderItemVo;
+import com.klp.crm.domain.bo.CrmOrderItemBo;
+import com.klp.crm.service.ICrmOrderItemService;
+import com.klp.common.core.page.TableDataInfo;
+
+/**
+ * 正式订单明细
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/crm/orderItem")
+public class CrmOrderItemController extends BaseController {
+
+ private final ICrmOrderItemService iCrmOrderItemService;
+
+ /**
+ * 查询正式订单明细列表
+ */
+ @GetMapping("/list")
+ public TableDataInfo list(CrmOrderItemBo bo, PageQuery pageQuery) {
+ return iCrmOrderItemService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出正式订单明细列表
+ */
+ @Log(title = "正式订单明细", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(CrmOrderItemBo bo, HttpServletResponse response) {
+ List list = iCrmOrderItemService.queryList(bo);
+ ExcelUtil.exportExcel(list, "正式订单明细", CrmOrderItemVo.class, response);
+ }
+
+ /**
+ * 获取正式订单明细详细信息
+ *
+ * @param itemId 主键
+ */
+ @GetMapping("/{itemId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable String itemId) {
+ return R.ok(iCrmOrderItemService.queryById(itemId));
+ }
+
+ /**
+ * 新增正式订单明细
+ */
+ @Log(title = "正式订单明细", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody CrmOrderItemBo bo) {
+ return toAjax(iCrmOrderItemService.insertByBo(bo));
+ }
+
+ /**
+ * 修改正式订单明细
+ */
+ @Log(title = "正式订单明细", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody CrmOrderItemBo bo) {
+ return toAjax(iCrmOrderItemService.updateByBo(bo));
+ }
+
+ /**
+ * 删除正式订单明细
+ *
+ * @param itemIds 主键串
+ */
+ @Log(title = "正式订单明细", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{itemIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable String[] itemIds) {
+ return toAjax(iCrmOrderItemService.deleteWithValidByIds(Arrays.asList(itemIds), true));
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderOperationTraceController.java b/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderOperationTraceController.java
new file mode 100644
index 00000000..38494aec
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/controller/CrmOrderOperationTraceController.java
@@ -0,0 +1,99 @@
+package com.klp.crm.controller;
+
+import java.util.List;
+import java.util.Arrays;
+
+import lombok.RequiredArgsConstructor;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.*;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import com.klp.common.annotation.RepeatSubmit;
+import com.klp.common.annotation.Log;
+import com.klp.common.core.controller.BaseController;
+import com.klp.common.core.domain.PageQuery;
+import com.klp.common.core.domain.R;
+import com.klp.common.core.validate.AddGroup;
+import com.klp.common.core.validate.EditGroup;
+import com.klp.common.enums.BusinessType;
+import com.klp.common.utils.poi.ExcelUtil;
+import com.klp.crm.domain.vo.CrmOrderOperationTraceVo;
+import com.klp.crm.domain.bo.CrmOrderOperationTraceBo;
+import com.klp.crm.service.ICrmOrderOperationTraceService;
+import com.klp.common.core.page.TableDataInfo;
+
+/**
+ * 订单操作追溯
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/crm/orderOperationTrace")
+public class CrmOrderOperationTraceController extends BaseController {
+
+ private final ICrmOrderOperationTraceService iCrmOrderOperationTraceService;
+
+ /**
+ * 查询订单操作追溯列表
+ */
+ @GetMapping("/list")
+ public TableDataInfo list(CrmOrderOperationTraceBo bo, PageQuery pageQuery) {
+ return iCrmOrderOperationTraceService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出订单操作追溯列表
+ */
+ @Log(title = "订单操作追溯", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(CrmOrderOperationTraceBo bo, HttpServletResponse response) {
+ List list = iCrmOrderOperationTraceService.queryList(bo);
+ ExcelUtil.exportExcel(list, "订单操作追溯", CrmOrderOperationTraceVo.class, response);
+ }
+
+ /**
+ * 获取订单操作追溯详细信息
+ *
+ * @param traceId 主键
+ */
+ @GetMapping("/{traceId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable String traceId) {
+ return R.ok(iCrmOrderOperationTraceService.queryById(traceId));
+ }
+
+ /**
+ * 新增订单操作追溯
+ */
+ @Log(title = "订单操作追溯", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody CrmOrderOperationTraceBo bo) {
+ return toAjax(iCrmOrderOperationTraceService.insertByBo(bo));
+ }
+
+ /**
+ * 修改订单操作追溯
+ */
+ @Log(title = "订单操作追溯", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody CrmOrderOperationTraceBo bo) {
+ return toAjax(iCrmOrderOperationTraceService.updateByBo(bo));
+ }
+
+ /**
+ * 删除订单操作追溯
+ *
+ * @param traceIds 主键串
+ */
+ @Log(title = "订单操作追溯", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{traceIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable String[] traceIds) {
+ return toAjax(iCrmOrderOperationTraceService.deleteWithValidByIds(Arrays.asList(traceIds), true));
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/controller/CrmSalesContractController.java b/klp-crm/src/main/java/com/klp/crm/controller/CrmSalesContractController.java
new file mode 100644
index 00000000..aa9f0f25
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/controller/CrmSalesContractController.java
@@ -0,0 +1,99 @@
+package com.klp.crm.controller;
+
+import java.util.List;
+import java.util.Arrays;
+
+import lombok.RequiredArgsConstructor;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.*;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import com.klp.common.annotation.RepeatSubmit;
+import com.klp.common.annotation.Log;
+import com.klp.common.core.controller.BaseController;
+import com.klp.common.core.domain.PageQuery;
+import com.klp.common.core.domain.R;
+import com.klp.common.core.validate.AddGroup;
+import com.klp.common.core.validate.EditGroup;
+import com.klp.common.enums.BusinessType;
+import com.klp.common.utils.poi.ExcelUtil;
+import com.klp.crm.domain.vo.CrmSalesContractVo;
+import com.klp.crm.domain.bo.CrmSalesContractBo;
+import com.klp.crm.service.ICrmSalesContractService;
+import com.klp.common.core.page.TableDataInfo;
+
+/**
+ * 销售合同
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/crm/salesContract")
+public class CrmSalesContractController extends BaseController {
+
+ private final ICrmSalesContractService iCrmSalesContractService;
+
+ /**
+ * 查询销售合同列表
+ */
+ @GetMapping("/list")
+ public TableDataInfo list(CrmSalesContractBo bo, PageQuery pageQuery) {
+ return iCrmSalesContractService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出销售合同列表
+ */
+ @Log(title = "销售合同", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(CrmSalesContractBo bo, HttpServletResponse response) {
+ List list = iCrmSalesContractService.queryList(bo);
+ ExcelUtil.exportExcel(list, "销售合同", CrmSalesContractVo.class, response);
+ }
+
+ /**
+ * 获取销售合同详细信息
+ *
+ * @param contractId 主键
+ */
+ @GetMapping("/{contractId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable String contractId) {
+ return R.ok(iCrmSalesContractService.queryById(contractId));
+ }
+
+ /**
+ * 新增销售合同
+ */
+ @Log(title = "销售合同", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody CrmSalesContractBo bo) {
+ return toAjax(iCrmSalesContractService.insertByBo(bo));
+ }
+
+ /**
+ * 修改销售合同
+ */
+ @Log(title = "销售合同", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody CrmSalesContractBo bo) {
+ return toAjax(iCrmSalesContractService.updateByBo(bo));
+ }
+
+ /**
+ * 删除销售合同
+ *
+ * @param contractIds 主键串
+ */
+ @Log(title = "销售合同", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{contractIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable String[] contractIds) {
+ return toAjax(iCrmSalesContractService.deleteWithValidByIds(Arrays.asList(contractIds), true));
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/controller/CrmSalesObjectionController.java b/klp-crm/src/main/java/com/klp/crm/controller/CrmSalesObjectionController.java
new file mode 100644
index 00000000..eebaca7b
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/controller/CrmSalesObjectionController.java
@@ -0,0 +1,99 @@
+package com.klp.crm.controller;
+
+import java.util.List;
+import java.util.Arrays;
+
+import lombok.RequiredArgsConstructor;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.*;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import com.klp.common.annotation.RepeatSubmit;
+import com.klp.common.annotation.Log;
+import com.klp.common.core.controller.BaseController;
+import com.klp.common.core.domain.PageQuery;
+import com.klp.common.core.domain.R;
+import com.klp.common.core.validate.AddGroup;
+import com.klp.common.core.validate.EditGroup;
+import com.klp.common.enums.BusinessType;
+import com.klp.common.utils.poi.ExcelUtil;
+import com.klp.crm.domain.vo.CrmSalesObjectionVo;
+import com.klp.crm.domain.bo.CrmSalesObjectionBo;
+import com.klp.crm.service.ICrmSalesObjectionService;
+import com.klp.common.core.page.TableDataInfo;
+
+/**
+ * 销售异议管理
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/crm/salesObjection")
+public class CrmSalesObjectionController extends BaseController {
+
+ private final ICrmSalesObjectionService iCrmSalesObjectionService;
+
+ /**
+ * 查询销售异议管理列表
+ */
+ @GetMapping("/list")
+ public TableDataInfo list(CrmSalesObjectionBo bo, PageQuery pageQuery) {
+ return iCrmSalesObjectionService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 导出销售异议管理列表
+ */
+ @Log(title = "销售异议管理", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(CrmSalesObjectionBo bo, HttpServletResponse response) {
+ List list = iCrmSalesObjectionService.queryList(bo);
+ ExcelUtil.exportExcel(list, "销售异议管理", CrmSalesObjectionVo.class, response);
+ }
+
+ /**
+ * 获取销售异议管理详细信息
+ *
+ * @param objectionId 主键
+ */
+ @GetMapping("/{objectionId}")
+ public R getInfo(@NotNull(message = "主键不能为空")
+ @PathVariable String objectionId) {
+ return R.ok(iCrmSalesObjectionService.queryById(objectionId));
+ }
+
+ /**
+ * 新增销售异议管理
+ */
+ @Log(title = "销售异议管理", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R add(@Validated(AddGroup.class) @RequestBody CrmSalesObjectionBo bo) {
+ return toAjax(iCrmSalesObjectionService.insertByBo(bo));
+ }
+
+ /**
+ * 修改销售异议管理
+ */
+ @Log(title = "销售异议管理", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R edit(@Validated(EditGroup.class) @RequestBody CrmSalesObjectionBo bo) {
+ return toAjax(iCrmSalesObjectionService.updateByBo(bo));
+ }
+
+ /**
+ * 删除销售异议管理
+ *
+ * @param objectionIds 主键串
+ */
+ @Log(title = "销售异议管理", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{objectionIds}")
+ public R remove(@NotEmpty(message = "主键不能为空")
+ @PathVariable String[] objectionIds) {
+ return toAjax(iCrmSalesObjectionService.deleteWithValidByIds(Arrays.asList(objectionIds), true));
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/CrmCustomer.java b/klp-crm/src/main/java/com/klp/crm/domain/CrmCustomer.java
new file mode 100644
index 00000000..8cb53c73
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/CrmCustomer.java
@@ -0,0 +1,69 @@
+package com.klp.crm.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.klp.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+/**
+ * 客户信息对象 crm_customer
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("crm_customer")
+public class CrmCustomer extends BaseEntity {
+
+ private static final long serialVersionUID=1L;
+
+ /**
+ * 客户ID(主键)
+ */
+ @TableId(value = "customer_id")
+ private String customerId;
+ /**
+ * 客户统一编码
+ */
+ private String customerCode;
+ /**
+ * 公司名称
+ */
+ private String companyName;
+ /**
+ * 联系人
+ */
+ private String contactPerson;
+ /**
+ * 联系方式(电话/微信等)
+ */
+ private String contactWay;
+ /**
+ * 所属行业
+ */
+ private String industry;
+ /**
+ * 客户等级(如:VIP/普通)
+ */
+ private String customerLevel;
+ /**
+ * 客户地址(需权限查看)
+ */
+ private String address;
+ /**
+ * 银行信息(多条,需权限查看,JSON格式存储)
+ */
+ private String bankInfo;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 删除标识 0正常 2删除
+ */
+ @TableLogic
+ private Long delFlag;
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/CrmOrder.java b/klp-crm/src/main/java/com/klp/crm/domain/CrmOrder.java
new file mode 100644
index 00000000..8e5a09aa
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/CrmOrder.java
@@ -0,0 +1,87 @@
+package com.klp.crm.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 正式订单主对象 crm_order
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("crm_order")
+public class CrmOrder extends BaseEntity {
+
+ private static final long serialVersionUID=1L;
+
+ /**
+ * 订单ID(主键)
+ */
+ @TableId(value = "order_id")
+ private String orderId;
+ /**
+ * 订单编号
+ */
+ private String orderCode;
+ /**
+ * 订单类型:pre-预订单,formal-正式订单
+ */
+ private Long orderType;
+ /**
+ * 关联客户ID
+ */
+ private String customerId;
+ /**
+ * 订单总金额
+ */
+ private BigDecimal orderAmount;
+ /**
+ * 销售员
+ */
+ private String salesman;
+ /**
+ * 交货日期
+ */
+ private Date deliveryDate;
+ /**
+ * 预订单状态
+ */
+ private Long preOrderStatus;
+ /**
+ * 审核人
+ */
+ private String auditUser;
+ /**
+ * 审核时间
+ */
+ private Date auditTime;
+ /**
+ * 订单状态
+ */
+ private Long orderStatus;
+ /**
+ * 财务状态
+ */
+ private Long financeStatus;
+ /**
+ * 未结款数额
+ */
+ private BigDecimal unpaidAmount;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 删除标识 0正常 2删除
+ */
+ @TableLogic
+ private Long delFlag;
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/CrmOrderItem.java b/klp-crm/src/main/java/com/klp/crm/domain/CrmOrderItem.java
new file mode 100644
index 00000000..d92ffe91
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/CrmOrderItem.java
@@ -0,0 +1,61 @@
+package com.klp.crm.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+/**
+ * 正式订单明细对象 crm_order_item
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("crm_order_item")
+public class CrmOrderItem extends BaseEntity {
+
+ private static final long serialVersionUID=1L;
+
+ /**
+ * 正式订单明细ID(主键)
+ */
+ @TableId(value = "item_id")
+ private String itemId;
+ /**
+ * 关联正式订单ID(外键)
+ */
+ private String orderId;
+ /**
+ * 产品类型
+ */
+ private String productType;
+ /**
+ * 规格要求
+ */
+ private String specRequire;
+ /**
+ * 产品数量
+ */
+ private Long productNum;
+ /**
+ * 特殊要求
+ */
+ private String specialRequire;
+ /**
+ * 明细金额(单商品金额)
+ */
+ private BigDecimal itemAmount;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 删除标识 0正常 2删除
+ */
+ @TableLogic
+ private Long delFlag;
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/CrmOrderOperationTrace.java b/klp-crm/src/main/java/com/klp/crm/domain/CrmOrderOperationTrace.java
new file mode 100644
index 00000000..2212faf3
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/CrmOrderOperationTrace.java
@@ -0,0 +1,66 @@
+package com.klp.crm.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 订单操作追溯对象 crm_order_operation_trace
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("crm_order_operation_trace")
+public class CrmOrderOperationTrace extends BaseEntity {
+
+ private static final long serialVersionUID=1L;
+
+ /**
+ * 追溯ID(主键)
+ */
+ @TableId(value = "trace_id")
+ private String traceId;
+ /**
+ * 关联订单ID(外键)
+ */
+ private String orderId;
+ /**
+ * 操作类型(如:创建/修改/审核/取消/发货等)
+ */
+ private String operationType;
+ /**
+ * 操作前状态
+ */
+ private String oldStatus;
+ /**
+ * 操作后状态
+ */
+ private String newStatus;
+ /**
+ * 操作内容(如:修改了交货日期)
+ */
+ private String operationContent;
+ /**
+ * 操作人
+ */
+ private String operator;
+ /**
+ * 操作时间
+ */
+ private Date operationTime;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 删除标识 0正常 2删除
+ */
+ @TableLogic
+ private Long delFlag;
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/CrmSalesContract.java b/klp-crm/src/main/java/com/klp/crm/domain/CrmSalesContract.java
new file mode 100644
index 00000000..62443253
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/CrmSalesContract.java
@@ -0,0 +1,91 @@
+package com.klp.crm.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 销售合同对象 crm_sales_contract
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("crm_sales_contract")
+public class CrmSalesContract extends BaseEntity {
+
+ private static final long serialVersionUID=1L;
+
+ /**
+ * 合同ID(主键)
+ */
+ @TableId(value = "contract_id")
+ private String contractId;
+ /**
+ * 合同编号
+ */
+ private String contractCode;
+ /**
+ * 合同类型
+ */
+ private Long contractType;
+ /**
+ * 关联客户ID(外键)
+ */
+ private String customerId;
+ /**
+ * 合同总金额
+ */
+ private BigDecimal totalAmount;
+ /**
+ * 交货日期
+ */
+ private Date deliveryDate;
+ /**
+ * 合同状态
+ */
+ private Long contractStatus;
+ /**
+ * 录入人
+ */
+ private String createUser;
+ /**
+ * 评审人
+ */
+ private String reviewUser;
+ /**
+ * 评审时间
+ */
+ private Date reviewTime;
+ /**
+ * 审核人
+ */
+ private String auditUser;
+ /**
+ * 审核时间
+ */
+ private Date auditTime;
+ /**
+ * 下发人
+ */
+ private String issueUser;
+ /**
+ * 下发时间
+ */
+ private Date issueTime;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 删除标识 0正常 2删除
+ */
+ @TableLogic
+ private Long delFlag;
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/CrmSalesObjection.java b/klp-crm/src/main/java/com/klp/crm/domain/CrmSalesObjection.java
new file mode 100644
index 00000000..a82b651c
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/CrmSalesObjection.java
@@ -0,0 +1,78 @@
+package com.klp.crm.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 销售异议管理对象 crm_sales_objection
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("crm_sales_objection")
+public class CrmSalesObjection extends BaseEntity {
+
+ private static final long serialVersionUID=1L;
+
+ /**
+ * 异议ID(主键)
+ */
+ @TableId(value = "objection_id")
+ private String objectionId;
+ /**
+ * 异议编号
+ */
+ private String objectionCode;
+ /**
+ * 关联订单ID(外键)
+ */
+ private String orderId;
+ /**
+ * 关联客户ID(外键)
+ */
+ private String customerId;
+ /**
+ * 异议类型(如:质量异议)
+ */
+ private String objectionType;
+ /**
+ * 异议内容
+ */
+ private String objectionContent;
+ /**
+ * 异议状态
+ */
+ private Long objectionStatus;
+ /**
+ * 处理内容
+ */
+ private String handleContent;
+ /**
+ * 处理人
+ */
+ private String handleUser;
+ /**
+ * 处理时间
+ */
+ private Date handleTime;
+ /**
+ * 结案时间
+ */
+ private Date closeTime;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 删除标识 0正常 2删除
+ */
+ @TableLogic
+ private Long delFlag;
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmCustomerBo.java b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmCustomerBo.java
new file mode 100644
index 00000000..0ab38599
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmCustomerBo.java
@@ -0,0 +1,71 @@
+package com.klp.crm.domain.bo;
+
+import com.klp.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import javax.validation.constraints.*;
+
+
+/**
+ * 客户信息业务对象 crm_customer
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CrmCustomerBo extends BaseEntity {
+
+ /**
+ * 客户ID(主键)
+ */
+ private String customerId;
+
+ /**
+ * 客户统一编码
+ */
+ private String customerCode;
+
+ /**
+ * 公司名称
+ */
+ private String companyName;
+
+ /**
+ * 联系人
+ */
+ private String contactPerson;
+
+ /**
+ * 联系方式(电话/微信等)
+ */
+ private String contactWay;
+
+ /**
+ * 所属行业
+ */
+ private String industry;
+
+ /**
+ * 客户等级(如:VIP/普通)
+ */
+ private String customerLevel;
+
+ /**
+ * 客户地址(需权限查看)
+ */
+ private String address;
+
+ /**
+ * 银行信息(多条,需权限查看,JSON格式存储)
+ */
+ private String bankInfo;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderBo.java b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderBo.java
new file mode 100644
index 00000000..42e58d91
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderBo.java
@@ -0,0 +1,94 @@
+package com.klp.crm.domain.bo;
+
+import com.klp.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import javax.validation.constraints.*;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 正式订单主业务对象 crm_order
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CrmOrderBo extends BaseEntity {
+
+ /**
+ * 订单ID(主键)
+ */
+ private String orderId;
+
+ /**
+ * 订单编号
+ */
+ private String orderCode;
+
+ /**
+ * 订单类型:pre-预订单,formal-正式订单
+ */
+ private Long orderType;
+
+ /**
+ * 关联客户ID
+ */
+ private String customerId;
+
+ /**
+ * 订单总金额
+ */
+ private BigDecimal orderAmount;
+
+ /**
+ * 销售员
+ */
+ private String salesman;
+
+ /**
+ * 交货日期
+ */
+ private Date deliveryDate;
+
+ /**
+ * 预订单状态
+ */
+ private Long preOrderStatus;
+
+ /**
+ * 审核人
+ */
+ private String auditUser;
+
+ /**
+ * 审核时间
+ */
+ private Date auditTime;
+
+ /**
+ * 订单状态
+ */
+ private Long orderStatus;
+
+ /**
+ * 财务状态
+ */
+ private Long financeStatus;
+
+ /**
+ * 未结款数额
+ */
+ private BigDecimal unpaidAmount;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderItemBo.java b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderItemBo.java
new file mode 100644
index 00000000..b7e5fd91
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderItemBo.java
@@ -0,0 +1,62 @@
+package com.klp.crm.domain.bo;
+
+import com.klp.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import javax.validation.constraints.*;
+
+import java.math.BigDecimal;
+
+/**
+ * 正式订单明细业务对象 crm_order_item
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CrmOrderItemBo extends BaseEntity {
+
+ /**
+ * 正式订单明细ID(主键)
+ */
+ private String itemId;
+
+ /**
+ * 关联正式订单ID(外键)
+ */
+ private String orderId;
+
+ /**
+ * 产品类型
+ */
+ private String productType;
+
+ /**
+ * 规格要求
+ */
+ private String specRequire;
+
+ /**
+ * 产品数量
+ */
+ private Long productNum;
+
+ /**
+ * 特殊要求
+ */
+ private String specialRequire;
+
+ /**
+ * 明细金额(单商品金额)
+ */
+ private BigDecimal itemAmount;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderOperationTraceBo.java b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderOperationTraceBo.java
new file mode 100644
index 00000000..d5a08cf4
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmOrderOperationTraceBo.java
@@ -0,0 +1,68 @@
+package com.klp.crm.domain.bo;
+
+import com.klp.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import javax.validation.constraints.*;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 订单操作追溯业务对象 crm_order_operation_trace
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CrmOrderOperationTraceBo extends BaseEntity {
+
+ /**
+ * 追溯ID(主键)
+ */
+ private String traceId;
+
+ /**
+ * 关联订单ID(外键)
+ */
+ private String orderId;
+
+ /**
+ * 操作类型(如:创建/修改/审核/取消/发货等)
+ */
+ private String operationType;
+
+ /**
+ * 操作前状态
+ */
+ private String oldStatus;
+
+ /**
+ * 操作后状态
+ */
+ private String newStatus;
+
+ /**
+ * 操作内容(如:修改了交货日期)
+ */
+ private String operationContent;
+
+ /**
+ * 操作人
+ */
+ private String operator;
+
+ /**
+ * 操作时间
+ */
+ private Date operationTime;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmSalesContractBo.java b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmSalesContractBo.java
new file mode 100644
index 00000000..6877cd03
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmSalesContractBo.java
@@ -0,0 +1,99 @@
+package com.klp.crm.domain.bo;
+
+import com.klp.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import javax.validation.constraints.*;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 销售合同业务对象 crm_sales_contract
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CrmSalesContractBo extends BaseEntity {
+
+ /**
+ * 合同ID(主键)
+ */
+ private String contractId;
+
+ /**
+ * 合同编号
+ */
+ private String contractCode;
+
+ /**
+ * 合同类型
+ */
+ private Long contractType;
+
+ /**
+ * 关联客户ID(外键)
+ */
+ private String customerId;
+
+ /**
+ * 合同总金额
+ */
+ private BigDecimal totalAmount;
+
+ /**
+ * 交货日期
+ */
+ private Date deliveryDate;
+
+ /**
+ * 合同状态
+ */
+ private Long contractStatus;
+
+ /**
+ * 录入人
+ */
+ private String createUser;
+
+ /**
+ * 评审人
+ */
+ private String reviewUser;
+
+ /**
+ * 评审时间
+ */
+ private Date reviewTime;
+
+ /**
+ * 审核人
+ */
+ private String auditUser;
+
+ /**
+ * 审核时间
+ */
+ private Date auditTime;
+
+ /**
+ * 下发人
+ */
+ private String issueUser;
+
+ /**
+ * 下发时间
+ */
+ private Date issueTime;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmSalesObjectionBo.java b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmSalesObjectionBo.java
new file mode 100644
index 00000000..0bd027c0
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/bo/CrmSalesObjectionBo.java
@@ -0,0 +1,83 @@
+package com.klp.crm.domain.bo;
+
+import com.klp.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import javax.validation.constraints.*;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 销售异议管理业务对象 crm_sales_objection
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CrmSalesObjectionBo extends BaseEntity {
+
+ /**
+ * 异议ID(主键)
+ */
+ private String objectionId;
+
+ /**
+ * 异议编号
+ */
+ private String objectionCode;
+
+ /**
+ * 关联订单ID(外键)
+ */
+ private String orderId;
+
+ /**
+ * 关联客户ID(外键)
+ */
+ private String customerId;
+
+ /**
+ * 异议类型(如:质量异议)
+ */
+ private String objectionType;
+
+ /**
+ * 异议内容
+ */
+ private String objectionContent;
+
+ /**
+ * 异议状态
+ */
+ private Long objectionStatus;
+
+ /**
+ * 处理内容
+ */
+ private String handleContent;
+
+ /**
+ * 处理人
+ */
+ private String handleUser;
+
+ /**
+ * 处理时间
+ */
+ private Date handleTime;
+
+ /**
+ * 结案时间
+ */
+ private Date closeTime;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmCustomerVo.java b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmCustomerVo.java
new file mode 100644
index 00000000..7bbf4ad3
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmCustomerVo.java
@@ -0,0 +1,88 @@
+package com.klp.crm.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.klp.common.annotation.ExcelDictFormat;
+import com.klp.common.convert.ExcelDictConvert;
+import lombok.Data;
+
+
+/**
+ * 客户信息视图对象 crm_customer
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class CrmCustomerVo {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 客户ID(主键)
+ */
+ @ExcelProperty(value = "客户ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "主=键")
+ private String customerId;
+
+ /**
+ * 客户统一编码
+ */
+ @ExcelProperty(value = "客户统一编码")
+ private String customerCode;
+
+ /**
+ * 公司名称
+ */
+ @ExcelProperty(value = "公司名称")
+ private String companyName;
+
+ /**
+ * 联系人
+ */
+ @ExcelProperty(value = "联系人")
+ private String contactPerson;
+
+ /**
+ * 联系方式(电话/微信等)
+ */
+ @ExcelProperty(value = "联系方式", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "电=话/微信等")
+ private String contactWay;
+
+ /**
+ * 所属行业
+ */
+ @ExcelProperty(value = "所属行业")
+ private String industry;
+
+ /**
+ * 客户等级(如:VIP/普通)
+ */
+ @ExcelProperty(value = "客户等级", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "如=:VIP/普通")
+ private String customerLevel;
+
+ /**
+ * 客户地址(需权限查看)
+ */
+ @ExcelProperty(value = "客户地址", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "需=权限查看")
+ private String address;
+
+ /**
+ * 银行信息(多条,需权限查看,JSON格式存储)
+ */
+ @ExcelProperty(value = "银行信息", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "多=条,需权限查看,JSON格式存储")
+ private String bankInfo;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderItemVo.java b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderItemVo.java
new file mode 100644
index 00000000..51b6870d
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderItemVo.java
@@ -0,0 +1,75 @@
+package com.klp.crm.domain.vo;
+
+import java.math.BigDecimal;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.klp.common.annotation.ExcelDictFormat;
+import com.klp.common.convert.ExcelDictConvert;
+import lombok.Data;
+
+
+/**
+ * 正式订单明细视图对象 crm_order_item
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class CrmOrderItemVo {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 正式订单明细ID(主键)
+ */
+ @ExcelProperty(value = "正式订单明细ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "主=键")
+ private String itemId;
+
+ /**
+ * 关联正式订单ID(外键)
+ */
+ @ExcelProperty(value = "关联正式订单ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "外=键")
+ private String orderId;
+
+ /**
+ * 产品类型
+ */
+ @ExcelProperty(value = "产品类型")
+ private String productType;
+
+ /**
+ * 规格要求
+ */
+ @ExcelProperty(value = "规格要求")
+ private String specRequire;
+
+ /**
+ * 产品数量
+ */
+ @ExcelProperty(value = "产品数量")
+ private Long productNum;
+
+ /**
+ * 特殊要求
+ */
+ @ExcelProperty(value = "特殊要求")
+ private String specialRequire;
+
+ /**
+ * 明细金额(单商品金额)
+ */
+ @ExcelProperty(value = "明细金额", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "单=商品金额")
+ private BigDecimal itemAmount;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderOperationTraceVo.java b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderOperationTraceVo.java
new file mode 100644
index 00000000..37621505
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderOperationTraceVo.java
@@ -0,0 +1,83 @@
+package com.klp.crm.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.klp.common.annotation.ExcelDictFormat;
+import com.klp.common.convert.ExcelDictConvert;
+import lombok.Data;
+
+
+/**
+ * 订单操作追溯视图对象 crm_order_operation_trace
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class CrmOrderOperationTraceVo {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 追溯ID(主键)
+ */
+ @ExcelProperty(value = "追溯ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "主=键")
+ private String traceId;
+
+ /**
+ * 关联订单ID(外键)
+ */
+ @ExcelProperty(value = "关联订单ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "外=键")
+ private String orderId;
+
+ /**
+ * 操作类型(如:创建/修改/审核/取消/发货等)
+ */
+ @ExcelProperty(value = "操作类型", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "如=:创建/修改/审核/取消/发货等")
+ private String operationType;
+
+ /**
+ * 操作前状态
+ */
+ @ExcelProperty(value = "操作前状态")
+ private String oldStatus;
+
+ /**
+ * 操作后状态
+ */
+ @ExcelProperty(value = "操作后状态")
+ private String newStatus;
+
+ /**
+ * 操作内容(如:修改了交货日期)
+ */
+ @ExcelProperty(value = "操作内容", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "如=:修改了交货日期")
+ private String operationContent;
+
+ /**
+ * 操作人
+ */
+ @ExcelProperty(value = "操作人")
+ private String operator;
+
+ /**
+ * 操作时间
+ */
+ @ExcelProperty(value = "操作时间")
+ private Date operationTime;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderVo.java b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderVo.java
new file mode 100644
index 00000000..12a5ecb3
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmOrderVo.java
@@ -0,0 +1,111 @@
+package com.klp.crm.domain.vo;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.klp.common.annotation.ExcelDictFormat;
+import com.klp.common.convert.ExcelDictConvert;
+import lombok.Data;
+
+
+/**
+ * 正式订单主视图对象 crm_order
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class CrmOrderVo {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 订单ID(主键)
+ */
+ @ExcelProperty(value = "订单ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "主=键")
+ private String orderId;
+
+ /**
+ * 订单编号
+ */
+ @ExcelProperty(value = "订单编号")
+ private String orderCode;
+
+ /**
+ * 订单类型:pre-预订单,formal-正式订单
+ */
+ @ExcelProperty(value = "订单类型:pre-预订单,formal-正式订单")
+ private Long orderType;
+
+ /**
+ * 关联客户ID
+ */
+ @ExcelProperty(value = "关联客户ID")
+ private String customerId;
+
+ /**
+ * 订单总金额
+ */
+ @ExcelProperty(value = "订单总金额")
+ private BigDecimal orderAmount;
+
+ /**
+ * 销售员
+ */
+ @ExcelProperty(value = "销售员")
+ private String salesman;
+
+ /**
+ * 交货日期
+ */
+ @ExcelProperty(value = "交货日期")
+ private Date deliveryDate;
+
+ /**
+ * 预订单状态
+ */
+ @ExcelProperty(value = "预订单状态")
+ private Long preOrderStatus;
+
+ /**
+ * 审核人
+ */
+ @ExcelProperty(value = "审核人")
+ private String auditUser;
+
+ /**
+ * 审核时间
+ */
+ @ExcelProperty(value = "审核时间")
+ private Date auditTime;
+
+ /**
+ * 订单状态
+ */
+ @ExcelProperty(value = "订单状态")
+ private Long orderStatus;
+
+ /**
+ * 财务状态
+ */
+ @ExcelProperty(value = "财务状态")
+ private Long financeStatus;
+
+ /**
+ * 未结款数额
+ */
+ @ExcelProperty(value = "未结款数额")
+ private BigDecimal unpaidAmount;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmSalesContractVo.java b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmSalesContractVo.java
new file mode 100644
index 00000000..71cacfce
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmSalesContractVo.java
@@ -0,0 +1,118 @@
+package com.klp.crm.domain.vo;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.klp.common.annotation.ExcelDictFormat;
+import com.klp.common.convert.ExcelDictConvert;
+import lombok.Data;
+
+
+/**
+ * 销售合同视图对象 crm_sales_contract
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class CrmSalesContractVo {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 合同ID(主键)
+ */
+ @ExcelProperty(value = "合同ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "主=键")
+ private String contractId;
+
+ /**
+ * 合同编号
+ */
+ @ExcelProperty(value = "合同编号")
+ private String contractCode;
+
+ /**
+ * 合同类型
+ */
+ @ExcelProperty(value = "合同类型")
+ private Long contractType;
+
+ /**
+ * 关联客户ID(外键)
+ */
+ @ExcelProperty(value = "关联客户ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "外=键")
+ private String customerId;
+
+ /**
+ * 合同总金额
+ */
+ @ExcelProperty(value = "合同总金额")
+ private BigDecimal totalAmount;
+
+ /**
+ * 交货日期
+ */
+ @ExcelProperty(value = "交货日期")
+ private Date deliveryDate;
+
+ /**
+ * 合同状态
+ */
+ @ExcelProperty(value = "合同状态")
+ private Long contractStatus;
+
+ /**
+ * 录入人
+ */
+ @ExcelProperty(value = "录入人")
+ private String createUser;
+
+ /**
+ * 评审人
+ */
+ @ExcelProperty(value = "评审人")
+ private String reviewUser;
+
+ /**
+ * 评审时间
+ */
+ @ExcelProperty(value = "评审时间")
+ private Date reviewTime;
+
+ /**
+ * 审核人
+ */
+ @ExcelProperty(value = "审核人")
+ private String auditUser;
+
+ /**
+ * 审核时间
+ */
+ @ExcelProperty(value = "审核时间")
+ private Date auditTime;
+
+ /**
+ * 下发人
+ */
+ @ExcelProperty(value = "下发人")
+ private String issueUser;
+
+ /**
+ * 下发时间
+ */
+ @ExcelProperty(value = "下发时间")
+ private Date issueTime;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmSalesObjectionVo.java b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmSalesObjectionVo.java
new file mode 100644
index 00000000..9ebf0f7f
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/domain/vo/CrmSalesObjectionVo.java
@@ -0,0 +1,101 @@
+package com.klp.crm.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.klp.common.annotation.ExcelDictFormat;
+import com.klp.common.convert.ExcelDictConvert;
+import lombok.Data;
+
+
+/**
+ * 销售异议管理视图对象 crm_sales_objection
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class CrmSalesObjectionVo {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 异议ID(主键)
+ */
+ @ExcelProperty(value = "异议ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "主=键")
+ private String objectionId;
+
+ /**
+ * 异议编号
+ */
+ @ExcelProperty(value = "异议编号")
+ private String objectionCode;
+
+ /**
+ * 关联订单ID(外键)
+ */
+ @ExcelProperty(value = "关联订单ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "外=键")
+ private String orderId;
+
+ /**
+ * 关联客户ID(外键)
+ */
+ @ExcelProperty(value = "关联客户ID", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "外=键")
+ private String customerId;
+
+ /**
+ * 异议类型(如:质量异议)
+ */
+ @ExcelProperty(value = "异议类型", converter = ExcelDictConvert.class)
+ @ExcelDictFormat(readConverterExp = "如=:质量异议")
+ private String objectionType;
+
+ /**
+ * 异议内容
+ */
+ @ExcelProperty(value = "异议内容")
+ private String objectionContent;
+
+ /**
+ * 异议状态
+ */
+ @ExcelProperty(value = "异议状态")
+ private Long objectionStatus;
+
+ /**
+ * 处理内容
+ */
+ @ExcelProperty(value = "处理内容")
+ private String handleContent;
+
+ /**
+ * 处理人
+ */
+ @ExcelProperty(value = "处理人")
+ private String handleUser;
+
+ /**
+ * 处理时间
+ */
+ @ExcelProperty(value = "处理时间")
+ private Date handleTime;
+
+ /**
+ * 结案时间
+ */
+ @ExcelProperty(value = "结案时间")
+ private Date closeTime;
+
+ /**
+ * 备注
+ */
+ @ExcelProperty(value = "备注")
+ private String remark;
+
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/mapper/CrmCustomerMapper.java b/klp-crm/src/main/java/com/klp/crm/mapper/CrmCustomerMapper.java
new file mode 100644
index 00000000..afba5029
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/mapper/CrmCustomerMapper.java
@@ -0,0 +1,15 @@
+package com.klp.crm.mapper;
+
+import com.klp.crm.domain.CrmCustomer;
+import com.klp.crm.domain.vo.CrmCustomerVo;
+import com.klp.common.core.mapper.BaseMapperPlus;
+
+/**
+ * 客户信息Mapper接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface CrmCustomerMapper extends BaseMapperPlus {
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderItemMapper.java b/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderItemMapper.java
new file mode 100644
index 00000000..9dde0157
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderItemMapper.java
@@ -0,0 +1,15 @@
+package com.klp.crm.mapper;
+
+import com.klp.crm.domain.CrmOrderItem;
+import com.klp.crm.domain.vo.CrmOrderItemVo;
+import com.klp.common.core.mapper.BaseMapperPlus;
+
+/**
+ * 正式订单明细Mapper接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface CrmOrderItemMapper extends BaseMapperPlus {
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderMapper.java b/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderMapper.java
new file mode 100644
index 00000000..4287ac88
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderMapper.java
@@ -0,0 +1,15 @@
+package com.klp.crm.mapper;
+
+import com.klp.crm.domain.CrmOrder;
+import com.klp.crm.domain.vo.CrmOrderVo;
+import com.klp.common.core.mapper.BaseMapperPlus;
+
+/**
+ * 正式订单主Mapper接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface CrmOrderMapper extends BaseMapperPlus {
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderOperationTraceMapper.java b/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderOperationTraceMapper.java
new file mode 100644
index 00000000..e370aa68
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/mapper/CrmOrderOperationTraceMapper.java
@@ -0,0 +1,15 @@
+package com.klp.crm.mapper;
+
+import com.klp.crm.domain.CrmOrderOperationTrace;
+import com.klp.crm.domain.vo.CrmOrderOperationTraceVo;
+import com.klp.common.core.mapper.BaseMapperPlus;
+
+/**
+ * 订单操作追溯Mapper接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface CrmOrderOperationTraceMapper extends BaseMapperPlus {
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/mapper/CrmSalesContractMapper.java b/klp-crm/src/main/java/com/klp/crm/mapper/CrmSalesContractMapper.java
new file mode 100644
index 00000000..905592d6
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/mapper/CrmSalesContractMapper.java
@@ -0,0 +1,15 @@
+package com.klp.crm.mapper;
+
+import com.klp.crm.domain.CrmSalesContract;
+import com.klp.crm.domain.vo.CrmSalesContractVo;
+import com.klp.common.core.mapper.BaseMapperPlus;
+
+/**
+ * 销售合同Mapper接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface CrmSalesContractMapper extends BaseMapperPlus {
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/mapper/CrmSalesObjectionMapper.java b/klp-crm/src/main/java/com/klp/crm/mapper/CrmSalesObjectionMapper.java
new file mode 100644
index 00000000..0bcaa86d
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/mapper/CrmSalesObjectionMapper.java
@@ -0,0 +1,15 @@
+package com.klp.crm.mapper;
+
+import com.klp.crm.domain.CrmSalesObjection;
+import com.klp.crm.domain.vo.CrmSalesObjectionVo;
+import com.klp.common.core.mapper.BaseMapperPlus;
+
+/**
+ * 销售异议管理Mapper接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface CrmSalesObjectionMapper extends BaseMapperPlus {
+
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/ICrmCustomerService.java b/klp-crm/src/main/java/com/klp/crm/service/ICrmCustomerService.java
new file mode 100644
index 00000000..7649a614
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/ICrmCustomerService.java
@@ -0,0 +1,49 @@
+package com.klp.crm.service;
+
+import com.klp.crm.domain.CrmCustomer;
+import com.klp.crm.domain.vo.CrmCustomerVo;
+import com.klp.crm.domain.bo.CrmCustomerBo;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 客户信息Service接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface ICrmCustomerService {
+
+ /**
+ * 查询客户信息
+ */
+ CrmCustomerVo queryById(String customerId);
+
+ /**
+ * 查询客户信息列表
+ */
+ TableDataInfo queryPageList(CrmCustomerBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询客户信息列表
+ */
+ List queryList(CrmCustomerBo bo);
+
+ /**
+ * 新增客户信息
+ */
+ Boolean insertByBo(CrmCustomerBo bo);
+
+ /**
+ * 修改客户信息
+ */
+ Boolean updateByBo(CrmCustomerBo bo);
+
+ /**
+ * 校验并批量删除客户信息信息
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderItemService.java b/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderItemService.java
new file mode 100644
index 00000000..c55da3c3
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderItemService.java
@@ -0,0 +1,49 @@
+package com.klp.crm.service;
+
+import com.klp.crm.domain.CrmOrderItem;
+import com.klp.crm.domain.vo.CrmOrderItemVo;
+import com.klp.crm.domain.bo.CrmOrderItemBo;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 正式订单明细Service接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface ICrmOrderItemService {
+
+ /**
+ * 查询正式订单明细
+ */
+ CrmOrderItemVo queryById(String itemId);
+
+ /**
+ * 查询正式订单明细列表
+ */
+ TableDataInfo queryPageList(CrmOrderItemBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询正式订单明细列表
+ */
+ List queryList(CrmOrderItemBo bo);
+
+ /**
+ * 新增正式订单明细
+ */
+ Boolean insertByBo(CrmOrderItemBo bo);
+
+ /**
+ * 修改正式订单明细
+ */
+ Boolean updateByBo(CrmOrderItemBo bo);
+
+ /**
+ * 校验并批量删除正式订单明细信息
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderOperationTraceService.java b/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderOperationTraceService.java
new file mode 100644
index 00000000..f92ed32d
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderOperationTraceService.java
@@ -0,0 +1,49 @@
+package com.klp.crm.service;
+
+import com.klp.crm.domain.CrmOrderOperationTrace;
+import com.klp.crm.domain.vo.CrmOrderOperationTraceVo;
+import com.klp.crm.domain.bo.CrmOrderOperationTraceBo;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 订单操作追溯Service接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface ICrmOrderOperationTraceService {
+
+ /**
+ * 查询订单操作追溯
+ */
+ CrmOrderOperationTraceVo queryById(String traceId);
+
+ /**
+ * 查询订单操作追溯列表
+ */
+ TableDataInfo queryPageList(CrmOrderOperationTraceBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询订单操作追溯列表
+ */
+ List queryList(CrmOrderOperationTraceBo bo);
+
+ /**
+ * 新增订单操作追溯
+ */
+ Boolean insertByBo(CrmOrderOperationTraceBo bo);
+
+ /**
+ * 修改订单操作追溯
+ */
+ Boolean updateByBo(CrmOrderOperationTraceBo bo);
+
+ /**
+ * 校验并批量删除订单操作追溯信息
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderService.java b/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderService.java
new file mode 100644
index 00000000..6c7d2236
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/ICrmOrderService.java
@@ -0,0 +1,49 @@
+package com.klp.crm.service;
+
+import com.klp.crm.domain.CrmOrder;
+import com.klp.crm.domain.vo.CrmOrderVo;
+import com.klp.crm.domain.bo.CrmOrderBo;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 正式订单主Service接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface ICrmOrderService {
+
+ /**
+ * 查询正式订单主
+ */
+ CrmOrderVo queryById(String orderId);
+
+ /**
+ * 查询正式订单主列表
+ */
+ TableDataInfo queryPageList(CrmOrderBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询正式订单主列表
+ */
+ List queryList(CrmOrderBo bo);
+
+ /**
+ * 新增正式订单主
+ */
+ Boolean insertByBo(CrmOrderBo bo);
+
+ /**
+ * 修改正式订单主
+ */
+ Boolean updateByBo(CrmOrderBo bo);
+
+ /**
+ * 校验并批量删除正式订单主信息
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/ICrmSalesContractService.java b/klp-crm/src/main/java/com/klp/crm/service/ICrmSalesContractService.java
new file mode 100644
index 00000000..ac7bbc75
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/ICrmSalesContractService.java
@@ -0,0 +1,49 @@
+package com.klp.crm.service;
+
+import com.klp.crm.domain.CrmSalesContract;
+import com.klp.crm.domain.vo.CrmSalesContractVo;
+import com.klp.crm.domain.bo.CrmSalesContractBo;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 销售合同Service接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface ICrmSalesContractService {
+
+ /**
+ * 查询销售合同
+ */
+ CrmSalesContractVo queryById(String contractId);
+
+ /**
+ * 查询销售合同列表
+ */
+ TableDataInfo queryPageList(CrmSalesContractBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询销售合同列表
+ */
+ List queryList(CrmSalesContractBo bo);
+
+ /**
+ * 新增销售合同
+ */
+ Boolean insertByBo(CrmSalesContractBo bo);
+
+ /**
+ * 修改销售合同
+ */
+ Boolean updateByBo(CrmSalesContractBo bo);
+
+ /**
+ * 校验并批量删除销售合同信息
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/ICrmSalesObjectionService.java b/klp-crm/src/main/java/com/klp/crm/service/ICrmSalesObjectionService.java
new file mode 100644
index 00000000..a8193680
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/ICrmSalesObjectionService.java
@@ -0,0 +1,49 @@
+package com.klp.crm.service;
+
+import com.klp.crm.domain.CrmSalesObjection;
+import com.klp.crm.domain.vo.CrmSalesObjectionVo;
+import com.klp.crm.domain.bo.CrmSalesObjectionBo;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 销售异议管理Service接口
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+public interface ICrmSalesObjectionService {
+
+ /**
+ * 查询销售异议管理
+ */
+ CrmSalesObjectionVo queryById(String objectionId);
+
+ /**
+ * 查询销售异议管理列表
+ */
+ TableDataInfo queryPageList(CrmSalesObjectionBo bo, PageQuery pageQuery);
+
+ /**
+ * 查询销售异议管理列表
+ */
+ List queryList(CrmSalesObjectionBo bo);
+
+ /**
+ * 新增销售异议管理
+ */
+ Boolean insertByBo(CrmSalesObjectionBo bo);
+
+ /**
+ * 修改销售异议管理
+ */
+ Boolean updateByBo(CrmSalesObjectionBo bo);
+
+ /**
+ * 校验并批量删除销售异议管理信息
+ */
+ Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/impl/CrmCustomerServiceImpl.java b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmCustomerServiceImpl.java
new file mode 100644
index 00000000..f02841bd
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmCustomerServiceImpl.java
@@ -0,0 +1,116 @@
+package com.klp.crm.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.klp.common.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import com.klp.crm.domain.bo.CrmCustomerBo;
+import com.klp.crm.domain.vo.CrmCustomerVo;
+import com.klp.crm.domain.CrmCustomer;
+import com.klp.crm.mapper.CrmCustomerMapper;
+import com.klp.crm.service.ICrmCustomerService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 客户信息Service业务层处理
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@RequiredArgsConstructor
+@Service
+public class CrmCustomerServiceImpl implements ICrmCustomerService {
+
+ private final CrmCustomerMapper baseMapper;
+
+ /**
+ * 查询客户信息
+ */
+ @Override
+ public CrmCustomerVo queryById(String customerId){
+ return baseMapper.selectVoById(customerId);
+ }
+
+ /**
+ * 查询客户信息列表
+ */
+ @Override
+ public TableDataInfo queryPageList(CrmCustomerBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询客户信息列表
+ */
+ @Override
+ public List queryList(CrmCustomerBo bo) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(CrmCustomerBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.eq(StringUtils.isNotBlank(bo.getCustomerCode()), CrmCustomer::getCustomerCode, bo.getCustomerCode());
+ lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), CrmCustomer::getCompanyName, bo.getCompanyName());
+ lqw.eq(StringUtils.isNotBlank(bo.getContactPerson()), CrmCustomer::getContactPerson, bo.getContactPerson());
+ lqw.eq(StringUtils.isNotBlank(bo.getContactWay()), CrmCustomer::getContactWay, bo.getContactWay());
+ lqw.eq(StringUtils.isNotBlank(bo.getIndustry()), CrmCustomer::getIndustry, bo.getIndustry());
+ lqw.eq(StringUtils.isNotBlank(bo.getCustomerLevel()), CrmCustomer::getCustomerLevel, bo.getCustomerLevel());
+ lqw.eq(StringUtils.isNotBlank(bo.getAddress()), CrmCustomer::getAddress, bo.getAddress());
+ lqw.eq(StringUtils.isNotBlank(bo.getBankInfo()), CrmCustomer::getBankInfo, bo.getBankInfo());
+ return lqw;
+ }
+
+ /**
+ * 新增客户信息
+ */
+ @Override
+ public Boolean insertByBo(CrmCustomerBo bo) {
+ CrmCustomer add = BeanUtil.toBean(bo, CrmCustomer.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setCustomerId(add.getCustomerId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改客户信息
+ */
+ @Override
+ public Boolean updateByBo(CrmCustomerBo bo) {
+ CrmCustomer update = BeanUtil.toBean(bo, CrmCustomer.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(CrmCustomer entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 批量删除客户信息
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteBatchIds(ids) > 0;
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderItemServiceImpl.java b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderItemServiceImpl.java
new file mode 100644
index 00000000..9ee3aa50
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderItemServiceImpl.java
@@ -0,0 +1,114 @@
+package com.klp.crm.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.klp.common.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import com.klp.crm.domain.bo.CrmOrderItemBo;
+import com.klp.crm.domain.vo.CrmOrderItemVo;
+import com.klp.crm.domain.CrmOrderItem;
+import com.klp.crm.mapper.CrmOrderItemMapper;
+import com.klp.crm.service.ICrmOrderItemService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 正式订单明细Service业务层处理
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@RequiredArgsConstructor
+@Service
+public class CrmOrderItemServiceImpl implements ICrmOrderItemService {
+
+ private final CrmOrderItemMapper baseMapper;
+
+ /**
+ * 查询正式订单明细
+ */
+ @Override
+ public CrmOrderItemVo queryById(String itemId){
+ return baseMapper.selectVoById(itemId);
+ }
+
+ /**
+ * 查询正式订单明细列表
+ */
+ @Override
+ public TableDataInfo queryPageList(CrmOrderItemBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询正式订单明细列表
+ */
+ @Override
+ public List queryList(CrmOrderItemBo bo) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(CrmOrderItemBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.eq(StringUtils.isNotBlank(bo.getOrderId()), CrmOrderItem::getOrderId, bo.getOrderId());
+ lqw.eq(StringUtils.isNotBlank(bo.getProductType()), CrmOrderItem::getProductType, bo.getProductType());
+ lqw.eq(StringUtils.isNotBlank(bo.getSpecRequire()), CrmOrderItem::getSpecRequire, bo.getSpecRequire());
+ lqw.eq(bo.getProductNum() != null, CrmOrderItem::getProductNum, bo.getProductNum());
+ lqw.eq(StringUtils.isNotBlank(bo.getSpecialRequire()), CrmOrderItem::getSpecialRequire, bo.getSpecialRequire());
+ lqw.eq(bo.getItemAmount() != null, CrmOrderItem::getItemAmount, bo.getItemAmount());
+ return lqw;
+ }
+
+ /**
+ * 新增正式订单明细
+ */
+ @Override
+ public Boolean insertByBo(CrmOrderItemBo bo) {
+ CrmOrderItem add = BeanUtil.toBean(bo, CrmOrderItem.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setItemId(add.getItemId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改正式订单明细
+ */
+ @Override
+ public Boolean updateByBo(CrmOrderItemBo bo) {
+ CrmOrderItem update = BeanUtil.toBean(bo, CrmOrderItem.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(CrmOrderItem entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 批量删除正式订单明细
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteBatchIds(ids) > 0;
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderOperationTraceServiceImpl.java b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderOperationTraceServiceImpl.java
new file mode 100644
index 00000000..8ba98523
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderOperationTraceServiceImpl.java
@@ -0,0 +1,115 @@
+package com.klp.crm.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.klp.common.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import com.klp.crm.domain.bo.CrmOrderOperationTraceBo;
+import com.klp.crm.domain.vo.CrmOrderOperationTraceVo;
+import com.klp.crm.domain.CrmOrderOperationTrace;
+import com.klp.crm.mapper.CrmOrderOperationTraceMapper;
+import com.klp.crm.service.ICrmOrderOperationTraceService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 订单操作追溯Service业务层处理
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@RequiredArgsConstructor
+@Service
+public class CrmOrderOperationTraceServiceImpl implements ICrmOrderOperationTraceService {
+
+ private final CrmOrderOperationTraceMapper baseMapper;
+
+ /**
+ * 查询订单操作追溯
+ */
+ @Override
+ public CrmOrderOperationTraceVo queryById(String traceId){
+ return baseMapper.selectVoById(traceId);
+ }
+
+ /**
+ * 查询订单操作追溯列表
+ */
+ @Override
+ public TableDataInfo queryPageList(CrmOrderOperationTraceBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询订单操作追溯列表
+ */
+ @Override
+ public List queryList(CrmOrderOperationTraceBo bo) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(CrmOrderOperationTraceBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.eq(StringUtils.isNotBlank(bo.getOrderId()), CrmOrderOperationTrace::getOrderId, bo.getOrderId());
+ lqw.eq(StringUtils.isNotBlank(bo.getOperationType()), CrmOrderOperationTrace::getOperationType, bo.getOperationType());
+ lqw.eq(StringUtils.isNotBlank(bo.getOldStatus()), CrmOrderOperationTrace::getOldStatus, bo.getOldStatus());
+ lqw.eq(StringUtils.isNotBlank(bo.getNewStatus()), CrmOrderOperationTrace::getNewStatus, bo.getNewStatus());
+ lqw.eq(StringUtils.isNotBlank(bo.getOperationContent()), CrmOrderOperationTrace::getOperationContent, bo.getOperationContent());
+ lqw.eq(StringUtils.isNotBlank(bo.getOperator()), CrmOrderOperationTrace::getOperator, bo.getOperator());
+ lqw.eq(bo.getOperationTime() != null, CrmOrderOperationTrace::getOperationTime, bo.getOperationTime());
+ return lqw;
+ }
+
+ /**
+ * 新增订单操作追溯
+ */
+ @Override
+ public Boolean insertByBo(CrmOrderOperationTraceBo bo) {
+ CrmOrderOperationTrace add = BeanUtil.toBean(bo, CrmOrderOperationTrace.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setTraceId(add.getTraceId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改订单操作追溯
+ */
+ @Override
+ public Boolean updateByBo(CrmOrderOperationTraceBo bo) {
+ CrmOrderOperationTrace update = BeanUtil.toBean(bo, CrmOrderOperationTrace.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(CrmOrderOperationTrace entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 批量删除订单操作追溯
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteBatchIds(ids) > 0;
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderServiceImpl.java b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderServiceImpl.java
new file mode 100644
index 00000000..ae39a9b4
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmOrderServiceImpl.java
@@ -0,0 +1,120 @@
+package com.klp.crm.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.klp.common.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import com.klp.crm.domain.bo.CrmOrderBo;
+import com.klp.crm.domain.vo.CrmOrderVo;
+import com.klp.crm.domain.CrmOrder;
+import com.klp.crm.mapper.CrmOrderMapper;
+import com.klp.crm.service.ICrmOrderService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 正式订单主Service业务层处理
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@RequiredArgsConstructor
+@Service
+public class CrmOrderServiceImpl implements ICrmOrderService {
+
+ private final CrmOrderMapper baseMapper;
+
+ /**
+ * 查询正式订单主
+ */
+ @Override
+ public CrmOrderVo queryById(String orderId){
+ return baseMapper.selectVoById(orderId);
+ }
+
+ /**
+ * 查询正式订单主列表
+ */
+ @Override
+ public TableDataInfo queryPageList(CrmOrderBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询正式订单主列表
+ */
+ @Override
+ public List queryList(CrmOrderBo bo) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(CrmOrderBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.eq(StringUtils.isNotBlank(bo.getOrderCode()), CrmOrder::getOrderCode, bo.getOrderCode());
+ lqw.eq(bo.getOrderType() != null, CrmOrder::getOrderType, bo.getOrderType());
+ lqw.eq(StringUtils.isNotBlank(bo.getCustomerId()), CrmOrder::getCustomerId, bo.getCustomerId());
+ lqw.eq(bo.getOrderAmount() != null, CrmOrder::getOrderAmount, bo.getOrderAmount());
+ lqw.eq(StringUtils.isNotBlank(bo.getSalesman()), CrmOrder::getSalesman, bo.getSalesman());
+ lqw.eq(bo.getDeliveryDate() != null, CrmOrder::getDeliveryDate, bo.getDeliveryDate());
+ lqw.eq(bo.getPreOrderStatus() != null, CrmOrder::getPreOrderStatus, bo.getPreOrderStatus());
+ lqw.eq(StringUtils.isNotBlank(bo.getAuditUser()), CrmOrder::getAuditUser, bo.getAuditUser());
+ lqw.eq(bo.getAuditTime() != null, CrmOrder::getAuditTime, bo.getAuditTime());
+ lqw.eq(bo.getOrderStatus() != null, CrmOrder::getOrderStatus, bo.getOrderStatus());
+ lqw.eq(bo.getFinanceStatus() != null, CrmOrder::getFinanceStatus, bo.getFinanceStatus());
+ lqw.eq(bo.getUnpaidAmount() != null, CrmOrder::getUnpaidAmount, bo.getUnpaidAmount());
+ return lqw;
+ }
+
+ /**
+ * 新增正式订单主
+ */
+ @Override
+ public Boolean insertByBo(CrmOrderBo bo) {
+ CrmOrder add = BeanUtil.toBean(bo, CrmOrder.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setOrderId(add.getOrderId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改正式订单主
+ */
+ @Override
+ public Boolean updateByBo(CrmOrderBo bo) {
+ CrmOrder update = BeanUtil.toBean(bo, CrmOrder.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(CrmOrder entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 批量删除正式订单主
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteBatchIds(ids) > 0;
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/impl/CrmSalesContractServiceImpl.java b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmSalesContractServiceImpl.java
new file mode 100644
index 00000000..f27b062e
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmSalesContractServiceImpl.java
@@ -0,0 +1,121 @@
+package com.klp.crm.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.klp.common.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import com.klp.crm.domain.bo.CrmSalesContractBo;
+import com.klp.crm.domain.vo.CrmSalesContractVo;
+import com.klp.crm.domain.CrmSalesContract;
+import com.klp.crm.mapper.CrmSalesContractMapper;
+import com.klp.crm.service.ICrmSalesContractService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 销售合同Service业务层处理
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@RequiredArgsConstructor
+@Service
+public class CrmSalesContractServiceImpl implements ICrmSalesContractService {
+
+ private final CrmSalesContractMapper baseMapper;
+
+ /**
+ * 查询销售合同
+ */
+ @Override
+ public CrmSalesContractVo queryById(String contractId){
+ return baseMapper.selectVoById(contractId);
+ }
+
+ /**
+ * 查询销售合同列表
+ */
+ @Override
+ public TableDataInfo queryPageList(CrmSalesContractBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询销售合同列表
+ */
+ @Override
+ public List queryList(CrmSalesContractBo bo) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(CrmSalesContractBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.eq(StringUtils.isNotBlank(bo.getContractCode()), CrmSalesContract::getContractCode, bo.getContractCode());
+ lqw.eq(bo.getContractType() != null, CrmSalesContract::getContractType, bo.getContractType());
+ lqw.eq(StringUtils.isNotBlank(bo.getCustomerId()), CrmSalesContract::getCustomerId, bo.getCustomerId());
+ lqw.eq(bo.getTotalAmount() != null, CrmSalesContract::getTotalAmount, bo.getTotalAmount());
+ lqw.eq(bo.getDeliveryDate() != null, CrmSalesContract::getDeliveryDate, bo.getDeliveryDate());
+ lqw.eq(bo.getContractStatus() != null, CrmSalesContract::getContractStatus, bo.getContractStatus());
+ lqw.eq(StringUtils.isNotBlank(bo.getCreateUser()), CrmSalesContract::getCreateUser, bo.getCreateUser());
+ lqw.eq(StringUtils.isNotBlank(bo.getReviewUser()), CrmSalesContract::getReviewUser, bo.getReviewUser());
+ lqw.eq(bo.getReviewTime() != null, CrmSalesContract::getReviewTime, bo.getReviewTime());
+ lqw.eq(StringUtils.isNotBlank(bo.getAuditUser()), CrmSalesContract::getAuditUser, bo.getAuditUser());
+ lqw.eq(bo.getAuditTime() != null, CrmSalesContract::getAuditTime, bo.getAuditTime());
+ lqw.eq(StringUtils.isNotBlank(bo.getIssueUser()), CrmSalesContract::getIssueUser, bo.getIssueUser());
+ lqw.eq(bo.getIssueTime() != null, CrmSalesContract::getIssueTime, bo.getIssueTime());
+ return lqw;
+ }
+
+ /**
+ * 新增销售合同
+ */
+ @Override
+ public Boolean insertByBo(CrmSalesContractBo bo) {
+ CrmSalesContract add = BeanUtil.toBean(bo, CrmSalesContract.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setContractId(add.getContractId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改销售合同
+ */
+ @Override
+ public Boolean updateByBo(CrmSalesContractBo bo) {
+ CrmSalesContract update = BeanUtil.toBean(bo, CrmSalesContract.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(CrmSalesContract entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 批量删除销售合同
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteBatchIds(ids) > 0;
+ }
+}
diff --git a/klp-crm/src/main/java/com/klp/crm/service/impl/CrmSalesObjectionServiceImpl.java b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmSalesObjectionServiceImpl.java
new file mode 100644
index 00000000..d2589a0b
--- /dev/null
+++ b/klp-crm/src/main/java/com/klp/crm/service/impl/CrmSalesObjectionServiceImpl.java
@@ -0,0 +1,118 @@
+package com.klp.crm.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.klp.common.core.page.TableDataInfo;
+import com.klp.common.core.domain.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.klp.common.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import com.klp.crm.domain.bo.CrmSalesObjectionBo;
+import com.klp.crm.domain.vo.CrmSalesObjectionVo;
+import com.klp.crm.domain.CrmSalesObjection;
+import com.klp.crm.mapper.CrmSalesObjectionMapper;
+import com.klp.crm.service.ICrmSalesObjectionService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 销售异议管理Service业务层处理
+ *
+ * @author klp
+ * @date 2025-12-15
+ */
+@RequiredArgsConstructor
+@Service
+public class CrmSalesObjectionServiceImpl implements ICrmSalesObjectionService {
+
+ private final CrmSalesObjectionMapper baseMapper;
+
+ /**
+ * 查询销售异议管理
+ */
+ @Override
+ public CrmSalesObjectionVo queryById(String objectionId){
+ return baseMapper.selectVoById(objectionId);
+ }
+
+ /**
+ * 查询销售异议管理列表
+ */
+ @Override
+ public TableDataInfo queryPageList(CrmSalesObjectionBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 查询销售异议管理列表
+ */
+ @Override
+ public List queryList(CrmSalesObjectionBo bo) {
+ LambdaQueryWrapper lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper buildQueryWrapper(CrmSalesObjectionBo bo) {
+ Map params = bo.getParams();
+ LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
+ lqw.eq(StringUtils.isNotBlank(bo.getObjectionCode()), CrmSalesObjection::getObjectionCode, bo.getObjectionCode());
+ lqw.eq(StringUtils.isNotBlank(bo.getOrderId()), CrmSalesObjection::getOrderId, bo.getOrderId());
+ lqw.eq(StringUtils.isNotBlank(bo.getCustomerId()), CrmSalesObjection::getCustomerId, bo.getCustomerId());
+ lqw.eq(StringUtils.isNotBlank(bo.getObjectionType()), CrmSalesObjection::getObjectionType, bo.getObjectionType());
+ lqw.eq(StringUtils.isNotBlank(bo.getObjectionContent()), CrmSalesObjection::getObjectionContent, bo.getObjectionContent());
+ lqw.eq(bo.getObjectionStatus() != null, CrmSalesObjection::getObjectionStatus, bo.getObjectionStatus());
+ lqw.eq(StringUtils.isNotBlank(bo.getHandleContent()), CrmSalesObjection::getHandleContent, bo.getHandleContent());
+ lqw.eq(StringUtils.isNotBlank(bo.getHandleUser()), CrmSalesObjection::getHandleUser, bo.getHandleUser());
+ lqw.eq(bo.getHandleTime() != null, CrmSalesObjection::getHandleTime, bo.getHandleTime());
+ lqw.eq(bo.getCloseTime() != null, CrmSalesObjection::getCloseTime, bo.getCloseTime());
+ return lqw;
+ }
+
+ /**
+ * 新增销售异议管理
+ */
+ @Override
+ public Boolean insertByBo(CrmSalesObjectionBo bo) {
+ CrmSalesObjection add = BeanUtil.toBean(bo, CrmSalesObjection.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setObjectionId(add.getObjectionId());
+ }
+ return flag;
+ }
+
+ /**
+ * 修改销售异议管理
+ */
+ @Override
+ public Boolean updateByBo(CrmSalesObjectionBo bo) {
+ CrmSalesObjection update = BeanUtil.toBean(bo, CrmSalesObjection.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(CrmSalesObjection entity){
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+ /**
+ * 批量删除销售异议管理
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
+ if(isValid){
+ //TODO 做一些业务上的校验,判断是否需要校验
+ }
+ return baseMapper.deleteBatchIds(ids) > 0;
+ }
+}
diff --git a/klp-crm/src/main/resources/mapper/CrmCustomerMapper.xml b/klp-crm/src/main/resources/mapper/CrmCustomerMapper.xml
new file mode 100644
index 00000000..f3e8f5f7
--- /dev/null
+++ b/klp-crm/src/main/resources/mapper/CrmCustomerMapper.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/klp-crm/src/main/resources/mapper/CrmOrderItemMapper.xml b/klp-crm/src/main/resources/mapper/CrmOrderItemMapper.xml
new file mode 100644
index 00000000..1ae1f99d
--- /dev/null
+++ b/klp-crm/src/main/resources/mapper/CrmOrderItemMapper.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/klp-crm/src/main/resources/mapper/CrmOrderMapper.xml b/klp-crm/src/main/resources/mapper/CrmOrderMapper.xml
new file mode 100644
index 00000000..bf196548
--- /dev/null
+++ b/klp-crm/src/main/resources/mapper/CrmOrderMapper.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/klp-crm/src/main/resources/mapper/CrmOrderOperationTraceMapper.xml b/klp-crm/src/main/resources/mapper/CrmOrderOperationTraceMapper.xml
new file mode 100644
index 00000000..1f579958
--- /dev/null
+++ b/klp-crm/src/main/resources/mapper/CrmOrderOperationTraceMapper.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/klp-crm/src/main/resources/mapper/CrmSalesContractMapper.xml b/klp-crm/src/main/resources/mapper/CrmSalesContractMapper.xml
new file mode 100644
index 00000000..111c1668
--- /dev/null
+++ b/klp-crm/src/main/resources/mapper/CrmSalesContractMapper.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/klp-crm/src/main/resources/mapper/CrmSalesObjectionMapper.xml b/klp-crm/src/main/resources/mapper/CrmSalesObjectionMapper.xml
new file mode 100644
index 00000000..2c6f6500
--- /dev/null
+++ b/klp-crm/src/main/resources/mapper/CrmSalesObjectionMapper.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index c8b192a5..f8cf3f6a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -396,6 +396,11 @@
klp-hrm
${klp-flowable-plus.version}
+
+ com.klp
+ klp-crm
+ ${klp-flowable-plus.version}
+
@@ -420,6 +425,7 @@
klp-pocket
klp-erp
klp-hrm
+ klp-crm
pom