吴树波 1 mesiac pred
rodič
commit
a14cfbc966

+ 9 - 1
fs-service/src/main/java/com/fs/crm/domain/CrmCustomer.java

@@ -142,7 +142,7 @@ public class CrmCustomer extends BaseEntity
 
     /** 客户来源 */
     @Excel(name = "客户来源")
-    private Integer source;
+    private String source;
 
     /** 标签 */
     @Excel(name = "标签")
@@ -182,6 +182,14 @@ public class CrmCustomer extends BaseEntity
     private String intention;
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date visitTime;
+    // 购买商品
+    private String goodsName;
+    // 购买规格
+    private String goodsSpecification;
+    // 店铺名称
+    private String shopName;
+    // 平台名称
+    private String platformName;
 
 
 

+ 7 - 1
fs-service/src/main/java/com/fs/crm/param/CrmCompanyLineCustomerImportParam.java

@@ -1,5 +1,6 @@
 package com.fs.crm.param;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
@@ -15,7 +16,7 @@ public class CrmCompanyLineCustomerImportParam implements Serializable {
     @Excel(name = "进线日期", width = 20)
     private String registerDate;
 
-    @Excel(name = "客户来源",dictType = "crm_customer_source")
+    @Excel(name = "客户来源")
     private String source;
 
     @Excel(name = "来源渠道编码" )
@@ -125,5 +126,10 @@ public class CrmCompanyLineCustomerImportParam implements Serializable {
     /** 客户类型 */
     private Integer customerType;
 
+    @Excel(name = "聊天内容" )
+    @TableField(exist = false)
+    private String msg;
+
+
 
 }

+ 33 - 17
fs-service/src/main/java/com/fs/crm/service/impl/CrmCustomerServiceImpl.java

@@ -25,6 +25,7 @@ import com.fs.crm.mapper.*;
 import com.fs.crm.param.*;
 import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.service.ICrmMsgService;
+import com.fs.crm.utils.CidUserOrderExtractor;
 import com.fs.crm.vo.*;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
@@ -231,9 +232,6 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
                     }
                 }
                 crmCustomer.setImportType(0);
-                if (customer.getSource()!=null && !"".equals(customer.getSource())){
-                    crmCustomer.setSource(Integer.parseInt(customer.getSource()));
-                }
                 crmCustomer.setCreateTime(new Date());
                 crmCustomerMapper.insertCrmCustomer(crmCustomer);
                 successNum++;
@@ -555,13 +553,13 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
         {
             try
             {
-//                String regex = "^1[3456789]\\d{9}$";
-//                if(!customer.getMobile().matches(regex)){
-//                    failureNum++;
-//                    String msg = "<br/>" + failureNum + "、客户 " + customer.getMobile() + " 导入失败:电话号码格式不正确";
-//                    failureMsg.append(msg );
-//                    continue;
-//                }
+                String regex = "^1[3456789]\\d{9}$";
+                if(!customer.getMobile().matches(regex)){
+                    failureNum++;
+                    String msg = "<br/>" + failureNum + "、客户 " + customer.getMobile() + " 导入失败:电话号码格式不正确";
+                    failureMsg.append(msg );
+                    continue;
+                }
                 CrmCustomer crmCustomer=new CrmCustomer();
                 BeanUtils.copyProperties(customer,crmCustomer);
                 crmCustomer.setIsDel(0);
@@ -569,16 +567,34 @@ public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCu
                 crmCustomer.setCompanyId(companyId);
                 crmCustomer.setStatus(1);
                 crmCustomer.setIsReceive(1);
-                if(StringUtils.isNotEmpty(customer.getSource())){
-                    try {
-                        crmCustomer.setSource(Integer.parseInt(customer.getSource()));
-                    }
-                    catch (Exception e){
-                    }
-                }
                 crmCustomer.setCustomerCode(OrderUtils.getOrderNo());
                 crmCustomer.setCreateTime(new Date());
                 crmCustomer.setCreateUserId(companyUserId);
+                CrmOrderInfoVo crmOrderInfoVo = CidUserOrderExtractor.extractSingleOrder(customer.getMsg());
+                if(crmOrderInfoVo != null){
+                    if(crmOrderInfoVo.getPayAmount() != null){
+                        crmCustomer.setPayMoney(crmOrderInfoVo.getPayAmount());
+                    }
+                    if(crmOrderInfoVo.getQuantity() != null){
+                        crmCustomer.setBuyCount(crmOrderInfoVo.getQuantity());
+                    }
+                    if(crmOrderInfoVo.getQuantity() != null){
+                        crmCustomer.setBuyCount(crmOrderInfoVo.getQuantity());
+                    }
+                    if(crmOrderInfoVo.getProductName() != null){
+                        crmCustomer.setGoodsName(crmOrderInfoVo.getProductName());
+                    }
+                    if(crmOrderInfoVo.getSpecification() != null){
+                        crmCustomer.setGoodsSpecification(crmOrderInfoVo.getSpecification());
+                    }
+                    if(crmOrderInfoVo.getShop() != null){
+                        crmCustomer.setShopName(crmOrderInfoVo.getShop());
+                    }
+                    if(crmOrderInfoVo.getPlatform() != null){
+                        crmCustomer.setPlatformName(crmOrderInfoVo.getPlatform());
+                    }
+                }
+                crmCustomer.setReceiveTime(new Date());
                 crmCustomerMapper.insertCrmCustomer(crmCustomer);
                 successNum++;
                 successMsg.append("<br/>" + successNum + "、客户 " + customer.getCustomerName() + " 导入成功");

+ 117 - 0
fs-service/src/main/java/com/fs/crm/utils/CidUserOrderExtractor.java

@@ -0,0 +1,117 @@
+package com.fs.crm.utils;
+
+import com.fs.crm.vo.CrmOrderInfoVo;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 订单信息提取工具类(适配字段间隔不确定 + Java 8日期转换)
+ */
+public class CidUserOrderExtractor {
+    // 优化后的正则:加入\\s*匹配任意空白间隔,忽略字段间不确定的空格/换行
+    private static final String ORDER_REGEX =
+            "(.*?)\\s*-\\s*(.+?)\\s*(.*?)\\s*日期\\s*(\\d{4}-\\d{2}-\\d{2}\\s*\\d{2}:\\d{2}:\\d{2})\\s*" +
+                    "订单号\\s*(\\d+)\\s*商品\\s*(.+?)\\s*规格\\s*(.+?)\\s*物流\\s*(.+?)\\s*" +
+                    "数量(件)\\s*(\\d+)\\s*实付金额\\s*(\\d+(\\.\\d+)?)";
+
+    private static final Pattern ORDER_PATTERN = Pattern.compile(ORDER_REGEX);
+
+    // Java 8 日期格式化器(线程安全,可全局复用,对应订单日期格式:yyyy-MM-dd HH:mm:ss)
+    private static final DateTimeFormatter DATE_TIME_FORMATTER =
+            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    /**
+     * 提取单个订单文本的信息(适配间隔不确定)
+     * @param orderText 原始订单文本(允许字段间有任意空白/换行)
+     * @return 封装后的OrderInfo对象
+     */
+    public static CrmOrderInfoVo extractSingleOrder(String orderText) {
+        if (orderText == null || orderText.trim().isEmpty()) {
+            return null;
+        }
+
+        // 预处理:将多个连续空白替换为单个空格(可选,进一步提高匹配稳定性)
+        String standardizedText = orderText.replaceAll("\\s+", " ");
+        Matcher matcher = ORDER_PATTERN.matcher(standardizedText);
+        CrmOrderInfoVo orderInfo = new CrmOrderInfoVo();
+
+        if (matcher.find()) {
+            try {
+                // 1. 提取各分组字段(忽略间隔,正则已适配)
+                String platform = matcher.group(1).trim();
+                String shop = matcher.group(2).trim();
+                String dateStr = matcher.group(3).trim();
+                String orderNo = matcher.group(4).trim();
+                String productName = matcher.group(5).trim();
+                String specification = matcher.group(6).trim();
+                String logistics = matcher.group(7).trim();
+                String quantityStr = matcher.group(8).trim();
+                String payAmountStr = matcher.group(9).trim();
+
+                // 2. Java 8 日期转换:字符串 → LocalDateTime(核心步骤)
+                LocalDateTime buyDate = parseDateToLocalDateTime(dateStr);
+
+                // 3. 其他字段类型转换
+                Integer quantity = Integer.parseInt(quantityStr);
+                BigDecimal payAmount = new BigDecimal(payAmountStr);
+
+                // 4. 封装到实体类
+                orderInfo.setPlatform(platform);
+                orderInfo.setShop(shop);
+                orderInfo.setBuyDate(buyDate);
+                orderInfo.setOrderNo(orderNo);
+                orderInfo.setProductName(productName);
+                orderInfo.setSpecification(specification);
+                orderInfo.setQuantity(quantity);
+                orderInfo.setLogistics(logistics);
+                orderInfo.setPayAmount(payAmount);
+
+            } catch (NumberFormatException | DateTimeParseException e) {
+                System.err.println("字段类型转换失败:" + e.getMessage());
+            }
+        }
+
+        return orderInfo;
+    }
+
+    /**
+     * Java 8 日期字符串转换为LocalDateTime(单独抽取,便于复用和异常处理)
+     * @param dateStr 日期字符串(格式:yyyy-MM-dd HH:mm:ss,允许中间有多个空格)
+     * @return LocalDateTime对象,转换失败返回null
+     */
+    private static LocalDateTime parseDateToLocalDateTime(String dateStr) {
+        if (dateStr == null || dateStr.trim().isEmpty()) {
+            return null;
+        }
+
+        try {
+            // 标准化日期字符串:将中间的多个空格替换为单个空格(确保格式匹配)
+            String standardDateStr = dateStr.replaceAll("\\s+", " ");
+            // Java 8 核心转换方法:parse(String, DateTimeFormatter)
+            return LocalDateTime.parse(standardDateStr, DATE_TIME_FORMATTER);
+        } catch (DateTimeParseException e) {
+            System.err.println("日期转换失败,格式不匹配(要求:yyyy-MM-dd HH:mm:ss):" + e.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * Java 8 LocalDateTime转换为自定义格式字符串(扩展方法,便于展示/存储)
+     * @param localDateTime 待转换的LocalDateTime对象
+     * @param pattern 自定义日期格式(如:yyyy/MM/dd HH:mm)
+     * @return 格式化后的日期字符串
+     */
+    public static String formatLocalDateTime(LocalDateTime localDateTime, String pattern) {
+        if (localDateTime == null || pattern == null || pattern.trim().isEmpty()) {
+            return null;
+        }
+
+        DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern(pattern);
+        return localDateTime.format(customFormatter);
+    }
+}

+ 1 - 1
fs-service/src/main/java/com/fs/crm/vo/CrmLineCustomerListQueryVO.java

@@ -83,7 +83,7 @@ public class CrmLineCustomerListQueryVO implements Serializable
 
     private Long companyId;
 
-    private Integer source;
+    private String source;
     private Integer visitStatus;
 
     private String tags;

+ 0 - 19
fs-service/src/main/java/com/fs/crm/vo/CrmOrderInfo.java

@@ -1,19 +0,0 @@
-package com.fs.crm.vo;
-
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@Data
-public class CrmOrderInfo {
-    private String platform; // 平台(京东/天猫)
-    private String shop; // 店铺名称
-    private LocalDateTime buyDate; // 购买日期(Java 8 LocalDateTime类型)
-    private String orderNo; // 订单号
-    private String productName; // 商品名称
-    private String specification; // 商品规格
-    private Integer quantity; // 购买数量
-    private String logistics; // 物流信息
-    private BigDecimal payAmount; // 实付金额
-}

+ 28 - 0
fs-service/src/main/java/com/fs/crm/vo/CrmOrderInfoVo.java

@@ -0,0 +1,28 @@
+package com.fs.crm.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+public class CrmOrderInfoVo {
+    // 平台(京东/天猫)
+    private String platform;
+    // 店铺名称
+    private String shop;
+    // 购买日期
+    private LocalDateTime buyDate;
+    // 订单号
+    private String orderNo;
+    // 商品名称
+    private String productName;
+    // 商品规格
+    private String specification;
+    // 购买数量
+    private Integer quantity;
+    // 物流信息
+    private String logistics;
+    // 实付金额
+    private BigDecimal payAmount;
+}

+ 21 - 1
fs-service/src/main/resources/mapper/crm/CrmCustomerMapper.xml

@@ -54,10 +54,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="thirdAccount"    column="third_account"    />
         <result property="clueId"    column="clue_id"    />
         <result property="qwName"    column="qw_name"    />
+        <result property="platformName"    column="platform_name"    />
+        <result property="goodsName"    column="goods_name"    />
+        <result property="goodsSpecification"    column="goods_specification"    />
+        <result property="shopName"    column="shop_name"    />
     </resultMap>
 
     <sql id="selectCrmCustomerVo">
-        select customer_id, customer_code, customer_name, mobile, sex, weixin, remark, user_id, create_user_id, receive_user_id, customer_user_id, address,city_ids, location, detail_address, lng, lat, create_time, update_time, status, is_receive, dept_id, is_del, customer_type, receive_time, pool_time, company_id, is_line, source, tags,ext_json,visit_status,register_date,register_link_url,register_desc,register_submit_time,is_pool,register_type,pay_money,buy_count,source_code,push_time,push_code,visit_time,traffic_source,import_type,third_account,clue_id,qw_name from crm_customer
+        select * from crm_customer
     </sql>
 
     <select id="selectCrmCustomerList" parameterType="CrmCustomer" resultMap="CrmCustomerResult">
@@ -94,6 +98,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="thirdAccount != null "> and third_account = #{thirdAccount}</if>
             <if test="clueId != null "> and clue_id = #{clueId}</if>
             <if test="qwName != null "> and qw_name = #{qwName}</if>
+            <if test="platformName != null "> and platform_name = #{platformName}</if>
+            <if test="goodsName != null "> and goods_name = #{goodsName}</if>
+            <if test="goodsSpecification != null "> and goods_specification = #{goodsSpecification}</if>
+            <if test="shopName != null "> and shop_name = #{shopName}</if>
         </where>
         order by customer_id desc
     </select>
@@ -159,6 +167,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="thirdAccount != null">third_account,</if>
             <if test="clueId != null">clue_id,</if>
             <if test="qwName != null">qw_name,</if>
+            <if test="platformName != null">platform_name,</if>
+            <if test="goodsName != null">goods_name,</if>
+            <if test="goodsSpecification != null">goods_specification,</if>
+            <if test="shopName != null">shop_name,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="customerCode != null">#{customerCode},</if>
@@ -209,6 +221,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="thirdAccount != null">#{thirdAccount},</if>
             <if test="clueId != null">#{clueId},</if>
             <if test="qwName != null">#{qwName},</if>
+            <if test="platformName != null">#{platformName},</if>
+            <if test="goodsName != null">#{goodsName},</if>
+            <if test="goodsSpecification != null">#{goodsSpecification},</if>
+            <if test="shopName != null">#{shopName},</if>
          </trim>
     </insert>
 
@@ -263,6 +279,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="thirdAccount != null">third_account = #{thirdAccount},</if>
             <if test="clueId != null">clue_id = #{clueId},</if>
             <if test="qwName != null">qw_name = #{qwName},</if>
+            <if test="platformName != null">platform_name = #{platformName},</if>
+            <if test="goodsName != null">goods_name = #{goodsName},</if>
+            <if test="goodsSpecification != null">goods_specification = #{goodsSpecification},</if>
+            <if test="shopName != null">shop_name = #{shopName},</if>
         </trim>
         where customer_id = #{customerId}
     </update>

+ 34 - 0
fs-wx-api/src/main/java/com/fs/FSServletInitializer.java

@@ -1,8 +1,15 @@
 package com.fs;
 
+import com.fs.crm.utils.CidUserOrderExtractor;
+import com.fs.crm.vo.CrmOrderInfoVo;
 import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
 
 public class FSServletInitializer extends SpringBootServletInitializer
 {
@@ -11,4 +18,31 @@ public class FSServletInitializer extends SpringBootServletInitializer
     {
         return application.sources(FsWxApiApplication.class);
     }
+
+
+    public static void main(String[] args) {
+        // 构造带不确定间隔的订单文本(空格、换行、制表符混合)
+        List<String> orderTextList = Arrays.asList(
+                "京东-关舒宝医药旗舰店(侯)日期2026-01-12 09:13:36订单号3376231002663571商品盐酸氨基葡萄糖颗粒(关舒宝)规格0.48g*12袋/盒物流京东-京东-8192JDVG04843590091数量(件)3实付金额128",
+                "天猫-挑宝大药房旗舰店(侯)日期2026-01-12 10:10:12订单号3178588622077244779商品今正牌氨糖硫酸软骨素钙片(今正)规格10g(1g/片*10片)/盒物流天猫-中通菜鸟-侯78973651022516数量(件)3实付金额79.9"
+        );
+
+        // Java 8 Stream API 批量提取
+        List<CrmOrderInfoVo> orderInfoList = orderTextList.stream()
+                .map(CidUserOrderExtractor::extractSingleOrder)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+
+        // 打印结果(验证日期转换和间隔适配)
+        System.out.println("订单提取结果(适配间隔不确定):");
+        orderInfoList.forEach(System.out::println);
+
+        // 演示:Java 8 日期格式化(LocalDateTime → 自定义字符串格式)
+        if (!orderInfoList.isEmpty()) {
+            String customDate = CidUserOrderExtractor.formatLocalDateTime(
+                    orderInfoList.get(0).getBuyDate(), "yyyy/MM/dd HH:mm"
+            );
+            System.out.println("\n自定义格式日期示例:" + customDate);
+        }
+    }
 }