From 474ddd0b76f343b09038e6f60e2826684d5eecd2 Mon Sep 17 00:00:00 2001
From: buhuazhen <hua100783@gmail.com>
Date: 星期五, 08 五月 2026 13:32:57 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_浪潮_pro' into dev_浪潮_pro

---
 src/main/java/com/ruoyi/basic/pojo/Area.java                                   |   32 ++
 src/main/java/com/ruoyi/basic/pojo/BusinessOpportunity.java                    |  147 ++++++++++
 src/main/java/com/ruoyi/basic/mapper/BusinessOpportunityMapper.java            |   23 +
 src/main/java/com/ruoyi/basic/pojo/BusinessDescription.java                    |   81 +++++
 src/main/resources/mapper/basic/BusinessOpportunityMapper.xml                  |   58 ++++
 src/main/java/com/ruoyi/basic/controller/BusinessDescriptionController.java    |   18 +
 src/main/java/com/ruoyi/basic/dto/ProductDto.java                              |    3 
 src/main/java/com/ruoyi/basic/service/impl/BusinessDescriptionServiceImpl.java |   20 +
 src/main/java/com/ruoyi/common/enums/FileNameType.java                         |    3 
 src/main/java/com/ruoyi/basic/service/BusinessDescriptionService.java          |   16 +
 src/main/java/com/ruoyi/basic/mapper/AreaMapper.java                           |    9 
 src/main/java/com/ruoyi/basic/mapper/BusinessDescriptionMapper.java            |   18 +
 src/main/java/com/ruoyi/basic/service/BusinessOpportunityService.java          |   37 ++
 src/main/java/com/ruoyi/basic/controller/CustomerContactController.java        |    6 
 src/main/java/com/ruoyi/basic/dto/BusinessDescriptionDto.java                  |   15 +
 src/main/java/com/ruoyi/basic/service/impl/BusinessOpportunityServiceImpl.java |  157 +++++++++++
 src/main/resources/mapper/basic/BusinessDescriptionMapper.xml                  |   20 +
 src/main/java/com/ruoyi/basic/dto/BusinessOpportunityDto.java                  |   31 ++
 src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java             |    9 
 src/main/resources/mapper/basic/CustomerContactMapper.xml                      |   16 
 src/main/java/com/ruoyi/basic/pojo/ProductModel.java                           |    6 
 src/main/java/com/ruoyi/basic/controller/BusinessOpportunityController.java    |   88 ++++++
 src/main/java/com/ruoyi/basic/dto/AreaDto.java                                 |   14 +
 src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java                        |    2 
 24 files changed, 818 insertions(+), 11 deletions(-)

diff --git a/src/main/java/com/ruoyi/basic/controller/BusinessDescriptionController.java b/src/main/java/com/ruoyi/basic/controller/BusinessDescriptionController.java
new file mode 100644
index 0000000..618d355
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/controller/BusinessDescriptionController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.basic.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鍟嗘満瀹㈡埛鎻忚堪 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:21
+ */
+@RestController
+@RequestMapping("/businessDescription")
+public class BusinessDescriptionController {
+
+}
diff --git a/src/main/java/com/ruoyi/basic/controller/BusinessOpportunityController.java b/src/main/java/com/ruoyi/basic/controller/BusinessOpportunityController.java
new file mode 100644
index 0000000..70ea710
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/controller/BusinessOpportunityController.java
@@ -0,0 +1,88 @@
+package com.ruoyi.basic.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.BusinessDescriptionDto;
+import com.ruoyi.basic.dto.BusinessOpportunityDto;
+import com.ruoyi.basic.service.BusinessOpportunityService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import io.jsonwebtoken.lang.Collections;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鍟嗘満绠$悊 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:10
+ */
+@RestController
+@RequestMapping("/businessOpportunity")
+@AllArgsConstructor
+@Tag(name = "鍟嗘満绠$悊")
+public class BusinessOpportunityController {
+
+    private final BusinessOpportunityService businessOpportunityService;
+
+    @Operation(summary = "鑾峰彇鐪佺骇鍒楄〃")
+    @GetMapping("/getProvinceList")
+    public R getProvinceList() {
+        return R.ok(businessOpportunityService.getProvinceList());
+    }
+
+    @Operation(summary = "閫氳繃鐪佺骇id鑾峰彇鍩庡競鍒楄〃")
+    @GetMapping("/getCityList")
+    public R getCityList(@RequestParam("provinceId") Integer provinceId) {
+        return R.ok(businessOpportunityService.getCityList(provinceId));
+    }
+
+    @GetMapping("/listPage")
+    @Operation(summary = "鍟嗘満鍒楄〃")
+    public R listPage(Page page, BusinessOpportunityDto businessOpportunityDto) {
+        IPage<BusinessOpportunityDto> businessOpportunityIPage = businessOpportunityService.listPage(page, businessOpportunityDto);
+        return R.ok(businessOpportunityIPage);
+    }
+
+    @PostMapping("/add")
+    @Operation(summary = "娣诲姞鍟嗘満")
+    @Log(title = "鍟嗘満绠$悊-娣诲姞鍟嗘満", businessType = BusinessType.INSERT)
+    @Transactional(rollbackFor = Exception.class)
+    public R add(@RequestBody BusinessOpportunityDto businessOpportunity) throws Exception{
+        return  businessOpportunityService.add(businessOpportunity);
+    }
+
+
+    @PostMapping("/addDescription")
+    @Operation(summary = "娣诲姞鍟嗘満鎻忚堪")
+    @Log(title = "鍟嗘満绠$悊-娣诲姞鍟嗘満鎻忚堪", businessType = BusinessType.INSERT)
+    @Transactional(rollbackFor = Exception.class)
+    public R addDescription(@RequestBody BusinessDescriptionDto businessDescription) throws  Exception{
+      return businessOpportunityService.addDescription(businessDescription);
+    }
+
+
+    @PutMapping("/update")
+    @Operation( summary = "淇敼鍟嗘満")
+    @Log(title = "鍟嗘満绠$悊-淇敼鍟嗘満", businessType = BusinessType.UPDATE)
+    @Transactional(rollbackFor = Exception.class)
+    public R update(@RequestBody BusinessOpportunityDto businessOpportunity) throws  Exception{
+        return businessOpportunityService.updateBusinessOpportunityById(businessOpportunity) ? R.ok() : R.fail();
+    }
+
+    @DeleteMapping("/delete")
+    @Operation( summary = "鍒犻櫎鍟嗘満")
+    @Log(title = "鍟嗘満绠$悊-鍒犻櫎鍟嗘満", businessType = BusinessType.DELETE)
+    public R delete(@RequestBody List<Long> ids) {
+        if(Collections.isEmpty(ids)) return R.fail("璇烽�夋嫨瑕佸垹闄ょ殑鍟嗘満");
+        return businessOpportunityService.delete(ids) ? R.ok() : R.fail();
+    }
+}
diff --git a/src/main/java/com/ruoyi/basic/controller/CustomerContactController.java b/src/main/java/com/ruoyi/basic/controller/CustomerContactController.java
index e5e8ce9..f468b8d 100644
--- a/src/main/java/com/ruoyi/basic/controller/CustomerContactController.java
+++ b/src/main/java/com/ruoyi/basic/controller/CustomerContactController.java
@@ -9,6 +9,8 @@
 import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 /**
  * <p>
  * 瀹㈡埛鑱旂郴浜鸿〃 鍓嶇鎺у埗鍣�
@@ -58,7 +60,7 @@
 
     @DeleteMapping("/delete")
     @Operation(summary = "鍒犻櫎")
-    public R delete(@RequestBody CustomerContactDto customerContact) {
-        return R.ok(customerContactService.removeById(customerContact));
+    public R delete(@RequestBody List<Long> ids) {
+        return R.ok(customerContactService.removeByIds(ids));
     }
 }
diff --git a/src/main/java/com/ruoyi/basic/dto/AreaDto.java b/src/main/java/com/ruoyi/basic/dto/AreaDto.java
new file mode 100644
index 0000000..851f9fc
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/dto/AreaDto.java
@@ -0,0 +1,14 @@
+package com.ruoyi.basic.dto;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import java.awt.geom.Area;
+import java.util.List;
+
+public class AreaDto extends Area {
+
+    @TableField(exist = false)
+    @Schema(hidden = true) // 闅愯棌涓嶆樉绀哄湪鏂囨。涓�
+    private List<Area> children;
+}
diff --git a/src/main/java/com/ruoyi/basic/dto/BusinessDescriptionDto.java b/src/main/java/com/ruoyi/basic/dto/BusinessDescriptionDto.java
new file mode 100644
index 0000000..dbfecf1
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/dto/BusinessDescriptionDto.java
@@ -0,0 +1,15 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.BusinessDescription;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class BusinessDescriptionDto extends BusinessDescription {
+
+
+    private List<StorageBlobDTO> storageBlobDTOS;
+
+    private List<StorageBlobVO> storageBlobVO;
+}
diff --git a/src/main/java/com/ruoyi/basic/dto/BusinessOpportunityDto.java b/src/main/java/com/ruoyi/basic/dto/BusinessOpportunityDto.java
new file mode 100644
index 0000000..c96e22c
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/dto/BusinessOpportunityDto.java
@@ -0,0 +1,31 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.BusinessDescription;
+import com.ruoyi.basic.pojo.BusinessOpportunity;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class BusinessOpportunityDto extends BusinessOpportunity {
+
+
+    @Schema(description = "鏂囦欢id")
+    private List<Long> FileIds;
+    @Schema(description = "鍟嗘満鎻忚堪")
+    private List<BusinessDescription> businessDescription;
+
+    @ApiModelProperty(value = "寮�濮嬫椂闂�")
+    private String entryDateStart;
+
+    @ApiModelProperty(value = "缁撴潫鏃堕棿")
+    private String entryDateEnd;
+
+    private List<StorageBlobDTO> storageBlobDTOS;
+
+    private List<StorageBlobVO> businessCommonFiles;
+}
diff --git a/src/main/java/com/ruoyi/basic/dto/ProductDto.java b/src/main/java/com/ruoyi/basic/dto/ProductDto.java
index 7b38d99..ba6077f 100644
--- a/src/main/java/com/ruoyi/basic/dto/ProductDto.java
+++ b/src/main/java/com/ruoyi/basic/dto/ProductDto.java
@@ -9,5 +9,8 @@
 @Data
 public class ProductDto extends Product {
 
+    //娴疆鐢ㄤ簬鍖哄垎鎴愬搧鍜岀墿鏂�
+    private String productType;
+
     private List<ProductModel> productModelList;
 }
diff --git a/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java b/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
index d7d0649..a217dab 100644
--- a/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
@@ -208,6 +208,8 @@
     SALES_REFUND_AMOUNT_ORDER("sales_refund_amount_order"),
     SALES_RECEIPT_RETURN("sales_receipt_return"),
     ACCOUNT_EXPENSE("account_expense"),
+    BUSINESS_OPPORTUNITY("business_opportunity"),
+    BUSINESS_DESCRIPTION("business_description"),
     ACCOUNT_FILE("account_file");
 
     private final String type;
diff --git a/src/main/java/com/ruoyi/basic/mapper/AreaMapper.java b/src/main/java/com/ruoyi/basic/mapper/AreaMapper.java
new file mode 100644
index 0000000..ba18a44
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/mapper/AreaMapper.java
@@ -0,0 +1,9 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.basic.pojo.Area;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AreaMapper extends BaseMapper<Area> {
+}
diff --git a/src/main/java/com/ruoyi/basic/mapper/BusinessDescriptionMapper.java b/src/main/java/com/ruoyi/basic/mapper/BusinessDescriptionMapper.java
new file mode 100644
index 0000000..03bb978
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/mapper/BusinessDescriptionMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.basic.pojo.BusinessDescription;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鍟嗘満瀹㈡埛鎻忚堪 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:21
+ */
+@Mapper
+public interface BusinessDescriptionMapper extends BaseMapper<BusinessDescription> {
+
+}
diff --git a/src/main/java/com/ruoyi/basic/mapper/BusinessOpportunityMapper.java b/src/main/java/com/ruoyi/basic/mapper/BusinessOpportunityMapper.java
new file mode 100644
index 0000000..cf84959
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/mapper/BusinessOpportunityMapper.java
@@ -0,0 +1,23 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.BusinessOpportunityDto;
+import com.ruoyi.basic.pojo.BusinessOpportunity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 鍟嗘満绠$悊 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:10
+ */
+@Mapper
+public interface BusinessOpportunityMapper extends BaseMapper<BusinessOpportunity> {
+
+    IPage<BusinessOpportunityDto> listPage(Page page, @Param("businessOpportunityDto") BusinessOpportunityDto businessOpportunityDto);
+}
diff --git a/src/main/java/com/ruoyi/basic/pojo/Area.java b/src/main/java/com/ruoyi/basic/pojo/Area.java
new file mode 100644
index 0000000..0342158
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/pojo/Area.java
@@ -0,0 +1,32 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@TableName("area")
+@Schema(description = "鍖哄煙琛�")
+public class Area implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(type = IdType.AUTO)
+    @Schema(description = "搴忓彿", example = "1")
+    private Long id;
+
+    @Schema(description = "鐖剁骇ID锛�0=鐪侊紝鍏朵粬=瀵瑰簲涓婄骇ID", example = "0")
+    private Integer parentId;
+
+    @Schema(description = "鍖哄煙鍚嶇О锛堢渷/甯�/鍖哄幙锛�", example = "鍖椾含甯�")
+    private String name;
+
+    @Schema(description = "灞傜骇锛�1=鐪侊紝2=甯傦紝3=鍖哄幙", minimum = "1", maximum = "3")
+    private Integer level;
+
+
+}
diff --git a/src/main/java/com/ruoyi/basic/pojo/BusinessDescription.java b/src/main/java/com/ruoyi/basic/pojo/BusinessDescription.java
new file mode 100644
index 0000000..34be3f8
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/pojo/BusinessDescription.java
@@ -0,0 +1,81 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鍟嗘満瀹㈡埛鎻忚堪
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:21
+ */
+@Getter
+@Setter
+@ToString
+@TableName("business_description")
+@ApiModel(value = "BusinessDescription瀵硅薄", description = "鍟嗘満瀹㈡埛鎻忚堪")
+public class BusinessDescription implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 鍟嗘満涓昏〃id
+     */
+    @ApiModelProperty("鍟嗘満涓昏〃id")
+    private Long businessOpportunityId;
+
+    /**
+     * 鎻忚堪
+     */
+    @ApiModelProperty("鎻忚堪")
+    private String description;
+
+    /**
+     * 褰曞叆浜�
+     */
+    @ApiModelProperty("褰曞叆浜�")
+    private String entryPerson;
+
+    /**
+     * 褰曞叆鏃堕棿
+     */
+    @ApiModelProperty("褰曞叆鏃堕棿")
+    private LocalDate entryDate;
+
+    /**
+     * 鐘舵��
+     */
+    @ApiModelProperty("鐘舵��")
+    private String status;
+
+    private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+}
diff --git a/src/main/java/com/ruoyi/basic/pojo/BusinessOpportunity.java b/src/main/java/com/ruoyi/basic/pojo/BusinessOpportunity.java
new file mode 100644
index 0000000..5264b04
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/pojo/BusinessOpportunity.java
@@ -0,0 +1,147 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鍟嗘満绠$悊
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:10
+ */
+@Getter
+@Setter
+@ToString
+@TableName("business_opportunity")
+@ApiModel(value = "BusinessOpportunity瀵硅薄", description = "鍟嗘満绠$悊")
+public class BusinessOpportunity implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 鐘舵��
+     */
+    @ApiModelProperty("鐘舵��")
+    private String status;
+
+    /**
+     * 鐪佷唤
+     */
+    @ApiModelProperty("鐪佷唤")
+    private String province;
+
+    /**
+     * 鍩庡競
+     */
+    @ApiModelProperty("鍩庡競")
+    private String city;
+
+    /**
+     * 瀹㈡埛鍚嶇О
+     */
+    @ApiModelProperty("瀹㈡埛鍚嶇О")
+    private String customerName;
+
+    /**
+     * 鍟嗘満鏉ユ簮
+     */
+    @ApiModelProperty("鍟嗘満鏉ユ簮")
+    private String businessSource;
+
+    /**
+     * 褰曞叆鏃ユ湡
+     */
+    @ApiModelProperty("褰曞叆鏃ユ湡")
+    private LocalDate entryDate;
+
+    /**
+     * 褰曞叆浜�
+     */
+    @ApiModelProperty("褰曞叆浜�")
+    private String entryPerson;
+
+    private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    /**
+     * 淇℃伅鍖栫幇鐘�
+     */
+    @ApiModelProperty("淇℃伅鍖栫幇鐘�")
+    private String informationState;
+
+    /**
+     * 涓昏惀涓氬姟鏀跺叆
+     */
+    @ApiModelProperty("涓昏惀涓氬姟鏀跺叆")
+    private String mainBusinessRevenue;
+
+    /**
+     * 涓昏惀浜у搧
+     */
+    @ApiModelProperty("涓昏惀浜у搧")
+    private String mainProducts;
+
+    /**
+     * 瀹㈡埛瑙勬ā
+     */
+    @ApiModelProperty("瀹㈡埛瑙勬ā")
+    private String customerScale;
+
+    /**
+     * 琛屼笟
+     */
+    @ApiModelProperty("琛屼笟")
+    private String industry;
+
+    /**
+     * 鍚堝悓閲戦
+     */
+    @ApiModelProperty("鍚堝悓閲戦")
+    private BigDecimal contractAmount;
+
+    /**
+     * 浠樻鎻忚堪
+     */
+    @ApiModelProperty("浠樻鎻忚堪")
+    private String paymentDescription;
+
+    /**
+     * 鏀归�犲唴瀹�
+     */
+    @ApiModelProperty("鏀归�犲唴瀹�")
+    private String renContent;
+
+    @Schema(description = "閮ㄩ棬id")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
index f0e9470..cae6632 100644
--- a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
+++ b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -79,4 +79,10 @@
     @Schema(description = "椤堕儴鐖朵骇鍝乮d")
     @TableField(exist = false)
     private Long topProductParentId;
+
+    /**
+     * 搴撳瓨閲�
+     */
+    @Schema(description = "搴撳瓨閲�")
+    private BigDecimal stockInventory;
 }
diff --git a/src/main/java/com/ruoyi/basic/service/BusinessDescriptionService.java b/src/main/java/com/ruoyi/basic/service/BusinessDescriptionService.java
new file mode 100644
index 0000000..dc1515c
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/service/BusinessDescriptionService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.basic.service;
+
+import com.ruoyi.basic.pojo.BusinessDescription;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 鍟嗘満瀹㈡埛鎻忚堪 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:21
+ */
+public interface BusinessDescriptionService extends IService<BusinessDescription> {
+
+}
diff --git a/src/main/java/com/ruoyi/basic/service/BusinessOpportunityService.java b/src/main/java/com/ruoyi/basic/service/BusinessOpportunityService.java
new file mode 100644
index 0000000..acb1e54
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/service/BusinessOpportunityService.java
@@ -0,0 +1,37 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.dto.BusinessDescriptionDto;
+import com.ruoyi.basic.dto.BusinessOpportunityDto;
+import com.ruoyi.basic.pojo.Area;
+import com.ruoyi.basic.pojo.BusinessOpportunity;
+import com.ruoyi.framework.web.domain.R;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鍟嗘満绠$悊 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:10
+ */
+public interface BusinessOpportunityService extends IService<BusinessOpportunity> {
+
+    IPage<BusinessOpportunityDto> listPage(Page page, BusinessOpportunityDto businessOpportunityDto);
+
+    List<Area> getProvinceList();
+
+    List<Area> getCityList(Integer provinceId);
+
+    R add(BusinessOpportunityDto businessOpportunity);
+
+    R addDescription(BusinessDescriptionDto businessDescription);
+
+    boolean updateBusinessOpportunityById(BusinessOpportunityDto businessOpportunity);
+
+    boolean delete(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/basic/service/impl/BusinessDescriptionServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/BusinessDescriptionServiceImpl.java
new file mode 100644
index 0000000..b9da190
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/service/impl/BusinessDescriptionServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.basic.service.impl;
+
+import com.ruoyi.basic.pojo.BusinessDescription;
+import com.ruoyi.basic.mapper.BusinessDescriptionMapper;
+import com.ruoyi.basic.service.BusinessDescriptionService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鍟嗘満瀹㈡埛鎻忚堪 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:21
+ */
+@Service
+public class BusinessDescriptionServiceImpl extends ServiceImpl<BusinessDescriptionMapper, BusinessDescription> implements BusinessDescriptionService {
+
+}
diff --git a/src/main/java/com/ruoyi/basic/service/impl/BusinessOpportunityServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/BusinessOpportunityServiceImpl.java
new file mode 100644
index 0000000..db25ba6
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/service/impl/BusinessOpportunityServiceImpl.java
@@ -0,0 +1,157 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.dto.BusinessDescriptionDto;
+import com.ruoyi.basic.dto.BusinessOpportunityDto;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.mapper.AreaMapper;
+import com.ruoyi.basic.mapper.BusinessDescriptionMapper;
+import com.ruoyi.basic.mapper.BusinessOpportunityMapper;
+import com.ruoyi.basic.pojo.Area;
+import com.ruoyi.basic.pojo.BusinessDescription;
+import com.ruoyi.basic.pojo.BusinessOpportunity;
+import com.ruoyi.basic.service.BusinessOpportunityService;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.project.system.domain.SysNotice;
+import com.ruoyi.project.system.mapper.SysNoticeMapper;
+import com.ruoyi.project.system.service.impl.UnipushService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ * 鍟嗘満绠$悊 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-07 04:46:10
+ */
+@Service
+@RequiredArgsConstructor
+public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportunityMapper, BusinessOpportunity> implements BusinessOpportunityService {
+
+    private final BusinessOpportunityMapper businessOpportunityMapper;
+    private final AreaMapper areaMapper;
+    private final BusinessDescriptionMapper businessDescriptionMapper;
+    private final UnipushService unipushService;
+    private final SysNoticeMapper sysNoticeMapper;
+    private final FileUtil fileUtil;
+
+    @Override
+    public IPage<BusinessOpportunityDto> listPage(Page page, BusinessOpportunityDto businessOpportunityDto) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        IPage<BusinessOpportunityDto> businessOpportunityDtoIPage = businessOpportunityMapper.listPage(page, businessOpportunityDto);
+
+        businessOpportunityDtoIPage.getRecords().forEach(item -> {
+            item.setBusinessCommonFiles(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.BUSINESS_OPPORTUNITY, item.getId()));
+            item.setBusinessDescription(businessDescriptionMapper.selectList(Wrappers.lambdaQuery(BusinessDescription.class)
+                    .eq(BusinessDescription::getBusinessOpportunityId, item.getId())
+                    .orderByDesc(BusinessDescription::getCreateTime)));
+        });
+        return businessOpportunityDtoIPage;
+
+    }
+
+    @Override
+    public List<Area> getProvinceList() {
+        return areaMapper.selectList(new LambdaQueryWrapper<Area>().eq(Area::getLevel,1).eq(Area::getParentId,0));
+    }
+
+    @Override
+    public List<Area> getCityList(Integer provinceId) {
+        return areaMapper.selectList(new LambdaQueryWrapper<Area>().eq(Area::getLevel,2).eq(Area::getParentId,provinceId));
+    }
+
+    @Override
+    public R add(BusinessOpportunityDto businessOpportunity) {
+        this.save(businessOpportunity);
+        BusinessDescription businessDescription = new BusinessDescription();
+        BeanUtils.copyProperties(businessOpportunity, businessDescription);
+        businessDescription.setBusinessOpportunityId(businessOpportunity.getId());
+        // 杩佺Щ涓存椂鏂囦欢鍒版寮忔枃浠�
+//        commonFileService.migrateTempFilesToFormal(businessOpportunity.getId(), businessOpportunity.getTempFileIds());
+        ArrayList<StorageBlobDTO> storageBlobDTOS = new ArrayList<>();
+        for (StorageBlobVO businessCommonFile : businessOpportunity.getBusinessCommonFiles()) {
+            StorageBlobDTO storageBlobDTO = new StorageBlobDTO();
+            BeanUtils.copyProperties(businessCommonFile, storageBlobDTO);
+            storageBlobDTOS.add(storageBlobDTO);
+        }
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.BUSINESS_OPPORTUNITY, businessOpportunity.getId(),  storageBlobDTOS);
+        // 鎺ㄩ�佹秷鎭�
+        List<SysNotice> sysNoticeList = new ArrayList<>();
+        SysNotice sysNotice = new SysNotice();
+        sysNotice.setNoticeTitle("涓氬姟鍛� "+ businessOpportunity.getEntryPerson());
+        sysNotice.setNoticeContent("鏂板瀹㈡埛 " + businessOpportunity.getCustomerName() + " 閲戦 "+ businessOpportunity.getContractAmount());
+        sysNotice.setNoticeType("1");
+        sysNotice.setStatus("0");
+        sysNotice.setSenderId(SecurityUtils.getUserId());
+        // 鎺ㄩ�佺粰璋�  闇�瑕佸緟瀹�
+        sysNotice.setConsigneeId(105L);
+        sysNotice.setAppJumpPath("pages/opportunityManagement/index");
+        sysNoticeMapper.insert(sysNotice);
+        sysNoticeList.add(sysNotice);
+        unipushService.sendClientMessage(sysNoticeList);
+        return businessDescriptionMapper.insert(businessDescription) > 0 ? R.ok() : R.fail();
+    }
+
+    @Override
+    public R addDescription(BusinessDescriptionDto businessDescription) {
+        // 杩佺Щ涓存椂鏂囦欢鍒版寮忔枃浠�
+        BusinessOpportunity byId = this.getById(businessDescription.getBusinessOpportunityId());
+        if(byId != null){
+            byId.setStatus(businessDescription.getStatus());
+            this.updateById(byId);
+            // 鎺ㄩ�佹秷鎭�
+            List<SysNotice> sysNoticeList = new ArrayList<>();
+            SysNotice sysNotice = new SysNotice();
+            sysNotice.setNoticeTitle("涓氬姟鍛� "+ businessDescription.getEntryPerson());
+            sysNotice.setNoticeContent("瀹㈡埛 " + byId.getCustomerName() + " 閲戦 "+ byId.getContractAmount() + " 鐘舵�� " + businessDescription.getStatus());
+            sysNotice.setNoticeType("1");
+            sysNotice.setStatus("0");
+            sysNotice.setSenderId(SecurityUtils.getUserId());
+            sysNotice.setConsigneeId(105L);
+            sysNotice.setAppJumpPath("pages/opportunityManagement/index");
+            sysNoticeMapper.insert(sysNotice);
+            sysNoticeList.add(sysNotice);
+            unipushService.sendClientMessage(sysNoticeList);
+        }
+        int insert = businessDescriptionMapper.insert(businessDescription);
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.BUSINESS_DESCRIPTION, businessDescription.getBusinessOpportunityId(),  businessDescription.getStorageBlobDTOS());
+
+        return insert > 0 ? R.ok() : R.fail();
+    }
+
+    @Override
+    public boolean updateBusinessOpportunityById(BusinessOpportunityDto businessOpportunity) {
+        ArrayList<StorageBlobDTO> storageBlobDTOS = new ArrayList<>();
+        for (StorageBlobVO businessCommonFile : businessOpportunity.getBusinessCommonFiles()) {
+            StorageBlobDTO storageBlobDTO = new StorageBlobDTO();
+            BeanUtils.copyProperties(businessCommonFile, storageBlobDTO);
+            storageBlobDTOS.add(storageBlobDTO);
+        }
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.BUSINESS_OPPORTUNITY, businessOpportunity.getId(),  storageBlobDTOS);
+        return this.updateById(businessOpportunity);
+    }
+
+    @Override
+    public boolean delete(List<Long> ids) {
+        for (Long id : ids) {
+            fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.BUSINESS_OPPORTUNITY, id);
+        }
+        return this.removeBatchByIds(ids);
+    }
+}
diff --git a/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
index 5a7f679..3667bb6 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
@@ -14,11 +14,8 @@
 import com.ruoyi.basic.service.IProductService;
 import com.ruoyi.basic.vo.ProductModelVo;
 import com.ruoyi.common.utils.bean.BeanUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.web.domain.AjaxResult;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -42,6 +39,12 @@
         if (productDto.getProductName() != null && !productDto.getProductName().isEmpty()) {
             queryWrapper.like(Product::getProductName, productDto.getProductName());
         }
+        // 娴疆鐢ㄤ簬鍖哄垎鎴愬搧鍜岀墿鏂�
+        if (productDto.getProductType() != null && !productDto.getProductType().isEmpty()) {
+            if (productDto.getProductType().equals("鎴愬搧")){
+                queryWrapper.eq(Product::getProductName, productDto.getProductType());
+            }else queryWrapper.ne(Product::getProductName, "鎴愬搧");
+        }
 
         // 鏌ヨ鏍硅妭鐐瑰垪琛�
         List<Product> rootProducts = productMapper.selectList(queryWrapper);
diff --git a/src/main/java/com/ruoyi/common/enums/FileNameType.java b/src/main/java/com/ruoyi/common/enums/FileNameType.java
index 2deb5d6..144c1a1 100644
--- a/src/main/java/com/ruoyi/common/enums/FileNameType.java
+++ b/src/main/java/com/ruoyi/common/enums/FileNameType.java
@@ -17,7 +17,8 @@
     INSPECTION_PRODUCTION_BEFORE(10),
     INSPECTION_PRODUCTION_AFTER(11),
     INSPECTION(12),//宸℃ 鐢熶骇鍓�
-    APP(13);
+    APP(13),
+    BUSINESS_OPPORTUNITY(14);
 
     private final int value;
 
diff --git a/src/main/resources/mapper/basic/BusinessDescriptionMapper.xml b/src/main/resources/mapper/basic/BusinessDescriptionMapper.xml
new file mode 100644
index 0000000..0a0f026
--- /dev/null
+++ b/src/main/resources/mapper/basic/BusinessDescriptionMapper.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.BusinessDescriptionMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.BusinessDescription">
+        <id column="id" property="id" />
+        <result column="business_opportunity_id" property="businessOpportunityId" />
+        <result column="description" property="description" />
+        <result column="entry_person" property="entryPerson" />
+        <result column="entry_date" property="entryDate" />
+        <result column="status" property="status" />
+        <result column="tenant_id" property="tenantId" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/basic/BusinessOpportunityMapper.xml b/src/main/resources/mapper/basic/BusinessOpportunityMapper.xml
new file mode 100644
index 0000000..bfbbbe0
--- /dev/null
+++ b/src/main/resources/mapper/basic/BusinessOpportunityMapper.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.BusinessOpportunityMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.BusinessOpportunity">
+        <id column="id" property="id" />
+        <result column="status" property="status" />
+        <result column="province" property="province" />
+        <result column="city" property="city" />
+        <result column="customer_name" property="customerName" />
+        <result column="business_source" property="businessSource" />
+        <result column="entry_date" property="entryDate" />
+        <result column="entry_person" property="entryPerson" />
+        <result column="tenant_id" property="tenantId" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="information_state" property="informationState" />
+        <result column="main_business_revenue" property="mainBusinessRevenue" />
+        <result column="main_products" property="mainProducts" />
+        <result column="customer_scale" property="customerScale" />
+        <result column="industry" property="industry" />
+        <result column="contract_amount" property="contractAmount" />
+        <result column="payment_description" property="paymentDescription" />
+        <result column="ren_content" property="renContent" />
+    </resultMap>
+    <select id="listPage" resultType="com.ruoyi.basic.dto.BusinessOpportunityDto">
+        select * from
+        business_opportunity bo
+        <where>
+            <if test="businessOpportunityDto.customerName != null">
+                and bo.customer_name = #{businessOpportunityDto.customerName}
+            </if>
+            <if test="businessOpportunityDto.city != null">
+                and bo.city = #{businessOpportunityDto.city}
+            </if>
+            <if test="businessOpportunityDto.entryPerson != null">
+                and bo.entry_person = #{businessOpportunityDto.entryPerson}
+            </if>
+            <if test="businessOpportunityDto.status != null">
+                and bo.status = #{businessOpportunityDto.status}
+            </if>
+            <if test="businessOpportunityDto.customerName != null">
+                and bo.customer_name = #{businessOpportunityDto.customerName}
+            </if>
+            <if test="businessOpportunityDto.entryDateStart != null">
+                and bo.entry_date &gt;= STR_TO_DATE(#{businessOpportunityDto.entryDateStart}, '%Y-%m-%d')
+            </if>
+            <if test="businessOpportunityDto.entryDateEnd != null">
+                and bo.entry_date &lt;= STR_TO_DATE(#{businessOpportunityDto.entryDateEnd}, '%Y-%m-%d')
+            </if>
+        </where>
+        order by bo.entry_date desc
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/basic/CustomerContactMapper.xml b/src/main/resources/mapper/basic/CustomerContactMapper.xml
index 8a184e4..c680e53 100644
--- a/src/main/resources/mapper/basic/CustomerContactMapper.xml
+++ b/src/main/resources/mapper/basic/CustomerContactMapper.xml
@@ -17,22 +17,28 @@
         <result column="del_flag" property="delFlag" />
     </resultMap>
     <select id="listPage" resultType="com.ruoyi.basic.dto.CustomerContactDto">
+        select * from (
         SELECT
-        cc.*,
+        c.*,
         (
         SELECT GROUP_CONCAT(ci.customer_name SEPARATOR ',')
         FROM customer ci
-        WHERE FIND_IN_SET(ci.id, cc.customer_id)
+        WHERE FIND_IN_SET(ci.id, c.customer_id)
         ) AS customer_names
-        FROM customer_contact cc
+        FROM customer_contact c
+        ) as cc
         <where>
             cc.del_flag = 0
             <if test="customerContactDto.contactPerson != null and customerContactDto.contactPerson !=''">
-                and cc.contact_person = #{customerContactDto.contactPerson}
+                and cc.contact_person like concat('%',#{customerContactDto.contactPerson},'%')
             </if>
             <if test="customerContactDto.contactPhone != null and customerContactDto.contactPhone !=''">
-                and cc.contact_phone = #{customerContactDto.contactPhone}
+                and cc.contact_phone like concat('%',#{customerContactDto.contactPhone},'%')
             </if>
+            <if test="customerContactDto.customerId != null and customerContactDto.customerId !=''">
+                and FIND_IN_SET(#{customerContactDto.customerId}, cc.customer_id)
+            </if>
+
         </where>
     </select>
 </mapper>

--
Gitblit v1.9.3