ソースを参照

修复 分页功能
添加 test模块新增 测测是案例
修复 日志模块空指针出错误
新增 excel导出行列自动合并

18339543638 2 年 前
コミット
2c0e75fe06

+ 7 - 0
tr-dependencies/pom.xml

@@ -343,6 +343,13 @@
                 <version>${revision}</version>
             </dependency>
 
+            <!--表结构自动更新插件-->
+            <dependency>
+                <groupId>cn.tr</groupId>
+                <artifactId>tr-spring-boot-starter-plugin-mp-enhance-actable</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
             <!--打印banner插件-->
             <dependency>
                 <groupId>cn.tr</groupId>

+ 10 - 0
tr-plugins/tr-spring-boot-starter-plugin-biz-excel/src/main/java/cn/tr/plugin/excel/annotation/Excel.java

@@ -36,6 +36,16 @@ public @interface Excel
      */
     public String dateFormat() default "";
 
+    /**
+     * 当后边紧跟的单元格为空时,是否合并
+     */
+    public boolean mergeBlank() default false;
+
+    /**
+     * 当行数据一致时,合并行数据
+     */
+    public boolean mergeRowWhenSame() default false;
+
     /**
      * 字典码
      */

+ 87 - 15
tr-plugins/tr-spring-boot-starter-plugin-biz-excel/src/main/java/cn/tr/plugin/excel/config/ExcelHelper.java

@@ -2,6 +2,7 @@ package cn.tr.plugin.excel.config;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.convert.Convert;
+import cn.hutool.core.lang.Pair;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.StrUtil;
@@ -86,7 +87,7 @@ public class ExcelHelper<T> {
     /**
      * Excel sheet最大行数,默认65536
      */
-    private static final int sheetSize = 200000;
+    private static final int sheetSize = 10000;
 
     private int sheetNo;
     /**
@@ -471,17 +472,17 @@ public class ExcelHelper<T> {
      */
     public void exportExcel(OutputStream outputStream ,String fileName,List<T> list, String sheetName, String title) throws IOException {
         this.init(list, sheetName, title, Type.EXPORT);
-        threadPoolExecutor.submit(()->{
-            sheets.parallelStream().forEach(sheet -> { exportExcel(sheet,sheetDataMap.get(sheet)); });
-            try {
-                wb.write(outputStream);
-                //表格写入成功回调 将相应的下载任务置为成功 todo
-            }catch (Exception e){
-                //表格写入失败通知 将相应的下载任务置为失败并重新进入下载队列 todo
-             }finally {
-                IOUtils.closeQuietly(wb);
-            }
-        });
+//        threadPoolExecutor.submit(()->{
+        sheets.parallelStream().forEach(sheet -> { exportExcel(sheet,sheetDataMap.get(sheet)); });
+        try {
+            wb.write(outputStream);
+            //表格写入成功回调 将相应的下载任务置为成功 todo
+        }catch (Exception e){
+            //表格写入失败通知 将相应的下载任务置为失败并重新进入下载队列 todo
+        }finally {
+            IOUtils.closeQuietly(wb);
+        }
+//        });
     }
 
     /**
@@ -547,6 +548,8 @@ public class ExcelHelper<T> {
         int subMergedLastRowNum = getSheetIntValue(sheet,subMergedLastRowNumMap);
         int subMergedFirstRowNum = getSheetIntValue(sheet,subMergedFirstRowNumMap);
         AtomicInteger rowNo = getSheetValue(sheet,rowNumMap);
+        //上一个单元格的值  {"row",{"col",{"value","startRow"}}}
+        Map<Integer,Map<Integer, Pair<String,Integer>>> cellValueMap=new HashMap<>();
         for (int i = 0; i <  CollectionUtil.size(dataList); i++)
         {
             if(i>1){
@@ -571,6 +574,10 @@ public class ExcelHelper<T> {
                 }
             }
             int column = 0;
+
+            //合并空格的开始列
+            int mergeBlankStartCol=-1;
+            Cell cell=null;
             for (Object[] os : fields) {
                 Field field = (Field) os[0];
                 Excel excel = (Excel) os[1];
@@ -591,7 +598,7 @@ public class ExcelHelper<T> {
                             {
                                 subField.setAccessible(true);
                                 Excel attr = subField.getAnnotation(Excel.class);
-                                this.addCell(sheet,attr, row, (T) obj, subField, column + subIndex);
+                                cell=this.addCell(sheet,attr, row, (T) obj, subField, column + subIndex);
                             }
                             subIndex++;
                         }
@@ -601,12 +608,77 @@ public class ExcelHelper<T> {
                 }
                 else
                 {
-                    this.addCell(sheet,excel, row, vo, field, column++);
+                    cell=this.addCell(sheet,excel, row, vo, field, column++);
+                }
+                String currentValue = cell.getStringCellValue();
+                currentValue=StrUtil.isNullOrUndefined(currentValue)?null:currentValue;
+                //合并空单元格
+                if(excel!=null){
+                    //当列相同时,合并列
+                    boolean mergeRowWhenSame = excel.mergeRowWhenSame();
+                    int rowIndex = cell.getRowIndex();
+                    int colIndex=cell.getColumnIndex();
+                    int startRowIndex=rowIndex;
+                    if(mergeRowWhenSame){
+                        //合并单元格
+                        //上一个单元格的内容
+                        //首个数据不行进行合并单元格计算,仅存储单元格的值
+                        if(i>0||i==CollectionUtil.size(dataList)-1){
+                            Pair<String, Integer> lastCell = cellValueMap.get(rowIndex - 1).get(colIndex);
+                            if(!ObjectUtil.equals(lastCell.getKey(),currentValue)){
+                                CellRangeAddress region  = new CellRangeAddress(lastCell.getValue(), startRowIndex-1, colIndex, colIndex);
+                                sheet.addMergedRegion(region);
+                            }else if(i==CollectionUtil.size(dataList)-1){
+                                CellRangeAddress region  = new CellRangeAddress(lastCell.getValue(), startRowIndex, colIndex, colIndex);
+                                sheet.addMergedRegion(region);
+                            }else {
+                                //内容相同,置换开始行数
+                                startRowIndex=lastCell.getValue();
+                            }
+                        }
+                    }else {
+                        //合并列和合并行不能同时出现
+                        boolean mergeBlank = excel.mergeBlank();
+                        //在同一行合并空格列
+                        if(colIndex>0){
+                            Pair<String, Integer> valuePair = cellValueMap.get(rowIndex).get(colIndex - 1);
+                            if((colIndex==CollectionUtil.size(fields)-1||!isEmptyValue(cell))
+                                    &&mergeBlankStartCol!=-1){
+
+                                if(isEmptyValue(cell)){
+                                    CellRangeAddress region  = new CellRangeAddress(rowIndex, rowIndex, mergeBlankStartCol, colIndex);
+                                    sheet.addMergedRegion(region);
+                                    mergeBlankStartCol=-1;
+                                }
+                                //当前单元格非空时,判断前一个单元格是否为空
+                                //前一个单元格为空
+                                else if(StrUtil.isEmpty(valuePair.getKey())){
+                                    CellRangeAddress region  = new CellRangeAddress(rowIndex, rowIndex, mergeBlankStartCol, colIndex-1);
+                                    sheet.addMergedRegion(region);
+                                    mergeBlankStartCol=-1;
+                                }
+                            }
+                        }
+                        if(mergeBlank){
+                            mergeBlankStartCol=colIndex;
+                        }
+                    }
+
+                    cellValueMap.compute(rowIndex, (k, colMap) -> {
+                        if (colMap == null) {
+                            colMap = new HashMap<>();
+                        }
+                        return colMap;
+                    }).put(colIndex, Pair.of(currentValue, startRowIndex));
                 }
+
+
             }
         }
     }
-
+    private boolean isEmptyValue(Cell cell){
+        return StrUtil.isEmpty(cell.getStringCellValue())||StrUtil.isNullOrUndefined(cell.getStringCellValue());
+    }
     /**
      * 创建表格样式
      *

+ 28 - 6
tr-plugins/tr-spring-boot-starter-plugin-biz-excel/src/test/java/cn/tr/plugin/excel/ExcelTest.java

@@ -57,8 +57,14 @@ public class ExcelTest extends BaseMockitoUnitTest {
     public void exportExcel() throws Exception {
         File file = FileUtil.touch(pathPrefix + "111.xlsx");
         ArrayList<User> users = new ArrayList<>();
-        for (int i = 0; i < 100; i++) {
-            users.add(User.of(i,"用户"+i, RandomUtil.randomString("123",1),RandomUtil.randomInt(10,40)));
+        for (int i = 0; i < 76; i++) {
+            users.add(User.of(i,
+                    "用户"+(i/10),
+                    RandomUtil.randomInt(10,40),
+                    RandomUtil.randomBoolean()?"--":null,
+                    RandomUtil.randomBoolean()?"--":null,
+                    RandomUtil.randomString("1234",1)
+                   ));
         }
         long currentTimeMillis = System.currentTimeMillis();
         ExcelHelper excelHelper = excelHelperFactory.create(User.class);
@@ -72,12 +78,28 @@ public class ExcelTest extends BaseMockitoUnitTest {
     private static class User{
         @Excel(name = "序号")
         private Integer sort;
-        @Excel(name = "姓名")
+
+        @Excel(name = "姓名",mergeRowWhenSame = true)
         private String name;
-        @Excel(name = "性别",dictCode = "gender")
-        private String gender;
-        @Excel(name = "年龄",suffix = "岁")
+
+        @Excel(name = "年龄",suffix = "岁",mergeBlank = true)
         private Integer age;
+
+
+        @Excel(name = "随机空格")
+        private String blank;
+
+
+        @Excel(name = "随机空格2")
+        private String blank1;
+
+        @Excel(name = "性别",dictCode = "gender",combo = {"男","女","未知"})
+        private String gender;
+
+
+
+
+
     }
 
     @Getter

+ 31 - 4
tr-plugins/tr-spring-boot-starter-plugin-mp-enhance-actable/src/main/java/cn/tr/plugin/mp/enhance/actable/ActableAutoConfiguration.java

@@ -13,8 +13,12 @@ import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.config.BeanPostProcessor;
 import org.springframework.beans.factory.config.PropertiesFactoryBean;
 import org.springframework.context.annotation.*;
+import org.springframework.core.io.Resource;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
-
+import org.springframework.jdbc.datasource.init.DataSourceInitializer;
+import org.springframework.jdbc.datasource.init.DatabasePopulator;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import javax.sql.DataSource;
 /**
  * @ClassName : ActatbleAutoConfiguration
  * @Description :
@@ -23,7 +27,7 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
  */
 @ComponentScan(value = "com.gitee.sunchenbin.mybatis.actable.manager.*"
         ,excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {SysMysqlCreateTableManagerImpl.class, StartUpHandlerImpl.class})}
-        )
+)
 @MapperScan({"cn.tr.plugin.mp.enhance.actable","com.gitee.sunchenbin.mybatis.actable.dao.*"})
 @PropertySources({@org.springframework.context.annotation.PropertySource("classpath:mp-actable.properties")})
 public class ActableAutoConfiguration implements BeanPostProcessor {
@@ -46,7 +50,7 @@ public class ActableAutoConfiguration implements BeanPostProcessor {
                 TrStartUpHandlerImpl trStartUpHandler = new TrStartUpHandlerImpl(new TrSysMysqlCreateTableManagerImpl());
                 configurationProxy.addListener(aClass -> {
                     trStartUpHandler
-                    .startHandler();
+                            .startHandler();
                 });
                 ReflectUtil.setFieldValue(sqlSessionFactory,"configuration",configurationProxy);
                 trStartUpHandler.startHandler();
@@ -61,11 +65,34 @@ public class ActableAutoConfiguration implements BeanPostProcessor {
     public PropertiesFactoryBean configProperties() throws Exception{
         PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
         PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
-        propertiesFactoryBean.setLocations(resolver.getResources("classpath*:application.properties"));
+        propertiesFactoryBean.setLocations(resolver.getResources("classpath*:mp-actable.properties"));
         return propertiesFactoryBean;
     }
 
 
+//    @Bean
+    public DataSourceInitializer dataSourceInitializer(DataSource dataSource){
+        DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
+        dataSourceInitializer.setDataSource(dataSource);
+        try {
+            dataSourceInitializer.setDatabasePopulator(populator());
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return dataSourceInitializer;
+    }
+
+    private DatabasePopulator populator() throws Exception {
+        ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+        Resource[] resources = new PathMatchingResourcePatternResolver()
+                .getResources("classpath:sql/*.sql");
+        if(resources.length!=0){
+            for (Resource resource : resources) {
+                databasePopulator.addScript(resource);
+            }
+        }
+        return databasePopulator;
+    }
 
 
 }

+ 5 - 3
tr-plugins/tr-spring-boot-starter-plugin-mybatis/src/main/java/cn/tr/plugin/mybatis/TrMybatisAutoConfiguration.java

@@ -9,8 +9,10 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
 import java.util.*;
+
+import com.github.pagehelper.PageInterceptor;
+import org.apache.ibatis.plugin.Interceptor;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
@@ -69,8 +71,8 @@ public class TrMybatisAutoConfiguration {
      * 分页插件
      */
     @Bean
-    public InnerInterceptor paginationInnerInterceptor() {
-        return new PaginationInnerInterceptor();
+    public Interceptor paginationInnerInterceptor() {
+        return new PageInterceptor();
     }
 
     /**

+ 6 - 0
tr-plugins/tr-spring-boot-starter-plugin-operatelog/src/main/java/cn/tr/plugin/operatelog/config/OperateLogAspect.java

@@ -153,11 +153,17 @@ public class OperateLogAspect {
         MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
         String[] argNames = methodSignature.getParameterNames();
         Object[] argValues = joinPoint.getArgs();
+        if(argValues==null){
+            return null;
+        }
         // 拼接参数
         Map<String, Object> args = new HashMap<>();
         for (int i = 0; i < argNames.length; i++) {
             String argName = argNames[i];
             Object argValue = argValues[i];
+            if(argValue==null){
+                continue;
+            }
             // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起
             args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]");
         }

+ 1 - 1
tr-plugins/tr-spring-boot-starter-plugin-web/src/main/java/cn/tr/plugin/web/config/PageStrategyConfig.java

@@ -26,7 +26,7 @@ public class PageStrategyConfig {
                 current= ObjectUtil.isNull(pageMap.get("current"))?1:Integer.valueOf(String.valueOf(pageMap.get("current")));
                 size=ObjectUtil.isNull(pageMap.get("size"))?10:Integer.valueOf(String.valueOf(pageMap.get("size")));
             }catch (Exception e){
-                e.printStackTrace();
+
             }
             return new PageDomain(current,size);
         };

+ 45 - 0
tr-test/pom.xml

@@ -18,6 +18,17 @@
             <artifactId>tr-spring-boot-starter-plugin-web</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>cn.tr</groupId>
+            <artifactId>tr-spring-boot-starter-plugin-mp-enhance-actable</artifactId>
+            <version>0.0.9</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.tr</groupId>
+            <artifactId>tr-spring-boot-starter-plugin-mybatis</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>cn.tr</groupId>
             <artifactId>tr-spring-boot-starter-plugin-websocket</artifactId>
@@ -69,4 +80,38 @@
             </exclusions>
         </dependency>
     </dependencies>
+
+
+    <build>
+        <finalName>${project.name}</finalName>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <!--<pluginManagement>-->
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <mainClass> cn.tr.test.WebApplication</mainClass>
+                    <finalName>${project.build.finalName}</finalName>
+                    <layers>
+                        <enabled>true</enabled>
+                    </layers>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <!--</pluginManagement>-->
+    </build>
 </project>

+ 23 - 11
tr-test/src/main/java/cn/tr/test/TestController.java

@@ -1,10 +1,13 @@
 package cn.tr.test;
 
 import cn.tr.core.enums.IEnum;
+import cn.tr.core.strategy.PageStrategy;
 import cn.tr.plugin.desensitize.config.slider.annotation.ChineseNameDesensitize;
 import cn.tr.plugin.dict.annotation.Dict;
 import cn.tr.plugin.dict.bo.DictBO;
 import cn.tr.plugin.dict.config.cache.DictManager;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -18,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.PostConstruct;
+import javax.persistence.Column;
 import javax.validation.constraints.NotNull;
 import java.util.*;
 /**
@@ -34,39 +38,47 @@ public class TestController {
     @Autowired
     private DictManager dictManager;
 
+    @Autowired
+    private UserMapper userMapper;
     @PostConstruct
     public void init(){
         dictManager.load("gender",Arrays.asList(new DictBO("1","男"),new DictBO("2","女")));
     }
 
-    @GetMapping("/123")
-    @ApiOperationSupport(author = "lf")
-    @ApiOperation(value = "获取参数",authorizations = {@Authorization("ces")})
-    public User test(@RequestParam("test")@NotNull String test){
-        return User.of("id","1","上官吹雪",false,Grander.high);
-    }
+//    @GetMapping("/123")
+//    @ApiOperationSupport(author = "lf")
+//    @ApiOperation(value = "获取参数",authorizations = {@Authorization("ces")})
+//    public User test(@RequestParam("test")@NotNull String test){
+//        return User.of("id","1","上官吹雪",false,Grander.high);
+//    }
 
-    @PostMapping("/123")
+    @GetMapping("/123")
     @ApiOperationSupport(author = "lf")
     @ApiOperation(value = "获取参数123",authorizations = {@Authorization("ces")})
-    public User test(@RequestBody User test){
-        return User.of("id","1","上官吹雪",false,Grander.high);
+    public User test(@RequestBody(required = false) User test){
+        PageStrategy.tr.startPage.accept(PageStrategy.tr.createPage.get());
+        List<User> users = userMapper.selectList(new QueryWrapper<User>());
+        return User.of("id","1","上官吹雪",false);
     }
 
     @Data
     @AllArgsConstructor(staticName = "of")
     @NoArgsConstructor
+    @TableName("test")
     public static class User{
+        @Column(name = "id")
         private String id;
+
+        @Column(name = "name")
         @Dict("gender")
         private String name;
 
+        @Column(name = "nickname")
         @ChineseNameDesensitize
         private String nickname;
 
+        @Column(name = "test")
         private Boolean test;
-
-        private Grander grander;
     }
 
     @Getter

+ 14 - 0
tr-test/src/main/java/cn/tr/test/UserMapper.java

@@ -0,0 +1,14 @@
+package cn.tr.test;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.mybatis.spring.annotation.MapperScan;
+
+/**
+ * @Interface : UserMapper
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年03月24日
+ */
+@MapperScan
+public interface UserMapper extends BaseMapper<TestController.User> {
+}

+ 2 - 0
tr-test/src/main/java/cn/tr/test/WebApplication.java

@@ -3,6 +3,7 @@ package cn.tr.test;
 import cn.hutool.core.thread.ThreadUtil;
 import cn.tr.plugin.eventbus.config.EventBus;
 import cn.tr.plugin.eventbus.constant.EventBusConstant;
+import org.mybatis.spring.annotation.MapperScan;
 import org.redisson.api.RTopic;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -18,6 +19,7 @@ import javax.annotation.PostConstruct;
  * @Date: 2023年02月22日
  */
 @SpringBootApplication
+@MapperScan("cn.tr.test")
 public class WebApplication {
     public static void main(String[] args) {
         SpringApplication.run(WebApplication.class);

+ 12 - 0
tr-test/src/main/resources/application.yml

@@ -5,7 +5,19 @@ tr:
 server:
   shutdown: graceful
   port: 8083
+
+mybatis-plus:
+  mapper-locations: classpath*:com/gitee/sunchenbin/mybatis/actable/mapping/*/*.xml,classpath*:mapper/*/*.xml
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+
 spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://192.168.100.32:3306/tdms?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&autoReconnect=true
+    username: root
+    password: 123456
   redis:
     # 地址
     host: 192.168.100.32

+ 11 - 0
tr-test/src/main/resources/sql/test1.sql

@@ -0,0 +1,11 @@
+-- -- drop table if exists sys_dept;
+-- --
+-- -- create table `Test1` (
+-- --   `Id` int(11) not null comment '默认ID',
+-- --   `Name` varchar(20) not null comment '默认名字',
+-- --   primary key (`Id`)
+-- -- ) engine=innoDB default charset=utf8 comment='test';
+-- -- insert into `Test`(`Id`, `Name`) select 1 , 'jack';
+--
+-- insert into `Test` select 1 , 'cao' where not exists(select 1 from Test where id=1);
+-- insert into `Test` select 1 , 'cao' from dual where not exists(select 1 from Test where id=1);