浏览代码

luckysheet集成

wangming 1 年之前
父节点
当前提交
8af6321018
共有 68 个文件被更改,包括 9039 次插入4 次删除
  1. 53 0
      business-common/pom.xml
  2. 103 0
      business-common/src/main/java/com/rongwei/bscommon/sys/config/api/ResponseVO.java
  3. 146 0
      business-common/src/main/java/com/rongwei/bscommon/sys/config/redis/RedisCacheService.java
  4. 74 0
      business-common/src/main/java/com/rongwei/bscommon/sys/config/redis/RedisConfig.java
  5. 134 0
      business-common/src/main/java/com/rongwei/bscommon/sys/config/redis/RedisQueueService.java
  6. 69 0
      business-common/src/main/java/com/rongwei/bscommon/sys/constant/SysConstant.java
  7. 20 0
      business-common/src/main/java/com/rongwei/bscommon/sys/dao/LuckysheetDao.java
  8. 239 0
      business-common/src/main/java/com/rongwei/bscommon/sys/db/server/JfGridFileGetService.java
  9. 2202 0
      business-common/src/main/java/com/rongwei/bscommon/sys/db/server/JfGridUpdateService.java
  10. 119 0
      business-common/src/main/java/com/rongwei/bscommon/sys/exception/InterfaceRequestErrorAndPerformanceLog.java
  11. 12 0
      business-common/src/main/java/com/rongwei/bscommon/sys/exception/ServiceException.java
  12. 119 0
      business-common/src/main/java/com/rongwei/bscommon/sys/redisserver/GridFileRedisCacheService.java
  13. 179 0
      business-common/src/main/java/com/rongwei/bscommon/sys/redisserver/RedisLock.java
  14. 61 0
      business-common/src/main/java/com/rongwei/bscommon/sys/redisserver/RedisMessageModel.java
  15. 42 0
      business-common/src/main/java/com/rongwei/bscommon/sys/redisserver/RedisMessagePublish.java
  16. 24 0
      business-common/src/main/java/com/rongwei/bscommon/sys/service/LuckysheetService.java
  17. 9 0
      business-common/src/main/java/com/rongwei/bscommon/sys/service/ZhcxProjectManageService.java
  18. 208 0
      business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/LuckysheetServiceImpl.java
  19. 5 0
      business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ZhcxProjectDeviceNumberServiceImpl.java
  20. 2 1
      business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ZhcxProjectManageServiceImpl.java
  21. 87 0
      business-common/src/main/java/com/rongwei/bscommon/sys/utils/GzipHandle.java
  22. 40 0
      business-common/src/main/java/com/rongwei/bscommon/sys/utils/JsonUtil.java
  23. 636 0
      business-common/src/main/java/com/rongwei/bscommon/sys/utils/LuckySheet4SummaryHelp.java
  24. 33 0
      business-common/src/main/java/com/rongwei/bscommon/sys/utils/MyStringUtil.java
  25. 59 0
      business-common/src/main/java/com/rongwei/bscommon/sys/utils/MyURLUtil.java
  26. 282 0
      business-common/src/main/java/com/rongwei/bscommon/sys/utils/Pako_GzipUtils.java
  27. 22 0
      business-common/src/main/java/com/rongwei/bscommon/sys/utils/TimeUtil.java
  28. 83 0
      business-dameng/pom.xml
  29. 32 0
      business-dameng/src/main/java/com/rongwei/luckysheet/dameng/datasource/JdbcTempleConfig.java
  30. 51 0
      business-dameng/src/main/java/com/rongwei/luckysheet/dameng/datasource/ProfiledemoApplication.java
  31. 35 0
      business-dameng/src/main/java/com/rongwei/luckysheet/dameng/datasource/SnowFlakeConfig.java
  32. 19 0
      business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/BaseHandle.java
  33. 135 0
      business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/RecordDataInsertHandle.java
  34. 528 0
      business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/RecordDataUpdataHandle.java
  35. 84 0
      business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/RecordDelHandle.java
  36. 395 0
      business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/RecordSelectHandle.java
  37. 50 0
      business-db/pom.xml
  38. 223 0
      business-db/src/main/java/com/rongwei/luckysheet/JfGridConfigModel.java
  39. 32 0
      business-db/src/main/java/com/rongwei/luckysheet/db/IRecordDataInsertHandle.java
  40. 153 0
      business-db/src/main/java/com/rongwei/luckysheet/db/IRecordDataUpdataHandle.java
  41. 36 0
      business-db/src/main/java/com/rongwei/luckysheet/db/IRecordDelHandle.java
  42. 114 0
      business-db/src/main/java/com/rongwei/luckysheet/db/IRecordSelectHandle.java
  43. 57 0
      business-db/src/main/java/com/rongwei/luckysheet/entity/GridRecordDataModel.java
  44. 405 0
      business-db/src/main/java/com/rongwei/luckysheet/util/JfGridFileUtil.java
  45. 87 0
      business-db/src/main/java/com/rongwei/luckysheet/util/SnowFlake.java
  46. 46 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/LuckysheetDo.java
  47. 19 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/BaseModel.java
  48. 41 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/BaseOperationModel.java
  49. 102 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/ConfigMergeModel.java
  50. 28 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/LuckySheetGridModel.java
  51. 42 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/enummodel/DisabledTypeEnum.java
  52. 73 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/enummodel/ExcelCenterStyleEnum.java
  53. 17 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/enummodel/OperationTypeEnum.java
  54. 44 0
      business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/enummodel/SheetOperationEnum.java
  55. 46 0
      business-entity/src/main/java/com/rongwei/bsentity/dto/luckysheet/AssembleCellParam.java
  56. 38 0
      business-entity/src/main/java/com/rongwei/bsentity/dto/luckysheet/SheetConfigResultDto.java
  57. 23 0
      business-entity/src/main/java/com/rongwei/bsentity/dto/project/SheetInfoParam.java
  58. 19 0
      business-server/pom.xml
  59. 184 0
      business-server/src/main/java/com/rongwei/bsserver/controller/JfGridFileController.java
  60. 7 2
      business-server/src/main/java/com/rongwei/bsserver/controller/ZhcxProjectManageController.java
  61. 48 0
      business-server/src/main/java/com/rongwei/bsserver/redisserver/RedisMessageListener.java
  62. 38 0
      business-server/src/main/java/com/rongwei/bsserver/service/ConfigerService.java
  63. 77 0
      business-server/src/main/java/com/rongwei/bsserver/websocket/IpAndPortUtil.java
  64. 397 0
      business-server/src/main/java/com/rongwei/bsserver/websocket/MyWebSocketHandler.java
  65. 90 0
      business-server/src/main/java/com/rongwei/bsserver/websocket/MyWebSocketInterceptor.java
  66. 97 0
      business-server/src/main/java/com/rongwei/bsserver/websocket/WSUserModel.java
  67. 62 0
      business-server/src/main/java/com/rongwei/bsserver/websocket/WebSocketConfig.java
  68. 3 1
      pom.xml

+ 53 - 0
business-common/pom.xml

@@ -75,5 +75,58 @@
             <artifactId>springfox-swagger-ui</artifactId>
             <version>2.9.2</version>
         </dependency>
+
+
+        <!-- 解决maven打包 错误: 程序包com.sun.istack.internal不存在 - BBSMAX -->
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-impl</artifactId>
+            <version>2.2.11</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+            <version>13.0</version>
+        </dependency>
+        <!-- 解决maven打包 错误: 程序包com.sun.istack.internal不存在 - BBSMAX -->
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.2.4</version>
+        </dependency>
+
+        <!-- 数据库接口以及实现 -->
+        <dependency>
+            <groupId>com.rongwei</groupId>
+            <artifactId>business-db</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.rongwei</groupId>
+            <artifactId>business-dameng</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- websocket start -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+            <version>1.3.5.RELEASE</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-websocket</artifactId>
+            <version>4.3.6.RELEASE</version>
+        </dependency>
+        <!-- websocket end -->
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.70</version>
+        </dependency>
     </dependencies>
 </project>

+ 103 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/config/api/ResponseVO.java

@@ -0,0 +1,103 @@
+package com.rongwei.bscommon.sys.config.api;
+
+
+import com.rongwei.bscommon.sys.constant.SysConstant;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.Serializable;
+
+/**
+ * 返回对象
+ * @author Administrator
+ */
+@Data
+@ApiModel(value = "请求返回类",description = "请求响应参数")
+public class ResponseVO implements Serializable {
+
+    private static final long serialVersionUID = 1l;
+
+
+    /**
+     * 消息状态
+     */
+    @NotNull
+    @ApiModelProperty(value = "status",example = StringUtils.EMPTY)
+    private String status = StringUtils.EMPTY;
+
+    /**
+     * 交互结果消息描述
+     */
+    @NotNull
+    @ApiModelProperty(value = "msg",example = StringUtils.EMPTY)
+    private String msg = StringUtils.EMPTY;
+
+    /**
+     * 消息体
+     */
+    @NotNull
+    @ApiModelProperty(value = "data",example = "{}")
+    private Object data;
+
+    /**
+     * 消息代码
+     */
+    @NotNull
+    @ApiModelProperty(value = "code",example = StringUtils.EMPTY)
+    private String code = StringUtils.EMPTY;
+
+    /**
+     * 成功默认消息
+     * @return
+     */
+    private ResponseVO() {
+        this.status = SysConstant.STATUS.Valid;
+        this.msg = SysConstant.MSG.SUCCESS;
+        this.code = SysConstant.SYS_CODE.STATUS_SUCCESS;
+        this.data="{}";
+    }
+
+    /**
+     * 成功默认消息
+     * @return
+     */
+    public static ResponseVO successInstance() {
+        return new ResponseVO();
+    }
+
+    /**
+     * 成功-返回数据
+     * @param data
+     * @return
+     */
+    public static ResponseVO successInstance(Object data) {
+        if(data==null){
+            data="";
+        }
+        ResponseVO res = successInstance();
+        res.setData(data);
+        return res;
+    }
+
+
+    /**
+     * 失败错误消息
+     * @param msg
+     * @return
+     */
+    public static ResponseVO errorInstance(String msg) {
+        ResponseVO res = successInstance();
+
+        res.setStatus(SysConstant.STATUS.Invalid);
+        res.setCode(SysConstant.SYS_CODE.STATUS_ERROR);
+        res.setMsg(StringUtils.isBlank(msg) ? SysConstant.MSG.ERROR : msg);
+
+        return res;
+    }
+
+
+
+}

+ 146 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/config/redis/RedisCacheService.java

@@ -0,0 +1,146 @@
+package com.rongwei.bscommon.sys.config.redis;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+@Service
+public class RedisCacheService {
+
+    @Resource
+    private RedisTemplate<String,Object> redisTemplate;
+
+    /**
+     * 获取值
+     * @param name
+     * @param key
+     * @return
+     */
+    public Object getMapCache(String name,String key){
+        log.info("获取Map {},{}",name,key);
+        return redisTemplate.opsForHash().get(name,key);
+    }
+
+    /**
+     * 保存值
+     * @param key
+     * @param name
+     * @param value
+     */
+    public void setMapCache(String name,String key,Object value){
+        log.info("保存Map {},{},{}",name,key,value);
+        redisTemplate.opsForHash().put(name,key,value);
+    }
+    /**
+     * 删除值
+     * @param name
+     * @param key
+     */
+    public void delMapCache(String name,String key){
+        log.info("删除Map {},{}",name,key);
+        redisTemplate.opsForHash().delete(name,key);
+    }
+
+    /**
+     * 数据更新时间 默认30分钟
+     * @param key
+     * @param val
+     */
+    public void addCache(String key,Object val){
+        addCache(key,val,30);
+    }
+    /**
+     * 数据更新时间
+     * @param key
+     * @param val
+     * @param time 过期时间 以分钟为单位
+     */
+    public void addCache(String key,Object val,long time) {
+        ValueOperations opsForValue=redisTemplate.opsForValue();
+        opsForValue.set(key,val,time,TimeUnit.MINUTES);
+    }
+
+    /**
+     * 根据key查询对应缓存值
+     * @param key
+     * @return
+     */
+    public Object getCache(String key){
+        return redisTemplate.opsForValue().get(key);
+    }
+
+
+
+    /**
+     * 根据前缀批量删除redisKey
+     * @param prex 前缀
+     * @return 删除条数
+     */
+    public int deleteCaches(String prex){
+        String key=prex+"*";
+        Set<String> keys = redisTemplate.keys(key);
+        if(keys!=null && keys.size()>0){
+            redisTemplate.delete(keys);
+            return keys.size();
+        }
+        return 0;
+    }
+
+    /**
+     * 删除单条
+     * @param key 删除的key
+     * @return
+     */
+    public int deleteCacheByKey(String key){
+        Set<String> keys = redisTemplate.keys(key);
+        if(keys!=null && keys.size()>0){
+            redisTemplate.delete(keys);
+            return keys.size();
+        }
+        return 0;
+    }
+
+    /**
+     * 按数量获取
+     * @param key
+     * @param size
+     * @return
+     */
+    public List getListBySize(String key, long size){
+        List liststr=redisTemplate.opsForList().range(key, 0, size);
+        return liststr;
+    }
+    /**
+     * 从头部删除指定数量的key
+     * @param key
+     * @param size
+     */
+    public void delList(String key,int size){
+        for(int x=0;x<size;x++){
+            try{
+                redisTemplate.opsForList().leftPop(key);
+            }catch(Exception ex){
+
+            }
+        }
+    }
+    /**
+     * 添加队列(位置尾部)
+     * @param key
+     * @param val
+     * @return  返回val所在队列的序号
+     */
+    public long addList(String key,Object val){
+        return redisTemplate.opsForList().rightPush(key, val);
+    }
+}

+ 74 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/config/redis/RedisConfig.java

@@ -0,0 +1,74 @@
+package com.rongwei.bscommon.sys.config.redis;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Slf4j
+@Configuration
+public class RedisConfig {
+    /**
+     * 配置自定义redisTemplate
+     * @return
+     */
+    @Bean
+    RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+
+        log.info("start to config redisTemplate.");
+
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(redisConnectionFactory);
+
+        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
+        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        serializer.setObjectMapper(mapper);
+
+        template.setValueSerializer(serializer);
+        //使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(serializer);
+        template.afterPropertiesSet();
+
+        log.info("Config redisTemplate end.");
+        return template;
+    }
+
+}
+
+/*
+
+集群配置
+spring:
+  #RedisProperties配置spring data redis
+  redis:
+    timeout: 6000ms
+    password: 1qaz2wsx
+    lettuce:
+      pool:
+        max-active: 1000 #连接池最大连接数(使用负值表示没有限制)
+        max-idle: 10 # 连接池中的最大空闲连接
+        min-idle: 5 # 连接池中的最小空闲连接
+        max-wait: 30 # 连接池最大阻塞等待时间(使用负值表示没有限制)
+    cluster:
+      nodes:
+        - 47.103.218.34:7001
+        - 47.103.218.34:7002
+        - 47.103.218.34:7003
+        - 47.103.218.34:7004
+        - 47.103.218.34:7005
+        - 47.103.218.34:7006
+      maxRedirects: 3 # 获取失败 最大重定向次数
+
+ */

+ 134 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/config/redis/RedisQueueService.java

@@ -0,0 +1,134 @@
+package com.rongwei.bscommon.sys.config.redis;
+
+
+import com.rongwei.bscommon.sys.constant.SysConstant;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * redis 队列(左头右尾) 服务
+ * @author Administrator
+ */
+@Slf4j
+@Service
+public class RedisQueueService {
+
+    @Autowired
+    RedisTemplate<String, Object> redisTemplate;
+
+    /**
+     * 往队列尾加入一个值
+     *
+     * @param key
+     * @param val
+     */
+    public Long push(String key, Object val) {
+        return redisTemplate.opsForList().rightPush(key, val);
+    }
+
+    /**
+     * 从队列头部移出并获得值
+     *
+     * @param key
+     * @return
+     */
+    public Object pop(String key) {
+        return redisTemplate.opsForList().leftPop(key);
+    }
+
+    /**
+     * 从队列头部移出并获得值,x秒无数据断开
+     *
+     * @param key
+     * @param times
+     * @return
+     */
+    public Object pop(String key, int times) {
+        return redisTemplate.opsForList().leftPop(key, times, TimeUnit.SECONDS);
+    }
+
+    public void clear() {
+
+        redisTemplate.delete(SysConstant.Editor.editorQueue);
+    }
+
+    /**
+     * 获取list的数量
+     *
+     * @param key
+     * @return
+     */
+    public long getListNumber(String key) {
+        return redisTemplate.opsForList().size(key);
+    }
+
+    /**
+     * 往队列尾加入一个新数组
+     *
+     * @param key
+     * @param val
+     */
+    public Long pushList(String key, Object val) {
+        return redisTemplate.opsForList().rightPushAll(key, val);
+    }
+
+    /**
+     * 获取当前队列所有数据并删除数据
+     *
+     * @param key
+     * @return
+     */
+    public List popList(String key) {
+        long size = getListNumber(key);
+        List list = new ArrayList();
+        for (int i = 0; i < size; i++) {
+            Object obj = redisTemplate.opsForList().leftPop(key);
+            list.add(obj);
+        }
+        return list;
+    }
+
+    public void del(String key) {
+        redisTemplate.delete(key);
+    }
+
+    /**
+     * 读取redis数据数组中所有数据,不删除数据
+     * @param key
+     * @return
+     */
+    public List range(String key) {
+        long size = getListNumber(key);
+        return redisTemplate.opsForList().range(key, 0, size);
+    }
+
+    /**
+     * 从队列的左边获取数据,并删除已取出的数据
+     * @param key
+     * @param T
+     * @param count
+     * @param <T>
+     * @return
+     */
+    public <T> List<T> popList(String key,Class<T> T,int count){
+        List<T> _list=new ArrayList<T>();
+        try{
+            for(int x=0;x<count;x++){
+                Object obj=pop(key);
+                if(obj==null){
+                    break;
+                }
+                _list.add((T)obj);
+            }
+        }catch (Exception ex){
+            log.error(ex.getMessage());
+        }
+        return _list;
+    }
+}

+ 69 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/constant/SysConstant.java

@@ -0,0 +1,69 @@
+package com.rongwei.bscommon.sys.constant;
+
+
+/**
+ * @author Administrator
+ */
+public interface SysConstant {
+
+    interface MSG{
+        /**
+         * 操作成功
+         */
+        String SUCCESS = "操作成功";
+
+        /**
+         * 系统错误,请联系管理员
+         */
+        String ERROR = "系统错误,请联系管理员";
+    }
+
+    /**
+     * 状态
+     */
+    public interface STATUS {
+        /**
+         * 有效/成功
+         */
+        String Valid = "1";
+
+        /**
+         * 失效/失败
+         */
+        String Invalid = "0";
+
+
+    }
+
+    /**
+     * 系统消息代码
+     */
+    public interface SYS_CODE {
+        /**
+         * 消息代码前缀
+         */
+        String SYS = "SYS";
+        /**
+         * 成功
+         */
+        String STATUS_SUCCESS = SYS + "1";
+
+        /**
+         * 失败
+         */
+        String STATUS_ERROR = SYS + "0";
+
+    }
+
+    interface Editor {
+        /**
+         * 原子保存队列名字
+         */
+        String editorQueue = "redis_editor_queue";
+    }
+
+
+
+
+
+}

+ 20 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/dao/LuckysheetDao.java

@@ -0,0 +1,20 @@
+package com.rongwei.bscommon.sys.dao;
+
+import com.rongwei.bsentity.domain.LuckysheetDo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Insert;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author wm
+ * @since 2024-07-15
+ */
+public interface LuckysheetDao extends BaseMapper<LuckysheetDo> {
+
+    @Insert("insert into luckysheet(id, is_delete, \"index\", list_id, block_id, json_data, \"order\", \"status\") " +
+            "values (#{id}, #{isDelete}, #{index}, #{listId}, #{blockId}, #{jsonData}, #{order}, #{status})")
+    int insert(LuckysheetDo param);
+}

+ 239 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/db/server/JfGridFileGetService.java

@@ -0,0 +1,239 @@
+package com.rongwei.bscommon.sys.db.server;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.bscommon.sys.redisserver.GridFileRedisCacheService;
+import com.rongwei.bscommon.sys.utils.GzipHandle;
+import com.rongwei.luckysheet.JfGridConfigModel;
+import com.rongwei.luckysheet.db.IRecordDataInsertHandle;
+import com.rongwei.luckysheet.db.IRecordDataUpdataHandle;
+import com.rongwei.luckysheet.db.IRecordDelHandle;
+import com.rongwei.luckysheet.db.IRecordSelectHandle;
+import com.rongwei.luckysheet.util.JfGridFileUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+@Service
+public class JfGridFileGetService {
+
+    //达梦
+    @Resource(name = "damengRecordDataInsertHandle")
+    private IRecordDataInsertHandle recordDataInsertHandle;
+
+    @Resource(name = "damengRecordDataUpdataHandle")
+    private IRecordDataUpdataHandle recordDataUpdataHandle;
+
+    @Resource(name = "damengRecordDelHandle")
+    private IRecordDelHandle recordDelHandle;
+
+    @Resource(name = "damengRecordSelectHandle")
+    private IRecordSelectHandle recordSelectHandle;
+
+
+    //pg
+//    @Resource(name = "postgresRecordDataInsertHandle")
+//    private IRecordDataInsertHandle recordDataInsertHandle;
+//
+//    @Resource(name = "postgresRecordDataUpdataHandle")
+//    private IRecordDataUpdataHandle recordDataUpdataHandle;
+//
+//    @Resource(name = "postgresRecordDelHandle")
+//    private IRecordDelHandle recordDelHandle;
+//
+//    @Resource(name = "postgresRecordSelectHandle")
+//    private IRecordSelectHandle recordSelectHandle;
+
+    //mysql
+//    @Resource(name = "mysqlRecordDataInsertHandle")
+//    private IRecordDataInsertHandle recordDataInsertHandle;
+//
+//    @Resource(name = "mysqlRecordDataUpdataHandle")
+//    private IRecordDataUpdataHandle recordDataUpdataHandle;
+//
+//    @Resource(name = "mysqlRecordDelHandle")
+//    private IRecordDelHandle recordDelHandle;
+//
+//    @Resource(name = "mysqlRecordSelectHandle")
+//    private IRecordSelectHandle recordSelectHandle;
+
+    @Autowired
+    private GridFileRedisCacheService redisService;
+
+
+    /**
+     * 1.3.3	获取表格数据 按gridKey获取,默认载入status为1
+     * @param listId
+     * @return
+     */
+    public List<JSONObject> getDefaultByGridKey(String listId){
+        String i=recordSelectHandle.getFirstBlockIndexByGridKey(listId);
+        redisService.raddFlagContent(listId+i, true);
+        List<JSONObject>  dbObject=recordSelectHandle.getByGridKey_NOCelldata(listId);
+        log.info("getDefaultByGridKey--dbObjectList:start");
+        if(dbObject!=null && dbObject.size()>0){
+            log.info("getDefaultByGridKey--start---dbObject");
+            for(int x=0;x<dbObject.size();x++){
+                JSONObject _o =dbObject.get(x);
+                if(_o.containsKey("status") && _o.get("status").toString().equals("1")){
+                    //获取当前显示的数据
+                    //DBObject n=jfGridFileDao.getByGridKey(gridKey,Integer.parseInt(_o.get("index").toString()));
+                    //dbObject.set(x,n);
+                    String index=_o.get("index").toString();
+                    //覆盖当前对象的数据信息
+                    JSONArray _celldata=getCelldataBlockMergeByGridKey(listId,index);
+                    _o.put("celldata",_celldata);
+                }
+
+                if(_o.containsKey("calcChain")){
+                    Object calcChain= JfGridFileUtil.getObjectByIndex(_o, "calcChain");
+
+                    log.info("calcChain--"+calcChain);
+                    _o.put("calcChain", calcChain);
+                }
+
+            }
+        }
+        log.info("dbObject:true");
+        return dbObject;
+    }
+
+    /**
+     * 按list_id获取,返回指定sheet 当前sheet的全部分块数据(并合并)
+     * @param listId
+     * @param index
+     * @return
+     */
+    public JSONArray getCelldataBlockMergeByGridKey(String listId, String index){
+        //每一个分块数据合并后的对象
+        JSONArray _celldata=new JSONArray();
+        //获取全部块
+        List<JSONObject> blocks=getBlocksByGridKey(listId, index);
+        if(blocks!=null && blocks.size()>0){
+            for(JSONObject _b:blocks){
+                if(_b.containsKey("block_id")){
+                    if(JfGridConfigModel.FirstBlockID.equals(_b.get("block_id"))){
+                        //信息块
+                    }else{
+                        //数据块
+                        JSONObject db=JfGridFileUtil.getJSONObjectByIndex(_b, "json_data");
+                        JSONArray _blockCellData=JfGridFileUtil.getSheetByIndex(db);
+                        if(_blockCellData!=null){
+                            _celldata.addAll(_blockCellData);
+                        }
+                    }
+                }
+            }
+        }
+        return _celldata;
+    }
+
+    /**
+     * 按list_id获取,返回指定sheet分块组
+     * @param listId
+     * @param index
+     * @return
+     */
+    public List<JSONObject> getBlocksByGridKey(String listId, String index){
+        return recordSelectHandle.getBlockAllByGridKey(listId, index);
+    }
+
+    /**
+     * 1.3.4	获取sheet数据  参数为gridKey(表格主键) 和 index(sheet主键合集
+     * @param listId
+     * @param indexs
+     * @return
+     */
+    public LinkedHashMap getByGridKeys(String listId, List<String> indexs){
+        LinkedHashMap _resultModel=null;
+        if(indexs==null || indexs.size()==0){
+            return _resultModel;
+        }
+        //获取全部多个sheet的分块
+        List<JSONObject> dbObject=null;
+        if(indexs.size()==1){
+            dbObject=recordSelectHandle.getIndexsByGridKey(listId, indexs.get(0));
+        }else{
+            dbObject= recordSelectHandle.getAllIndexsByGridKey(listId.toString(),indexs);
+        }
+
+        if(dbObject!=null && dbObject.size()>0){
+            if(_resultModel==null){
+                _resultModel=new LinkedHashMap<Integer,Object>();
+            }
+            log.info("getByGridKeys--dbObject-start");
+            for(JSONObject _o:dbObject){
+                if(!_o.containsKey("block_id")){
+                    continue;
+                }
+                if(JfGridConfigModel.FirstBlockID.equals(_o.get("block_id"))){
+                    continue;
+                }
+                //数据块处理
+                if(_o.containsKey("index")){
+                    try{
+                        GzipHandle.toUncompressBySheet(_o);
+                        String _index=_o.get("index").toString();
+                        if(indexs.contains(_index)){
+                            //数据块
+                            JSONObject data=JfGridFileUtil.getJSONObjectByIndex(_o,"json_data");
+                            JSONArray _cellData=JfGridFileUtil.getSheetByIndex(data);
+                            if(_cellData!=null){
+                                if(_resultModel.containsKey(_index)){
+                                     JSONArray _blockCellData=(JSONArray)_resultModel.get(_index);
+                                    _blockCellData.addAll(_cellData);
+                                }else {
+                                    _resultModel.put(_index, _cellData);
+                                }
+                            }
+                        }
+                    }catch (Exception ex){
+                        log.error(ex.toString());
+                    }
+                }
+            }
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 获取全部结构以及数据
+     * @param gridKey
+     * @return
+     */
+    public List<JSONObject> getAllSheetByGridKey(String gridKey) {
+        //返回全部结构
+        List<JSONObject>  dbObject=recordSelectHandle.getByGridKey_NOCelldata(gridKey);
+        if(dbObject!=null&&dbObject.size()>0){
+            //获取全部的index
+            List<String> indexs=dbObject.stream().map(k->k.get("index").toString()).collect(Collectors.toList());
+            //获取数据
+            LinkedHashMap celldatas=getByGridKeys(gridKey,indexs);
+            if(celldatas!=null&&celldatas.size()>0) {
+                for (JSONObject _o : dbObject) {
+                    _o.put("celldata", celldatas.get(_o.get("index")));
+                }
+            }
+            return dbObject;
+        }
+        return null;
+    }
+
+    /**
+     * 获取指定的xls激活的sheet页的 返回index(控制块)
+     * @param gridKey
+     * @return
+     */
+    public String getFirstBlockIndexByGridKey(String gridKey){
+        return recordSelectHandle.getFirstBlockIndexByGridKey(gridKey);
+    }
+}

文件差异内容过多而无法显示
+ 2202 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/db/server/JfGridUpdateService.java


+ 119 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/exception/InterfaceRequestErrorAndPerformanceLog.java

@@ -0,0 +1,119 @@
+package com.rongwei.bscommon.sys.exception;
+
+import com.rongwei.bscommon.sys.config.api.ResponseVO;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+import javax.validation.ConstraintViolationException;
+import java.lang.reflect.Method;
+
+/**
+ * 切面切在controller上捕获全局异常并处理
+ * @author Administrator
+ */
+@Component
+@Aspect
+@Slf4j
+public class InterfaceRequestErrorAndPerformanceLog {
+    /**
+     * 切入到controller层的包和所有子包里的任意类的任意方法的执行
+     */
+    @Pointcut("execution(* com.rongwei..*.controller..*.*(..))")
+    public void pointCut() {
+    }
+
+
+    @Around("pointCut()")
+    public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
+        long startTm = System.currentTimeMillis();
+        Object res;
+        try {
+            //处理入参特殊字符和sql注入攻击
+            checkRequestParam(pjp);
+            //Signature s = pjp.getSignature();
+            //执行访问接口操作
+            res = pjp.proceed(pjp.getArgs());
+            Long consumeTime = System.currentTimeMillis() - startTm;
+            log.info("耗时:" + consumeTime + "(毫秒).");
+            //当接口请求时间大于3秒时,标记为异常调用时间,并记录入库
+            if (consumeTime > 3000) {
+                log.warn("{" + pjp.getSignature() + "的执行时间超过三秒" + "}");
+            }
+        } catch (Exception throwable) {
+            res = handlerException(pjp, throwable);
+        }
+        return res;
+    }
+
+    /**
+     * 处理接口调用异常
+     *
+     * @param pjp
+     * @param e
+     * @return
+     */
+    private ResponseVO handlerException(ProceedingJoinPoint pjp, Throwable e) {
+        //获取方法签名
+        Signature signature = pjp.getSignature();
+        //获取目标类
+        Object controller = pjp.getTarget();
+        //获取入参数
+        Object[] args = pjp.getArgs();
+        Class<?>[] parameterTypes = new Class<?>[args.length];
+        try {
+            for (int j = 0; j < args.length; j++) {
+                Object arg = args[j];
+                parameterTypes[j] = arg.getClass();
+            }
+
+            Method method = controller.getClass().getDeclaredMethod(signature.getName(), parameterTypes);
+            Class<?> returnType = method.getReturnType();
+            if (!returnType.equals(ResponseVO.class)) {
+                return null;
+            }
+        } catch (Exception ex) {
+            //TODO:出现空指针可能是get入参有问题
+            log.error("异常信息, {}", ex);
+        }
+        ResponseVO apiResponse;
+        if (e.getClass().isAssignableFrom(ServiceException.class)) {
+            apiResponse = ResponseVO.errorInstance(e.getMessage());
+        } else if (e instanceof ConstraintViolationException) {
+            //利用校验框架的验证异常
+            String s = e.getMessage();
+            String msg = s.substring(s.indexOf(":") + 1);
+            apiResponse = ResponseVO.errorInstance(msg);
+        } else if (e instanceof RuntimeException) {
+            log.error("RuntimeException{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + e.getMessage() + "}", e);
+            apiResponse = ResponseVO.errorInstance(e.getMessage());
+        } else {
+            log.error("异常{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + e.getMessage() + "}", e);
+            apiResponse = ResponseVO.errorInstance(e.getMessage());
+        }
+        log.error("异常信息, {}", e);
+        return apiResponse;
+    }
+
+    /**
+     * @Author: wzd
+     * @Description: 处理入参特殊字符和sql注入攻击
+     */
+    private void checkRequestParam(ProceedingJoinPoint pjp) {
+        String str = String.valueOf(pjp.getArgs());
+       /* if (!IllegalStrFilterUtil.sqlStrFilter(str)) {
+            logger.info("访问接口:" + pjp.getSignature() + ",输入参数存在SQL注入风险!参数为:" + Lists.newArrayList(pjp.getArgs()).toString());
+            DcErrorEntity dcErrorEntity = interfaceErrorService.processDcErrorEntity(pjp.getSignature() + "",Lists.newArrayList(pjp.getArgs()).toString(),"输入参数存在SQL注入风险!");
+            throw new DataCenterException(dcErrorEntity);
+        }
+        if (!IllegalStrFilterUtil.isIllegalStr(str)) {
+            logger.info("访问接口:" + pjp.getSignature() + ",输入参数含有非法字符!,参数为:" + Lists.newArrayList(pjp.getArgs()).toString());
+            DcErrorEntity dcErrorEntity = interfaceErrorService.processDcErrorEntity(pjp.getSignature() + "",Lists.newArrayList(pjp.getArgs()).toString(),"输入参数含有非法字符!");
+            throw new DataCenterException(dcErrorEntity);
+        }*/
+    }
+}

+ 12 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/exception/ServiceException.java

@@ -0,0 +1,12 @@
+package com.rongwei.bscommon.sys.exception;
+
+/**
+ * @author Administrator
+ */
+public class ServiceException extends RuntimeException {
+
+    public ServiceException(String message) {
+        super(message);
+    }
+
+}

+ 119 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/redisserver/GridFileRedisCacheService.java

@@ -0,0 +1,119 @@
+package com.rongwei.bscommon.sys.redisserver;
+
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.bscommon.sys.config.redis.RedisCacheService;
+import com.rongwei.bscommon.sys.config.redis.RedisQueueService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+@Service
+public class GridFileRedisCacheService {
+    @Autowired
+    private RedisCacheService redisCache;
+    @Autowired
+    private RedisQueueService redisQueueService;
+
+
+    /**
+     * 批量更新数据
+     */
+    private String dbdata_content="lk:dbdata:";
+
+    /**
+     * 收集指令信息
+     */
+    private String hand_flag_content="lk:upflag:";
+
+    /**
+     * 收集指令信息内容
+     */
+    private String qk_handle_content="lk:handler:";
+
+
+    public List<JSONObject> rgetDbDataContent(String key){
+        try{
+            String redisKey=dbdata_content+key;
+            List<JSONObject> lists=redisCache.getListBySize(redisKey, -1);
+            if(lists!=null && lists.size()>0){
+                //从redis中删除
+                redisCache.delList(redisKey, lists.size());
+                return lists;
+            }
+        }catch(Exception ex){
+            return null;
+        }
+        return null;
+    }
+
+
+    /**
+     *
+     * @param key
+     * @param db
+     */
+    public void raddDbContent(String key, JSONObject db){
+        String redisKey=dbdata_content+key;
+        redisCache.addList(redisKey, db);
+    }
+
+
+    /**
+     * 存入启用存储指令信息
+     * @param key
+     * @param val
+     */
+    public void raddFlagContent(String key, Object val) {
+        String redisKey = hand_flag_content + key;
+        log.info("raddFlagContent---redisKey="+redisKey+"val="+val);
+        redisCache.addCache(redisKey, val, 240);
+    }
+
+    /**
+     * 根据key 获得email验证码信息
+     * @param key
+     */
+    public Boolean rgetFlagContent(String key) {
+        Boolean flag=false;
+        try{
+            String redisKey = hand_flag_content + key;
+            log.info("rgetFlagContent---redisKey="+redisKey);
+            flag=(Boolean) redisCache.getCache(redisKey);
+        }catch (Exception e) {
+            // TODO: handle exception
+        }
+        return flag;
+    }
+
+
+    /**
+     * 获取数据
+     * @param key
+     * @return
+     */
+    public List<String> rgetHandlerContent(String key){
+        try{
+            String redisKey=qk_handle_content+key;
+            //多节点使用
+            List<String> lists=redisQueueService.popList(redisKey,String.class,500);
+            return lists;
+            //单节点使用
+//            List<String> lists=redisCache.getListBySize(redisKey, -1);
+//            if(lists!=null && lists.size()>0){
+//                //从redis中删除
+//                redisCache.delList(redisKey, lists.size());
+//                return lists;
+//            }
+        }catch(Exception ex){
+            return null;
+        }
+    }
+
+}

+ 179 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/redisserver/RedisLock.java

@@ -0,0 +1,179 @@
+package com.rongwei.bscommon.sys.redisserver;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+
+
+/**
+ * @author Administrator
+ */
+public class RedisLock {
+
+	@Autowired
+    private RedisTemplate redisTemplate;
+    /**
+     * 重试时间
+     */
+    private static final int DEFAULT_ACQUIRY_RETRY_MILLIS = 100;
+    /**
+     * 锁的前缀
+     */
+    private static final String LOCK_SUFFIX = "redis_lock:";
+    /**
+     * 锁的key
+     */
+    private String lockKey;
+    /**
+     * 锁超时时间,防止线程在入锁以后,防止阻塞后面的线程无法获取锁
+     */
+    private int expireMsecs = 60 * 1000;
+    /**
+     * 线程获取锁的等待时间
+     */
+    private int timeoutMsecs = 10 * 1000;
+    /**
+     * 是否锁定标志
+     */
+    private volatile boolean locked = false;
+
+    /**
+     * 当前线程
+     */
+    private String uid="";
+
+    /**
+     * 构造器
+     * @param redisTemplate
+     * @param lockKey 锁的key
+     */
+    public RedisLock(RedisTemplate redisTemplate, String lockKey) {
+        this.redisTemplate = redisTemplate;
+        this.lockKey = LOCK_SUFFIX+lockKey;
+    }
+
+    /**
+     * 构造器
+     * @param redisTemplate
+     * @param lockKey 锁的key
+     * @param timeoutMsecs 获取锁的超时时间
+     */
+    public RedisLock(RedisTemplate redisTemplate, String lockKey, int timeoutMsecs) {
+        this(redisTemplate, lockKey);
+        this.timeoutMsecs = timeoutMsecs;
+    }
+    public RedisLock(RedisTemplate redisTemplate, String lockKey, int timeoutMsecs, String uid) {
+        this(redisTemplate, lockKey);
+        this.timeoutMsecs = timeoutMsecs;
+        this.uid=uid;
+    }
+
+    /**
+     * 构造器
+     * @param redisTemplate
+     * @param lockKey 锁的key
+     * @param timeoutMsecs 获取锁的超时时间
+     * @param expireMsecs 锁的有效期
+     */
+    public RedisLock(RedisTemplate redisTemplate, String lockKey, int timeoutMsecs, int expireMsecs) {
+        this(redisTemplate, lockKey, timeoutMsecs);
+        this.expireMsecs = expireMsecs;
+    }
+
+    public String getLockKey() {
+        return lockKey;
+    }
+
+    /**
+     * 封装和jedis方法
+     * @param key
+     * @return
+     */
+    private String get(final String key) {
+        Object obj = redisTemplate.opsForValue().get(key);
+        return obj != null ? obj.toString() : null;
+    }
+
+    /**
+     * 封装和jedis方法
+     * @param key
+     * @param value
+     * @return
+     */
+    private boolean setNX(final String key, final String value) {
+        return redisTemplate.opsForValue().setIfAbsent(key,value);
+    }
+
+    /**
+     * 封装和jedis方法
+     * @param key
+     * @param value
+     * @return
+     */
+    private String getSet(final String key, final String value) {
+        Object obj = redisTemplate.opsForValue().getAndSet(key,value);
+        return obj != null ? (String) obj : null;
+    }
+
+    /**
+     * 获取锁
+     * @return 获取锁成功返回ture,超时返回false
+     * @throws InterruptedException
+     */
+    public synchronized boolean lock() throws InterruptedException {
+        //线程获取锁的等待时间
+        int timeout = timeoutMsecs;
+        while (timeout >= 0) {
+            //超时时间
+            long expires = System.currentTimeMillis() + expireMsecs + 1;
+            //锁到期时间
+            String expiresStr = String.valueOf(expires);
+            if (this.setNX(lockKey, expiresStr)) {
+                locked = true;
+                return true;
+            }
+            //redis里key的时间
+            String currentValue = this.get(lockKey);
+            //判断锁是否已经过期,过期则重新设置并获取
+            if (currentValue != null && Long.parseLong(currentValue) < System.currentTimeMillis()) {
+                //设置锁并返回旧值
+                String oldValue = this.getSet(lockKey, expiresStr);
+                //比较锁的时间,如果不一致则可能是其他锁已经修改了值并获取
+                if (oldValue != null && oldValue.equals(currentValue)) {
+                    locked = true;
+                    return true;
+                }
+            }
+            timeout -= DEFAULT_ACQUIRY_RETRY_MILLIS;
+            //延时
+            Thread.sleep(DEFAULT_ACQUIRY_RETRY_MILLIS);
+        }
+        return false;
+    }
+    /**
+     * 释放获取到的锁
+     */
+    public  synchronized void unlock() {
+        if (locked) {
+            redisTemplate.delete(lockKey);
+            locked = false;
+        }
+    }
+
+}
+
+/*
+
+
+    //使用方法,创建RedisLock对象
+    RedisLock lock = new RedisLock(redisTemplate, "lock_" + product.getId());
+    try {
+        if (lock.lock()) {}
+    } finally {
+        lock.unlock();
+    }
+
+
+
+*/
+
+

+ 61 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/redisserver/RedisMessageModel.java

@@ -0,0 +1,61 @@
+package com.rongwei.bscommon.sys.redisserver;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+/**
+ * redis消息
+ * @author Administrator
+ */
+@Data
+public class RedisMessageModel {
+
+    /**
+     * 节点端口与ip (或者其他唯一标示)
+     */
+    private String ipandport;
+    /**
+     * 文档id
+     */
+    private String gridkey;
+    /**
+     * 内容
+     */
+    private String content;
+
+    public RedisMessageModel(String _ipandport,String _gridkey,String _content){
+        this.ipandport=_ipandport;
+        this.gridkey=_gridkey;
+        this.content=_content;
+    }
+    public RedisMessageModel(JSONObject jsonObject){
+        if(jsonObject!=null) {
+            if (jsonObject.containsKey("ipandport")) {
+                this.ipandport = jsonObject.getString("ipandport");
+            }
+            if (jsonObject.containsKey("gridkey")) {
+                this.gridkey = jsonObject.getString("gridkey");
+            }
+            if (jsonObject.containsKey("content")) {
+                this.content = jsonObject.getString("content");
+            }
+        }
+    }
+
+    public JSONObject toDBObject(){
+        JSONObject jsonObject=new JSONObject();
+        jsonObject.put("ipandport",ipandport);
+        jsonObject.put("gridkey",gridkey);
+        jsonObject.put("content",content);
+        return jsonObject;
+    }
+
+    @Override
+    public String toString() {
+        return "RedisMessageModel{" +
+                "ipandport='" + ipandport + '\'' +
+                ", gridkey='" + gridkey + '\'' +
+                ", content='" + content + '\'' +
+                '}';
+    }
+}

+ 42 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/redisserver/RedisMessagePublish.java

@@ -0,0 +1,42 @@
+package com.rongwei.bscommon.sys.redisserver;
+
+import com.google.gson.Gson;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * 发布
+ * @author Administrator
+ */
+@Slf4j
+@Data
+@Service
+public class RedisMessagePublish {
+    /**
+     * 管道
+     */
+    public static String channel;
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    /**
+     * 发布者
+     * @param redisMessageModel  消息内容
+     * @return
+     */
+    public boolean publishMessage(RedisMessageModel redisMessageModel){
+        try{
+            redisTemplate.convertAndSend(channel,new Gson().toJson(redisMessageModel));
+            return true;
+        }catch (Exception ex){
+            log.error("publishMessage Error:{}",ex);
+            return false;
+        }
+    }
+
+}

+ 24 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/service/LuckysheetService.java

@@ -0,0 +1,24 @@
+package com.rongwei.bscommon.sys.service;
+
+import com.rongwei.bsentity.domain.LuckysheetDo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author wm
+ * @since 2024-07-15
+ */
+public interface LuckysheetService extends IService<LuckysheetDo> {
+
+    /**
+     * 生成项目汇总文件
+     *
+     * @param projectId
+     * @return
+     */
+    String genProjectSummaryFiles(String projectId);
+
+}

+ 9 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/service/ZhcxProjectManageService.java

@@ -2,6 +2,7 @@ package com.rongwei.bscommon.sys.service;
 
 import com.rongwei.bsentity.domain.ZhcxProjectManageDo;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.rongwei.bsentity.dto.project.ProjectSummaryParamExcelDto;
 import com.rongwei.rwcommonentity.commonservers.domain.SysFileItemDo;
 
 /**
@@ -20,4 +21,12 @@ public interface ZhcxProjectManageService extends IService<ZhcxProjectManageDo>
      * @param projectId
      */
     SysFileItemDo genSummaryFiles(String projectId);
+
+    /**
+     * 组装汇总文件参数
+     *
+     * @param manageDo
+     * @return
+     */
+    ProjectSummaryParamExcelDto assembleProjectSummaryParam(ZhcxProjectManageDo manageDo);
 }

+ 208 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/LuckysheetServiceImpl.java

@@ -0,0 +1,208 @@
+package com.rongwei.bscommon.sys.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.rongwei.bscommon.sys.service.ZhcxProjectManageService;
+import com.rongwei.bscommon.sys.utils.LuckySheet4SummaryHelp;
+import com.rongwei.bsentity.domain.LuckysheetDo;
+import com.rongwei.bscommon.sys.dao.LuckysheetDao;
+import com.rongwei.bscommon.sys.service.LuckysheetService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.rongwei.bsentity.domain.ZhcxProjectManageDo;
+import com.rongwei.bsentity.dto.luckysheet.SheetConfigResultDto;
+import com.rongwei.bsentity.dto.project.ProjectSummaryParamExcelDto;
+import com.rongwei.bsentity.dto.project.SheetInfoParam;
+import com.rongwei.luckysheet.JfGridConfigModel;
+import com.rongwei.luckysheet.util.SnowFlake;
+import com.rongwei.rwcommon.utils.SecurityUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author wm
+ * @since 2024-07-15
+ */
+@Service
+public class LuckysheetServiceImpl extends ServiceImpl<LuckysheetDao, LuckysheetDo> implements LuckysheetService {
+
+    @Autowired
+    private ZhcxProjectManageService projectManageService;
+
+    @Resource(name = "snowFlake")
+    protected SnowFlake snowFlake;
+
+    /**
+     * 生成项目汇总文件
+     *
+     * @param projectId
+     * @return
+     */
+    @Override
+    public String genProjectSummaryFiles(String projectId) {
+
+        //项目信息
+        ZhcxProjectManageDo project = projectManageService.getById(projectId);
+
+        //组装汇总文件参数
+        ProjectSummaryParamExcelDto paramExcelDto = projectManageService.assembleProjectSummaryParam(project);
+
+        //配置信息
+        SheetConfigResultDto configResultDto = assembleProjectSummaryTitle(paramExcelDto);
+
+        //生成excel
+        String listId = genLuckysheetObj(configResultDto);
+
+        ZhcxProjectManageDo projectEntity = new ZhcxProjectManageDo();
+        projectEntity.setId(projectId);
+        projectEntity.setSummaryfiles(listId);
+        projectManageService.updateById(projectEntity);
+        return listId;
+    }
+
+    /**
+     * 生成luckysheet对象
+     *
+     * @param configResultDto
+     * @return
+     */
+    private String genLuckysheetObj(SheetConfigResultDto configResultDto) {
+        SheetInfoParam sheet1 = SheetInfoParam.builder()
+                .index("1")
+                .sheetName("Sheet1")
+                .order(0)
+                .build();
+        JSONObject sheet = LuckySheet4SummaryHelp.getEmptySheet(sheet1);
+
+        JSONObject config = sheet.getJSONObject("config");
+        config.put("merge", configResultDto.getMergeConfig());
+        config.put("rowlen", configResultDto.getRowlenConfig());
+        config.put("borderInfo", configResultDto.getBorderInfoConfig());
+
+        sheet.getJSONObject("dataVerification").putAll(configResultDto.getDataVerification());
+
+        //保存结构
+        LuckysheetDo entity = new LuckysheetDo();
+        entity.setBlockId(JfGridConfigModel.FirstBlockID);
+        entity.setId(snowFlake.nextId().longValue());
+        entity.setIndex("1");
+        entity.setJsonData(sheet.toString(SerializerFeature.WriteMapNullValue));
+        entity.setIsDelete(0);
+        entity.setStatus(1);
+        entity.setOrder(0);
+        String listId = String.valueOf(entity.getId()).concat("#").concat(SecurityUtil.getUUID());
+        entity.setListId(listId);
+        save(entity);
+
+        //保存数据
+        LuckysheetDo entity2 = new LuckysheetDo();
+        entity2.setBlockId("0_0");
+        entity2.setId(snowFlake.nextId().longValue());
+        entity2.setIndex("1");
+        entity2.setStatus(0);
+        JSONObject celldata = new JSONObject();
+        celldata.put("celldata", configResultDto.getCelldata());
+
+        entity2.setJsonData(celldata.toString(SerializerFeature.WriteMapNullValue));
+        entity2.setIsDelete(0);
+        entity2.setListId(entity.getListId());
+        save(entity2);
+
+        return entity.getListId();
+    }
+
+    /**
+     * 组装汇总文件参数
+     *
+     * @param paramExcelDto
+     * @return
+     */
+    private SheetConfigResultDto assembleProjectSummaryTitle(ProjectSummaryParamExcelDto paramExcelDto) {
+        //合并配置
+        JSONObject mergeConfig = LuckySheet4SummaryHelp.getMergeConfig(paramExcelDto.getDeviceNumberList());
+        //边框信息
+        JSONArray borderInfo = LuckySheet4SummaryHelp.getBorderInfo(paramExcelDto.getDeviceNumberList());
+        //下拉框
+        JSONObject dataVerification = LuckySheet4SummaryHelp.getDataVerification(paramExcelDto);
+        //数据
+        JSONArray cellData = getCellData(paramExcelDto);
+        //行高
+        JSONObject rowLenObj = new JSONObject();
+        rowLenObj.put("0", 24);
+
+        return SheetConfigResultDto.builder()
+                .borderInfoConfig(borderInfo)
+                .dataVerification(dataVerification)
+                .celldata(cellData)
+                .mergeConfig(mergeConfig)
+                .rowlenConfig(rowLenObj)
+                .build();
+    }
+
+    /**
+     * 获取数据
+     *
+     * @param paramExcelDto
+     * @return
+     */
+    public JSONArray getCellData(ProjectSummaryParamExcelDto paramExcelDto) {
+
+        int colsSize = 10 + paramExcelDto.getDeviceNumberList().size() * 4;
+        //数据
+        JSONArray celldata = LuckySheet4SummaryHelp.assembleFirstTitle(paramExcelDto.getFileName(), colsSize);
+        //二级标题1
+        JSONArray celldata1 = LuckySheet4SummaryHelp.assembleCommonCol1();
+        JSONArray celldata2 = new JSONArray();
+
+        celldata2.addAll(LuckySheet4SummaryHelp.assembleCommonRow2Col1());
+        //遍历机号
+        for(int m = 0, n = paramExcelDto.getDeviceNumberList().size(); m < n; m++) {
+            //机号
+            celldata1.addAll(LuckySheet4SummaryHelp.genDeviceNumberFirstTitle(paramExcelDto.getDeviceNumberList().get(m), 4 + m * 4));
+            //机号标题
+            celldata2.addAll(LuckySheet4SummaryHelp.assembleDeviceNumberSecondTitle(4 + m * 4));
+        }
+
+        celldata1.addAll(LuckySheet4SummaryHelp.assembleCommonRow1Col2(4 + paramExcelDto.getDeviceNumberList().size() * 4));
+
+        //最后6列数据
+        celldata2.addAll(LuckySheet4SummaryHelp.assembleCommonCol2(4 + paramExcelDto.getDeviceNumberList().size() * 4));
+        celldata.addAll(celldata1);
+        celldata.addAll(celldata2);
+
+        return celldata;
+    }
+
+//    public static void main(String[] args) {
+//        List<String> deviceNumList = new ArrayList<>();
+//        deviceNumList.add("1#");
+//        deviceNumList.add("2#");
+//        deviceNumList.add("3#");
+//        deviceNumList.add("4#");
+//        deviceNumList.add("5#");
+//        deviceNumList.add("6#");
+//        deviceNumList.add("7#");
+//        deviceNumList.add("8#");
+//        deviceNumList.add("9#");
+//        deviceNumList.add("10#");
+//        deviceNumList.add("11#");
+//        deviceNumList.add("12#");
+//
+//        ProjectSummaryParamExcelDto excelDto = ProjectSummaryParamExcelDto.builder()
+//                .deviceNumberList(deviceNumList)
+//                .fileName("1002000938马士基埃及桥吊项目整改文字版")
+//                .build();
+//
+//        JSONArray cellData = getCellData(excelDto);
+//
+//        System.out.println(cellData.toString(SerializerFeature.WriteMapNullValue));
+//    }
+}

+ 5 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ZhcxProjectDeviceNumberServiceImpl.java

@@ -38,6 +38,11 @@ public class ZhcxProjectDeviceNumberServiceImpl extends ServiceImpl<ZhcxProjectD
         if(ObjectUtil.isEmpty(list)) {
             return Collections.emptyList();
         }
+        list.sort((sort1, sort2) -> {
+            int sort1Int = Integer.parseInt(sort1.getDeviceNumber().replace("#", ""));
+            int sort2Int = Integer.parseInt(sort2.getDeviceNumber().replace("#", ""));
+            return sort1Int - sort2Int;
+        });
         return list.stream().map(item -> item.getDeviceNumber()).collect(Collectors.toList());
     }
 }

+ 2 - 1
business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ZhcxProjectManageServiceImpl.java

@@ -72,7 +72,8 @@ public class ZhcxProjectManageServiceImpl extends ServiceImpl<ZhcxProjectManageD
      * @param manageDo
      * @return
      */
-    private ProjectSummaryParamExcelDto assembleProjectSummaryParam(ZhcxProjectManageDo manageDo) {
+    @Override
+    public ProjectSummaryParamExcelDto assembleProjectSummaryParam(ZhcxProjectManageDo manageDo) {
         // 文件名
         String fileName = manageDo.getProjectCode().concat(manageDo.getProjectEname());
 

+ 87 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/utils/GzipHandle.java

@@ -0,0 +1,87 @@
+package com.rongwei.bscommon.sys.utils;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+/**
+ * 压缩处理类
+ * @author Administrator
+ */
+@Slf4j
+public class GzipHandle {
+    /**
+     * 是否对celldata的数据压缩(分块存储,不再使用压缩)
+     */
+    public static boolean runGzip=false;
+
+    /**
+     * 加密 单个sheet,celldata处理
+     * @param sheet
+     */
+    public static void toCompressBySheet(JSONObject sheet){
+        if(runGzip){
+            if(sheet!=null && sheet.containsKey("celldata")){
+                List<JSONObject> _celldata=(List<JSONObject>)sheet.get("celldata");
+                //String _gzipStr= Pako_GzipUtils.compress(_celldata.toString());
+                sheet.put("celldata",toCompressByCelldata(_celldata));
+            }
+        }
+    }
+
+    /**
+     * 压缩  celldata
+     * @param _celldata
+     * @return
+     */
+    public static String toCompressByCelldata(List<JSONObject> _celldata){
+        if(_celldata!=null){
+            String _gzipStr= Pako_GzipUtils.compress(_celldata.toString());
+            return _gzipStr;
+        }else{
+            return "";
+        }
+    }
+
+    /**
+     * 压缩  celldata
+     * @param _celldata
+     * @return
+     */
+    public static String toCompressByCelldata(JSONArray _celldata){
+        if(_celldata!=null){
+            String _gzipStr= Pako_GzipUtils.compress(_celldata.toString());
+            return _gzipStr;
+        }else{
+            return "";
+        }
+    }
+
+    /**
+     * 将celldata中数据解压
+     * @param sheet
+     */
+    public static void toUncompressBySheet(JSONObject sheet){
+        if(sheet!=null && sheet.containsKey("celldata")){
+            if(sheet.get("celldata") instanceof String){
+                String celldataStr=sheet.get("celldata").toString();
+                sheet.put("celldata",toUncompressBySheet(celldataStr));
+            }
+        }
+    }
+    public static JSONArray toUncompressBySheet(String celldataStr){
+        JSONArray list=new JSONArray();
+        if(celldataStr!=null){
+            String _gzipStr= Pako_GzipUtils.uncompress(celldataStr);
+            try{
+                list= JSONArray.parseArray(_gzipStr);
+            }catch (Exception ex){
+                log.error(ex.getMessage());
+            }
+        }
+        return list;
+    }
+
+}

+ 40 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/utils/JsonUtil.java

@@ -0,0 +1,40 @@
+package com.rongwei.bscommon.sys.utils;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: 5
+ * Date: 17-3-27
+ * Time: 上午9:48
+ * To change this template use File | Settings | File Templates.
+ * @author Administrator
+ */
+public class JsonUtil {
+    static final Gson GSON=new Gson();
+    static final Gson GSONData=new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
+    static final Gson GSONDataTime=new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
+
+    public static String toJson(Object o){
+        return GSON.toJson(o);
+    }
+    public static String toJsonByDate(Object o){
+        return GSONData.toJson(o);
+    }
+    public static String toJsonByDateTime(Object o){
+        return GSONDataTime.toJson(o);
+    }
+
+    public static void main(String[]args){
+        String str="{\"day1\":\"2019-10-10\",\"day2\":null}";
+        Map<String,Date> map=GSONData.fromJson(str,Map.class);
+
+
+    }
+
+
+}

+ 636 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/utils/LuckySheet4SummaryHelp.java

@@ -0,0 +1,636 @@
+package com.rongwei.bscommon.sys.utils;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.bsentity.dto.luckysheet.AssembleCellParam;
+import com.rongwei.bsentity.dto.project.ProjectSummaryParamExcelDto;
+import com.rongwei.bsentity.dto.project.SheetInfoParam;
+
+import java.util.List;
+
+public class LuckySheet4SummaryHelp {
+
+    /**
+     * {
+     * 		"c": 0,
+     * 		"r": 0,
+     * 		"v": {
+     * 			"m": "1002000938马士基埃及桥吊项目整改文字版",
+     * 			"v": "1002000938马士基埃及桥吊项目整改文字版",
+     * 			"bg": "rgb(51, 102, 255)",
+     * 			"bl": 1,
+     * 			"ct": {
+     * 				"t": "g",
+     * 				"fa": "General"
+     *                        },
+     * 			"fc": "rgb(0, 0, 0)",
+     * 			"ff": 5,
+     * 			"fs": 16,
+     * 			"ht": 0,
+     * 			"it": 0,
+     * 			"mc": {
+     * 				"c": 0,
+     * 				"r": 0,
+     * 				"cs": 58,
+     * 				"rs": 1
+     *            },
+     * 			"vt": 0* 		}
+     *    }
+     *
+     * @param fileName
+     * @param colSize
+     * @return
+     */
+    public static JSONArray assembleFirstTitle(String fileName, int colSize) {
+
+        AssembleCellParam cellParam = AssembleCellParam.builder()
+                .fontsize(16)
+                .startRowPos(0)
+                .startColPos(0)
+                .rowSize(1)
+                .colSize(colSize)
+                .value(fileName)
+                .build();
+        return assembleMergeTitle(cellParam);
+    }
+
+    /**
+     * {
+     * 		"c": 0,
+     * 		"r": 1,
+     * 		"v": {
+     * 			"m": "总序号",
+     * 			"v": "总序号",
+     * 			"bg": "rgb(204, 255, 204)",
+     * 			"bl": 0,
+     * 			"ct": {
+     * 				"t": "g",
+     * 				"fa": "General"
+     *           },
+     * 			"fc": "rgb(0, 0, 0)",
+     * 			"ff": 5,
+     * 			"fs": 11,
+     * 			"ht": 0,
+     * 			"it": 0,
+     * 			"mc": {
+     * 				"c": 0,
+     * 				"r": 1,
+     * 				"cs": 1,
+     * 				"rs": 2
+     *           },
+     * 			"vt": 0
+     * 		}
+     * }
+     *
+     * @return
+     */
+    public static JSONArray assembleCommonCol1() {
+
+        JSONArray result = new JSONArray();
+
+        String[] cols = { "总序号","监理编号","部位","内容" };
+
+        for(int m = 0, n = cols.length; m < n; m++) {
+            //一级标题
+            JSONObject remark2 = new JSONObject();
+            remark2.put("c", m);
+            remark2.put("r", 1);
+            JSONObject remark2v = new JSONObject();
+            remark2v.put("m", cols[m]);
+            remark2v.put("v", cols[m]);
+            remark2v.put("bg", "rgb(204, 255, 204)");
+            remark2v.put("bl", 1);
+            remark2v.put("fc", "rgb(0, 0, 0)");
+            remark2v.put("ff", 5);
+            remark2v.put("fs", 11);
+            remark2v.put("ht", 0);
+            remark2v.put("it", 0);
+            remark2v.put("vt", 1);
+
+            JSONObject ct = new JSONObject();
+            ct.put("t", "g");
+            ct.put("fa", "General");
+            remark2v.put("ct", ct);
+
+            JSONObject mc = new JSONObject();
+            mc.put("c", m);
+            mc.put("r", 1);
+            mc.put("cs", 1);
+            mc.put("rs", 2);
+            remark2v.put("mc", mc);
+
+            remark2.put("v", remark2v);
+            result.add(remark2);
+        }
+
+        return result;
+    }
+
+    /**
+     * 第三行开头
+     *
+     * @return
+     */
+    public static JSONArray assembleCommonRow2Col1() {
+
+        JSONArray result = new JSONArray();
+
+        for(int m = 0; m < 4; m++) {
+            JSONObject temp = new JSONObject();
+
+            JSONObject mc2 = new JSONObject();
+            mc2.put("c", m);
+            mc2.put("r", 1);
+
+            JSONObject v = new JSONObject();
+            v.put("mc",  mc2);
+
+            temp.put("c", m);
+            temp.put("r", 2);
+            temp.put("v", v);
+            result.add(temp);
+        }
+
+        return result;
+    }
+
+    /**
+     * 状态	提出日期	整改期限	提出者	备注1	备注2
+     * {
+     * 		"c": 57,
+     * 		"r": 2,
+     * 		"v": {
+     * 			"m": "备注2",
+     * 			"v": "备注2",
+     * 			"bl": 1,
+     * 			"ct": {
+     * 				"t": "g",
+     * 				"fa": "General"
+     *                        },
+     * 			"fc": "rgb(0, 0, 0)",
+     * 			"ff": 5,
+     * 			"fs": 11,
+     * 			"ht": 0,
+     * 			"it": 0,
+     * 			"vt": 1
+     * 	    }
+     * }
+     *
+     * @param startColPosition 起始位置
+     * @return
+     */
+    public static JSONArray assembleCommonCol2(int startColPosition) {
+        String[] cols = {"状态","提出日期","整改期限","提出者","备注1","备注2"};
+        return assembleSingleTitle(startColPosition, 2, cols);
+    }
+
+    /**
+     * 第二行最后六个
+     * {
+     * 		"c": 56,
+     * 		"r": 1,
+     * 		"v": {
+     * 			"m": "",
+     * 			"bg": "rgb(204, 255, 204)",
+     * 			"bl": 1,
+     * 			"fc": "rgb(0, 0, 0)",
+     * 			"ff": 5,
+     * 			"fs": 11,
+     * 			"ht": 0,
+     * 			"it": 0,
+     * 			"vt": 0
+     *       }
+     * }
+     *
+     * @param startColPosition
+     * @return
+     */
+    public static JSONArray assembleCommonRow1Col2(int startColPosition) {
+
+        JSONArray result = new JSONArray();
+
+        for(int m = 0, n = 6; m < n; m++) {
+            //备注2
+            JSONObject remark2 = new JSONObject();
+            remark2.put("c", startColPosition + m);
+            remark2.put("r", 1);
+
+            JSONObject remark2v = new JSONObject();
+            remark2v.put("m", "");
+            remark2v.put("bl", 1);
+            remark2v.put("fc", "rgb(0, 0, 0)");
+            remark2v.put("ff", 5);
+            remark2v.put("fs", 11);
+            remark2v.put("ht", 0);
+            remark2v.put("it", 0);
+            remark2v.put("vt", 0);
+
+            remark2.put("v", remark2v);
+            result.add(remark2);
+        }
+        return result;
+    }
+
+    /**
+     * 机号一级标题
+     *
+     * @param startColPosition
+     * @return
+     */
+    public static JSONArray genDeviceNumberFirstTitle(String cellName, int startColPosition) {
+        AssembleCellParam cellParam = AssembleCellParam.builder()
+                .fontsize(11)
+                .startRowPos(1)
+                .startColPos(startColPosition)
+                .rowSize(1)
+                .colSize(4)
+                .value(cellName)
+                .build();
+        return assembleMergeTitle(cellParam);
+    }
+
+    /**
+     * 生成机号标题
+     *
+     * @param startColPosition
+     * @return
+     */
+    public static JSONArray assembleDeviceNumberSecondTitle(int startColPosition) {
+        String[] cols = {"状态", "施工部门", "责任部门", "完成日期"};
+        return assembleSingleTitle(startColPosition, 2,cols);
+    }
+
+    /**
+     * 生成单个单元格
+     *
+     * @param startColPosition
+     * @param cols
+     * @return
+     */
+    public static JSONArray assembleSingleTitle(int startColPosition, int startRowPosition, String[] cols) {
+
+        JSONArray result = new JSONArray();
+
+        for(int m = 0, n = cols.length; m < n; m++) {
+            //备注2
+            JSONObject remark2 = new JSONObject();
+            remark2.put("c", startColPosition + m);
+            remark2.put("r", startRowPosition);
+            JSONObject remark2v = new JSONObject();
+            remark2v.put("m", cols[m]);
+            remark2v.put("v", cols[m]);
+            remark2v.put("bl", 1);
+            remark2v.put("fc", "rgb(0, 0, 0)");
+            remark2v.put("ff", 5);
+            remark2v.put("fs", 11);
+            remark2v.put("ht", 0);
+            remark2v.put("it", 0);
+            remark2v.put("vt", 1);
+            JSONObject ct = new JSONObject();
+            ct.put("t", "g");
+            ct.put("fa", "General");
+            remark2v.put("ct", ct);
+            remark2.put("v", remark2v);
+            result.add(remark2);
+        }
+        return result;
+    }
+
+    /**
+     * 组装合并单元格
+     *
+     * @param param
+     * @return
+     */
+    public static JSONArray assembleMergeTitle(AssembleCellParam param) {
+        JSONArray result = new JSONArray();
+        //一级标题
+        JSONObject remark2 = new JSONObject();
+        remark2.put("c", param.getStartColPos());
+        remark2.put("r", param.getStartRowPos());
+        JSONObject remark2v = new JSONObject();
+        remark2v.put("m", param.getValue());
+        remark2v.put("v", param.getValue());
+        remark2v.put("bl", 1);
+        remark2v.put("fc", "rgb(0, 0, 0)");
+        remark2v.put("ff", 5);
+        remark2v.put("fs", param.getFontsize());
+        remark2v.put("ht", 0);
+        remark2v.put("it", 0);
+        remark2v.put("vt", 1);
+        JSONObject ct = new JSONObject();
+        ct.put("t", "g");
+        ct.put("fa", "General");
+        remark2v.put("ct", ct);
+
+        JSONObject mc = new JSONObject();
+        mc.put("c", param.getStartColPos());
+        mc.put("r", param.getStartRowPos());
+        mc.put("cs", param.getColSize());
+        mc.put("rs", param.getRowSize());
+        remark2v.put("mc", mc);
+
+        remark2.put("v", remark2v);
+        result.add(remark2);
+
+        /**
+         * {
+         * 		"c": 1,
+         * 		"r": 0,
+         * 		"v": {
+         * 			"mc": {
+         * 				"c": 0,
+         * 				"r": 0
+         *          }
+         *       }
+         * 	}
+         */
+        for(int m = 1; m < param.getColSize(); m++) {
+            JSONObject temp = new JSONObject();
+
+            JSONObject mc2 = new JSONObject();
+            mc2.put("c", param.getStartColPos());
+            mc2.put("r", param.getStartRowPos());
+
+            JSONObject v = new JSONObject();
+            v.put("mc",  mc2);
+
+            temp.put("c", m + param.getStartColPos());
+            temp.put("r", param.getStartRowPos());
+            temp.put("v", v);
+            result.add(temp);
+        }
+
+        return result;
+    }
+
+    /**
+     * 获取空的sheet对象
+     *
+     * {
+     * 	"row": 84,
+     * 	"name": "Sheet2",
+     * 	"chart": [],
+     * 	"color": "",
+     * 	"index": "2",
+     * 	"order": 1,
+     * 	"column": 60,
+     * 	"config": {},
+     * 	"status": 0,
+     * 	"celldata": [],
+     * 	"ch_width": 4748,
+     * 	"rowsplit": [],
+     * 	"rh_height": 1790,
+     * 	"scrollTop": 0,
+     * 	"scrollLeft": 0,
+     * 	"visibledatarow": [],
+     * 	"visibledatacolumn": [],
+     * 	"jfgird_select_save": [{
+     * 		"row": [4, 4],
+     * 		"top": 85,
+     * 		"left": 0,
+     * 		"width": 73,
+     * 		"column": [0, 0],
+     * 		"height": 19,
+     * 		"top_move": 85,
+     * 		"left_move": 0,
+     * 		"row_focus": 4,
+     * 		"width_move": 73,
+     * 		"height_move": 19,
+     * 		"column_focus": 0
+     *        }],
+     * 	"jfgrid_selection_range": {}
+     * }
+     *
+     * @param param
+     * @return
+     */
+    public static JSONObject getEmptySheet(SheetInfoParam param) {
+        JSONObject obj = new JSONObject();
+        obj.put("row", 84);
+        obj.put("name", param.getSheetName());
+        obj.put("chart", new JSONArray());
+        obj.put("color", "");
+        obj.put("index", param.getIndex());
+        obj.put("order", param.getOrder());
+        obj.put("column", 60);
+        obj.put("config", new JSONObject());
+        obj.put("status", 0);
+        obj.put("celldata", new JSONArray());
+        obj.put("ch_width", 4748);
+        obj.put("rowsplit", new JSONArray());
+        obj.put("rh_height", 1790);
+        obj.put("scrollTop", 0);
+        obj.put("scrollLeft", 0);
+        obj.put("dataVerification", new JSONObject());
+        obj.put("visibledatarow", new JSONArray());
+        obj.put("visibledatacolumn", new JSONArray());
+
+        /**
+         * {
+     * 		"row": [4, 4],
+     * 		"top": 85,
+     * 		"left": 0,
+     * 		"width": 73,
+     * 		"column": [0, 0],
+     * 		"height": 19,
+     * 		"top_move": 85,
+     * 		"left_move": 0,
+     * 		"row_focus": 4,
+     * 		"width_move": 73,
+     * 		"height_move": 19,
+     * 		"column_focus": 0
+     *        }
+         */
+        JSONObject selectSave = new JSONObject();
+        selectSave.put("row", new String[]{"4", "4"});
+        selectSave.put("top", 85);
+        selectSave.put("left", 0);
+        selectSave.put("width", 73);
+        selectSave.put("column", new String[]{"0", "0"});
+        selectSave.put("height", 19);
+        selectSave.put("top_move", 85);
+        selectSave.put("left_move", 0);
+        selectSave.put("row_focus", 4);
+        selectSave.put("width_move", 73);
+        selectSave.put("height_move", 19);
+        selectSave.put("column_focus", 0);
+
+        JSONArray selectSaves = new JSONArray();
+        selectSaves.add(selectSave);
+
+        obj.put("jfgird_select_save", selectSaves);
+        obj.put("jfgrid_selection_range", new JSONObject());
+
+        return obj;
+    }
+
+    /**
+     * 获取合并配置
+     *           "0_0": {
+     * 				"c": 0,
+     * 				"r": 0,
+     * 				"cs": 58,
+     * 				"rs": 1
+     *           },
+     *
+     * @param deviceNumberList
+     * @return
+     */
+    public static JSONObject getMergeConfig(List<String> deviceNumberList) {
+        JSONObject result = new JSONObject();
+
+        int colSize = deviceNumberList.size() * 4 + 10;
+
+        //第一行 标题
+        JSONObject row0Title = new JSONObject();
+        row0Title.put("c", 0);
+        row0Title.put("r", 0);
+        row0Title.put("cs", colSize);
+        row0Title.put("rs", 1);
+        result.put("0_0", row0Title);
+
+        //第二行 前4列
+        JSONObject row1Col0Title = new JSONObject();
+        row1Col0Title.put("c", 0);
+        row1Col0Title.put("r", 1);
+        row1Col0Title.put("cs", 1);
+        row1Col0Title.put("rs", 2);
+        result.put("1_0", row1Col0Title);
+
+        JSONObject row1Col1Title = new JSONObject();
+        row1Col1Title.put("c", 1);
+        row1Col1Title.put("r", 1);
+        row1Col1Title.put("cs", 1);
+        row1Col1Title.put("rs", 2);
+        result.put("1_1", row1Col1Title);
+
+        JSONObject row1Col2Title = new JSONObject();
+        row1Col2Title.put("c", 2);
+        row1Col2Title.put("r", 1);
+        row1Col2Title.put("cs", 1);
+        row1Col2Title.put("rs", 2);
+        result.put("1_2", row1Col2Title);
+
+        JSONObject row1Col3Title = new JSONObject();
+        row1Col3Title.put("c", 3);
+        row1Col3Title.put("r", 1);
+        row1Col3Title.put("cs", 1);
+        row1Col3Title.put("rs", 2);
+        result.put("1_3", row1Col3Title);
+
+        //第二行机号
+        for(int m = 0,  n = deviceNumberList.size(); m < n; m++) {
+            JSONObject deviceNumObj = new JSONObject();
+            int colPos = 4 + m * 4;
+            deviceNumObj.put("c", colPos);
+            deviceNumObj.put("r", 1);
+            deviceNumObj.put("cs", 4);
+            deviceNumObj.put("rs", 1);
+            result.put("1_".concat(String.valueOf(colPos)), deviceNumObj);
+        }
+
+        return result;
+    }
+
+    /**
+     * {
+     * 			"value": {
+     * 				"b": {
+     * 					"color": "rgb(0, 0, 0)",
+     * 					"style": 1
+     *              },
+     * 				"l": {
+     * 					"color": "rgb(0, 0, 0)",
+     * 					"style": 1
+     *              },
+     * 				"t": {
+     * 					"color": "rgb(0, 0, 0)",
+     * 					"style": 1
+     *                },
+     * 				"col_index": 0,
+     * 				"row_index": 0
+     * 			},
+     * 			"rangeType": "cell"
+     * }
+     *
+     * @param deviceNumberList
+     * @return
+     */
+    public static JSONArray getBorderInfo(List<String> deviceNumberList) {
+        JSONArray result = new JSONArray();
+
+        //计算列行
+        int rowsSize = 3, colsSize = 10 + deviceNumberList.size() * 4;
+
+        //行
+        for(int m = 0; m < rowsSize; m++) {
+            for(int n = 0; n < colsSize; n++) {
+                JSONObject value = new JSONObject();
+                JSONObject b = new JSONObject();
+                b.put("color", "rgb(0, 0, 0)");
+                b.put("style", 1);
+                value.put("b", b);
+
+                JSONObject l = new JSONObject();
+                l.put("color", "rgb(0, 0, 0)");
+                l.put("style", 1);
+                value.put("l", l);
+
+                JSONObject t = new JSONObject();
+                t.put("color", "rgb(0, 0, 0)");
+                t.put("style", 1);
+                value.put("t", t);
+
+                value.put("col_index", n);
+                value.put("row_index", m);
+
+                JSONObject obj = new JSONObject();
+                obj.put("rangeType", "cell");
+                obj.put("value", value);
+                result.add(obj);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * 数据校验
+     *
+     * @param paramExcelDto
+     * @return
+     */
+    public static JSONObject getDataVerification(ProjectSummaryParamExcelDto paramExcelDto) {
+        JSONObject result = new JSONObject();
+        for(int m = 0,  n = paramExcelDto.getDeviceNumberList().size(); m <= n; m++) {
+            int colPos = 4 + m * 4;
+            for(int startRows = 3, endRows = 200; startRows < endRows; startRows++) {
+                /**
+                 * "3_4": {
+                 * 			"type": "dropdown",
+                 * 			"remote": false,
+                 * 			"value1": "OK,X,√",
+                 * 			"value2": "",
+                 * 			"checked": false,
+                 * 			"hintShow": false,
+                 * 			"hintText": "",
+                 * 			"prohibitInput": false
+                 * }
+                 */
+                JSONObject statusObj = new JSONObject();
+                statusObj.put("type", "dropdown");
+                statusObj.put("remote", false);
+                statusObj.put("value1", "OK,X,√");
+                statusObj.put("value2", "");
+                statusObj.put("checked", false);
+                statusObj.put("hintShow", false);
+                statusObj.put("hintText", "");
+                statusObj.put("prohibitInput", false);
+                result.put(String.valueOf(startRows).concat("_").concat(String.valueOf(colPos)), statusObj);
+            }
+        }
+
+        return result;
+    }
+}

+ 33 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/utils/MyStringUtil.java

@@ -0,0 +1,33 @@
+package com.rongwei.bscommon.sys.utils;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * @author Administrator
+ */
+public class MyStringUtil {
+
+    private final static Pattern p = Pattern.compile("\\s*|\t|\r|\n");
+    public static String replaceBlank(String str) {
+        String dest = "";
+        if (str!=null) {
+            Matcher m = p.matcher(str);
+            dest = m.replaceAll("");
+        }
+        return dest;
+    }
+    public static String getStringShow(String str,int limit){
+        if(StringUtils.isEmpty(str)){
+            return "";
+        }else{
+            return str.length()<=limit?str:str.substring(0,limit);
+        }
+    }
+    public static String getStringShow(String str){
+        return getStringShow(str,50);
+    }
+}

+ 59 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/utils/MyURLUtil.java

@@ -0,0 +1,59 @@
+package com.rongwei.bscommon.sys.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: 1
+ * Date: 17-11-16
+ * Time: 上午9:38
+ * To change this template use File | Settings | File Templates.
+ * @author Administrator
+ */
+public class MyURLUtil {
+    /**
+     * 解码
+     * @param str
+     * @return
+     */
+    public static String urlDecode(String str){
+        try {
+            String strReturn= URLDecoder.decode(str, "UTF-8");
+            return strReturn;
+        } catch (UnsupportedEncodingException e) {
+           System.out.println("urlDecode error:"+str+" info:"+e.toString());
+        }
+        return null;
+    }
+
+    /**
+     * 编码
+     * @param str
+     * @return
+     */
+    public static String urlEncode(String str){
+        try {
+            String strReturn= URLEncoder.encode(str, "UTF-8");
+            return strReturn;
+        } catch (UnsupportedEncodingException e) {
+            System.out.println("urlEncode error:"+str+" info:"+e.toString());
+        }
+        return null;
+    }
+
+    //字符串转字节
+    public static byte[] stringTobyte(String str){
+        return stringTobyte(str,"ISO-8859-1");
+    }
+    public static byte[] stringTobyte(String str,String charsetName){
+        try {
+            return str.getBytes(charsetName);
+        } catch (UnsupportedEncodingException e) {
+            System.out.println("stringTobyte error:"+str+" info:"+e.toString());
+        }
+        return null;
+    }
+    
+}

+ 282 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/utils/Pako_GzipUtils.java

@@ -0,0 +1,282 @@
+package com.rongwei.bscommon.sys.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: 1
+ * Date: 17-11-16
+ * Time: 下午1:08
+ * To change this template use File | Settings | File Templates.
+ * @author Administrator
+ */
+@Slf4j
+public class Pako_GzipUtils {
+   // private static final Logger logger = Logger.getLogger(MyGzipUtils.class);
+
+    /**
+     * @param str:正常的字符串
+     * @return 压缩字符串 类型为: ‹‹ ³)°K,NIc i£_`Çe#‚  c¦%ÂXHòjyIÅÖ`
+     * @throws IOException
+     */
+    public static String compress(String str){
+        try{
+            if (str == null || str.length() == 0) {
+                return str;
+            }
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            GZIPOutputStream gzip = new GZIPOutputStream(out);
+            gzip.write(str.getBytes());
+            gzip.close();
+            return out.toString("ISO-8859-1");
+        }catch (Exception e){
+            log.error("gzip compress:"+str, e);
+        }
+        return "";
+    }
+
+    public static byte[] compress2(String str){
+        try{
+            if (str == null || str.length() == 0) {
+                return null;
+            }
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            GZIPOutputStream gzip = new GZIPOutputStream(out);
+            gzip.write(str.getBytes("UTF-8"));
+            gzip.close();
+            return out.toByteArray();
+        }catch (Exception e){
+            log.error("gzip compress2:", e);
+        }
+        return null;
+    }
+
+    public static void compress2(String str,OutputStream _out){
+        try{
+            if (str == null || str.length() == 0) {
+                return;
+            }
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            GZIPOutputStream gzip = new GZIPOutputStream(out);
+            gzip.write(str.getBytes("UTF-8"));
+            gzip.close();
+            out.writeTo(_out);
+        }catch (Exception e){
+            log.error("gzip compress2:", e);
+        }
+    }
+
+
+
+
+    /**
+     * @param str:类型为: ‹‹ ³)°K,NIc i£_`Çe#‚  c¦%ÂXHòjyIÅÖ`
+     * @return 解压字符串  生成正常字符串。
+     * @throws IOException
+     */
+    public static String uncompress(String str)  {
+        try{
+            if (str == null || str.length() == 0) {
+                return str;
+            }
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            ByteArrayInputStream in = new ByteArrayInputStream(str
+                    .getBytes("ISO-8859-1"));
+            GZIPInputStream gunzip = new GZIPInputStream(in);
+            byte[] buffer = new byte[256];
+            int n;
+            while ((n = gunzip.read(buffer)) >= 0) {
+                out.write(buffer, 0, n);
+            }
+            // toString()使用平台默认编码,也可以显式的指定如toString("GBK")
+            return out.toString();
+        }catch (Exception e){
+            log.error("gzip uncompress:"+str, e);
+        }
+        return "";
+
+    }
+
+    /**
+     * @param jsUriStr :字符串类型为:%1F%C2%8B%08%00%00%00%00%00%00%03%C2%B3)%C2%B0K%2CNI%03c%20i%C2%A3_%60%C3%87e%03%11%23%C2%82%0Dc%C2%A6%25%C3%82XH%C3%B2jyI%C3%85%05%C3%96%60%1E%00%17%C2%8E%3Dvf%00%00%00
+     * @return 生成正常字符串
+     * @throws IOException
+     */
+    public static String  unCompressURI(String jsUriStr) throws IOException {
+        String decodeJSUri= URLDecoder.decode(jsUriStr, "UTF-8");
+        String gzipCompress=uncompress(decodeJSUri);
+        return gzipCompress;
+    }
+    /**
+     * @param strData :字符串类型为: 正常字符串
+     * @return 生成字符串类型为:%1F%C2%8B%08%00%00%00%00%00%00%03%C2%B3)%C2%B0K%2CNI%03c%20i%C2%A3_%60%C3%87e%03%11%23%C2%82%0Dc%C2%A6%25%C3%82XH%C3%B2jyI%C3%85%05%C3%96%60%1E%00%17%C2%8E%3Dvf%00%00%00
+     * @throws IOException
+     */
+    public static String  compress2URI(String strData) throws IOException {
+        String encodeGzip=compress(strData);
+        String jsUriStr= URLEncoder.encode(encodeGzip, "UTF-8");
+        return jsUriStr;
+    }
+
+
+    /**
+     * @param jsUriStr :字符串类型为:%1F%C2%8B%08%00%00%00%00%00%00%03%C2%B3)%C2%B0K%2CNI%03c%20i%C2%A3_%60%C3%87e%03%11%23%C2%82%0Dc%C2%A6%25%C3%82XH%C3%B2jyI%C3%85%05%C3%96%60%1E%00%17%C2%8E%3Dvf%00%00%00
+     * @return 生成正常字符串
+     * @throws IOException
+     */
+    public static String  unCompressToURI(String jsUriStr)  {
+        if(jsUriStr==null){
+            return "";
+        }
+        try {
+            String gzipCompress=uncompress(jsUriStr);
+            String decodeJSUri= URLDecoder.decode(gzipCompress, "UTF-8");
+            return decodeJSUri;
+        } catch (Exception e) {
+            log.error("gzip unCompressToURI:"+jsUriStr, e);
+        }
+        return "";
+    }
+    /**
+     * @param strData :字符串类型为: 正常字符串
+     * @return 生成字符串类型为:%1F%C2%8B%08%00%00%00%00%00%00%03%C2%B3)%C2%B0K%2CNI%03c%20i%C2%A3_%60%C3%87e%03%11%23%C2%82%0Dc%C2%A6%25%C3%82XH%C3%B2jyI%C3%85%05%C3%96%60%1E%00%17%C2%8E%3Dvf%00%00%00
+     * @throws IOException
+     */
+    public static String  compressToURI(String strData){
+        if(strData==null){
+            return "";
+        }
+        try {
+            String jsUriStr = URLEncoder.encode(strData, "UTF-8");
+            String encodeGzip=compress(jsUriStr);
+            return encodeGzip;
+        } catch (Exception e) {
+            log.error("gzip compressToURI:"+strData, e);
+        }
+        return "";
+    }
+
+    public static void main(String[] args) {
+//        String  str="[{\"t\":\"v\",\"i\":1,\"v\":\"运输设备\",\"r\":1,\"c\":2}]";
+////        System.out.println(compress2URI(str));
+////
+////        String str1="%1F%C2%8B%08%00%00%00%00%00%00%00%C2%8B%C2%AEV*Q%C2%B2R*S%C3%92Q%C3%8AT%C2%B22%C3%94%01%C2%B2%C2%AC%C2%94%5E%C3%AC%C2%9F%C3%B0b%C3%9F%C3%A4%17%C3%AB%C3%B6%3D%5D%C3%92%0E%C2%94%28%02K%24%2BY%19%C3%95%C3%86%02%00%C3%93%C2%AD%C2%96%C3%920%00%00%00";
+////        System.out.println(unCompressURI(str1));
+//
+//        String _result1=compressToURI(str);
+//        System.out.println(_result1);
+//        System.out.println(unCompressToURI(_result1));
+//
+//        File outputFile = new File("C:\\Users\\1\\Downloads\\test1 (2).tu");
+//        readGZip(outputFile);
+//
+//        //File outputFile1 = new File("C:\\Users\\1\\Downloads\\test1 (1).tu");
+//        //readGZip(outputFile1);
+//
+//        File outputFile2 = new File("C:\\Users\\1\\Downloads\\test1_byte.tu");
+//        readGZip(outputFile2);
+
+        System.out.println(Pako_GzipUtils.unCompressToURI("\u001F\u008B\b"));
+
+    }
+
+    private static final int BUFFER_SIZE = 1024;
+    public static void readGZip(File file) {
+
+        GZIPInputStream gzipInputStream = null;
+        ByteArrayOutputStream baos = null;
+        try {
+            gzipInputStream = new GZIPInputStream(new FileInputStream(file));
+
+            baos = new ByteArrayOutputStream();
+
+            byte[] buf = new byte[BUFFER_SIZE];
+            int len = 0;
+            while((len=gzipInputStream.read(buf, 0, BUFFER_SIZE))!=-1){
+                baos.write(buf, 0, len);
+            }
+
+            baos.toByteArray();
+
+            String result = baos.toString("UTF-8");
+
+            System.out.println("result="+result);
+
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }finally{
+            if(gzipInputStream!=null){
+                try {
+                    gzipInputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if(baos!=null){
+                try {
+                    baos.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public static String readGZip(MultipartFile fileUpload) {
+
+        GZIPInputStream gzipInputStream = null;
+        ByteArrayOutputStream baos = null;
+        try {
+            gzipInputStream = new GZIPInputStream(fileUpload.getInputStream());
+
+            baos = new ByteArrayOutputStream();
+
+            byte[] buf = new byte[BUFFER_SIZE];
+            int len = 0;
+            while((len=gzipInputStream.read(buf, 0, BUFFER_SIZE))!=-1){
+                baos.write(buf, 0, len);
+            }
+
+            baos.toByteArray();
+
+            String result = baos.toString("UTF-8");
+            return result;
+            //System.out.println("result="+result);
+
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }finally{
+            if(gzipInputStream!=null){
+                try {
+                    gzipInputStream.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if(baos!=null){
+                try {
+                    baos.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return "";
+    }
+
+
+
+
+
+}

+ 22 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/utils/TimeUtil.java

@@ -0,0 +1,22 @@
+package com.rongwei.bscommon.sys.utils;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author zhouhang
+ * @description TimeUtil
+ * @date 2021/5/10
+ */
+public class TimeUtil {
+
+    public static int getTodayBeginTime() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(new Date());
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        return (int) (calendar.getTime().getTime() / 1000);
+    }
+
+}

+ 83 - 0
business-dameng/pom.xml

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>quality-inspection</artifactId>
+        <groupId>com.rongwei</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>business-dameng</artifactId>
+    <packaging>jar</packaging>
+    <name>business-dameng</name>
+    <description>达梦实现</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <version>5.1.6.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>1.3.2</version>
+        </dependency>
+
+        <!--自动生成set get方法-->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.12</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- spring-jdbc -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-jdbc</artifactId>
+            <version>5.1.10.RELEASE</version>
+        </dependency>
+
+        <!--阿里的druid数据源-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+            <version>1.1.20</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.dameng</groupId>
+            <artifactId>DmJdbcDriver18</artifactId>
+            <version>8.1.1.193</version>
+        </dependency>
+
+        <!---数据库接口-->
+        <dependency>
+            <groupId>com.rongwei</groupId>
+            <artifactId>business-db</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.70</version>
+        </dependency>
+    </dependencies>
+
+
+</project>

+ 32 - 0
business-dameng/src/main/java/com/rongwei/luckysheet/dameng/datasource/JdbcTempleConfig.java

@@ -0,0 +1,32 @@
+package com.rongwei.luckysheet.dameng.datasource;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.annotation.Resource;
+import javax.sql.DataSource;
+
+
+/**
+ * @author Administrator
+ */
+@Configuration
+@Slf4j
+public class JdbcTempleConfig {
+
+    /**
+     * postgre数据源
+     */
+//    @Resource(name = "damengDataSource")
+    @Autowired
+    private DataSource damengDataSource;
+
+    @Bean(name="damengJdbcTemplate")
+    public JdbcTemplate createPostgreJdbcTemplate(){
+        return new JdbcTemplate(damengDataSource);
+    }
+
+}

+ 51 - 0
business-dameng/src/main/java/com/rongwei/luckysheet/dameng/datasource/ProfiledemoApplication.java

@@ -0,0 +1,51 @@
+package com.rongwei.luckysheet.dameng.datasource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import org.springframework.transaction.annotation.TransactionManagementConfigurer;
+
+import javax.annotation.Resource;
+import javax.sql.DataSource;
+
+/**
+ * @author Administrator
+ */
+
+/**
+ * 开启注解事务管理,等同于xml配置文件中的 <tx:annotation-driven />
+ * @author Administrator
+ */
+//@EnableTransactionManagement
+//@Configuration
+//public class ProfiledemoApplication implements TransactionManagementConfigurer {
+public class ProfiledemoApplication {
+//    /**
+//     * postgre数据源
+//     */
+//    @Resource(name = "damengDataSource")
+//    @Autowired
+//    private DataSource damengDataSource;
+//
+//
+//    @Bean(name = "damengTxManager")
+//    public PlatformTransactionManager postgreTxManager() {
+//        return new DataSourceTransactionManager(damengDataSource);
+//    }
+//
+//
+//    @Resource(name="damengTxManager")
+//    private PlatformTransactionManager txManager;
+//
+//    /**
+//     * 实现接口 TransactionManagementConfigurer 方法,其返回值代表在拥有多个事务管理器的情况下默认使用的事务管理器
+//     * @return
+//     */
+//    @Override
+//    public PlatformTransactionManager annotationDrivenTransactionManager() {
+//        return txManager;
+//    }
+}

+ 35 - 0
business-dameng/src/main/java/com/rongwei/luckysheet/dameng/datasource/SnowFlakeConfig.java

@@ -0,0 +1,35 @@
+package com.rongwei.luckysheet.dameng.datasource;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.rongwei.luckysheet.util.SnowFlake;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+
+/**
+ * 数据源配置
+ * @author Administrator
+ */
+@Configuration
+@Slf4j
+public class SnowFlakeConfig {
+
+//    @Bean(name = "damengDataSource")
+////    @ConfigurationProperties(prefix = "spring.datasource.druid")
+//    public DataSource postgreDataSource(DataSource dataSource){
+////        DataSource dataSource = DataSourceBuilder.create().type(DruidDataSource.class).build();
+////        log.debug("数据源 dameng",dataSource);
+//        return dataSource;
+//    }
+
+    @Bean(name="snowFlake")
+    public SnowFlake getSnowFlake(){
+        return new SnowFlake(1l,1l);
+    }
+
+}

+ 19 - 0
business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/BaseHandle.java

@@ -0,0 +1,19 @@
+package com.rongwei.luckysheet.dameng.impl;
+
+import com.rongwei.luckysheet.util.SnowFlake;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Slf4j
+@Component
+public class BaseHandle {
+
+    @Resource(name = "damengJdbcTemplate")
+    protected JdbcTemplate jdbcTemplateDameng;
+
+    @Resource(name = "snowFlake")
+    protected SnowFlake snowFlake;
+}

+ 135 - 0
business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/RecordDataInsertHandle.java

@@ -0,0 +1,135 @@
+package com.rongwei.luckysheet.dameng.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.luckysheet.JfGridConfigModel;
+import com.rongwei.luckysheet.db.IRecordDataInsertHandle;
+import com.rongwei.luckysheet.entity.GridRecordDataModel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 添加
+ * @author Administrator
+ */
+@Slf4j
+@Repository(value = "damengRecordDataInsertHandle")
+public class RecordDataInsertHandle extends BaseHandle implements IRecordDataInsertHandle {
+
+    /**
+     * 新增Sheet页,并返回刚刚插入的_id
+     *
+     * @param pgModel
+     * @return
+     */
+    @Override
+    public String insert(GridRecordDataModel pgModel) {
+        String sql = "insert into "+ JfGridConfigModel.TABLENAME +" (id,block_id,\"index\",list_id,status,json_data,\"order\",is_delete) values " +
+                " (?,?,?,?,?,?,?,0)";
+        try{
+            jdbcTemplateDameng.update(sql,snowFlake.nextId().longValue(), pgModel.getBlock_id().trim(),pgModel.getIndex(),pgModel.getList_id(),pgModel.getStatus(),pgModel.getJson_data().toJSONString(),pgModel.getOrder());
+            return "";
+        }catch (Exception e){
+            log.warn(e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * 批量添加 添加jsonb
+     *
+     * @param models
+     * @return
+     */
+    @Override
+    public String InsertIntoBatch(List<GridRecordDataModel> models) {
+        String sql = "insert into "+JfGridConfigModel.TABLENAME +" (id,block_id,row_col,\"index\",list_id,status,\"order\",json_data,is_delete) values " +
+                " (?,?,?,?,?,?,?,?,0)";
+        List<Object[]>batch=new ArrayList<Object[]>();
+        for(GridRecordDataModel b : models){
+            List<Object> objectList=new ArrayList<Object>();
+            objectList.add(snowFlake.nextId().longValue());
+            objectList.add(b.getBlock_id().trim());
+            objectList.add(b.getRow_col());
+            objectList.add(b.getIndex());
+            objectList.add(b.getList_id());
+            objectList.add(b.getStatus());
+            objectList.add(b.getOrder());
+            objectList.add(b.getJson_data().toJSONString());
+
+            Object[] params=(Object[])objectList.toArray(new Object[objectList.size()]);
+            batch.add(params);
+        }
+        try{
+            log.info("InsertIntoBatch sql{}",sql);
+            int[] i= jdbcTemplateDameng.batchUpdate(sql,batch);
+            log.info("InsertIntoBatch count {}",i);
+            return "";
+        }catch (Exception ex){
+            log.error(ex.toString());
+            return null;
+        }
+    }
+
+    /**
+     * 批量添加 添加jsonb
+     *
+     * @param models
+     * @return
+     */
+    @Override
+    public String InsertBatchDb(List<JSONObject> models) {
+        String sql = "insert into "+JfGridConfigModel.TABLENAME+" (id,block_id,row_col,\"index\",list_id,status,\"order\",json_data,is_delete) values " +
+                " (?,?,?,?,?,?,?,?,0)";
+        List<Object[]>batch=new ArrayList<Object[]>();
+        int order=0;
+        for(JSONObject b : models){
+            List<Object> objectList=new ArrayList<Object>();
+            objectList.add(snowFlake.nextId().longValue());
+            objectList.add(b.get("block_id").toString().trim());
+            if(b.containsKey("row_col") && b.get("row_col")!=null){
+                objectList.add(b.get("row_col"));
+            }else{
+                objectList.add(null);
+            }
+            objectList.add(b.get("index"));
+            objectList.add(b.get("list_id"));
+            if(b.containsKey("status") && b.get("status")!=null){
+                objectList.add(b.get("status"));
+            }else{
+                objectList.add(0);
+            }
+
+            if(b.containsKey("order") && b.get("order")!=null){
+                objectList.add(b.get("order"));
+                order=Integer.valueOf(b.get("order").toString());
+            }else{
+                objectList.add(order);
+            }
+
+            JSONObject db=new JSONObject();
+            if(b.containsKey("json_data")){
+                db=(JSONObject) b.get("json_data");
+            }else{
+                db.put("celldata", b.get("celldata"));
+            }
+            objectList.add(db.toJSONString());
+
+            Object[] params=(Object[])objectList.toArray(new Object[objectList.size()]);
+            batch.add(params);
+        }
+
+        try{
+            log.info("InsertBatchDb sql{}",sql);
+            int[] i= jdbcTemplateDameng.batchUpdate(sql,batch);
+            log.info("InsertBatchDb count {}",i);
+            return "";
+        }catch (Exception ex){
+            log.error(ex.getMessage());
+            return null;
+        }
+    }
+}
+

+ 528 - 0
business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/RecordDataUpdataHandle.java

@@ -0,0 +1,528 @@
+package com.rongwei.luckysheet.dameng.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.rongwei.luckysheet.JfGridConfigModel;
+import com.rongwei.luckysheet.db.IRecordDataInsertHandle;
+import com.rongwei.luckysheet.db.IRecordDataUpdataHandle;
+import com.rongwei.luckysheet.db.IRecordDelHandle;
+import com.rongwei.luckysheet.entity.GridRecordDataModel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jdbc.core.BatchPreparedStatementSetter;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 更新
+ * @author Administrator
+ */
+@Slf4j
+@Repository(value ="damengRecordDataUpdataHandle" )
+public class RecordDataUpdataHandle extends BaseHandle implements IRecordDataUpdataHandle {
+
+    @Resource
+    @Qualifier("damengRecordDataInsertHandle")
+    private IRecordDataInsertHandle RecordDataInsertHandle;
+
+    @Resource
+    @Qualifier("damengRecordDelHandle")
+    private IRecordDelHandle recordDelHandle;
+
+    /**
+     * sheet多块更新(先删除后添加)
+     * 按IDS删除一组,然后新加处理后的
+     * @param blocks
+     * @param ids
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public Boolean updateMulti2(List<JSONObject> blocks, List<String> ids) {
+        try{
+            if(ids!=null && ids.size()>0){
+                recordDelHandle.delDocuments(ids);
+            }
+            String _mongodbKey = RecordDataInsertHandle.InsertBatchDb(blocks);
+            if (_mongodbKey == null) {
+                throw new RuntimeException("插入报错");
+            }
+            return true;
+        }catch (Exception e){
+            log.error(e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 批量更新order 按listId,index,首块
+     *
+     * @param models
+     * @return
+     */
+    @Override
+    public boolean batchUpdateForNoJsonbData(List<GridRecordDataModel> models) {
+        try{
+            String sql="update "+ JfGridConfigModel.TABLENAME+" set \"order\"=?  where  list_id=? and \"index\"=? and block_id=?";
+            log.info("batchUpdateForNoJsonbData:"+sql);
+            jdbcTemplateDameng.batchUpdate(sql, new BatchPreparedStatementSetter() {
+                public int getBatchSize() {
+                    return models.size();
+                    //这个方法设定更新记录数,通常List里面存放的都是我们要更新的,所以返回list.size();
+                }
+                public void setValues(PreparedStatement ps, int i)throws SQLException {
+                    GridRecordDataModel linkset =  models.get(i);
+                    ps.setInt(1, linkset.getOrder());
+                    ps.setString(2, linkset.getList_id());
+                    ps.setString(3, linkset.getIndex());
+                    ps.setString(4, JfGridConfigModel.FirstBlockID);
+                }
+            });
+            return true;
+        }catch (Exception e){
+            log.error(e.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 清除指定层级下某条数据
+     *
+     * @param query   键值对
+     * @param keyName
+     * @return
+     */
+    @Override
+    public boolean rmCellDataValue(JSONObject query, String keyName) {
+        String condition="";
+        try{
+            log.info("select:"+query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+            for (String key : queryDB.keySet()) {
+                condition=condition+"and \""+key+"\"='"+queryDB.get(key)+"'";
+            }
+            String updateSql="update "+JfGridConfigModel.TABLENAME+" set json_data=json_data #- '{"+keyName+"}'  where 1=1 " +condition;
+            log.info("rmCellDataValue--"+updateSql);
+            jdbcTemplateDameng.update(updateSql);
+            return true;
+        }catch (Exception ex){
+            log.error("异常信息", ex);
+            return false;
+        }
+    }
+
+    /**
+     * 更新jsonb中某条文本数据
+     *
+     * @param query    键值对
+     * @param keyName
+     * @param position
+     * @param v
+     * @return
+     */
+    @Override
+    public boolean updateCellDataListTxtValue(JSONObject query, String keyName, Integer position, Object v) {
+        String condition="";
+        try{
+            log.info("select:"+query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+            for (String key : queryDB.keySet()) {
+                condition=condition+"and \""+key+"\"='"+queryDB.get(key)+"'";
+            }
+            if(position!=null){
+                keyName=keyName+","+position;
+            }
+            StringBuffer updateSql=new StringBuffer();
+            updateSql.append("update "+JfGridConfigModel.TABLENAME+" set json_data=jsonb_set(json_data,'{"+keyName);
+            updateSql.append("}'::text[],'"+v+"',true) where 1=1 "+condition);
+
+            jdbcTemplateDameng.update(updateSql.toString());
+            return true;
+        }catch (Exception ex){
+            log.error("异常信息", ex);
+            return false;
+        }
+    }
+
+    /**
+     * 更新jsonb中某条文本数据
+     *
+     * @param query    键值对
+     * @param keyName
+     * @param position
+     * @param v
+     * @return
+     */
+    @Override
+    public boolean updateCellDataListValue(JSONObject query, String keyName, String position, Object v) {
+        String condition="";
+        try{
+            log.info("select:"+query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+            for (String key : queryDB.keySet()) {
+                condition=condition+"and \""+key+"\"='"+queryDB.get(key)+"'";
+            }
+            if(position!=null){
+                keyName=keyName+","+position;
+            }
+            StringBuffer updateSql=new StringBuffer();
+            updateSql.append("update "+JfGridConfigModel.TABLENAME+" set json_data=jsonb_set(json_data,'{"+keyName);
+            updateSql.append("}','"+v+"',true) where 1=1 "+condition);
+            log.info("updateSql:"+updateSql);
+            jdbcTemplateDameng.update(updateSql.toString());
+            return true;
+        }catch (Exception ex){
+            log.error("异常信息", ex);
+            return false;
+        }
+    }
+
+    /**
+     * jsonb数据中元素添加元素
+     *
+     * @param query
+     * @param word
+     * @param db
+     * @param position
+     * @return
+     */
+    @Override
+    public boolean updateJsonbForElementInsert(JSONObject query, String word, JSONObject db, Integer position) {
+        String condition="";
+        try{
+            log.info("select:"+query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+//            if(position!=null){
+//                word=word+","+position;
+//            }
+            List arr=new ArrayList<>();
+            for (String key : queryDB.keySet()) {
+                arr.add(queryDB.get(key));
+                condition=condition+"and \""+key+"\"=? ";
+            }
+            //(jsonb_v,'{myinfo,celldata,0}','{"c":1,"r":1,"v":{"con":"str"}}',false)
+//            String updateSql="update "+JfGridConfigModel.TABLENAME+" set json_data=JSON_ARRAY_APPEND(json_data,'$."+word+"','"+db+"') where 1=1 " +condition;
+
+            StringBuffer updateSql=new StringBuffer();
+            updateSql.append("update "+JfGridConfigModel.TABLENAME+" t set t.json_data=JSON_ARRAY_APPEND(t.json_data,'$."+word+"',");
+            updateSql.append("CAST('"+db.toString(SerializerFeature.WriteMapNullValue)+"' as JSON)");
+            updateSql.append(") where 1=1 "+condition);
+
+            log.info("updateSql:"+updateSql.toString());
+            jdbcTemplateDameng.update(updateSql.toString(), arr.toArray());
+            return true;
+        }catch (Exception ex){
+            log.error("异常信息", ex);
+            return false;
+        }
+    }
+
+    /**
+     * 更新
+     *
+     * @param query
+     * @param word
+     * @return
+     */
+    @Override
+    public boolean rmJsonbDataForEmpty(JSONObject query, String word) {
+        String condition="";
+        try{
+            log.info("select:"+query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+            List arr=new ArrayList<>();
+            for (String key : queryDB.keySet()) {
+                arr.add(queryDB.get(key));
+                condition=condition+"and \""+key+"\"=? ";
+            }
+            String sql="update "+JfGridConfigModel.TABLENAME+" set json_data=json_data||'{"+word+"}'::jsonb where 1=1 "+condition;
+            log.info("updateSql:"+sql);
+            jdbcTemplateDameng.update(sql,arr.toArray());
+            return true;
+        }catch (Exception e){
+            log.error(e.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 更新
+     *
+     * @param query
+     * @param word
+     * @return
+     */
+    @Override
+    public boolean updateJsonbDataForKeys(JSONObject query, JSONObject word) {
+        String condition="";
+        try{
+            log.info("select:"+query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+
+            List arr=new ArrayList<>();
+            for (String key : queryDB.keySet()) {
+                arr.add(queryDB.get(key));
+                condition=condition+"and \""+key+"\"=? ";
+            }
+            String sql="update "+JfGridConfigModel.TABLENAME+" set json_data=json_data||'"+word.toString()+"'::jsonb where 1=1 "+condition;
+            log.info("updateSql:"+sql);
+            jdbcTemplateDameng.update(sql,arr.toArray());
+            return true;
+        }catch (Exception e){
+            log.error(e.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 更新status状态
+     *
+     * @param model
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean updateDataStatus(GridRecordDataModel model) {
+        try{
+            String sql1="update "+JfGridConfigModel.TABLENAME+" set status=0  where  list_id=? and status=1 and block_id=?";
+            log.info("updateSql1:"+sql1);
+            jdbcTemplateDameng.update(sql1,new Object[]{model.getList_id(),model.getBlock_id()});
+
+            String sql2="update "+JfGridConfigModel.TABLENAME+" set status=1  where  list_id=? and \"index\"=? and block_id=?";
+            log.info("updateSql2:"+sql2);
+            jdbcTemplateDameng.update(sql2,new Object[]{model.getList_id(),model.getIndex(),model.getBlock_id()});
+            return true;
+        }catch (Exception e){
+            log.error(e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 更新sheet隐藏状态
+     *
+     * @param model
+     * @param hide
+     * @param index1
+     * @param index2
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean updateDataMsgHide(GridRecordDataModel model, Integer hide, String index1, String index2) {
+        try{
+            String sql1="update "+JfGridConfigModel.TABLENAME+" set status=0 ,json_data=jsonb_set(json_data,'{hide}'::text[],'"+hide+"',true) where  list_id='"+model.getList_id()+"' and \"index\"='"+index1+"' and block_id='fblock'";
+            log.info("updateSql1:"+sql1);
+            jdbcTemplateDameng.update(sql1);
+            String sql2="update "+JfGridConfigModel.TABLENAME+" set status=1  where  list_id=? and \"index\"=? and block_id=?";
+            log.info("updateSql2:"+sql2);
+            jdbcTemplateDameng.update(sql2,new Object[]{model.getList_id(),index2,model.getBlock_id()});
+            return true;
+        }catch (Exception e){
+            log.error(e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 更新sheet隐藏状态
+     *
+     * @param model
+     * @param hide
+     * @param index
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean updateDataMsgNoHide(GridRecordDataModel model, Integer hide, String index) {
+        try{
+            String sql1="update "+JfGridConfigModel.TABLENAME+" set status=0  where  list_id=?  and block_id=?";
+            log.info("updateSql1:"+sql1);
+            jdbcTemplateDameng.update(sql1,new Object[]{model.getList_id(),model.getBlock_id()});
+
+            String sql2="update "+JfGridConfigModel.TABLENAME+" set status=1 ,json_data=jsonb_set(json_data,'{hide}'::text[],'"+hide+"',true) where  list_id='"+model.getList_id()+"' and \"index\"='"+index+"' and block_id='"+model.getBlock_id()+"'";
+            log.info("updateSql2:"+sql2);
+            jdbcTemplateDameng.update(sql2);
+            return true;
+        }catch (Exception e){
+            log.error(e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 更新jsonb中某条文本数据
+     *
+     * @param block_ids
+     * @param models
+     * @return
+     */
+    @Override
+    public boolean batchUpdateCellDataValue(List<String> block_ids, List<GridRecordDataModel> models) {
+        try{
+            String id="";
+            for (String str : block_ids) {
+                id=id+"'"+str+"',";
+            }
+            id=id.substring(0, id.length()-1);
+            log.info("id:"+id);
+            String delsql="DELETE from "+JfGridConfigModel.TABLENAME+" where list_id=? and block_id in ("+id+") and \"index\"=? ";
+            jdbcTemplateDameng.update(delsql,new Object[]{models.get(0).getList_id(),models.get(0).getIndex()});
+            String sql = "insert into "+JfGridConfigModel.TABLENAME+" (id,block_id,\"index\",list_id,status,\"order\",json_data,is_delete) values " +
+                    " (?,?,?,?,?,?,?,0)";
+            List<Object[]>batch=new ArrayList<Object[]>();
+            for(GridRecordDataModel b : models){
+                List<Object> objectList=new ArrayList<Object>();
+                objectList.add(snowFlake.nextId().longValue());
+                objectList.add(b.getBlock_id().trim());
+                objectList.add(b.getIndex());
+                objectList.add(b.getList_id());
+                objectList.add(b.getStatus());
+                objectList.add(b.getOrder());
+                objectList.add(b.getJson_data().toString(SerializerFeature.WriteMapNullValue));
+
+                Object[] params=(Object[])objectList.toArray(new Object[objectList.size()]);
+                batch.add(params);
+            }
+            log.info("sqls:{}",sql);
+            jdbcTemplateDameng.batchUpdate(sql,batch);
+            log.info("batchUpdateCellDataValue--end");
+            return true;
+
+
+        }catch (Exception ex){
+            log.error("异常信息", ex);
+            return false;
+        }
+    }
+
+    /**
+     * jsonb数据中元素添加元素(集合插入)
+     *
+     * @param query
+     * @param word
+     * @param db
+     * @param position
+     * @param words
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean updateJsonbForInsertNull(JSONObject query, String word, JSONObject db, Integer position, String words) {
+        String condition="";
+        try{
+            log.info("select:"+query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+            List arr=new ArrayList<>();
+            for (String key : queryDB.keySet()) {
+                arr.add(queryDB.get(key));
+                condition=condition+"and \""+key+"\"=? ";
+            }
+            String createSql="update "+JfGridConfigModel.TABLENAME+" set json_data=json_data||'{"+words+"}'::jsonb where 1=1 " +condition;
+            log.info("createSql:{}",createSql);
+            jdbcTemplateDameng.update(createSql,arr.toArray());
+//            if(position!=null){
+//                word=word+","+position;
+//            }
+            //(jsonb_v,'{myinfo,celldata,0}','{"c":1,"r":1,"v":{"con":"str"}}',false)
+//            String updateSql="update "+JfGridConfigModel.TABLENAME+" set json_data=jsonb_insert(json_data,'{"+word+"}','"+db.toString()+"',false) where 1=1 " +condition;
+
+            StringBuffer updateSql=new StringBuffer();
+            updateSql.append("update "+JfGridConfigModel.TABLENAME+" t set t.json_data=JSON_ARRAY_APPEND(t.json_data,'$."+word+"',");
+            updateSql.append("CAST('"+db.toString(SerializerFeature.WriteMapNullValue)+"' as JSON)");
+            updateSql.append(") where 1=1 "+condition);
+
+            log.info("updateSql:{}",updateSql.toString());
+            jdbcTemplateDameng.update(updateSql.toString(),arr.toArray());
+            return true;
+        }catch (Exception ex){
+            log.error("异常信息", ex);
+            throw new RuntimeException(ex.getMessage());
+        }
+    }
+
+    /**
+     * jsonb数据中元素添加元素
+     *
+     * @param query
+     * @param word
+     * @param db
+     * @param position
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean updateJsonbForSetNull(JSONObject query, String word, JSONObject db, Integer position) {
+        String condition="";
+        try{
+            log.info("select:"+query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+            List arr=new ArrayList<>();
+            for (String key : queryDB.keySet()) {
+                arr.add(queryDB.get(key));
+                condition=condition+"and \""+key+"\"=? ";
+            }
+            log.info("arr:"+arr);
+            String createSql="update "+JfGridConfigModel.TABLENAME+" set json_data=jsonb_set(json_data,'{"+word+"}'::text[],'[]',true)  where 1=1 " +condition;
+            log.info("createSql:"+createSql);
+            jdbcTemplateDameng.update(createSql,arr.toArray());
+            if(position!=null){
+                word=word+","+position;
+            }
+            //(jsonb_v,'{myinfo,celldata,0}','{"c":1,"r":1,"v":{"con":"str"}}',false)
+            String updateSql="update "+JfGridConfigModel.TABLENAME+" set json_data=jsonb_set(json_data,'{"+word+"}'::text[],'"+db.toString()+"',true) where 1=1 " +condition;
+            log.info("updateSql:"+updateSql);
+            jdbcTemplateDameng.update(updateSql,arr.toArray());
+            return true;
+        }catch (Exception ex){
+            log.error("异常信息", ex);
+            throw new RuntimeException(ex.getMessage());
+        }
+    }
+
+    /**
+     * jsonb数据中元素添加元素(根节点)
+     *
+     * @param query
+     * @param word
+     * @param db
+     * @param position
+     * @param words
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public boolean updateJsonbForSetRootNull(JSONObject query, String word, JSONObject db, Integer position, String words) {
+        String condition="";
+        try{
+            log.info("select:{}",query.toString(SerializerFeature.WriteMapNullValue));
+            Map<String,Object> queryDB=query.getInnerMap();
+            List arr=new ArrayList<>();
+            for (String key : queryDB.keySet()) {
+                arr.add(queryDB.get(key));
+                condition=condition+"and \""+key+"\"=? ";
+            }
+            String createSql="update "+JfGridConfigModel.TABLENAME+" set json_data=json_data||'{"+words+"}'::jsonb where 1=1 " +condition;
+            log.info("createSql:"+createSql);
+            jdbcTemplateDameng.update(createSql,arr.toArray());
+            if(position!=null){
+                word=word+","+position;
+            }
+            //(jsonb_v,'{myinfo,celldata,0}','{"c":1,"r":1,"v":{"con":"str"}}',false)
+            String updateSql="update "+JfGridConfigModel.TABLENAME+" set json_data=jsonb_set(json_data,'{"+word+"}','"+db.toString()+"',false) where 1=1 " +condition;
+            log.info("updateSql:"+updateSql);
+            jdbcTemplateDameng.update(updateSql,arr.toArray());
+            return true;
+        }catch (Exception ex){
+            log.error("异常信息", ex);
+            throw new RuntimeException(ex.getMessage());
+        }
+    }
+}

+ 84 - 0
business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/RecordDelHandle.java

@@ -0,0 +1,84 @@
+package com.rongwei.luckysheet.dameng.impl;
+
+import com.rongwei.luckysheet.JfGridConfigModel;
+import com.rongwei.luckysheet.db.IRecordDelHandle;
+import com.rongwei.luckysheet.entity.GridRecordDataModel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.jdbc.object.BatchSqlUpdate;
+import org.springframework.stereotype.Repository;
+
+import javax.sql.DataSource;
+import java.sql.Types;
+import java.util.List;
+
+/**
+ * 删除
+ * @author Administrator
+ */
+@Slf4j
+@Repository(value = "damengRecordDelHandle")
+public class RecordDelHandle extends BaseHandle implements IRecordDelHandle {
+
+    /**
+     * 删除sheet(非物理删除)
+     *
+     * @param model
+     * @return
+     */
+    @Override
+    public boolean updateDataForReDel(GridRecordDataModel model) {
+        try{
+            String sql1="update "+ JfGridConfigModel.TABLENAME+"  set is_delete=?  where  list_id=? and index=? ";
+            log.info("updateSql1:"+sql1);
+            jdbcTemplateDameng.update(sql1,new Object[]{model.getIs_delete(),model.getList_id(),model.getIndex()});
+            return true;
+        }catch (Exception e){
+            log.error(e.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 按ID 删除多个文档 (物理删除)
+     *
+     * @param ids
+     * @return
+     */
+    @Override
+    public String delDocuments(List<String> ids) {
+        try{
+            String id="";
+            for (String str : ids) {
+                id=id+str+",";
+            }
+            id=id.substring(0, id.length()-1);
+            String delsql="DELETE from "+JfGridConfigModel.TABLENAME+" where id in ("+id+")";
+            jdbcTemplateDameng.update(delsql);
+            return "";
+        }catch (Exception ex){
+            log.error(ex.toString());
+            return ex.toString();
+        }
+    }
+
+    /**
+     * 按list_id 删除记录 (物理删除)
+     *
+     * @param listIds
+     * @return
+     */
+    @Override
+    public int[] delete(List<String> listIds) {
+        if(listIds==null && listIds.size()==0){
+            return new int[]{};
+        }
+        DataSource ds = jdbcTemplateDameng.getDataSource();
+        BatchSqlUpdate bsu = new BatchSqlUpdate(ds, " delete  from "+JfGridConfigModel.TABLENAME +" where list_id = ? ");
+        bsu.setBatchSize(4);
+        bsu.setTypes(new int[]{Types.VARCHAR});
+        for(int i = 0; i < listIds.size(); i++){
+            log.info(bsu.update(new Object[]{listIds.get(i)})+"");
+        }
+        return bsu.flush();
+    }
+}

+ 395 - 0
business-dameng/src/main/java/com/rongwei/luckysheet/dameng/impl/RecordSelectHandle.java

@@ -0,0 +1,395 @@
+package com.rongwei.luckysheet.dameng.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.luckysheet.JfGridConfigModel;
+import com.rongwei.luckysheet.db.IRecordSelectHandle;
+import com.rongwei.luckysheet.util.JfGridFileUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 查询
+ * @author Administrator
+ */
+@Slf4j
+@Repository(value = "damengRecordSelectHandle")
+public class RecordSelectHandle extends BaseHandle implements IRecordSelectHandle {
+    /**
+     * 查看指定sheet页 第一块是否存在(控制块)
+     *
+     * @param listId
+     * @param index
+     * @return
+     */
+    @Override
+    public Integer getFirstBlockByGridKey(String listId, String index) {
+        //默认获取第一块
+        String sql="select count(1) from "+ JfGridConfigModel.TABLENAME +" p where p.list_id=? and p.\"index\"=? and p.block_id=? and p.is_delete=0";
+        try{
+            return  jdbcTemplateDameng.queryForObject(sql, new Object[]{listId,index,JfGridConfigModel.FirstBlockID},Integer.class);
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取指定的xls激活的sheet页的 返回index(控制块)
+     *
+     * @param listId
+     * @return
+     */
+    @Override
+    public String getFirstBlockIndexByGridKey(String listId) {
+        //默认获取第一块
+        String sql="select p.\"index\" from "+JfGridConfigModel.TABLENAME+" p where p.list_id=? and p.block_id=? and p.status=1 and p.is_delete=0 ";
+        try{
+            log.info("sql: {}", sql);
+            return  jdbcTemplateDameng.queryForObject(sql, new Object[]{listId,JfGridConfigModel.FirstBlockID},String.class);
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取指定的xls,sheet 第一块的行列信息(控制块)
+     *
+     * @param listId
+     * @param index
+     * @return
+     */
+    @Override
+    public String getFirstBlockRowColByGridKey(String listId,String index) {
+        //默认获取第一块
+        String sql="select p.row_col from "+JfGridConfigModel.TABLENAME+" p where p.list_id=? and p.\"index\"=? and p.block_id=? and p.is_delete=0";
+        try{
+            return  jdbcTemplateDameng.queryForObject(sql, new Object[]{listId,index,JfGridConfigModel.FirstBlockID},String.class);
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 按指定xls,sheet顺序返回整个xls结构
+     * 不返回celldata ,只获取信息块
+     *
+     * @param listId
+     * @return
+     */
+    @Override
+    public List<JSONObject> getByGridKey_NOCelldata(String listId) {
+        try{
+            String sql="select id,block_id,\"index\",list_id,status,json_remove(json_data,'$.celldata') AS json_data,\"order\" from "+JfGridConfigModel.TABLENAME+" p where p.list_id=? and p.block_id=? and p.is_delete=0  order by p.\"order\"";
+            List<Map<String, Object>> list= jdbcTemplateDameng.queryForList(sql, new Object[]{listId,JfGridConfigModel.FirstBlockID});
+            List<JSONObject> result=new ArrayList<JSONObject>();
+
+            for (Map<String, Object> map : list) {
+                JSONObject pgd=JSONObject.parseObject(map.get("json_data").toString(),JSONObject.class);
+                for (String key : map.keySet()) {
+                    if("json_data".equals(key)){
+                    }else{
+                        pgd.put(key.toLowerCase(), map.get(key));
+                    }
+                }
+                result.add(pgd);
+            }
+            return result;
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 按指定xls,sheet获取,返回指定的sheet集合
+     *
+     * @param listId
+     * @param index
+     * @return
+     */
+    @Override
+    public List<JSONObject> getBlockAllByGridKey(String listId, String index) {
+        try{
+            String sql="select * from "+JfGridConfigModel.TABLENAME+" p where  p.list_id=? and p.\"index\" =? and p.is_delete=0 order by p.\"order\" asc";
+            List<Map<String, Object>> list= jdbcTemplateDameng.queryForList(sql, new Object[]{listId,index});
+            List<JSONObject> result=new ArrayList<JSONObject>(4);
+            for (Map<String, Object> map : list) {
+                result.add(getDBObjectFromMap(map));
+            }
+            return result;
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取指定xls,sheet,block 的数据
+     *
+     * @param listId
+     * @param index
+     * @param blockId
+     * @return
+     */
+    @Override
+    public JSONObject getCelldataByGridKey(String listId, String index, String blockId) {
+        try{
+            String sql="select \"index\",JSON_EXTRACT(json_data, '$.celldata') AS celldata,JSON_EXTRACT(json_data, '$.column') AS \"column\",JSON_EXTRACT(json_data, '$.row') AS \"row\" from "+JfGridConfigModel.TABLENAME+" p where  p.list_id=? and p.\"index\"=? and p.block_id=? and p.is_delete=0 ORDER BY p.id DESC LIMIT 1 ";
+            Map<String, Object> map= jdbcTemplateDameng.queryForMap(sql, new Object[]{listId,index,blockId});
+            JSONObject db=new JSONObject();
+
+            for (String key : map.keySet()) {
+                if("celldata".equalsIgnoreCase(key)){
+                    JSONArray pgd=JSONArray.parseArray(map.get(key).toString());
+                    db.put(key.toLowerCase(), pgd);
+                }else{
+                    db.put(key.toLowerCase(), map.get(key));
+                }
+            }
+            return db;
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取指定xls、sheet中的config中数据 (存放在第一块中)
+     *
+     * @param listId
+     * @param index
+     * @return
+     */
+    @Override
+    public JSONObject getConfigByGridKey(String listId, String index) {
+        try{
+            String sql="select \"index\",list_id,JSON_EXTRACT(json_data, '$.config') AS config,JSON_EXTRACT(json_data, '$.calcChain') AS calcChain,JSON_EXTRACT(json_data, '$.filter') AS \"filter\" from "+JfGridConfigModel.TABLENAME+" p where p.list_id=? and p.\"index\"=? and p.block_id=? and p.is_delete=0 ";
+            Map<String, Object> map= jdbcTemplateDameng.queryForMap(sql, new Object[]{listId,index,JfGridConfigModel.FirstBlockID});
+            JSONObject db=new JSONObject();
+
+            for (String key : map.keySet()) {
+                if("config".equals(key)|| "calcChain".equals(key)|| "filter".equals(key)){
+                    JSONObject pgd=null;
+                    try{
+                        if(map.get(key)!=null){
+                            pgd=JSONObject.parseObject(map.get(key).toString(),JSONObject.class);
+                        }else{
+                            pgd=JSONObject.parseObject("");
+                        }
+                    }catch (Exception e) {
+                        pgd=JSONObject.parseObject(map.get(key).toString(),JSONObject.class);
+                    }
+                    db.put(key.toLowerCase(), pgd);
+                }else{
+                    db.put(key.toLowerCase(), map.get(key));
+                }
+            }
+            return db;
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 按list_id,index获取,返回指定sheet 当前sheet的全部分块数据(并合并)getMergeByGridKey
+     * 返回是DBObject,而下面这个方法返回仅仅只有celldata
+     *
+     * @param listId
+     * @param index
+     * @param ids
+     * @return
+     */
+    @Override
+    public JSONObject getBlockMergeByGridKey(String listId, String index, List<String> ids) {
+        JSONObject _fblock=new JSONObject();
+        JSONArray _celldata=new JSONArray();
+        //获取全部块
+        List<JSONObject> blocks=getBlockAllByGridKey(listId, index);
+        if(blocks!=null && blocks.size()>0){
+            for(JSONObject _b:blocks){
+                if(ids!=null){
+                    if(_b.containsKey("id")){
+                        ids.add(_b.get("id").toString());
+                    }
+                }
+                if(_b.containsKey("block_id")){
+                    if(JfGridConfigModel.FirstBlockID.equals(_b.get("block_id").toString().trim())){
+                        //信息块
+                        _fblock=_b;
+                    }else{
+                        //数据块
+                        JSONObject db= JfGridFileUtil.getJSONObjectByIndex(_b, "json_data");
+                        JSONArray _blockCellData=JfGridFileUtil.getSheetByIndex(db);
+                        if(_blockCellData!=null){
+                            _celldata.addAll(_blockCellData);
+                        }
+                    }
+                }
+            }
+        }
+        _fblock.put("celldata",_celldata);
+        return _fblock;
+    }
+
+    /**
+     * 按list_id获取(id,index),返回sheet集合
+     *
+     * @param listId
+     * @param flag 是否仅仅获取主要模块
+     * @return
+     */
+    @Override
+    public List<JSONObject> getBlocksByGridKey(String listId, boolean flag) {
+        try{
+            List<Object> _param=new ArrayList<>(2);
+            String sql="select id,\"index\" from "+JfGridConfigModel.TABLENAME+" p where  p.list_id=? ";
+            _param.add(listId);
+            if(flag){
+                sql=sql+" and block_id=? ";
+                _param.add(JfGridConfigModel.FirstBlockID);
+            }
+            sql=sql+" and p.is_delete=0 ";
+
+            List<Map<String, Object>> list= jdbcTemplateDameng.queryForList(sql, Arrays.asList(_param));
+            List<JSONObject> result=new ArrayList<JSONObject>();
+            for (Map<String, Object> map : list) {
+                result.add(getDBObjectFromMap(map));
+            }
+            return result;
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取指定xls,多个sheet的全部分块
+     *
+     * @param listId
+     * @param indexs
+     * @return
+     */
+    @Override
+    public List<JSONObject> getAllIndexsByGridKey(String listId, List<String> indexs) {
+        try{
+            StringBuffer sql=new StringBuffer();
+            sql.append("select * from "+JfGridConfigModel.TABLENAME+" p where  p.list_id=? and p.\"index\" in (");
+            String mockInStatement="";
+            int i=0;
+            for (String type: indexs){
+                if (i < indexs.size()-1){
+                    mockInStatement = mockInStatement + "'"+type + "',";
+                }
+                else {
+                    mockInStatement = mockInStatement + "'"+type+"'";
+                }
+                i++;
+            }
+            sql.append(mockInStatement);
+            sql.append(") and p.is_delete=0 order by p.\"order\" asc");
+            List<Map<String, Object>> list= jdbcTemplateDameng.queryForList(sql.toString(), new Object[]{listId});
+            List<JSONObject> result=new ArrayList<JSONObject>();
+            for (Map<String, Object> map : list) {
+                result.add(getDBObjectFromMap(map));
+            }
+            return result;
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取指定xls,sheet全部内容
+     *
+     * @param listId
+     * @param index
+     * @return
+     */
+    @Override
+    public List<JSONObject> getIndexsByGridKey(String listId, String index) {
+        try{
+            StringBuffer sql=new StringBuffer();
+            sql.append("select * from "+JfGridConfigModel.TABLENAME+" p where  p.list_id=? and p.\"index\" =? and p.is_delete=0 order by p.id asc ");
+            List<Map<String, Object>> list= jdbcTemplateDameng.queryForList(sql.toString(), new Object[]{listId,index});
+            List<JSONObject> result=new ArrayList<JSONObject>();
+            for (Map<String, Object> map : list) {
+                result.add(getDBObjectFromMap(map));
+            }
+            return result;
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取图表数据(第一块)
+     *
+     * @param listId
+     * @param index
+     * @return
+     */
+    @Override
+    public JSONObject getChartByGridKey(String listId, String index) {
+        //默认获取第一块
+        try{
+            String sql="select index,list_id,json_data->>'chart' AS chart,block_id from "+JfGridConfigModel.TABLENAME+" p where p.list_id=? and p.\"index\"=? and p.block_id=? and p.is_delete=0 ";
+            Map<String, Object> map= jdbcTemplateDameng.queryForMap(sql, new Object[]{listId,index,JfGridConfigModel.FirstBlockID});
+            JSONObject db=new JSONObject();
+
+            for (String key : map.keySet()) {
+                if("chart".equals(key)){
+                    if(map.get(key)!=null){
+                        JSONArray pgd=JSONArray.parseArray(map.get(key).toString());
+                        db.put(key.toLowerCase(), pgd);
+                    }else{
+                        db.put(key.toLowerCase(), null);
+                    }
+
+                }else{
+                    db.put(key.toLowerCase(), map.get(key));
+                }
+            }
+            return db;
+        }catch (Exception e){
+            log.error("sql执行异常:{}", e);
+            return null;
+        }
+    }
+
+
+
+    private JSONObject getDBObjectFromMap(Map<String, Object> map){
+        JSONObject db=new JSONObject();
+
+        for (String key : map.keySet()) {
+            try{
+                if("json_data".equals(key)){
+                    JSONObject pgd=null;
+                    try{
+                        pgd=JSONObject.parseObject(map.get(key).toString(),JSONObject.class);
+                    }catch (Exception e) {
+                        pgd=JSONObject.parseObject(map.get(key).toString(),JSONObject.class);
+                    }
+                    db.put(key.toLowerCase(), pgd);
+                }else{
+                    db.put(key.toLowerCase(), map.get(key));
+                }
+            }catch (Exception e) {
+                log.error(e.toString());
+                continue;
+            }
+        }
+        return db;
+    }
+}

+ 50 - 0
business-db/pom.xml

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>quality-inspection</artifactId>
+        <groupId>com.rongwei</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>business-db</artifactId>
+    <packaging>jar</packaging>
+    <name>business-db</name>
+    <description>数据库接口</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+            <version>2.4.1</version>
+        </dependency>
+
+        <!-- 工具包 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.8.1</version>
+        </dependency>
+        <!--自动生成set get方法-->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>false</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.70</version>
+        </dependency>
+    </dependencies>
+
+
+</project>

+ 223 - 0
business-db/src/main/java/com/rongwei/luckysheet/JfGridConfigModel.java

@@ -0,0 +1,223 @@
+package com.rongwei.luckysheet;
+
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+public class JfGridConfigModel {
+
+    /**
+     * 表名
+     */
+    public static final String TABLENAME="luckysheet";
+
+    /**
+     * 每一块的行、列范围
+     */
+    public static Integer row_size;
+    public static Integer col_size;
+    /**
+     * 第一块只保存二维数据以外的东西,其他“列号_行号”
+     */
+    public static final String FirstBlockID="fblock";
+
+
+    /**
+     * 默认第一块的编号
+     */
+    private static String FirstBlockId="";
+
+    static {
+        try {
+            //获取默认第一块的编号
+            FirstBlockId= JfGridConfigModel.FirstBlockID;
+        } catch (Exception e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    /**
+     * 返回设置的块范围
+     * @return
+     */
+    public static String getRowCol(){
+        return row_size+"_"+col_size;
+    }
+    private static Integer getRow(String rowCol){
+        if(StringUtils.isBlank(rowCol)){
+            return row_size;
+        }
+        try{
+            return Integer.parseInt(rowCol.split("_")[0]);
+        }catch (Exception ex){
+            return row_size;
+        }
+    }
+    private static Integer getCol(String rowCol){
+        if(StringUtils.isBlank(rowCol)){
+            return col_size;
+        }
+        try{
+            return Integer.parseInt(rowCol.split("_")[1]);
+        }catch (Exception ex){
+            return col_size;
+        }
+    }
+
+
+
+    /**
+     * 获取块的范围
+     * @param r 当前行
+     * @param c 当前列
+     * @param rowSize 行范围
+     * @param colSize 列范围
+     * @return
+     */
+    public static String getRange(Integer r,Integer c,Integer rowSize,Integer colSize){
+        String _r=r/rowSize+"";
+        String _c=c/colSize+"";
+        String _result=_r+"_"+_c;
+        return _result;
+    }
+    public static String getRange(Integer r,Integer c,String rowCol){
+        return getRange(r,c,getRow(rowCol),getCol(rowCol));
+    }
+
+    /**
+     * 获取块的范围
+     * @param bson
+     * @param rowSize
+     * @param colSize
+     * @return
+     */
+    private static String getRange(JSONObject bson, Integer rowSize, Integer colSize){
+        if(bson.containsKey("r") && bson.containsKey("c")){
+            try{
+                //单元格的行号
+                Integer _r=Integer.parseInt(bson.get("r").toString());
+                //单元格的列号
+                Integer _c=Integer.parseInt(bson.get("c").toString());
+                return getRange(_r,_c,rowSize,colSize);
+            }catch (Exception ex){
+                log.error(ex.toString());
+                return null;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 单个sheet数据拆分成多个(使用默认块大小)
+     * @param sheet 一个sheet
+     */
+    public static List<JSONObject> toDataSplit(String rowCol, JSONObject sheet) {
+        return toDataSplit(getRow(rowCol),getCol(rowCol),sheet);
+    }
+
+    public static Integer getSheetCount(List<JSONObject> dbObject){
+        int i=0;
+        if(dbObject!=null && dbObject.size()>0){
+            for(JSONObject b:dbObject){
+                if(b.containsKey("block_id") && FirstBlockID.equals(b.get("block_id"))){
+                    i++;
+                }
+            }
+        }
+        return i;
+    }
+
+    /**
+     * 单个sheet数据拆分成多个
+     * @param rowSize 行数量
+     * @param colSize 列数量
+     * @param sheet 一个sheet
+     */
+    private static List<JSONObject> toDataSplit(Integer rowSize,Integer colSize,JSONObject sheet){
+        List<JSONObject> list=new ArrayList<JSONObject>();
+        if(sheet!=null && sheet.containsKey("celldata")){
+            //单元格数据
+            List<JSONObject> celldata=(List<JSONObject>)sheet.get("celldata");
+            //相同的索引
+            Object index=sheet.get("index");
+            //序号
+            Object list_id=null;
+            if(sheet.containsKey("list_id")){
+                list_id=sheet.get("list_id");
+            }
+            //Object order=sheet.get("order");//相同的位置
+
+            //k 行号+列号 v 位置_datas下标
+            Map<String,Integer> pos=new HashMap<String, Integer>();
+            //分组的数据
+            List<List<JSONObject>> datas=new ArrayList<List<JSONObject>>();
+
+            if(celldata!=null && celldata.size()>0){
+                for(JSONObject bson:celldata){
+                    //获取到位置
+                    String _pos=getRange(bson,rowSize,colSize);
+                    if(_pos!=null){
+                        //获取到数据集合
+                        List<JSONObject> _data=null;
+                        if(pos.containsKey(_pos)){
+                            //获取对应集合
+                            _data=datas.get(pos.get(_pos));
+                        }else{
+                            _data=new ArrayList<JSONObject>();
+                            //保存位置信息
+                            pos.put(_pos,datas.size());
+                            //添加集合
+                            datas.add(_data);
+                        }
+                        //添加新数据
+                        _data.add(bson);
+                    }
+                }
+            }
+
+            //替换原始的数据
+            //if(pos.containsKey(FirstBlockID)){
+            //    sheet.put("celldata",datas.get(pos.get(FirstBlockID)));
+            //}
+            if(sheet.containsKey("_id")){
+                sheet.remove("_id");
+            }
+            sheet.put("celldata",new ArrayList());
+            list.add(sheet);
+
+            for(String _pos:pos.keySet()){
+                //if(_pos.equals(FirstBlockID)){
+                //    continue;
+                //}
+                //获取对应集合
+                List<JSONObject> _data=datas.get(pos.get(_pos));
+                JSONObject _sheet=new JSONObject();
+                _sheet.put("block_id",_pos);
+                _sheet.put("celldata",_data);
+                _sheet.put("index",index);
+                if(list_id!=null){
+                    _sheet.put("list_id",list_id);
+                }
+                list.add(_sheet);
+                //_sheet.put("order",order);
+            }
+
+        }else{
+            list.add(sheet);
+        }
+        return  list;
+
+    }
+
+
+}

+ 32 - 0
business-db/src/main/java/com/rongwei/luckysheet/db/IRecordDataInsertHandle.java

@@ -0,0 +1,32 @@
+package com.rongwei.luckysheet.db;
+
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.luckysheet.entity.GridRecordDataModel;
+
+import java.util.List;
+
+/**
+ * 插入数据
+ * @author Administrator
+ */
+public interface IRecordDataInsertHandle {
+    /**
+     * 新增Sheet页,并返回刚刚插入的_id
+     * @param pgModel
+     * @return
+     */
+    String insert(GridRecordDataModel pgModel);
+    /**
+     * 批量添加 添加jsonb
+     * @param models
+     * @return
+     */
+    String InsertIntoBatch(List<GridRecordDataModel> models);
+
+    /**
+     * 批量添加 添加jsonb
+     * @param models
+     * @return
+     */
+    String InsertBatchDb(List<JSONObject> models);
+}

+ 153 - 0
business-db/src/main/java/com/rongwei/luckysheet/db/IRecordDataUpdataHandle.java

@@ -0,0 +1,153 @@
+package com.rongwei.luckysheet.db;
+
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.luckysheet.entity.GridRecordDataModel;
+
+import java.util.List;
+
+/**
+ * json数据更新处理
+ * @author Administrator
+ */
+public interface IRecordDataUpdataHandle {
+
+    /**
+     * sheet多块更新(先删除后添加)
+     * 按IDS删除一组,然后新加处理后的
+     * @param blocks
+     * @param ids
+     * @return
+     */
+    Boolean updateMulti2(List<JSONObject> blocks, List<String> ids);
+
+
+    /**
+     * 批量更新
+     * @param models
+     * @return
+     */
+    boolean batchUpdateForNoJsonbData(List<GridRecordDataModel> models);
+
+    /**
+     * 清除指定层级下某条数据
+     * @param query   键值对
+     * @param keyName
+     * @return
+     */
+    boolean rmCellDataValue(JSONObject query, String keyName);
+
+    /**
+     * 更新jsonb中某条文本数据
+     * @param query    键值对
+     * @param keyName
+     * @param position
+     * @param v
+     * @return
+     */
+    boolean updateCellDataListTxtValue(JSONObject query, String keyName, Integer position, Object v);
+
+    /**
+     * 更新jsonb中某条文本数据
+     * @param query    键值对
+     * @param keyName
+     * @param position
+     * @param v
+     * @return
+     */
+    boolean updateCellDataListValue(JSONObject query, String keyName, String position, Object v);
+
+    /**
+     * jsonb数据中元素添加元素
+     * @param query
+     * @param word
+     * @param db
+     * @param position
+     * @return
+     */
+    boolean updateJsonbForElementInsert(JSONObject query, String word, JSONObject db, Integer position);
+
+    /**
+     * 更新
+     * @param query
+     * @param word
+     * @return
+     */
+    boolean rmJsonbDataForEmpty(JSONObject query, String word);
+
+    /**
+     * 更新
+     * @param query
+     * @param word
+     * @return
+     */
+    boolean updateJsonbDataForKeys(JSONObject query, JSONObject word);
+
+    /**
+     * 更新status状态
+     * @param model
+     * @return
+     */
+    boolean updateDataStatus(GridRecordDataModel model);
+
+    /**
+     * 更新sheet隐藏状态
+     * @param model
+     * @param hide
+     * @param index1
+     * @param index2
+     * @return
+     */
+    boolean updateDataMsgHide(GridRecordDataModel model, Integer hide, String index1, String index2);
+
+    /**
+     * 更新sheet隐藏状态
+     * @param model
+     * @param hide
+     * @param index
+     * @return
+     */
+    boolean updateDataMsgNoHide(GridRecordDataModel model, Integer hide, String index);
+
+    /**
+     * 更新jsonb中某条文本数据
+     * @param block_ids
+     * @param models
+     * @return
+     */
+    boolean batchUpdateCellDataValue(List<String> block_ids, List<GridRecordDataModel> models);
+
+    /**
+     * jsonb数据中元素添加元素(集合插入)
+     * @param query
+     * @param word
+     * @param db
+     * @param position
+     * @param words
+     * @return
+     */
+    boolean updateJsonbForInsertNull(JSONObject query, String word, JSONObject db, Integer position, String words);
+
+    /**
+     * jsonb数据中元素添加元素
+     * @param query
+     * @param word
+     * @param db
+     * @param position
+     * @return
+     */
+    boolean updateJsonbForSetNull(JSONObject query, String word, JSONObject db, Integer position);
+
+
+    /**
+     * jsonb数据中元素添加元素(根节点)
+     * @param query
+     * @param word
+     * @param db
+     * @param position
+     * @param words
+     * @return
+     */
+    boolean updateJsonbForSetRootNull(JSONObject query, String word, JSONObject db, Integer position, String words);
+
+
+}

+ 36 - 0
business-db/src/main/java/com/rongwei/luckysheet/db/IRecordDelHandle.java

@@ -0,0 +1,36 @@
+package com.rongwei.luckysheet.db;
+
+import com.rongwei.luckysheet.entity.GridRecordDataModel;
+
+import java.util.List;
+
+/**
+ * 删除
+ * @author Administrator
+ */
+public interface IRecordDelHandle {
+    /**
+     * 删除sheet(非物理删除)
+     * @param model
+     * @return
+     */
+    boolean updateDataForReDel(GridRecordDataModel model);
+
+    /**
+     * 按ID 删除多个文档 (物理删除)
+     * @param ids
+     * @return
+     */
+    String delDocuments(List<String> ids);
+
+    /**
+     * 按list_id 删除记录 (物理删除)
+     * @param listIds
+     * @return
+     */
+    int[] delete(List<String> listIds);
+
+
+
+
+}

+ 114 - 0
business-db/src/main/java/com/rongwei/luckysheet/db/IRecordSelectHandle.java

@@ -0,0 +1,114 @@
+package com.rongwei.luckysheet.db;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.List;
+
+/**
+ * 记录处理
+ * @author Administrator
+ */
+public interface IRecordSelectHandle {
+
+    /**
+     * 查看指定sheet页 查看第一块是否存在(控制块)
+     * @param listId
+     * @param index
+     * @return
+     */
+     Integer getFirstBlockByGridKey(String listId, String index);
+
+    /**
+     * 获取指定的xls激活的sheet页的 返回index(控制块)
+     * @param listId
+     * @return
+     */
+     String getFirstBlockIndexByGridKey(String listId);
+
+    /**
+     * 获取指定的xls,sheet 第一块的行列信息(控制块)
+     * @param listId
+     * @param index
+     * @return
+     */
+     String getFirstBlockRowColByGridKey(String listId,String index);
+
+    /**
+     * 按指定xls,sheet顺序返回整个xls结构
+     * 不返回celldata ,只获取信息块
+     * @param listId
+     * @return
+     */
+     List<JSONObject> getByGridKey_NOCelldata(String listId);
+
+    /**
+     * 按指定xls,sheet获取,返回指定的sheet集合
+     * @param listId
+     * @param index
+     * @return
+     */
+     List<JSONObject> getBlockAllByGridKey(String listId, String index);
+
+    /**
+     * 获取指定xls,sheet,block的数据
+     * @param listId
+     * @param index
+     * @param blockId
+     * @return
+     */
+     JSONObject getCelldataByGridKey(String listId, String index, String blockId);
+
+    /**
+     * 获取指定xls、sheet中的config中数据 (存放在第一块中)
+     * @param listId
+     * @param index
+     * @return
+     */
+     JSONObject getConfigByGridKey(String listId, String index);
+
+    /**
+     * 按list_id获取,返回指定sheet 当前sheet的全部分块数据(并合并)getMergeByGridKey
+     * 返回是DBObject,而下面这个方法返回仅仅只有celldata
+     * @param listId
+     * @param index
+     * @param ids 返回记录存在数据库的ID
+     * @return
+     */
+     JSONObject getBlockMergeByGridKey(String listId, String index, List<String> ids);
+
+    /**
+     * 按list_id获取(id,index),返回sheet集合
+     *
+     * @param listId
+     * @param flag 是否仅仅获取主要模块
+     * @return
+     */
+     List<JSONObject> getBlocksByGridKey(String listId, boolean flag);
+
+    /**
+     *  获取指定xls,多个sheet的全部分块
+     * @param listId
+     * @param indexs
+     * @return
+     */
+     List<JSONObject> getAllIndexsByGridKey(String listId, List<String> indexs);
+
+    /**
+     * 获取指定xls,sheet全部内容
+     * @param listId
+     * @param index
+     * @return
+     */
+     List<JSONObject> getIndexsByGridKey(String listId, String index);
+
+    /**
+     * 获取图表数据(第一块)
+     * @param listId
+     * @param index
+     * @return
+     */
+     JSONObject getChartByGridKey(String listId, String index);
+
+
+
+}

+ 57 - 0
business-db/src/main/java/com/rongwei/luckysheet/entity/GridRecordDataModel.java

@@ -0,0 +1,57 @@
+package com.rongwei.luckysheet.entity;
+
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 存储对象类
+ * @author Administrator
+ */
+@Data
+public class GridRecordDataModel {
+    /**
+     * 记录序列
+     */
+    Long id;
+    /**
+     * 文档ID
+     */
+    String list_id;
+    /**
+     * 本记录的行_列
+     */
+    String row_col;
+    /**
+     * sheet序号
+     */
+    String index;
+    /**
+     * 状态是否当前sheet页
+     */
+    Integer status;
+    /**
+     * 块编号 第一块 fblock
+     */
+    String block_id;
+    /**
+     * json串
+     */
+    JSONObject json_data;
+    /**
+     * 排序位置
+     */
+    Integer order;
+    /**
+     * 是否删除
+     */
+    Integer is_delete;
+
+    /**
+     * sheet页数据 未编号分组
+     */
+    List<JSONObject> dataList;
+
+}

+ 405 - 0
business-db/src/main/java/com/rongwei/luckysheet/util/JfGridFileUtil.java

@@ -0,0 +1,405 @@
+package com.rongwei.luckysheet.util;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @author Administrator
+ */
+@Slf4j
+public class JfGridFileUtil {
+
+    /**
+     * 按工作簿index获取对应集合
+     * @param dbObject
+     * @param index
+     * @return
+     */
+    public static JSONArray getSheetByIndex(JSONObject dbObject, Integer index){
+        JSONArray _resultModel=null;
+        if(dbObject!=null && dbObject instanceof List){
+            List<JSONObject> _list=(List<JSONObject>)dbObject;
+            for(JSONObject _o:_list){
+                if(_o.containsKey("index")){
+                    try{
+                        if(index.equals(_o.get("index").toString())){
+                            if(_o.containsKey("celldata")){
+                                _resultModel=_o.getJSONArray("celldata");
+                            }
+                        }
+                    }catch (Exception ex){
+                        log.error(ex.toString());
+                    }
+                }
+            }
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 从对象中获取数据calldata信息
+     * @param dbObject
+     * @return
+     */
+    public static JSONArray getSheetByIndex(JSONObject dbObject){
+        JSONArray _resultModel=null;
+        if(dbObject!=null){
+            if(dbObject.containsKey("celldata")){
+                _resultModel=dbObject.getJSONArray("celldata");
+            }
+        }
+        if(_resultModel == null) {
+            return new JSONArray();
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 按工作簿数量
+     * @param dbObject
+     * @return
+     */
+    public static Integer getSheetCount(JSONObject dbObject){
+        Integer _resultModel=0;
+        if(dbObject!=null){
+            if(dbObject.containsKey("jfgridfile")){
+                JSONObject _bs=dbObject.getJSONObject("jfgridfile");
+                return getSheetCount(_bs);
+            }else if(dbObject instanceof List){
+                List<JSONObject> _list=(List<JSONObject>)dbObject;
+                if(_list!=null){
+                    _resultModel=_list.size();
+                }
+            }
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 按工作簿index获取对应集合的序号
+     * @param dbObject
+     * @param index
+     * @return
+     */
+    public static Integer getSheetPositionByIndex(JSONObject dbObject,Integer index){
+        Integer _resultModel=null;
+        if(dbObject!=null && dbObject instanceof List){
+            List<JSONObject> _list=(List<JSONObject>)dbObject;
+            //for(DBObject _o:_list){
+            for(int x=0;x<_list.size();x++){
+                JSONObject _o=_list.get(x);
+                if(_o.containsKey("index")){
+                    try{
+                        if(index.equals(_o.get("index").toString())){
+                            _resultModel=x;
+                            break;
+                        }
+                    }catch (Exception ex){
+                        log.error(ex.toString());
+                    }
+                }
+            }
+        }
+        return _resultModel;
+    }
+    public static Integer getSheetPositionByIndex(List<JSONObject> _list,String index){
+        Integer _resultModel=null;
+        if(_list!=null ){
+            for(int x=0;x<_list.size();x++){
+                JSONObject _o=_list.get(x);
+                if(_o.containsKey("index")){
+                    try{
+                        if(index.equals(_o.get("index").toString())){
+                            _resultModel=x;
+                            break;
+                        }
+                    }catch (Exception ex){
+                        log.error(ex.toString());
+                    }
+                }
+            }
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 按index值获取mongodb的key
+     * @param _list
+     * @param index
+     * @return
+     */
+    public static List<String> getSheetKeyByIndex(List<JSONObject> _list,Integer index){
+        List<String> _resultModel=new ArrayList<String>();
+        if(_list!=null ){
+            for(int x=0;x<_list.size();x++){
+                JSONObject _o=_list.get(x);
+                if(_o.containsKey("index")){
+                    try{
+                        if(index.equals(_o.get("index").toString())){
+                            if(_o.containsKey("_id")){
+                                //_resultModel=_o.get("_id").toString();
+                                _resultModel.add(_o.get("_id").toString());
+                            }
+                            //break;
+                        }
+                    }catch (Exception ex){
+                        log.error(ex.toString());
+                    }
+                }
+            }
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 按工作簿index 获取对象每一个工作簿的第一层对象
+     * @param dbObject
+     * @param index
+     * @param k
+     * @return
+     */
+    public static JSONObject getObjectByIndex(JSONObject dbObject,Integer index,String k){
+        JSONObject _resultModel=null;
+        if(dbObject!=null && dbObject instanceof List){
+            List<JSONObject> _list=(List<JSONObject>)dbObject;
+            for(JSONObject _o:_list){
+                if(_o.containsKey("index")){
+                    try{
+                        if(index.equals(_o.get("index").toString())){
+                            if(_o.containsKey(k)){
+                                _resultModel=_o.getJSONObject(k);
+                            }
+                            break;
+                        }
+                    }catch (Exception ex){
+                        log.error(ex.toString());
+                    }
+                }
+            }
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 按工作簿index 获取对象每一个工作簿的第一层对象(传入为单sheet)
+     * @param dbObject
+     * @param k
+     * @return
+     */
+    public static Object getObjectByIndex(JSONObject dbObject,String k){
+        Object _resultModel=null;
+        if(dbObject!=null){
+            if(dbObject.containsKey(k)){
+                _resultModel=dbObject.get(k);
+            }
+        }
+        return _resultModel;
+    }
+    public static JSONObject getJSONObjectByIndex(JSONObject dbObject,String k){
+            JSONObject _resultModel=null;
+        if(dbObject!=null){
+            if(dbObject.containsKey(k)){
+                if(dbObject.get(k) instanceof JSONObject) {
+                    _resultModel=dbObject.getJSONObject(k);
+                } else if(dbObject.get(k) instanceof String) {
+                    _resultModel = dbObject.getJSONObject(k);
+                }
+
+            }
+        }
+        return _resultModel;
+    }
+    public static JSONArray getJSONArrayByIndex(JSONObject dbObject,String k){
+        JSONArray _resultModel=null;
+        if(dbObject!=null){
+            if(dbObject.containsKey(k)&& dbObject.get(k) instanceof JSONArray){
+                _resultModel=dbObject.getJSONArray(k);
+            }
+        }
+        return _resultModel;
+    }
+
+
+    /**
+     * 按工作簿index 获取对象每一个工作簿的第一层对象
+     * @param dbObject
+     * @param index
+     * @param k
+     * @return
+     */
+    public static Integer getIntegerByIndex(JSONObject dbObject,Integer index,String k){
+        Integer _resultModel=null;
+        if(dbObject!=null && dbObject instanceof List){
+            List<JSONObject> _list=(List<JSONObject>)dbObject;
+            for(JSONObject _o:_list){
+                if(_o.containsKey("index")){
+                    try{
+                        if(index.equals(_o.get("index").toString())){
+                            if(_o.containsKey(k)){
+                                _resultModel=(Integer)_o.get(k);
+                            }
+                            break;
+                        }
+                    }catch (Exception ex){
+                        log.error(ex.toString());
+                    }
+                }
+            }
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 按工作簿index 获取对象每一个工作簿的第一层对象(单个工作簿)
+     * @param dbObject
+     * @param k
+     * @return
+     */
+    public static Integer getIntegerByIndex(JSONObject dbObject,String k){
+        Integer _resultModel=null;
+        if(dbObject!=null){
+            if(dbObject.containsKey(k)){
+                _resultModel=(Integer)dbObject.get(k);
+            }
+        }
+        return _resultModel;
+    }
+
+    /**
+     * 从对象中获取一个指定的对象
+     * @param dbObject
+     * @param k
+     * @return
+     */
+    public static JSONObject getObjectByObject(JSONObject dbObject,String k){
+        if(dbObject!=null){
+            if(dbObject.containsKey(k)){
+                return dbObject.getJSONObject(k);
+            }
+        }
+        return null;
+    }
+
+
+
+    /**
+     * /获取测试用二维数组
+     * @param rc
+     * @param len
+     * @return
+     */
+    public static JSONArray getTestData(String rc,int len){
+        int row=0;
+        int column=0;
+        if(rc.equals("r")){
+            //增加行
+            row=len;
+            column=5;
+        }else{
+            //增加列
+            row=5;
+            column=len;
+        }
+        Object[][] strs=new String[row][column];
+        for(int x=0;x<row;x++){
+            for(int x1=0;x1<column;x1++){
+                if(x1==x){
+                    //continue;
+                }
+                strs[x][x1]=x+""+x1;
+            }
+        }
+        System.out.println(JSONArray.toJSONString(strs));
+        List<Object> strs1=JSONObject.parseObject(JSONArray.toJSONString(strs),ArrayList.class);
+
+        JSONArray _db=new JSONArray();
+        _db.addAll(strs1);
+        return _db;
+    }
+
+    /**
+     * 给出查询条件
+     * @param query
+     * @return
+     */
+    public static String getCondition(JSONObject query){
+        return getCondition(query, false);
+    }
+
+    /**
+     * 给出查询条件
+     * @param query
+     * @return
+     */
+    public static String getCondition(JSONObject query, boolean escapeFlag){
+        String condition="";
+        if(query!=null) {
+            Map<String, Object> queryDB = query.getInnerMap();
+            for (String key : queryDB.keySet()) {
+                if(escapeFlag) {
+                    condition = condition + " and t.\"" + key + "\"='" + queryDB.get(key) + "'";
+                    continue;
+                }
+                condition = condition + " and t." + key + "='" + queryDB.get(key) + "'";
+            }
+        }
+        return condition;
+    }
+
+    /**
+     * 给出查询条件
+     * @param query
+     * @return
+     */
+    public static String getCondition(JSONObject query,List arr){
+        return getCondition(query, arr, false);
+    }
+
+    /**
+     * 给出查询条件
+     * @param query
+     * @return
+     */
+    public static String getCondition(JSONObject query,List arr, boolean escapeFlag){
+        String condition="";
+        if(query!=null&&arr!=null) {
+            Map<String,Object> queryDB=query.getInnerMap();
+            for (String key : queryDB.keySet()) {
+                arr.add(queryDB.get(key));
+                if(escapeFlag) {
+                    condition=condition+" and t.\""+key+"\"=? ";
+                    continue;
+                }
+                condition=condition+" and t."+key+"=? ";
+            }
+        }
+        return condition;
+    }
+
+    /**
+     * 从jsonObject中找到第一个key的名字
+     * @param jsonObject
+     * @return
+     */
+    public static String getKeyName(JSONObject jsonObject){
+        try{
+            if(jsonObject!=null&&jsonObject.size()>0) {
+                Map<String, Object> map = jsonObject.getInnerMap();
+                return map.keySet().stream().findFirst().get();
+//                for(String key:map.keySet()){
+//                    return key;
+//                }
+            }
+        }catch (Exception ex){
+            log.error("jsonObject:{};{}",jsonObject.toString(SerializerFeature.WriteMapNullValue),ex.toString());
+        }
+        return "";
+    }
+}

+ 87 - 0
business-db/src/main/java/com/rongwei/luckysheet/util/SnowFlake.java

@@ -0,0 +1,87 @@
+package com.rongwei.luckysheet.util;
+
+/**
+ * 雪花算法
+ * @author Administrator
+ */
+public class SnowFlake {
+    // 起始的时间戳
+    private final static long START_STMP = 1577808000000L; //2020-01-01
+    // 每一部分占用的位数,就三个
+    private final static long SEQUENCE_BIT = 12; //序列号占用的位数
+    private final static long MACHINE_BIT = 5; //机器标识占用的位数
+    private final static long DATACENTER_BIT = 5; //数据中心占用的位数
+    // 每一部分最大值
+    private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
+    private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
+    private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
+    // 每一部分向左的位移
+    private final static long MACHINE_LEFT = SEQUENCE_BIT;
+    private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
+    private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
+    private long datacenterId; //数据中心
+    private long machineId; //机器标识
+    private long sequence = 0L; //序列号
+    private long lastStmp = -1L; //上一次时间戳
+    //1323969484872069121
+    //1323969557093789698
+    public SnowFlake(long datacenterId, long machineId) {
+        if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
+            throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
+        }
+        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
+            throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
+        }
+        this.datacenterId = datacenterId;
+        this.machineId = machineId;
+    }
+
+    //产生下一个ID
+    public synchronized Number nextId() {
+        long currStmp = timeGen();
+        if (currStmp < lastStmp) {
+            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
+        }
+
+        if (currStmp == lastStmp) {
+            //if条件里表示当前调用和上一次调用落在了相同毫秒内,只能通过第三部分,序列号自增来判断为唯一,所以+1.
+            sequence = (sequence + 1) & MAX_SEQUENCE;
+            //同一毫秒的序列数已经达到最大,只能等待下一个毫秒
+            if (sequence == 0L) {
+                currStmp = getNextMill();
+            }
+        } else {
+            //不同毫秒内,序列号置为0
+            //执行到这个分支的前提是currTimestamp > lastTimestamp,说明本次调用跟上次调用对比,已经不再同一个毫秒内了,这个时候序号可以重新回置0了。
+            sequence = 0L;
+        }
+
+        lastStmp = currStmp;
+        //就是用相对毫秒数、机器ID和自增序号拼接
+        return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
+                | datacenterId << DATACENTER_LEFT       //数据中心部分
+                | machineId << MACHINE_LEFT             //机器标识部分
+                | sequence;                             //序列号部分
+    }
+
+    private long getNextMill() {
+        long mill = timeGen();
+        while (mill <= lastStmp) {
+            mill = timeGen();
+        }
+        return mill;
+    }
+
+    private long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+//    public static void main(String[] args){
+//        SnowFlake n1=new SnowFlake(0,Math.abs("127.0.0.1".hashCode())%32);
+//        SnowFlake n2=new SnowFlake(0,Math.abs("127.0.0.1".hashCode())%32);
+//
+//        System.out.println(n2.nextId());
+//        System.out.println(n1.nextId());
+//        System.out.println(n1.nextId()+"===="+n2.nextId());
+//    }
+}

+ 46 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/LuckysheetDo.java

@@ -0,0 +1,46 @@
+package com.rongwei.bsentity.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.rongwei.rwcommon.base.BaseDo;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.sql.Clob;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wm
+ * @since 2024-07-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+@TableName("luckysheet")
+public class LuckysheetDo extends BaseDo {
+
+    private static final long serialVersionUID=1L;
+
+    private Long id;
+    @TableField("block_id")
+    private String blockId;
+    @TableField("row_col")
+    private String rowCol;
+    @TableField("\"index\"")
+    private String index;
+    @TableField("list_id")
+    private String listId;
+    @TableField("\"status\"")
+    private Integer status;
+    @TableField("json_data")
+    private String jsonData;
+    @TableField("\"order\"")
+    private Integer order;
+    @TableField("is_delete")
+    private Integer isDelete;
+
+
+}

+ 19 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/BaseModel.java

@@ -0,0 +1,19 @@
+package com.rongwei.bsentity.domain.luckysheet;
+
+
+/**
+ * @author Administrator
+ */
+public interface BaseModel {
+    //错误提示
+    String errorNotBlank="不能为空";
+    String errorNotSet="未设置";
+    String errorNotChose="未选择";
+
+//    public void del(){
+//        errorNotBlank=null;
+//        errorNotSet=null;
+//        errorNotChose=null;
+//    }
+
+}

+ 41 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/BaseOperationModel.java

@@ -0,0 +1,41 @@
+package com.rongwei.bsentity.domain.luckysheet;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: 1
+ * Date: 17-12-12
+ * Time: 下午3:43
+ * To change this template use File | Settings | File Templates.
+ * @author Administrator
+ */
+@Data
+public class BaseOperationModel implements BaseModel,Serializable {
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+    /**
+     * 创建时间
+     */
+	private Date create_time;
+    /**
+     * 修改时间
+     */
+    private Date update_time;
+    /**
+     * 创建人id
+     */
+    private Long create_user_id;
+    /**
+     * 修改人id
+     */
+    private Long update_user_id;
+
+
+}

+ 102 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/ConfigMergeModel.java

@@ -0,0 +1,102 @@
+package com.rongwei.bsentity.domain.luckysheet;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * config 中 merge 对象
+ * @author Administrator
+ */
+@Slf4j
+@Data
+public class ConfigMergeModel {
+    /**
+     * 行
+     */
+    private int r;
+    /**
+     * 列
+     */
+    private int c;
+    /**
+     * 行数
+     */
+    private int rs;
+    /**
+     * 列数
+     */
+    private int cs;
+
+    /**
+     * 最大行
+     */
+    private int maxr;
+    /**
+     * 最大列
+     */
+    private int maxc;
+
+    /**
+     * 将config的merge对象转换为对象
+     * @param mc
+     * @return
+     */
+    public static List<ConfigMergeModel>getListByDBObject(JSONObject mc){
+        List<ConfigMergeModel> _list=new ArrayList<ConfigMergeModel>();
+        if(mc!=null){
+            for(String k:mc.keySet()){
+                try{
+                    ConfigMergeModel c=getByDBObject(mc.getJSONObject(k));
+                    if(c!=null){
+                        _list.add(c);
+                    }
+                }catch (Exception ex){
+
+                }
+            }
+        }
+        return _list;
+    }
+    private static ConfigMergeModel getByDBObject(JSONObject mc){
+        if(mc!=null){
+            if(mc.containsKey("r") && mc.containsKey("c") && mc.containsKey("rs") && mc.containsKey("cs")){
+               try{
+                   ConfigMergeModel c=new ConfigMergeModel();
+                   c.r=Integer.parseInt(mc.get("r").toString());
+                   c.c=Integer.parseInt(mc.get("c").toString());
+                   c.rs=Integer.parseInt(mc.get("rs").toString());
+                   c.cs=Integer.parseInt(mc.get("cs").toString());
+
+                   //   { "2_1" : { "rs" : 5 , "cs" : 2 , "r" : 2 , "c" : 1}}
+                   //   1~2   c=1  cs=2
+                   //   2~6   r=2  rs=5
+                   c.maxc=c.c+c.cs-1;
+                   c.maxr=c.r+c.rs-1;
+
+                   return c;
+               }catch (Exception ex){
+                   return null;
+               }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 是否在范围内
+     * @param r
+     * @param c
+     * @return
+     */
+    public boolean isRange(int r,int c){
+        if(r>=this.r && r<=this.maxr && c>=this.c && c<=this.maxc){
+            return true;
+        }
+        return false;
+    }
+
+}

+ 28 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/LuckySheetGridModel.java

@@ -0,0 +1,28 @@
+package com.rongwei.bsentity.domain.luckysheet;
+
+
+import lombok.Data;
+
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: 1
+ * Date: 17-12-15
+ * Time: 上午11:34
+ * To change this template use File | Settings | File Templates.
+ * @author cr
+ */
+@Data
+public class LuckySheetGridModel implements BaseModel {
+    private String list_id;
+
+    /**
+     * 表格名称
+     */
+    private String grid_name;
+    /**
+     *  '缩略图'
+     */
+    private byte[] grid_thumb;
+
+}

+ 42 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/enummodel/DisabledTypeEnum.java

@@ -0,0 +1,42 @@
+package com.rongwei.bsentity.domain.luckysheet.enummodel;
+
+/**
+ * @author zhouhang
+ * @description 禁用状态
+ * @date 2021/2/1
+ */
+public enum DisabledTypeEnum {
+
+    /**
+     * 启用
+     */
+    ENABLE(0, "启用"),
+    /**
+     * 禁用
+     */
+    DISABLE(1, "禁用"),
+    ;
+
+    DisabledTypeEnum(Integer index, String name) {
+        this.index = index;
+        this.name = name;
+    }
+
+    /**
+     * index
+     */
+    private final Integer index;
+
+    /**
+     * 名称
+     */
+    private final String name;
+
+    public Integer getIndex() {
+        return index;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

+ 73 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/enummodel/ExcelCenterStyleEnum.java

@@ -0,0 +1,73 @@
+package com.rongwei.bsentity.domain.luckysheet.enummodel;
+
+/**
+ * @author zhouhang
+ * @description EXCEL居中方式
+ * @date 2021/4/26
+ */
+public enum ExcelCenterStyleEnum {
+    /**
+     * 左对齐
+     */
+    LEFT((short) 1, 1, "左对齐"),
+    /**
+     * 右对齐
+     */
+    RIGHT((short) 3, 2, "右对齐"),
+    /**
+     * 居中
+     */
+    CENTER((short) 2, 0, "居中"),
+    ;
+
+    /**
+     * excel居中code
+     */
+    private final short excelCode;
+
+    /**
+     * 在线文档居中code
+     */
+    private final Integer onlineExcelCode;
+
+    /**
+     * 名称
+     */
+    private final String name;
+
+
+    public Integer getOnlineExcelCode() {
+        return onlineExcelCode;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public short getExcelCode() {
+        return excelCode;
+    }
+
+    ExcelCenterStyleEnum(short excelCode, Integer onlineExcelCode, String name) {
+        this.excelCode = excelCode;
+        this.onlineExcelCode = onlineExcelCode;
+        this.name = name;
+    }
+
+    /**
+     * @param code excel居中样式code
+     * @return Enum_ExcelCenterStyle
+     * @description 根据excel居中样式获取在线文档居中样式
+     * @author zhouhang
+     * @date 2021/4/26
+     */
+    public static ExcelCenterStyleEnum getExcelCenterStyleByExcelCenterCode(short code) {
+        for (ExcelCenterStyleEnum value : ExcelCenterStyleEnum.values()) {
+            if (code == value.getExcelCode()) {
+                return value;
+            }
+        }
+        return CENTER;
+    }
+
+}

+ 17 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/enummodel/OperationTypeEnum.java

@@ -0,0 +1,17 @@
+package com.rongwei.bsentity.domain.luckysheet.enummodel;
+
+
+/**
+ * @author Administrator
+ */
+
+public enum OperationTypeEnum {
+    /**
+     * 读取
+     */
+    Read,
+    /**
+     * 修改
+     */
+    Update;
+}

+ 44 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/luckysheet/enummodel/SheetOperationEnum.java

@@ -0,0 +1,44 @@
+package com.rongwei.bsentity.domain.luckysheet.enummodel;
+
+/**
+ * 各类操作
+ */
+public enum SheetOperationEnum {
+    fc, //3.4.1 函数链接
+    f,//3.6.1 选择筛选条件
+    fsc,//3.6.2	清除筛
+    fsr,//3.6.3	恢复筛选
+
+    thumb, //3.10.2	缩略图    修改数据库
+    na,   //3.10.1	表格名称 修改数据库
+
+    c,     //3.9	图表操作 全部转向rails
+
+    sh,    //3.8.1	隐藏    3.8	sheet属性sh
+    shs,   //3.7.5	激活shs
+    shr,   //3.7.4	位置shr
+    shd,   //3.7.3	删除shd
+    shc,   //3.7.2	复制shc
+    sha,   //3.7.1	新建sha  3.7 sheet操作
+
+    arc,   //3.5.2	增加行或列
+    drc,   //3.5.1 删除行或列
+    all, //3.3 通用保存
+    cg, //3.2   config操作cg
+    v,  //3.1	单元格操作v
+    rv,//批量单元格操作
+    shre,//撤销删除
+	mv;//记录光标位置不保存
+
+
+    public static boolean contains(String _name){
+        SheetOperationEnum[] season = values();
+        for(SheetOperationEnum s:season){
+            if(s.name().equals(_name)){
+                return true;
+            }
+        }
+        return false;
+
+    }
+}

+ 46 - 0
business-entity/src/main/java/com/rongwei/bsentity/dto/luckysheet/AssembleCellParam.java

@@ -0,0 +1,46 @@
+package com.rongwei.bsentity.dto.luckysheet;
+
+import lombok.*;
+
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class AssembleCellParam {
+
+    /**
+     * 起始单元格列
+     */
+    private Integer startColPos;
+
+    /**
+     * 起始单元格行
+     */
+    private Integer startRowPos;
+
+    /**
+     * 列数
+     */
+    private Integer colSize;
+
+    /**
+     * 行数
+     */
+    private Integer rowSize;
+
+    /**
+     * 单元格值
+     */
+    private String value;
+
+    /**
+     * 字体大小
+     */
+    private Integer fontsize;
+
+    /**
+     * 垂直对齐:0 中间、1 上、2下
+     */
+    private Integer verticaltype;
+}

+ 38 - 0
business-entity/src/main/java/com/rongwei/bsentity/dto/luckysheet/SheetConfigResultDto.java

@@ -0,0 +1,38 @@
+package com.rongwei.bsentity.dto.luckysheet;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.*;
+
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class SheetConfigResultDto {
+
+    /**
+     * 合并配置
+     */
+    private JSONObject mergeConfig;
+
+    /**
+     * 边框配置
+     */
+    private JSONArray borderInfoConfig;
+
+    /**
+     * 行高配置
+     */
+    private JSONObject rowlenConfig;
+
+    /**
+     * 下拉框
+     */
+    private JSONObject dataVerification;
+
+    /**
+     * 单元格数据
+     */
+    private JSONArray celldata;
+}

+ 23 - 0
business-entity/src/main/java/com/rongwei/bsentity/dto/project/SheetInfoParam.java

@@ -0,0 +1,23 @@
+package com.rongwei.bsentity.dto.project;
+
+import lombok.*;
+
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class SheetInfoParam {
+
+    /**
+     * sheet页名称
+     */
+    private String sheetName;
+
+    private String index;
+
+    /**
+     * 下标
+     */
+    private Integer order;
+}

+ 19 - 0
business-server/pom.xml

@@ -75,6 +75,25 @@
             <artifactId>druid-spring-boot2-starter</artifactId>
             <version>1.1.10</version>
         </dependency>
+
+        <!-- 数据库接口以及实现 -->
+        <dependency>
+            <groupId>com.rongwei</groupId>
+            <artifactId>business-db</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.rongwei</groupId>
+            <artifactId>business-dameng</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.70</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 184 - 0
business-server/src/main/java/com/rongwei/bsserver/controller/JfGridFileController.java

@@ -0,0 +1,184 @@
+package com.rongwei.bsserver.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.bscommon.sys.db.server.JfGridFileGetService;
+import com.rongwei.bscommon.sys.utils.JsonUtil;
+import com.rongwei.bscommon.sys.utils.Pako_GzipUtils;
+import com.rongwei.bsentity.domain.luckysheet.LuckySheetGridModel;
+import com.rongwei.bsentity.domain.luckysheet.enummodel.OperationTypeEnum;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *  图表格页面调用
+ * @author Administrator
+ */
+@Slf4j
+@RestController
+@Api(description = "luckysheet测试接口")
+@RequestMapping(value = {"/luckysheet"})
+public class JfGridFileController {
+    /*
+        /load       加载默认表格   ()
+        /loadsheet  加载指定表格   ()
+
+        打开表格
+        /tu/api?id=listid
+    */
+
+
+    @Autowired
+    private JfGridFileGetService jfGridFileGetService;
+
+    /**
+     * 默认加载表格 分块
+     * @param request
+     * @param response
+     * @param gridKey
+     * @return
+     */
+    @ApiOperation(value = "默认加载表格",notes = "默认加载表格")
+    @PostMapping("/load")
+    public String load(HttpServletRequest request, HttpServletResponse response, @RequestParam(defaultValue = "") String gridKey) {
+        //告诉浏览器,当前发送的是gzip格式的内容
+        response.setHeader("Content-Encoding", "gzip");
+        response.setContentType("text/html");
+        String resultStr="";
+        if(gridKey.trim().length()!=0){
+            try {
+                gridKey = gridKey.split("_:_")[0];
+                String _checkStr=check(request,gridKey.toString(),null, OperationTypeEnum.Read);
+                if(_checkStr.length()>0){
+                    return null;
+                }
+                List<JSONObject> dbObject=null;
+                dbObject=jfGridFileGetService.getDefaultByGridKey(gridKey);
+                if(dbObject!=null){
+                    delErrorKey(dbObject);
+                    resultStr= JsonUtil.toJson(dbObject);
+                }
+            } catch (Exception e) {
+                log.error(gridKey+e.getMessage());
+            }
+
+
+        }
+        log.info("load");
+        try {
+            byte dest[]= Pako_GzipUtils.compress2(resultStr);
+            OutputStream out=response.getOutputStream();
+            out.write(dest);
+            out.close();
+            out.flush();
+        } catch (Exception e) {
+            log.error("load---ioerror:"+e);
+        }
+        return null;
+    }
+
+    /**
+     * 加载指定表格
+     * @param map
+     * @param request
+     * @param response
+     * @param gridKey
+     * @param index
+     * @return
+     */
+    @ApiOperation(value = "加载指定表格",notes = "加载指定表格")
+    @PostMapping("/loadsheet")
+    public byte[] loadsheet(Map map, HttpServletRequest request, HttpServletResponse response,
+                            @RequestParam(defaultValue = "") String gridKey,
+                            @RequestParam(defaultValue = "") String[] index) {
+        log.info("loadsheet--gridKey:"+gridKey+" index:"+ Arrays.toString(index));
+        ////告诉浏览器,当前发送的是gzip格式的内容
+        response.setHeader("Content-Encoding", "gzip");
+        response.setContentType("text/html");
+        String resultStr="";
+        if(gridKey.trim().length()!=0){
+            try {
+                gridKey = gridKey.split("_:_")[0];
+                String _id=gridKey;
+                String _checkStr=check(request,_id,null,OperationTypeEnum.Read);
+                log.info(_checkStr);
+                if(_checkStr.length()>0){
+                    return null;
+                }
+                LinkedHashMap dbObject=null;
+                dbObject=jfGridFileGetService.getByGridKeys(_id, Arrays.asList(index));
+                log.info("loadsheet--dbObject--");
+                if(dbObject!=null){
+                    resultStr=JsonUtil.toJson(dbObject);
+                }
+            } catch (Exception e) {
+                log.info(gridKey+e.getMessage());
+            }
+        }
+
+        byte dest[]= Pako_GzipUtils.compress2(resultStr);
+        log.info("loadsheet");
+        OutputStream out=null;
+        try {
+            out = response.getOutputStream();
+            out.write(dest);
+            out.close();
+            out.flush();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            log.error("loadsheet---ioerror:"+e);
+        }catch (Exception ex){
+            log.error("loadsheet---error:"+ex);
+        }
+
+        return null;
+    }
+
+    /**
+     * 文档权限的检查
+     * @param request
+     * @param _id
+     * @param curmodel
+     * @param operationTypeEnum
+     * @return
+     */
+    private String check(HttpServletRequest request, String _id, LuckySheetGridModel curmodel, OperationTypeEnum operationTypeEnum){
+        //校验代码
+        return "";
+    }
+
+
+
+    /**
+     * 数据返回时,去掉数组变字符串,引发错误的key
+     * 删除会发生错误的对象
+     */
+    private void delErrorKey(List<JSONObject> dbObject){
+        if(dbObject!=null){
+            for(JSONObject obj :dbObject){
+                delErrorKeyByCheck(obj,"calcChain");
+                delErrorKeyByCheck(obj,"luckysheet_alternateformat_save");
+                delErrorKeyByCheck(obj,"luckysheet_conditionformat_save");
+            }
+        }
+    }
+    private void delErrorKeyByCheck(JSONObject obj, String key){
+        if(obj.containsKey(key) && obj.get(key) instanceof String){
+            obj.remove(key);
+        }
+    }
+}

+ 7 - 2
business-server/src/main/java/com/rongwei/bsserver/controller/ZhcxProjectManageController.java

@@ -1,10 +1,12 @@
 package com.rongwei.bsserver.controller;
 
 
+import com.rongwei.bscommon.sys.service.LuckysheetService;
 import com.rongwei.bscommon.sys.service.ZhcxProjectManageService;
 import com.rongwei.bsentity.domain.ZhcxProjectManageDo;
 import com.rongwei.rwcommon.base.R;
 import com.rongwei.rwcommonentity.commonservers.domain.SysFileItemDo;
+import com.rongwei.rwcommonentity.commonservers.dto.office.SaveOfficeNotifyReq;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -28,6 +30,9 @@ public class ZhcxProjectManageController {
 
     @Autowired
     private ZhcxProjectManageService service;
+
+    @Autowired
+    private LuckysheetService luckysheetService;
     /**
      * 复制新增
      * @param projectManageDo
@@ -36,8 +41,8 @@ public class ZhcxProjectManageController {
     @PostMapping("/genSummaryFiles")
     @ApiOperation("生成汇总文件")
     public R genSummaryFiles(@RequestBody ZhcxProjectManageDo projectManageDo){
-        SysFileItemDo itemDo = service.genSummaryFiles(projectManageDo.getId());
-        return R.ok(itemDo);
+        String files = luckysheetService.genProjectSummaryFiles(projectManageDo.getId());
+        return R.ok(files);
     }
 }
 

+ 48 - 0
business-server/src/main/java/com/rongwei/bsserver/redisserver/RedisMessageListener.java

@@ -0,0 +1,48 @@
+package com.rongwei.bsserver.redisserver;
+
+import com.google.gson.Gson;
+import com.rongwei.bscommon.sys.redisserver.RedisMessageModel;
+import com.rongwei.bscommon.sys.utils.MyStringUtil;
+import com.rongwei.bsserver.websocket.MyWebSocketHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.connection.MessageListener;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.RedisSerializer;
+
+/**
+ * 监听
+ * @author Administrator
+ */
+public class RedisMessageListener implements MessageListener {
+
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    /**
+     * 订阅者收到消息
+     * @param message
+     * @param pattern
+     */
+    @Override
+    public void onMessage(Message message, byte[] pattern) {
+        //JSON.parse(serializerValue.deserialize(message.getBody()).toString())
+        RedisSerializer<?> serializerKey = redisTemplate.getKeySerializer();
+        RedisSerializer<?> serializerValue = redisTemplate.getValueSerializer();
+        Object channel = serializerKey.deserialize(message.getChannel());
+        Object body = serializerValue.deserialize(message.getBody());
+        //System.out.println("主题: " + channel);
+        //System.out.println("消息内容: " + String.valueOf(body));
+        RedisMessageModel bson1=new Gson().fromJson(body.toString(), RedisMessageModel.class);
+        System.out.println("得到Redis推送消息:"+ MyStringUtil.getStringShow(bson1.toString()));
+        MyWebSocketHandler.sendMessageToUserByRedis(bson1);
+    }
+
+    public RedisTemplate<String, String> getRedisTemplate() {
+        return redisTemplate;
+    }
+
+    public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
+        this.redisTemplate = redisTemplate;
+    }
+}

+ 38 - 0
business-server/src/main/java/com/rongwei/bsserver/service/ConfigerService.java

@@ -0,0 +1,38 @@
+package com.rongwei.bsserver.service;
+
+
+import com.rongwei.bscommon.sys.redisserver.RedisMessagePublish;
+import com.rongwei.bsserver.websocket.WebSocketConfig;
+import com.rongwei.luckysheet.JfGridConfigModel;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+@Configuration
+@Service
+public class ConfigerService {
+
+    @Value("${redis.channel}")
+    public void setRedisChannel(String path){
+        RedisMessagePublish.channel=path;
+    }
+    @Value("${row_size}")
+    public void setRowSize(Integer rowSize){
+        JfGridConfigModel.row_size=rowSize;
+    }
+    @Value("${col_size}")
+    public void setColSize(Integer colSize){
+        JfGridConfigModel.col_size=colSize;
+    }
+    @Value("${servertype}")
+    public void setServerType(String servertype){
+        WebSocketConfig.servertype=servertype;
+    }
+
+}

+ 77 - 0
business-server/src/main/java/com/rongwei/bsserver/websocket/IpAndPortUtil.java

@@ -0,0 +1,77 @@
+package com.rongwei.bsserver.websocket;
+
+
+import lombok.extern.slf4j.Slf4j;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.Query;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Set;
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+public class IpAndPortUtil {
+
+    /**
+     * 获取ip地址及端口port
+     * @return
+     * @throws MalformedObjectNameException
+     * @throws NullPointerException
+     * @throws UnknownHostException
+     */
+    public static String getIpAddressAndPort() {
+      try{
+          MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
+          Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
+                  Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
+          String host = InetAddress.getLocalHost().getHostAddress();
+          String port = objectNames.iterator().next().getKeyProperty("port");
+          //String ipadd = "http" + "://" + host + ":" + port;
+          String ipadd = host + ":" + port;
+          //System.out.println(ipadd);
+          return ipadd;
+      }catch (Exception ex){
+    	  log.error("getIpAddressAndPort+EXCEPTION:"+ex);
+          return "";
+      }
+    }
+
+
+    /**
+     * 获得Linux下的WebLogic的IP
+     * @return
+     */
+    public static String getIpWeblogic(){
+        Context ctx=null;
+        String listenAddr=null;
+        String port=null;
+        try {
+            ctx = new InitialContext();
+            MBeanServer tMBeanServer = (MBeanServer) ctx.lookup("java:comp/env/jmx/runtime");
+            ObjectName tObjectName = new ObjectName("com.bea:Name=RuntimeService,Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean");
+            ObjectName serverrt = (ObjectName) tMBeanServer.getAttribute(tObjectName, "ServerRuntime");
+            port = String.valueOf(tMBeanServer.getAttribute(serverrt, "ListenPort"));
+            listenAddr =(String)tMBeanServer.getAttribute(serverrt,"ListenAddress");
+            String[] tempAddr = listenAddr.split("/");
+            if(tempAddr.length == 1){
+                listenAddr = tempAddr[0];
+            } else if(tempAddr[tempAddr.length - 1].trim().length() != 0){
+                listenAddr = tempAddr[tempAddr.length - 1];
+            } else if (tempAddr.length > 2){
+                listenAddr=tempAddr[tempAddr.length-2];
+            }
+        } catch (Exception e) {
+          log.error("getIpWeblogic+EXCEPTION:"+e);
+        }
+        return listenAddr+":"+port;
+
+    }
+}

+ 397 - 0
business-server/src/main/java/com/rongwei/bsserver/websocket/MyWebSocketHandler.java

@@ -0,0 +1,397 @@
+package com.rongwei.bsserver.websocket;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.rongwei.bscommon.sys.db.server.JfGridFileGetService;
+import com.rongwei.bscommon.sys.db.server.JfGridUpdateService;
+import com.rongwei.bscommon.sys.redisserver.GridFileRedisCacheService;
+import com.rongwei.bscommon.sys.redisserver.RedisLock;
+import com.rongwei.bscommon.sys.redisserver.RedisMessageModel;
+import com.rongwei.bscommon.sys.redisserver.RedisMessagePublish;
+import com.rongwei.bscommon.sys.utils.MyStringUtil;
+import com.rongwei.bscommon.sys.utils.MyURLUtil;
+import com.rongwei.bscommon.sys.utils.Pako_GzipUtils;
+import io.netty.util.internal.StringUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.socket.CloseStatus;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketMessage;
+import org.springframework.web.socket.WebSocketSession;
+import org.springframework.web.socket.handler.TextWebSocketHandler;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Socket处理器(包括发送信息,接收信息,信息错误等方法。)
+ *
+ * 代码中rv,rv_end说明
+ * 因为websocket传输大小限制
+ * 批量更新范围单元格的时候
+ * 一次最多1000个单元格
+ * 要求 每次传'rv'  最后一次传他'rv_end'
+ * rv_end就是个信号
+ * 表示这次范围更新数据全部传输完,它自身这次不带数据过去的
+ * @author Administrator
+ */
+@Slf4j
+@Component
+public class MyWebSocketHandler extends TextWebSocketHandler {
+
+    @Autowired
+    private RedisMessagePublish redisMessagePublish;
+    @Autowired
+    private JfGridUpdateService jfGridUpdateService;
+    @Autowired
+    private JfGridFileGetService jfGridFileGetService;
+    @Autowired
+    private RedisTemplate redisTemplate;
+    @Autowired
+    private GridFileRedisCacheService redisService;
+
+    /**
+     * 先注册一个websocket服务器,将连接上的所有用户放进去
+     * 外层key gridKey(文档id),内层key session ID(用户id)
+     */
+    private static final Hashtable<String, Hashtable<String, WSUserModel>> USER_SOCKET_SESSION_MAP;
+    /**
+     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
+     */
+    private static int onlineCount = 0;
+
+    public static String ipAndPort;
+
+    static {
+        USER_SOCKET_SESSION_MAP = new Hashtable<String, Hashtable<String, WSUserModel>>(12);
+    }
+
+    /**
+     * 前台连接并且注册了账户
+     */
+    @Override
+    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
+        session.setTextMessageSizeLimit(2048000);
+        session.setBinaryMessageSizeLimit(2048000);
+        openConn(session);
+    }
+
+    /**
+     * 接受消息
+     * @param session
+     * @param message
+     * @throws Exception
+     */
+    @Override
+    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
+        if (message.getPayloadLength() == 0) {
+            //无消息直接返回
+            return;
+        }
+        //返回消息类型type :0:连接成功,1.发送给发送信息用户,2.发送信息给其他用户,3.发送选区位置信息 999、用户连接断开
+        Map map = new HashMap<>();
+        boolean _b = true;
+        boolean s = true;
+        ObjectMapper obj = new ObjectMapper();
+        WSUserModel wsUserModel = new WSUserModel(session);
+        String content = message.getPayload().toString();
+        if ("rub".equals(content)) {
+            log.info("保持连接状态信息");
+        } else {
+            log.info("消息解压前:" + MyStringUtil.getStringShow(content));
+            String contentReal = Pako_GzipUtils.unCompressToURI(content);
+            log.info("消息解压后:" + MyStringUtil.getStringShow(contentReal));
+            //content=contentReal;
+            JSONObject bson = null;
+            try {
+                bson = JSONObject.parseObject(contentReal);
+            } catch (Exception ex) {
+                log.error("json字符串转换错误str:" + JSONObject.toJSONString(contentReal));
+                return;
+            }
+            String _id = wsUserModel.getGridKey();
+            String gridKey = MyURLUtil.urlDecode(_id);
+            if (bson != null && !StringUtil.isNullOrEmpty(_id)) {
+                if (bson.get("t").equals("mv")) {
+                    //记录光标位置
+                    s = false;
+                    map.put("type", 3);
+                    map.put("username", wsUserModel.getUserName());
+                    map.put("id", "" + wsUserModel.getWs().getId());
+                    jfGridUpdateService.Operation_mv(gridKey, bson);
+                } else if (bson.get("t").equals("rv_end")) {
+                    //当前sheet的index值
+                    String i = bson.get("i").toString();
+                    String key = gridKey + wsUserModel.getWs().getId();
+                    key = key + i;
+                    jfGridUpdateService.updateRvDbContent(gridKey, bson, key);
+                } else if (bson.get("t").equals("rv")) {
+                    String key = gridKey + wsUserModel.getWs().getId();
+                    jfGridUpdateService.getIndexRvForThread(key, bson);
+                } else {
+                    //其它操作
+                    RedisLock redisLock = new RedisLock(redisTemplate, gridKey);
+                    try {
+                        if (redisLock.lock()) {
+                            String _str = "";
+                            _str = jfGridUpdateService.handleUpdate(gridKey, bson);
+
+                            if (_str.length() == 0) {
+
+                            } else {
+                                log.info("handleUpdate--error:{}" ,_str);
+                                _b = false;
+                            }
+                        } else {
+                            log.info("handleUpdate--:redisLock---lock");
+                            _b = false;
+                        }
+                    } catch (Exception e) {
+                        log.error("handleUpdate--:redisLock--error:{}",e);
+                        _b = false;
+                    } finally {
+                        redisLock.unlock();
+                    }
+                }
+
+            } else {
+                _b = false;
+            }
+            Map maps = new HashMap<>();
+            //执行其他操作成功后,可调用消息发送给窗口
+            String returnMessage = "error";
+            if (_b) {
+                //表示发送其他共享编辑者收到更新信息(0:更新)
+                returnMessage = "success";
+                map.put("status", "0");
+                maps.put("status", "0");
+                map.put("returnMessage", returnMessage);
+                map.put("createTime", System.currentTimeMillis());
+
+                //发送消息给本机其他用户
+                if (s) {
+                    map.put("type", 2);
+                }
+                map.put("data", contentReal);
+                String param = obj.writeValueAsString(map);
+                //消息发送到redis
+                redisMessagePublish.publishMessage(new RedisMessageModel(ipAndPort, wsUserModel.getGridKey(), param));
+                sendMessageToUserByCurrent(wsUserModel, param);
+            } else {
+                maps.put("status", "1");
+                maps.put("data", contentReal);
+            }
+            //只给发送此信息的用户发送信息
+            maps.put("returnMessage", returnMessage);
+            maps.put("createTime", System.currentTimeMillis());
+            maps.put("type", 1);
+            String params = obj.writeValueAsString(maps);
+            sendMessageToUser(session, params);
+
+        }
+    }
+
+    /**
+     * 消息传输错误处理,如果出现错误直接断开连接
+     */
+    @Override
+    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
+        log.error("handleTransportError:{};exception:{}" ,session,exception);
+        if (session.isOpen()) {
+            session.close();
+        }
+        closeConn(session, true);
+    }
+
+    /**
+     * 关闭连接后
+     */
+    @Override
+    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
+        closeConn(session, false);
+    }
+
+    private void openConn(WebSocketSession session) {
+        //创建一个连接窗口,并加入的队列中
+        WSUserModel ws = new WSUserModel(session);
+        WSUserModel.webSocketMapAdd(USER_SOCKET_SESSION_MAP, ws);
+        addOnlineCount();           //在线数加1
+        log.info("有新窗口开始监听:" + ws.getId() + ",当前在线人数为" + getOnlineCount());
+        try {
+            Map map = new HashMap<>();
+            map.put("message", "连接成功");
+            map.put("status", "0");
+            map.put("type", "0");
+            ObjectMapper obj = new ObjectMapper();
+            String params = obj.writeValueAsString(map);
+            sendMessageToUser(session, params);
+            //建立type为4的指令将所有加载期间其他人发送的指令进行收集
+
+            String gridkey = ws.getGridKey();
+            String index = jfGridFileGetService.getFirstBlockIndexByGridKey(gridkey);
+            String key = gridkey + index;
+            Boolean flag = redisService.rgetFlagContent(key);
+            //判断是否又存在sheet信息被重新加载
+            if (flag) {
+                List<String> arr = redisService.rgetHandlerContent(key);
+                //如未收集到任何指令,不发送type为4信息
+                if (arr == null) {
+                    redisService.raddFlagContent(key, false);
+                    return;
+                }
+                String data = "";
+                for (String str : arr) {
+                    data = data + "&*&" + str;
+                }
+                Map map1 = new HashMap<>();
+                map1.put("message", "反馈以前操作信息");
+                map1.put("status", "0");
+                map1.put("type", "4");
+                map1.put("data", data);
+                String param = obj.writeValueAsString(map1);
+                redisService.raddFlagContent(key, false);
+                sendMessageToUser(session, param);
+            }
+
+        } catch (Exception e) {
+            log.error("openConn--Exception:" + e);
+        }
+    }
+
+    private void closeConn(WebSocketSession session, boolean isError) {
+        WSUserModel wsUserModel = new WSUserModel(session);
+        WSUserModel.webSocketMapRemove(USER_SOCKET_SESSION_MAP, wsUserModel);
+
+        if (isError) {
+            log.info("窗口关闭(Error):{},当前在线人数为{}" ,wsUserModel.getId() ,getOnlineCount());
+        } else {
+            subOnlineCount();              //在线数减1
+            log.info("窗口关闭:{},当前在线人数为:{}",wsUserModel.getId(),getOnlineCount());
+            try{
+                Map map = new HashMap<>(2);
+                map.put("message", "用户退出");
+                map.put("type", 999);
+                map.put("username", wsUserModel.getUserName());
+                map.put("id", "" + wsUserModel.getWs().getId());
+                String param =new ObjectMapper().writeValueAsString(map);
+                //消息发送到redis
+                redisMessagePublish.publishMessage(new RedisMessageModel(ipAndPort, wsUserModel.getGridKey(), param));
+                sendMessageToUserByCurrent(wsUserModel, param);
+            }catch (Exception ex){
+                log.error("用户下线群发失败:{}",ex);
+            }
+        }
+
+    }
+
+    @Override
+    public boolean supportsPartialMessages() {
+        return false;
+    }
+
+
+    /**
+     * 群发消息(本节点,其他窗口)
+     *
+     * @param _wsUserModel 消息提供者
+     * @param _content     内容
+     */
+    public void sendMessageToUserByCurrent(WSUserModel _wsUserModel, String _content) {
+        if (USER_SOCKET_SESSION_MAP != null && _wsUserModel != null && _content != null) {
+            if (USER_SOCKET_SESSION_MAP.containsKey(_wsUserModel.getGridKey())) {
+                //必须是同一个文档
+                Hashtable<String, WSUserModel> _userMap = USER_SOCKET_SESSION_MAP.get(_wsUserModel.getGridKey());
+                sendMessageToUser(_userMap, _content, _wsUserModel.getWs().getId());
+            }
+        }
+    }
+
+
+    /**
+     * 群发消息(redis消息订阅)
+     **/
+    public static void sendMessageToUserByRedis(RedisMessageModel model) {
+        sendMessageToUserByRedis(model.getIpandport(), model.getGridkey(), model.getContent());
+    }
+
+    /**
+     * 群发消息(redis消息订阅)
+     *
+     * @param _ipAndPort 提供数据的节点
+     * @param _gridkey   文档id
+     * @param _content   内容
+     */
+    private static void sendMessageToUserByRedis(String _ipAndPort, String _gridkey, String _content) {
+        if (USER_SOCKET_SESSION_MAP != null && _ipAndPort != null && _gridkey != null && _content != null) {
+            if (!_ipAndPort.equals(ipAndPort)) {
+                //不是本机的
+                if (USER_SOCKET_SESSION_MAP.containsKey(_gridkey)) {
+                    //必须是同一个文档
+                    Hashtable<String, WSUserModel> _userMap = USER_SOCKET_SESSION_MAP.get(_gridkey);
+                    sendMessageToUser(_userMap, _content, null);
+                }
+            }
+        }
+    }
+
+    /**
+     * 给同一个文档的全部用户发消息(除了提供消息的用户)
+     *
+     * @param _userMap 用户组
+     * @param _content 内容
+     * @param _uid     数据提供的用户sessionid(redis订阅设定为null)
+     */
+    private static void sendMessageToUser(Hashtable<String, WSUserModel> _userMap, String _content, String _uid) {
+        if (_userMap != null && _content != null) {
+            TextMessage message = new TextMessage(_content);
+            //BinaryMessage message= new BinaryMessage(_content.getBytes());
+            _userMap.forEach((k, v) -> {
+                if (null == _uid || !k.equals(_uid)) {
+                    //给(非消息提供者)打开改文档的用户发消息
+                    sendMessageToUser(v.getWs(), message);
+                }
+            });
+        }
+    }
+
+    /**
+     * 给单个用户发消息
+     *
+     * @param session
+     * @param message
+     */
+    private static void sendMessageToUser(WebSocketSession session, WebSocketMessage message) {
+        try {
+            log.info("sendMessageToUser--WebSocketSession");
+            synchronized (session) {
+                session.sendMessage(message);
+            }
+        } catch (Exception ex) {
+            log.error(ex.toString() + ";WebSocketSession:" + session + "message" + message);
+        }
+    }
+
+    private static void sendMessageToUser(WebSocketSession session, String message) {
+
+        log.info("sendMessageToUser--onlyForUser");
+        sendMessageToUser(session, new TextMessage(message));
+    }
+
+
+    //全局的在线人数
+    public static synchronized int getOnlineCount() {
+        return onlineCount;
+    }
+
+    public static synchronized void addOnlineCount() {
+        onlineCount++;
+    }
+
+    public static synchronized void subOnlineCount() {
+        onlineCount--;
+    }
+}

+ 90 - 0
business-server/src/main/java/com/rongwei/bsserver/websocket/MyWebSocketInterceptor.java

@@ -0,0 +1,90 @@
+package com.rongwei.bsserver.websocket;
+
+import com.rongwei.bscommon.sys.utils.MyURLUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.http.server.ServletServerHttpRequest;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
+
+import javax.servlet.http.HttpSession;
+import java.util.Map;
+
+/**
+ * Socket建立连接(握手)和断开
+ * @author Administrator
+ */
+@Slf4j
+public class MyWebSocketInterceptor extends HttpSessionHandshakeInterceptor {
+
+    @Override
+    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
+                                   Map<String, Object> attributes) throws Exception {
+
+        //解决The extension [x-webkit-deflate-frame] is not supported问题
+//        if (request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {
+//            request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
+//        }
+
+        //websocket系统启动连接程序,启动的时候就会把他的session值传过来,放入到websocketsession(websocket的一个内置服务器)里面
+        ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
+        HttpSession session=servletRequest.getServletRequest().getSession(false);
+        log.info("beforeHandshake--session:{}",session);
+
+        //用户token
+        String token =getParam(servletRequest, WSUserModel.USER_TOKEN);
+        //文档id
+        String gridKey = getParam(servletRequest, WSUserModel.USER_GRIDKEY);
+        if (null!=token && null!=gridKey) {
+        	//验证用户信息
+        	String gridKeys= MyURLUtil.urlDecode(gridKey);
+        	String _checkStr=check(gridKeys);
+            log.info("link gridKey:{};userToken:{};check:{}",gridKeys,token,_checkStr);
+        	if(_checkStr.length()>0){
+        	    return false;
+        	}
+
+            String[] split = gridKeys.split("_:_");
+
+            String[] userInfo = split[1].split("_\\|_");
+            attributes.put(WSUserModel.USER_ID, userInfo[0]);
+            attributes.put(WSUserModel.USER_NAME, userInfo[1]);
+
+            attributes.put(WSUserModel.USER_TOKEN, token);
+            attributes.put(WSUserModel.USER_GRIDKEY, split[0]);
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+
+    @Override
+    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
+                               Exception exception) {
+    	log.info("exception:{}",exception);
+    }
+
+
+    private String getParam(ServletServerHttpRequest servletRequest, String key){
+        String value=servletRequest.getServletRequest().getParameter(key);
+        if(value!=null){
+            value=value.trim();
+            if(value.length()>0){
+                return  value;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * /修改、读取ajax 如果_ObjectId为空,使用id
+     * @param _id
+     * @return
+     */
+    private String check(String _id){
+        //此处校验代码
+        return "";
+    }
+}

+ 97 - 0
business-server/src/main/java/com/rongwei/bsserver/websocket/WSUserModel.java

@@ -0,0 +1,97 @@
+package com.rongwei.bsserver.websocket;
+
+import lombok.Data;
+import org.springframework.web.socket.WebSocketSession;
+
+import java.util.Hashtable;
+
+/**
+ * @author Administrator
+ */
+@Data
+public class WSUserModel {
+
+    /**
+     * 用户key
+     */
+    public static final String USER_TOKEN="t";
+    /**
+     * 文档key
+     */
+    public static final String USER_GRIDKEY="g";
+
+    /**
+     * 用户id key
+     */
+    public static final String USER_ID = "u_i";
+
+    /**
+     * 用户名称key
+     */
+    public static final String USER_NAME = "u_n";
+
+    /**
+     * ws-session
+     */
+    private WebSocketSession ws;
+    /**
+     * session id
+     */
+    private String id;
+    /**
+     * 接收token
+     */
+    private String token;
+    /**
+     * 文档id
+     */
+    private String gridKey;
+    /**
+     * 连接的用户名
+     */
+    private String userName;
+
+    public WSUserModel(WebSocketSession ws){
+        this.id=ws.getId();
+        this.userName=ws.getAttributes().get(USER_NAME).toString();
+        if(ws.getAttributes().get(USER_TOKEN)!=null){
+            this.token=ws.getAttributes().get(USER_TOKEN).toString();
+        }else{
+            this.token="i";
+        }
+        if(ws.getAttributes().get(USER_GRIDKEY)!=null){
+            this.gridKey=ws.getAttributes().get(USER_GRIDKEY).toString();
+        }else{
+            this.gridKey="1";
+        }
+
+        this.ws=ws;
+    }
+
+
+    /**
+     * 外层key gridKey(文档id),内层key session ID(用户id)
+     * @param maps
+     * @param wm
+     */
+    public static void webSocketMapAdd(Hashtable<String,Hashtable<String, WSUserModel>> maps, WSUserModel wm){
+        if(maps.containsKey(wm.getGridKey())){
+            maps.get(wm.getGridKey()).put(wm.getId(),wm);
+        }else{
+            Hashtable<String, WSUserModel> _map=new Hashtable<String, WSUserModel>();
+            _map.put(wm.getId(),wm);
+            maps.put(wm.getGridKey(),_map);
+        }
+    }
+    public static void webSocketMapRemove(Hashtable<String,Hashtable<String, WSUserModel>> maps, WSUserModel wm){
+        if(maps.containsKey(wm.getGridKey())){
+            if(maps.get(wm.getGridKey())!=null){
+                Hashtable<String, WSUserModel> _map=maps.get(wm.getGridKey());
+                if(_map!=null && _map.containsKey(wm.getId())){
+                    _map.remove(wm.getId());
+                }
+            }
+        }
+    }
+
+}

+ 62 - 0
business-server/src/main/java/com/rongwei/bsserver/websocket/WebSocketConfig.java

@@ -0,0 +1,62 @@
+package com.rongwei.bsserver.websocket;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+@Configuration
+@EnableWebSocket
+public class WebSocketConfig implements WebSocketConfigurer {
+
+    public static String servertype;
+
+    @Override
+    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
+        //1.注册WebSocket
+        //设置websocket的地址
+        String websocket_url = "/websocket/luckysheet";
+        //注册Handler
+        registry.addHandler(getMyWebSocketHandler(), websocket_url).
+                //注册Interceptor
+                addInterceptors(getMyWebSocketInterceptor())
+                //配置*代表允许所有的ip进行调用
+                .setAllowedOrigins("*");
+
+        //2.注册SockJS,提供SockJS支持(主要是兼容ie8)
+        //设置sockjs的地址
+        String sockjs_url = "/sockjs/luckysheet";
+        //注册Handler
+        registry.addHandler(getMyWebSocketHandler(), sockjs_url).
+                //注册Interceptor
+                addInterceptors(getMyWebSocketInterceptor())
+                //配置*代表允许所有的ip进行调用
+                .setAllowedOrigins("*").withSockJS();
+
+        //获取系统ip
+        log.info("registerWebSocketHandlers:"+servertype);
+        if(servertype!=null && servertype.equals("weblogic")){
+            MyWebSocketHandler.ipAndPort= IpAndPortUtil.getIpWeblogic();
+        }else{
+            MyWebSocketHandler.ipAndPort= IpAndPortUtil.getIpAddressAndPort();
+        }
+
+    }
+
+    @Bean
+    public MyWebSocketHandler getMyWebSocketHandler(){
+        return new MyWebSocketHandler();
+    }
+
+    @Bean
+    public MyWebSocketInterceptor getMyWebSocketInterceptor(){
+        return new MyWebSocketInterceptor();
+    }
+
+}

+ 3 - 1
pom.xml

@@ -11,6 +11,8 @@
         <module>business-server</module>
         <module>business-common</module>
         <module>business-entity</module>
+        <module>business-db</module>
+        <module>business-dameng</module>
     </modules>
 
     <!--<parent>
@@ -86,7 +88,7 @@
             <dependency>
                 <groupId>com.alibaba</groupId>
                 <artifactId>fastjson</artifactId>
-                <version>1.2.33</version>
+                <version>1.2.70</version>
             </dependency>
             <dependency>
                 <groupId>org.springframework.cloud</groupId>