dcs 1 rok temu
rodzic
commit
a9656b98b0

+ 5 - 0
virgo.core/pom.xml

@@ -136,5 +136,10 @@
 		    <artifactId>core</artifactId>
 		    <version>3.3.0</version>
 		</dependency>
+		<dependency>
+			<groupId>cn.hutool</groupId>
+			<artifactId>hutool-all</artifactId>
+			<version>5.8.5</version>
+		</dependency>
 	</dependencies>
 </project>

+ 1 - 0
virgo.core/src/main/java/com/bosshand/virgo/core/config/ShiroConfig.java

@@ -61,6 +61,7 @@ public class ShiroConfig {
 		filterChainDefinitionMap.put("/configuration/**","anon");
 
 
+		filterChainDefinitionMap.put("/client/downloadModel", "anon");
 		filterChainDefinitionMap.put("/project/getProjectName/**", "anon");
 		filterChainDefinitionMap.put("/projectItemFromYui/**", "anon");
 		filterChainDefinitionMap.put("/flow/projectFromYui/**","anon");

+ 4 - 1
virgo.core/src/main/java/com/bosshand/virgo/core/dao/MgrClientDao.java

@@ -5,12 +5,15 @@ import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 
 @Mapper
 public interface MgrClientDao {
 
     int insert(MgrClient mgrClient);
 
+    int batchInsert(List<MgrClient> list);
+
     int update(MgrClient mgrClient);
 
     MgrClient get(long id);
@@ -21,5 +24,5 @@ public interface MgrClientDao {
 
     List<MgrClient> getLimit(@Param("p") MgrClient p, @Param("currIndex") int currIndex, @Param("pageSize") int pageSize);
 
-
+    List<Map<Integer, Integer>> typeCount(MgrClient mgrClient);
 }

+ 39 - 41
virgo.core/src/main/java/com/bosshand/virgo/core/model/MgrClient.java

@@ -4,19 +4,6 @@ package com.bosshand.virgo.core.model;
  * 客户
  */
 public class MgrClient {
-
-    private long id;
-
-    /**
-     * 组织id
-     */
-    private long organizationId;
-
-    /**
-     * 创建者id
-     */
-    private long userId;
-
     /**
      * 客户名称
      */
@@ -25,7 +12,7 @@ public class MgrClient {
     /**
      * 客户类型
      */
-    private int type;
+    private Integer type;
 
     /**
      * 联系人
@@ -45,7 +32,7 @@ public class MgrClient {
     /**
      * 跟进状态
      */
-    private int followUpState;
+    private Integer followUpState;
 
     /**
      * 职位
@@ -98,33 +85,21 @@ public class MgrClient {
     private Integer status;
 
     /**
-     * 公海
+     * 公海状态
      */
     private Integer highSeas;
 
-    public long getId() {
-        return id;
-    }
-
-    public void setId(long id) {
-        this.id = id;
-    }
-
-    public long getOrganizationId() {
-        return organizationId;
-    }
-
-    public void setOrganizationId(long organizationId) {
-        this.organizationId = organizationId;
-    }
+    private long id;
 
-    public long getUserId() {
-        return userId;
-    }
+    /**
+     * 组织id
+     */
+    private long organizationId;
 
-    public void setUserId(long userId) {
-        this.userId = userId;
-    }
+    /**
+     * 创建者id
+     */
+    private long userId;
 
     public String getName() {
         return name;
@@ -134,11 +109,11 @@ public class MgrClient {
         this.name = name;
     }
 
-    public int getType() {
+    public Integer getType() {
         return type;
     }
 
-    public void setType(int type) {
+    public void setType(Integer type) {
         this.type = type;
     }
 
@@ -166,11 +141,11 @@ public class MgrClient {
         this.weChatAccount = weChatAccount;
     }
 
-    public int getFollowUpState() {
+    public Integer getFollowUpState() {
         return followUpState;
     }
 
-    public void setFollowUpState(int followUpState) {
+    public void setFollowUpState(Integer followUpState) {
         this.followUpState = followUpState;
     }
 
@@ -262,4 +237,27 @@ public class MgrClient {
         this.highSeas = highSeas;
     }
 
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public long getOrganizationId() {
+        return organizationId;
+    }
+
+    public void setOrganizationId(long organizationId) {
+        this.organizationId = organizationId;
+    }
+
+    public long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(long userId) {
+        this.userId = userId;
+    }
 }

+ 124 - 0
virgo.core/src/main/java/com/bosshand/virgo/core/utils/ExcelUtils.java

@@ -0,0 +1,124 @@
+package com.bosshand.virgo.core.utils;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.poi.excel.ExcelReader;
+import cn.hutool.poi.excel.ExcelUtil;
+
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.*;
+
+public class ExcelUtils {
+
+    /**
+     * 将Excel转换为实体类集合
+     *
+     * @param file       excel文件
+     * @param sheetIndex sheet索引
+     * @param startIndex 起始行数(忽略前几行),一般需要忽略到属性名之前
+     * @param endIndex   结束行数(忽略最后几行)
+     * @param size       集合初始容量(由于ArrayList自动扩容耗费时间,应指定初始容量)
+     * @param tClass     转换的实体类class对象
+     * @param <T>
+     * @return
+     */
+    public static <T> List<T> dispose(InputStream file, int sheetIndex, int startIndex, int endIndex, int size, Class<T> tClass) {
+        //用于存储合并单元格的数据
+        Map<Integer, Object> tempMap = new HashMap<>();
+        //创建指定初始大小的集合
+        List<T> list = new ArrayList<>(size);
+        ExcelReader reader = ExcelUtil.getReader(file, sheetIndex - 1);
+        List<List<Object>> read = reader.read();
+        //对集合进行分割,去除开始之前的数据和最后的数据
+        read = read.subList(startIndex, read.size() - endIndex);
+        read.forEach(o -> {
+            for (int i = 0; i < o.size(); i++) {
+                String s = StrUtil.toString(o.get(i));
+                //如果该列的属性值不为空,则放入集合
+                if (StrUtil.isNotBlank(s)) {
+                    tempMap.put(i, s);
+                } else {
+                    //为空,则从集合中取出上一次存储的值
+                    o.set(i, tempMap.get(i));
+                }
+
+            }
+            try {
+                //将处理后的List<Object>对象转换为实体对象
+                T t = listObjToEntity(o, tClass);
+                list.add(t);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+
+        });
+        //关闭流
+        reader.close();
+        return list;
+    }
+
+    /**
+     * 将List<Object>转换为实体对象
+     *
+     * @param listObj List<Object>对象  其中是实体对象的属性值
+     * @param tClass  实体的Class对象
+     * @param <T>
+     * @return 实体对象
+     * @throws Exception
+     */
+    public static <T> T listObjToEntity(List<Object> listObj, Class<T> tClass) throws Exception {
+        //通过反射创建对象
+        Constructor<T> constructor = tClass.getConstructor();
+        T entity = constructor.newInstance();
+        for (int i = 0; i < listObj.size(); i++) {
+            //获取对象的属性
+            Field field = tClass.getDeclaredFields()[i];
+            field.setAccessible(true);
+            //获取对象的属性值
+            Object o = listObj.get(i);
+            //获取属性值的Class对象
+            Class<?> type = field.getType();
+            if (o != null) {
+                //将属性值转换为实体类中需要的数据类型
+                o = objToAttribute(o, type);
+            }
+            //设置属性值
+            field.set(entity, o);
+
+        }
+        return entity;
+    }
+
+    /**
+     * 将任意数据类型转换为自己需要的数据类型
+     *
+     * @param o    Object数据类型
+     * @param type 需要的数据类型的Class对象
+     * @param <T>
+     * @return 转换后的对象
+     * @throws Exception
+     */
+    public static <T> T objToAttribute(Object o, Class<T> type) {
+        Object o1;
+        try {
+            //如果需要的类型为为字符串,则不需要额外处理
+            if (type == String.class) {
+                return (T) o.toString();
+            }
+            if (type != Date.class) {
+                //通过反射创建对象并赋值
+                //日期无法通过字符串生成,但是在读取Excel时已经自动转成Date对象了,所以对日期不需要处理
+                Constructor<?> constructor = type.getDeclaredConstructor(String.class);
+                constructor.setAccessible(true);
+                o1 = constructor.newInstance(o.toString());
+            } else {
+                o1 = o;
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("非法转换");
+        }
+        return (T) o1;
+    }
+
+}

+ 40 - 6
virgo.core/src/main/resources/mapper/MgrClientMapper.xml

@@ -34,6 +34,15 @@
                 #{customerIndustry}, #{followUpPerson}, #{firsTimeRoom}, #{visitingChannels}, #{visitingTime}, #{remark}, #{status}, #{highSeas})
     </insert>
 
+    <insert id="batchInsert" parameterType="com.bosshand.virgo.core.model.MgrClient" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO mgr_client(`organizationId`, `userId`, `name`, `type`, `person`, `phone`, `weChatAccount`, `followUpState`, `job`, `demand`, `decorationRequirements`,
+                               `customerIndustry`, `followUpPerson`, `firsTimeRoom`, `visitingChannels`, `visitingTime`, `remark`, `status`, `highSeas`) VALUES
+        <foreach collection="list" item="item" index="index" separator=",">
+               (#{item.organizationId}, #{item.userId}, #{item.name}, #{item.type}, #{item.person}, #{item.phone}, #{item.weChatAccount}, #{item.followUpState}, #{item.job}, #{item.demand}, #{item.decorationRequirements},
+                #{item.customerIndustry}, #{item.followUpPerson}, #{item.firsTimeRoom}, #{item.visitingChannels}, #{item.visitingTime}, #{item.remark}, #{item.status}, #{item.highSeas})
+        </foreach>
+    </insert>
+
     <delete id="delete">
         DELETE from mgr_client where id=#{id}
     </delete>
@@ -42,11 +51,11 @@
         UPDATE mgr_client
         <trim prefix="set" suffixOverrides=",">
             <if test="name!=null">name=#{name},</if>
-            <if test="type!=0">type=#{type},</if>
+            <if test="type!=null">type=#{type},</if>
             <if test="person!=null">person=#{person},</if>
             <if test="phone!=null">phone=#{phone},</if>
             <if test="weChatAccount!=null">weChatAccount=#{weChatAccount},</if>
-            <if test="followUpState!=0">followUpState=#{followUpState},</if>
+            <if test="followUpState!=null">followUpState=#{followUpState},</if>
             <if test="job!=null">job=#{job},</if>
             <if test="demand!=null">demand=#{demand},</if>
             <if test="decorationRequirements!=null">decorationRequirements=#{decorationRequirements},</if>
@@ -66,16 +75,41 @@
         SELECT * FROM mgr_client where id = #{id}
     </select>
 
+    <select id="typeCount" resultType="map">
+        SELECT type, COUNT(*) as number FROM mgr_client
+        <where>
+            <if test="organizationId!=0">and organizationId=#{organizationId}</if>
+            <if test="userId!=0">and userId=#{userId}</if>
+            <if test="name!=null">and name=#{name}</if>
+            <if test="type!=null">and type=#{type}</if>
+            <if test="person!=null">and person=#{person}</if>
+            <if test="weChatAccount!=null">and weChatAccount=#{weChatAccount}</if>
+            <if test="followUpState!=null">and followUpState=#{followUpState}</if>
+            <if test="job!=null">and job=#{job}</if>
+            <if test="demand!=null">and demand=#{demand}</if>
+            <if test="decorationRequirements!=null">and decorationRequirements=#{decorationRequirements}</if>
+            <if test="customerIndustry!=null">and customerIndustry=#{customerIndustry}</if>
+            <if test="followUpPerson!=null">and followUpPerson=#{followUpPerson}</if>
+            <if test="firsTimeRoom!=null">and firsTimeRoom=#{firsTimeRoom}</if>
+            <if test="visitingChannels!=null">and visitingChannels=#{visitingChannels}</if>
+            <if test="visitingTime!=null">and visitingTime=#{visitingTime}</if>
+            <if test="remark!=null">and remark=#{remark}</if>
+            <if test="status!=null">and status=#{status}</if>
+            <if test="highSeas!=null">and highSeas=#{highSeas}</if>
+        </where>
+        GROUP BY type
+    </select>
+
     <select id="getTotalCount" parameterType="com.bosshand.virgo.core.model.MgrClient" resultType="Integer">
         SELECT count(*) FROM mgr_client
         <where>
             <if test="organizationId!=0">and organizationId=#{organizationId}</if>
             <if test="userId!=0">and userId=#{userId}</if>
             <if test="name!=null">and name=#{name}</if>
-            <if test="type!=0">and type=#{type}</if>
+            <if test="type!=null">and type=#{type}</if>
             <if test="person!=null">and person=#{person}</if>
             <if test="weChatAccount!=null">and weChatAccount=#{weChatAccount}</if>
-            <if test="followUpState!=0">and followUpState=#{followUpState}</if>
+            <if test="followUpState!=null">and followUpState=#{followUpState}</if>
             <if test="job!=null">and job=#{job}</if>
             <if test="demand!=null">and demand=#{demand}</if>
             <if test="decorationRequirements!=null">and decorationRequirements=#{decorationRequirements}</if>
@@ -96,10 +130,10 @@
             <if test="p.organizationId!=0">and organizationId=#{p.organizationId}</if>
             <if test="p.userId!=0">and userId=#{p.userId}</if>
             <if test="p.name!=null">and name=#{p.name}</if>
-            <if test="p.type!=0">and type=#{p.type}</if>
+            <if test="p.type!=null">and type=#{p.type}</if>
             <if test="p.person!=null">and person=#{p.person}</if>
             <if test="p.weChatAccount!=null">and weChatAccount=#{p.weChatAccount}</if>
-            <if test="p.followUpState!=0">and followUpState=#{p.followUpState}</if>
+            <if test="p.followUpState!=null">and followUpState=#{p.followUpState}</if>
             <if test="p.job!=null">and job=#{p.job}</if>
             <if test="p.demand!=null">and demand=#{p.demand}</if>
             <if test="p.decorationRequirements!=null">and decorationRequirements=#{p.decorationRequirements}</if>

+ 5 - 0
virgo.manager/pom.xml

@@ -61,6 +61,11 @@
             <artifactId>gexin-rp-sdk-http</artifactId>
             <version>4.1.1.4</version>
         </dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml</artifactId>
+			<version>5.2.3</version>
+		</dependency>
 		<dependency>
 			<groupId>org.springframework.cloud</groupId>
 			<artifactId>spring-cloud-starter-openfeign</artifactId>

+ 67 - 0
virgo.manager/src/main/java/com/bosshand/virgo/controller/ClientController.java

@@ -3,11 +3,21 @@ package com.bosshand.virgo.controller;
 import com.bosshand.virgo.core.model.MgrClient;
 import com.bosshand.virgo.core.response.Response;
 import com.bosshand.virgo.core.utils.ContextUtils;
+import com.bosshand.virgo.core.utils.ExcelUtils;
+import com.bosshand.virgo.exception.BadRequestException;
+import com.bosshand.virgo.exception.Constant;
 import com.bosshand.virgo.service.ClientService;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -41,6 +51,57 @@ public class ClientController {
         return Response.ok();
     }
 
+    @ApiOperation("标准模板下载")
+    @RequestMapping(value = "/downloadModel", method = RequestMethod.GET)
+    public void getModel(final HttpServletResponse response) throws Exception {
+        byte[] data = null;
+        OutputStream outputStream = null;
+        try {
+            data = clientService.getModel();
+            response.setCharacterEncoding("UTF-8");
+            response.setContentType("application/x-msdownload");
+            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("标准模版.xlsx", "UTF-8"));
+            OutputStream outputSream = response.getOutputStream();
+            outputSream.write(data);
+            outputSream.flush();
+        } catch (IOException e) {
+            throw new BadRequestException("Fail to write stream", Constant.RET_DOCUMENT_ERROR, e);
+        } finally {
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+    }
+
+    @ApiOperation("批量导入")
+    @RequestMapping(value = "/import/{organizationId}", method = RequestMethod.POST)
+    public Response insert(@ApiParam(name = "uploadFile", required = true) MultipartFile uploadFile, @PathVariable long organizationId) {
+        long userId = ContextUtils.getCurrentUser().getId();
+        InputStream inputStream = null;
+        try {
+            inputStream = uploadFile.getInputStream();
+            List<MgrClient> list = ExcelUtils.dispose(inputStream, 1, 1, 0, 1000, MgrClient.class);
+            for (MgrClient mc : list) {
+                mc.setUserId(userId);
+                mc.setOrganizationId(organizationId);
+            }
+            clientService.batchInsert(list);
+            return Response.ok();
+        } catch (IOException e) {
+            return Response.fail(Constant.CODE_BAD_REQUEST, Constant.RET_INPUT_ERROR);
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+    }
+
     @ApiOperation("更新")
     @RequestMapping(value = "/update", method = RequestMethod.PUT)
     public Response update(@RequestBody MgrClient mgrClient) {
@@ -61,4 +122,10 @@ public class ClientController {
         return Response.ok(clientService.get(id));
     }
 
+    @ApiOperation("按类型统计数量")
+    @RequestMapping(value = "/typeCount", method = RequestMethod.POST)
+    public Response typeCount(@RequestBody MgrClient mgrClient) {
+        return Response.ok(clientService.typeCount(mgrClient));
+    }
+
 }

+ 52 - 0
virgo.manager/src/main/java/com/bosshand/virgo/service/ClientService.java

@@ -2,10 +2,18 @@ package com.bosshand.virgo.service;
 
 import com.bosshand.virgo.core.dao.MgrClientDao;
 import com.bosshand.virgo.core.model.MgrClient;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 
 @Service
 public class ClientService {
@@ -17,6 +25,10 @@ public class ClientService {
         return clientDao.insert(mgrClient);
     }
 
+    public int batchInsert(List<MgrClient> list) {
+        return clientDao.batchInsert(list);
+    }
+
     public int update(MgrClient mgrClient) {
         return clientDao.update(mgrClient);
     }
@@ -37,4 +49,44 @@ public class ClientService {
         int currIndex = (currPage - 1) * pageSize;
         return clientDao.getLimit(mgrClient, currIndex, pageSize);
     }
+
+    public List<Map<Integer, Integer>> typeCount(MgrClient mgrClient) {
+        return clientDao.typeCount(mgrClient);
+    }
+
+    /**
+     *  获取Excel模板
+     */
+    public byte[] getModel() {
+        // 创建一个新的工作簿
+        Workbook workbook = new XSSFWorkbook();
+        // 创建一个工作表(sheet)
+        Sheet sheet = workbook.createSheet("model");
+        // 创建行(0基索引)
+        Row row = sheet.createRow(0);
+        // 创建单元格并写入数据
+        String st = "客户名称,客户类型,联系人,联系电话,微信号,跟进状态,职位,需求区间,装修要求,客户行业,跟进人,首次带看房源,来访渠道,首次来访时间,备注,状态,公海状态";
+        String[] split = st.split(",");
+        for (int i = 0; i < split.length; i++) {
+            Cell cell = row.createCell(i);
+            cell.setCellValue(split[i]);
+        }
+        // 写入到文件
+        try {
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            workbook.write(outputStream);
+            return outputStream.toByteArray();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            // 清理资源
+            try {
+                workbook.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
 }