Ver código fonte

企业采购

zoujiajian 3 meses atrás
pai
commit
61cef9fd24

+ 7 - 0
netflix-dao/src/main/java/com/cyksj/mapper/enterprise/EnterprisePurchaseLeadMapper.java

@@ -0,0 +1,7 @@
+package com.cyksj.mapper.enterprise;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.EnterprisePurchaseLead;
+
+public interface EnterprisePurchaseLeadMapper extends BaseMapper<EnterprisePurchaseLead> {
+}

+ 33 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/EnterprisePurchaseLead.java

@@ -0,0 +1,33 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@Accessors(chain = true)
+@TableName("enterprise_purchase_lead")
+public class EnterprisePurchaseLead extends BaseEntity {
+
+    private String contactName;
+
+    private String companyName;
+
+    private String phone;
+
+    private String email;
+
+    private String modelCodes;
+
+    private String expectedUsage;
+
+    private String status;
+
+    private String remark;
+
+    private String submitIp;
+
+    private String userAgent;
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/request/EnterprisePurchaseLeadRemarkReq.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+@Getter
+@Setter
+public class EnterprisePurchaseLeadRemarkReq {
+
+    @NotNull(message = "id is required")
+    private Long id;
+
+    @Size(max = 2000, message = "remark max length is 2000")
+    private String remark;
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/request/EnterprisePurchaseLeadStatusReq.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+public class EnterprisePurchaseLeadStatusReq {
+
+    @NotNull(message = "id is required")
+    private Long id;
+
+    @NotBlank(message = "status is required")
+    private String status;
+}

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/request/EnterprisePurchaseLeadSubmitReq.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+@Getter
+@Setter
+public class EnterprisePurchaseLeadSubmitReq {
+
+    @NotBlank(message = "contactName is required")
+    @Size(max = 64, message = "contactName max length is 64")
+    private String contactName;
+
+    @NotBlank(message = "companyName is required")
+    @Size(max = 128, message = "companyName max length is 128")
+    private String companyName;
+
+    @NotBlank(message = "phone is required")
+    @Size(max = 32, message = "phone max length is 32")
+    private String phone;
+
+    @NotBlank(message = "email is required")
+    @Email(message = "email format is invalid")
+    @Size(max = 128, message = "email max length is 128")
+    private String email;
+
+    @NotEmpty(message = "models is required")
+    @Size(max = 20, message = "models max size is 20")
+    private List<String> models;
+
+    @NotBlank(message = "expectedUsage is required")
+    @Size(max = 128, message = "expectedUsage max length is 128")
+    private String expectedUsage;
+}

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/model/views/EnterprisePurchaseLeadView.java

@@ -0,0 +1,34 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+import java.util.List;
+
+@Getter
+@Setter
+public class EnterprisePurchaseLeadView {
+
+    private Long id;
+
+    private Date createdTime;
+
+    private Date updateTime;
+
+    private String contactName;
+
+    private String companyName;
+
+    private String phone;
+
+    private String email;
+
+    private List<String> models;
+
+    private String expectedUsage;
+
+    private String status;
+
+    private String remark;
+}

+ 20 - 0
netflix-service/src/main/java/com/cyksj/service/enterprise/EnterprisePurchaseLeadService.java

@@ -0,0 +1,20 @@
+package com.cyksj.service.enterprise;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.EnterprisePurchaseLead;
+import com.cyksj.model.request.EnterprisePurchaseLeadRemarkReq;
+import com.cyksj.model.request.EnterprisePurchaseLeadStatusReq;
+import com.cyksj.model.request.EnterprisePurchaseLeadSubmitReq;
+import com.cyksj.model.views.EnterprisePurchaseLeadView;
+
+public interface EnterprisePurchaseLeadService extends IService<EnterprisePurchaseLead> {
+
+    Long submit(EnterprisePurchaseLeadSubmitReq req, String submitIp, String userAgent);
+
+    Page<EnterprisePurchaseLeadView> page(String status, String keyword, Integer start, Integer limit);
+
+    void updateStatus(EnterprisePurchaseLeadStatusReq req);
+
+    void updateRemark(EnterprisePurchaseLeadRemarkReq req);
+}

+ 154 - 0
netflix-service/src/main/java/com/cyksj/service/enterprise/impl/EnterprisePurchaseLeadServiceImpl.java

@@ -0,0 +1,154 @@
+package com.cyksj.service.enterprise.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.enterprise.EnterprisePurchaseLeadMapper;
+import com.cyksj.model.entity.EnterprisePurchaseLead;
+import com.cyksj.model.request.EnterprisePurchaseLeadRemarkReq;
+import com.cyksj.model.request.EnterprisePurchaseLeadStatusReq;
+import com.cyksj.model.request.EnterprisePurchaseLeadSubmitReq;
+import com.cyksj.model.views.EnterprisePurchaseLeadView;
+import com.cyksj.service.enterprise.EnterprisePurchaseLeadService;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Service
+public class EnterprisePurchaseLeadServiceImpl extends ServiceImpl<EnterprisePurchaseLeadMapper, EnterprisePurchaseLead> implements EnterprisePurchaseLeadService {
+
+    private static final String STATUS_PENDING = "pending";
+    private static final String STATUS_CONTACTED = "contacted";
+    private static final String STATUS_INVALID = "invalid";
+    private static final Set<String> ALLOW_STATUSES = Set.of(STATUS_PENDING, STATUS_CONTACTED, STATUS_INVALID);
+
+    @Override
+    public Long submit(EnterprisePurchaseLeadSubmitReq req, String submitIp, String userAgent) {
+        List<String> models = normalizeModels(req.getModels());
+        if (models.isEmpty()) {
+            throw new BusinessRuntimeException("models is required");
+        }
+
+        EnterprisePurchaseLead lead = new EnterprisePurchaseLead()
+                .setContactName(limit(req.getContactName(), 64))
+                .setCompanyName(limit(req.getCompanyName(), 128))
+                .setPhone(limit(req.getPhone(), 32))
+                .setEmail(limit(req.getEmail(), 128))
+                .setModelCodes(String.join(",", models))
+                .setExpectedUsage(limit(req.getExpectedUsage(), 128))
+                .setStatus(STATUS_PENDING)
+                .setSubmitIp(limit(submitIp, 64))
+                .setUserAgent(limit(userAgent, 512))
+                .setRemark("");
+        save(lead);
+        return lead.getId();
+    }
+
+    @Override
+    public Page<EnterprisePurchaseLeadView> page(String status, String keyword, Integer start, Integer limit) {
+        int current = start == null || start < 1 ? 1 : start;
+        int size = limit == null || limit < 1 ? 10 : Math.min(limit, 100);
+
+        LambdaQueryWrapper<EnterprisePurchaseLead> wrapper = new LambdaQueryWrapper<>();
+        if (StrUtil.isNotBlank(status) && !"all".equals(status)) {
+            validateStatus(status);
+            wrapper.eq(EnterprisePurchaseLead::getStatus, status);
+        }
+        if (StrUtil.isNotBlank(keyword)) {
+            String kw = keyword.trim();
+            wrapper.and(w -> w.like(EnterprisePurchaseLead::getCompanyName, kw)
+                    .or().like(EnterprisePurchaseLead::getContactName, kw)
+                    .or().like(EnterprisePurchaseLead::getPhone, kw)
+                    .or().like(EnterprisePurchaseLead::getEmail, kw));
+        }
+        wrapper.orderByDesc(EnterprisePurchaseLead::getCreatedTime);
+
+        Page<EnterprisePurchaseLead> entityPage = page(new Page<>(current, size), wrapper);
+        Page<EnterprisePurchaseLeadView> viewPage = new Page<>(entityPage.getCurrent(), entityPage.getSize());
+        viewPage.setTotal(entityPage.getTotal());
+        viewPage.setRecords(entityPage.getRecords().stream().map(this::toView).collect(Collectors.toList()));
+        return viewPage;
+    }
+
+    @Override
+    public void updateStatus(EnterprisePurchaseLeadStatusReq req) {
+        validateStatus(req.getStatus());
+        EnterprisePurchaseLead lead = new EnterprisePurchaseLead()
+                .setStatus(req.getStatus());
+        lead.setId(req.getId());
+        if (!updateById(lead)) {
+            throw new BusinessRuntimeException("lead not found");
+        }
+    }
+
+    @Override
+    public void updateRemark(EnterprisePurchaseLeadRemarkReq req) {
+        EnterprisePurchaseLead lead = new EnterprisePurchaseLead()
+                .setRemark(limit(req.getRemark(), 2000));
+        lead.setId(req.getId());
+        if (!updateById(lead)) {
+            throw new BusinessRuntimeException("lead not found");
+        }
+    }
+
+    private EnterprisePurchaseLeadView toView(EnterprisePurchaseLead lead) {
+        EnterprisePurchaseLeadView view = new EnterprisePurchaseLeadView();
+        view.setId(lead.getId());
+        view.setCreatedTime(lead.getCreatedTime());
+        view.setUpdateTime(lead.getUpdateTime());
+        view.setContactName(lead.getContactName());
+        view.setCompanyName(lead.getCompanyName());
+        view.setPhone(lead.getPhone());
+        view.setEmail(lead.getEmail());
+        view.setModels(splitModels(lead.getModelCodes()));
+        view.setExpectedUsage(lead.getExpectedUsage());
+        view.setStatus(lead.getStatus());
+        view.setRemark(lead.getRemark());
+        return view;
+    }
+
+    private List<String> normalizeModels(List<String> models) {
+        if (models == null) {
+            return Collections.emptyList();
+        }
+        return models.stream()
+                .filter(StrUtil::isNotBlank)
+                .map(String::trim)
+                .map(item -> item.replace(",", ""))
+                .map(item -> limit(item, 128))
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
+    private List<String> splitModels(String modelCodes) {
+        if (StrUtil.isBlank(modelCodes)) {
+            return Collections.emptyList();
+        }
+        return Arrays.stream(modelCodes.split(","))
+                .filter(StrUtil::isNotBlank)
+                .collect(Collectors.toList());
+    }
+
+    private void validateStatus(String status) {
+        if (!ALLOW_STATUSES.contains(status)) {
+            throw new BusinessRuntimeException("status is invalid");
+        }
+    }
+
+    private String limit(String value, int maxLength) {
+        if (value == null) {
+            return "";
+        }
+        String trim = value.trim();
+        if (trim.length() <= maxLength) {
+            return trim;
+        }
+        return StrUtil.subPre(trim, maxLength);
+    }
+}

+ 43 - 0
netflix-web/src/main/java/com/cyksj/web/controller/enterprise/EnterprisePurchaseLeadFrontController.java

@@ -0,0 +1,43 @@
+package com.cyksj.web.controller.enterprise;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.request.EnterprisePurchaseLeadSubmitReq;
+import com.cyksj.service.enterprise.EnterprisePurchaseLeadService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+@RestController
+@RequiredArgsConstructor
+@RequestMapping({"/applet/enterprise/lead", "/applets/enterprise/lead"})
+public class EnterprisePurchaseLeadFrontController {
+
+    private final EnterprisePurchaseLeadService enterprisePurchaseLeadService;
+
+    private final HttpServletRequest request;
+
+    @PostMapping
+    public Result<Long> submit(@RequestBody @Validated EnterprisePurchaseLeadSubmitReq req) {
+        Long id = enterprisePurchaseLeadService.submit(req, getClientIp(), request.getHeader("User-Agent"));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(id);
+    }
+
+    private String getClientIp() {
+        String ip = request.getHeader("X-Forwarded-For");
+        if (ip != null && !ip.isBlank()) {
+            int commaIndex = ip.indexOf(',');
+            return commaIndex > -1 ? ip.substring(0, commaIndex).trim() : ip.trim();
+        }
+        ip = request.getHeader("X-Real-IP");
+        if (ip != null && !ip.isBlank()) {
+            return ip.trim();
+        }
+        return request.getRemoteAddr();
+    }
+}

+ 46 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/enterprise/CmsEnterprisePurchaseLeadController.java

@@ -0,0 +1,46 @@
+package com.cyksj.web.controller.manage.enterprise;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.EnterprisePurchaseLead;
+import com.cyksj.model.request.EnterprisePurchaseLeadRemarkReq;
+import com.cyksj.model.request.EnterprisePurchaseLeadStatusReq;
+import com.cyksj.model.views.EnterprisePurchaseLeadView;
+import com.cyksj.service.enterprise.EnterprisePurchaseLeadService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/manage/enterprise/lead")
+public class CmsEnterprisePurchaseLeadController {
+
+    private final EnterprisePurchaseLeadService enterprisePurchaseLeadService;
+
+    @GetMapping
+    public Result<Page<EnterprisePurchaseLeadView>> page(String status,
+                                                         String keyword,
+                                                         @RequestParam(defaultValue = "1") Integer start,
+                                                         @RequestParam(defaultValue = "10") Integer limit) {
+        return GatewayResponse.SUCCESS.newBuilder().toResult(enterprisePurchaseLeadService.page(status, keyword, start, limit));
+    }
+
+    @GetMapping("/{id}")
+    public Result<EnterprisePurchaseLead> detail(@PathVariable Long id) {
+        return GatewayResponse.SUCCESS.newBuilder().toResult(enterprisePurchaseLeadService.getById(id));
+    }
+
+    @PutMapping("/status")
+    public Result<String> updateStatus(@RequestBody @Validated EnterprisePurchaseLeadStatusReq req) {
+        enterprisePurchaseLeadService.updateStatus(req);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    @PutMapping("/remark")
+    public Result<String> updateRemark(@RequestBody @Validated EnterprisePurchaseLeadRemarkReq req) {
+        enterprisePurchaseLeadService.updateRemark(req);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+}