Commit 50f004f6 by 刘泽志

29

parent 67cc7580
package com.tbyf.his.web.controller.dataImport;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tbyf.his.common.annotation.IgnoreWebSecurity;
import com.tbyf.his.common.core.domain.AjaxResult;
import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.emport.domain.param.QueryTemplateParam;
import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.common.utils.bean.BeanUtils;
import com.tbyf.his.web.dataImport.domain.param.*;
import com.tbyf.his.web.dataImport.entity.DataDict;
import com.tbyf.his.web.dataImport.entity.DataImportTemplate;
import com.tbyf.his.web.dataImport.service.DataDictService;
import com.tbyf.his.web.dataImport.service.DataImportTemplateService;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author lzz
......@@ -22,10 +34,101 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j
public class DataImportController {
@Autowired
private DataImportTemplateService dataImportService;
@Autowired
private DataDictService dictService;
@IgnoreWebSecurity
@GetMapping("/template")
@ApiOperation("分页模板查询")
@ApiOperation("模板查询")
public AjaxResult queryTemplate(@Validated QueryTemplateParam param) {
final LambdaQueryWrapper<DataImportTemplate> wrapper = Wrappers.lambdaQuery(DataImportTemplate.class)
.eq(DataImportTemplate::getYear, param.getYear());
return AjaxResult.success(dataImportService.list(wrapper));
}
@IgnoreWebSecurity
@PostMapping("/template")
@ApiOperation("模板新增")
public AjaxResult addTemplate(@RequestBody @Validated AddTemplateParam param) {
DataImportTemplate template = new DataImportTemplate();
BeanUtils.copyProperties(param, template);
template.initAdd();
dataImportService.save(template);
return AjaxResult.success();
}
@IgnoreWebSecurity
@PutMapping("/template")
@ApiOperation("修改模板")
public AjaxResult updateTemplate(@RequestBody @Validated UpdateTemplateParam param) {
DataImportTemplate template = new DataImportTemplate();
BeanUtils.copyProperties(param, template);
template.initAdd();
dataImportService.updateById(template);
return AjaxResult.success();
}
@IgnoreWebSecurity
@DeleteMapping("/template")
@ApiOperation("删除模板")
public AjaxResult deleteTemplate(@RequestParam String templateId) {
dataImportService.removeById(templateId);
//TODO 需要删除字段以及其字段关联的规则与其它数据
return AjaxResult.success();
}
@IgnoreWebSecurity
@GetMapping("/dict")
@ApiOperation("字典查询")
public AjaxResult queryDict(@RequestParam String type) {
final LambdaQueryWrapper<DataDict> wrapper = Wrappers.lambdaQuery(DataDict.class)
.eq(DataDict::getType, type);
final List<Map<String, String>> list = dictService.list(wrapper).stream().map(item -> {
String json = item.getRemarks();
item.setRemarks(null);
final Map<String, String> map = BeanUtils.getFieldValueMap(item);
if (StringUtils.isNotBlank(json)) {
try {
final JSONObject object = JSON.parseObject(json);
object.forEach((key, value) -> {
map.put(key, (String) value);
});
} catch (Exception ignore) {
}
}
return map;
}).collect(Collectors.toList());
return AjaxResult.success(list);
}
@IgnoreWebSecurity
@PostMapping("/dict")
@ApiOperation("新增字典")
public AjaxResult addDict(@RequestBody AddDictParam param) {
DataDict dict = new DataDict();
BeanUtils.copyProperties(param, dict);
dictService.save(dict);
return AjaxResult.success();
}
@IgnoreWebSecurity
@PutMapping("/dict")
@ApiOperation("修改字典")
public AjaxResult updateDict(@RequestBody @Validated UpdateDictParam param) {
DataDict template = new DataDict();
BeanUtils.copyProperties(param, template);
dictService.updateById(template);
return AjaxResult.success();
}
@IgnoreWebSecurity
@DeleteMapping("/dict")
@ApiOperation("删除字典")
public AjaxResult deleteDict(@RequestParam String dictId) {
dictService.removeById(dictId);
return AjaxResult.success();
}
......
package com.tbyf.his.web.controller.emport;
import com.alibaba.druid.pool.DruidDataSource;
import com.tbyf.his.common.core.domain.AjaxResult;
import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.common.core.text.StrFormatter;
import com.tbyf.his.emport.domain.param.*;
import com.tbyf.his.emport.entity.ExcelRule;
import com.tbyf.his.emport.entity.ExcelTemplate;
import com.tbyf.his.emport.service.ExcelFieldRuleService;
import com.tbyf.his.emport.service.ExcelRuleService;
import com.tbyf.his.emport.service.ExcelTemplateFieldService;
import com.tbyf.his.emport.service.ExcelTemplateService;
import com.tbyf.his.framework.datasource.DataSourceUtil;
import com.tbyf.his.framework.datasource.DynamicDataSourceContextHolder;
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.jdbc.core.JdbcTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @author lzz
* @date 2023/1/10 15:52
*/
@RestController
@Api(tags = "excel导入接口")
@RequestMapping("/emport")
@Slf4j
public class EmportController {
@Autowired
private ExcelTemplateService excelTemplateService;
@Autowired
private ExcelTemplateFieldService excelTemplateFieldService;
@Autowired
private ExcelRuleService excelRuleService;
@Autowired
private ExcelFieldRuleService excelFieldRuleService;
/*===================模板接口====================*/
@GetMapping("/template")
@ApiOperation("分页模板查询")
public TableDataInfo queryTemplate(@Validated QueryTemplateParam param) {
return excelTemplateService.queryTemplate(param);
}
@GetMapping("/template/download")
@ApiOperation("模板下载")
public void downloadTemplate(@RequestParam Long templateId, HttpServletResponse response) {
excelTemplateService.downloadTemplate(templateId, response);
}
@PostMapping("/template")
@ApiOperation("新增模板信息")
public AjaxResult addTemplate(@RequestBody @Validated ExcelTemplate template) {
boolean result = excelTemplateService.addTemplate(template);
return AjaxResult.success();
}
@PutMapping("/template")
@ApiOperation("修改模板信息")
public AjaxResult updateTemplate(@RequestBody @Validated ExcelTemplate template) {
if (Objects.isNull(template.getId())) {
return AjaxResult.error("id不能为空");
}
boolean result = excelTemplateService.updateTemplate(template);
return AjaxResult.success();
}
@DeleteMapping("/template")
@ApiOperation("删除模板信息")
public AjaxResult deleteTemplate(@RequestParam Long templateId) {
boolean result = excelTemplateService.deleteTemplate(templateId);
return AjaxResult.success();
}
/*===================模板字段接口====================*/
@GetMapping("/template/field")
@ApiOperation("分页模板字段查询")
public TableDataInfo queryTemplateField(@Validated QueryTemplateFieldParam param) {
return excelTemplateFieldService.queryTemplateField(param);
}
@DeleteMapping("/template/field")
@ApiOperation("删除模板字段")
public AjaxResult deleteTemplateField(@RequestParam Long templateFieldId) {
boolean result = excelTemplateFieldService.deleteTemplateField(templateFieldId);
return AjaxResult.success();
}
@PostMapping("/template/field")
@ApiOperation("新增模板字段配置")
public AjaxResult addTemplateField(@RequestBody @Validated AddExcelTemplateFieldParam param) {
boolean result = excelTemplateFieldService.addTemplateField(param);
return AjaxResult.success();
}
@PutMapping("/template/field")
@ApiOperation("修改模板字段配置")
public AjaxResult updateTemplateField(@RequestBody @Validated UpdateExcelTemplateFieldParam param) {
boolean result = excelTemplateFieldService.updateTemplateField(param);
return AjaxResult.success();
}
@GetMapping("/template/field/test")
@ApiOperation("模板字段规则测试")
public AjaxResult fieldRuleTest(@RequestParam String fieldId, @RequestParam String value) {
return excelTemplateFieldService.fieldRuleTest(fieldId, value);
}
/*===================规则接口====================*/
@GetMapping("/rule")
@ApiOperation("规则信息查询")
public TableDataInfo queryRule(@Validated QueryExcelRuleParam param) {
return excelRuleService.queryRule(param);
}
@GetMapping("/rule/dict")
@ApiOperation("规则字典查询")
public AjaxResult queryRuleDict() {
return AjaxResult.success(excelRuleService.queryRuleDict());
}
@DeleteMapping("/rule")
@ApiOperation("删除规则")
public AjaxResult deleteRule(@RequestParam Long ruleId) {
boolean result = excelRuleService.deleteRule(ruleId);
return AjaxResult.success();
}
@PostMapping("/rule")
@ApiOperation("新增规则配置")
public AjaxResult addRule(@RequestBody @Validated AddExcelRuleParam param) {
boolean result = excelRuleService.addRule(param);
return AjaxResult.success();
}
@PutMapping("/rule")
@ApiOperation("修改规则配置")
public AjaxResult updateRule(@RequestBody @Validated UpdateExcelRuleParam param) {
boolean result = excelRuleService.updateRule(param);
return AjaxResult.success();
}
@PostMapping("/rule/test")
@ApiOperation("规则测试接口")
public AjaxResult testRule(@RequestBody @Validated TestRuleParam param) {
return excelRuleService.testRule(param);
}
@GetMapping("/rule/name")
@ApiOperation("查询规则名称集合")
public AjaxResult getRuleNames(@RequestParam String ids) {
return AjaxResult.success(excelRuleService.getRuleNames(ids));
}
/*===================模板规则接口====================*/
@PostMapping("/fieldRule")
@ApiOperation("配置字段规则绑定")
public AjaxResult bindRule(@RequestBody @Validated BindRulesParam param) {
boolean result = excelFieldRuleService.bindRules(param);
return AjaxResult.success();
}
@GetMapping("/fieldRule")
@ApiOperation("查询模板绑定规则")
public AjaxResult listFieldRule(@RequestParam String fieldId) {
List<ExcelRule> result = excelFieldRuleService.listFieldRule(fieldId);
return AjaxResult.success(result);
}
@PostMapping("/upload")
@ApiOperation("导入excel")
public AjaxResult upload(@Validated UploadExcelParam param) {
excelTemplateService.importExcel(param);
return AjaxResult.success();
}
@PostMapping("/initTemplate")
@ApiOperation("模板初始化")
public AjaxResult initTemplate(@Validated UploadExcelParam param) {
excelTemplateService.initTemplate(param);
return AjaxResult.success();
}
@Autowired
private JdbcTemplate jdbcTemplate;
@GetMapping("/db/table")
@ApiOperation("获取指定数据库中所有的表")
public AjaxResult getDbTable(@RequestParam String dataSourceId) {
try {
DataSourceUtil.switchDs(dataSourceId);
final DruidDataSource dataSource = (DruidDataSource) DynamicDataSourceContextHolder.dataSourcesMap.get(dataSourceId);
String sql = "select TABLE_NAME AS NAME,COMMENTS AS COMMENTS from user_tab_comments WHERE TABLE_TYPE = 'TABLE'";
if (dataSource.getDriverClassName().toLowerCase().contains("mysql")) {
sql = "select TABLE_NAME AS NAME ,table_comment AS COMMENTS from information_schema.tables where table_type='BASE TABLE'";
}
final List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return AjaxResult.success(maps.stream().filter(
distinctByKey(b -> b.get("NAME"))
).distinct().collect(Collectors.toList()));
} finally {
DataSourceUtil.switchDefaultDs();
}
}
@GetMapping("/db/field")
@ApiOperation("获取指定表的字段信息")
public AjaxResult getDbField(@RequestParam String dataSourceId,
@RequestParam String tableName) {
try {
DataSourceUtil.switchDs(dataSourceId);
final DruidDataSource dataSource = (DruidDataSource) DynamicDataSourceContextHolder.dataSourcesMap.get(dataSourceId);
String sql = StrFormatter.format("SELECT UTC.COLUMN_NAME AS CNAME,UTC.DATA_TYPE AS CTYPE,( SELECT UCC.COMMENTS FROM user_col_comments UCC WHERE UCC.COLUMN_NAME = UTC.COLUMN_NAME AND UCC.TABLE_NAME = UTC.TABLE_NAME ) AS CCOMMENT FROM user_tab_columns UTC WHERE UTC.TABLE_NAME = '{}'", tableName);
if (dataSource.getDriverClassName().toLowerCase().contains("mysql")) {
sql = StrFormatter.format("SELECT column_name AS CNAME, DATA_TYPE AS CTYPE, column_comment AS CCOMMENT FROM information_schema.COLUMNS WHERE table_name = '{}'", tableName);
}
final List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
return AjaxResult.success(maps);
} finally {
DataSourceUtil.switchDefaultDs();
}
}
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}
package com.tbyf.his.emport.domain;
package com.tbyf.his.web.dataImport.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tbyf.his.common.core.domain.model.LoginUser;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Date;
......@@ -23,46 +19,46 @@ public class BaseMp {
public static final String TIMEZONE = "GMT+8";
@ApiModelProperty(value = "创建人")
@TableField("CREATE_BY")
private String createBy;
// @ApiModelProperty(value = "创建人")
// @TableField("CREATE_BY")
// private String createBy;
@JsonFormat(pattern = FORMAT, timezone = TIMEZONE)
@ApiModelProperty(value = "创建时间")
@TableField("CREATE_TIME")
@TableField("create_time")
private Date createTime;
@ApiModelProperty(value = "更新人")
@TableField("UPDATE_BY")
private String updateBy;
// @ApiModelProperty(value = "更新人")
// @TableField("UPDATE_BY")
// private String updateBy;
@JsonFormat(pattern = FORMAT, timezone = TIMEZONE)
@ApiModelProperty(value = "更新时间")
@TableField("UPDATE_TIME")
@TableField("update_time")
private Date updateTime;
@ApiModelProperty(value = "备注")
@TableField("REMARK")
private String remark;
@TableField("remarks")
private String remarks;
public void initAdd() {
this.createTime = new Date();
this.updateTime = new Date();
SecurityContext sc = SecurityContextHolder.getContext();
Authentication auth = sc.getAuthentication();
LoginUser user = (LoginUser) auth.getPrincipal();
this.createBy = String.valueOf(user.getUserId());
this.updateBy = String.valueOf(user.getUserId());
// SecurityContext sc = SecurityContextHolder.getContext();
// Authentication auth = sc.getAuthentication();
// LoginUser user = (LoginUser) auth.getPrincipal();
// this.createBy = String.valueOf(user.getUserId());
// this.updateBy = String.valueOf(user.getUserId());
}
public void initUpdate() {
this.createTime = null;
this.updateTime = new Date();
SecurityContext sc = SecurityContextHolder.getContext();
Authentication auth = sc.getAuthentication();
LoginUser user = (LoginUser) auth.getPrincipal();
this.createBy = null;
this.updateBy = String.valueOf(user.getUserId());
// SecurityContext sc = SecurityContextHolder.getContext();
// Authentication auth = sc.getAuthentication();
// LoginUser user = (LoginUser) auth.getPrincipal();
// this.createBy = null;
// this.updateBy = String.valueOf(user.getUserId());
}
}
package com.tbyf.his.emport.domain.param;
package com.tbyf.his.web.dataImport.domain.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
......@@ -17,20 +15,24 @@ import java.io.Serializable;
@Data
@Accessors(chain = true)
@ApiModel(value = "Excel导入", description = "Excel导入")
public class UploadExcelParam implements Serializable {
@ApiModel(value = "新增字典", description = "新增字典")
public class AddDictParam implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "上传类型")
@ApiModelProperty(value = "字典类型")
@NotBlank(message = "字典类型不能为空")
private String type;
@ApiModelProperty(value = "上传类型")
@NotBlank(message = "templateId不能为空")
private String templateId;
@ApiModelProperty(value = "展示")
@NotBlank(message = "字典标签不能为空")
private String label;
@ApiModelProperty(value = "excel")
@NotNull(message = "file不能为空")
private MultipartFile file;
@ApiModelProperty(value = "数据值")
@NotBlank(message = "字典值不能为空")
private String value;
@ApiModelProperty(value = "备注")
private String remarks;
}
package com.tbyf.his.web.dataImport.domain.param;
import com.tbyf.his.web.dataImport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "新增模板", description = "新增模板")
public class AddTemplateParam extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "模板名称")
private String name;
@ApiModelProperty(value = "机构类型")
@NotBlank(message = "机构类型不能为空")
private String orgName;
@ApiModelProperty(value = "导入状态 1-已导入 0-未导入")
private String importStatus = "0";
@ApiModelProperty(value = "数据年份")
@NotBlank(message = "数据年份不能为空")
private String year;
@ApiModelProperty(value = "数据源ID")
private String dataSourceId;
@ApiModelProperty(value = "表名")
private String tableName;
}
package com.tbyf.his.emport.domain.param;
package com.tbyf.his.web.dataImport.domain.param;
import com.tbyf.his.emport.domain.ParamMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
/**
* @author lzz
* @date 2023/1/10 17:01
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "模板查询参数", description = "模板查询参数")
public class QueryTemplateParam extends ParamMp {
public class QueryTemplateParam {
@ApiModelProperty(value = "查询关键字,模糊查询模板名称")
private String keyword;
@ApiModelProperty(value = "数据年份")
@NotBlank(message = "年份不能为空")
private String year;
}
package com.tbyf.his.emport.domain.param;
package com.tbyf.his.web.dataImport.domain.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -15,26 +15,22 @@ import java.io.Serializable;
@Data
@Accessors(chain = true)
@ApiModel(value = "规则测试参数", description = "规则测试参数")
public class TestRuleParam implements Serializable {
@ApiModel(value = "修改字典", description = "修改字典")
public class UpdateDictParam implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "模板ID")
@NotBlank(message = "模板ID不能为空")
private String id;
@ApiModelProperty(value = "规则类型 1-基础规则 2-组合规则")
@NotBlank(message = "ruleType不能为空")
private String ruleType;
@ApiModelProperty(value = "展示")
private String label;
@ApiModelProperty(value = "规则验证模式 基础规则有:正则,判空,大小,插件 组合规则有 || &&")
@NotBlank(message = "ruleMode不能为空")
private String ruleMode;
@ApiModelProperty(value = "规则验证内容 基础规则有: 正则表达式 大于小于的值,插件ID 组合规则就是规则ID的集合")
@NotBlank(message = "ruleContent不能为空")
private String ruleContent;
@ApiModelProperty(value = "用于测试的值")
@NotBlank(message = "value不能为空")
@ApiModelProperty(value = "数据值")
private String value;
@ApiModelProperty(value = "备注")
private String remarks;
}
package com.tbyf.his.web.dataImport.domain.param;
import com.tbyf.his.web.dataImport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "更新模板", description = "更新模板")
public class UpdateTemplateParam extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "模板ID")
@NotBlank(message = "模板ID不能为空")
private String id;
@ApiModelProperty(value = "模板名称")
private String name;
@ApiModelProperty(value = "机构类型")
private String orgName;
@ApiModelProperty(value = "导入状态 1-已导入 0-未导入")
private String importStatus;
@ApiModelProperty(value = "数据年份")
private String year;
@ApiModelProperty(value = "数据源ID")
private String dataSourceId;
@ApiModelProperty(value = "表名")
private String tableName;
}
package com.tbyf.his.web.dataImport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@Accessors(chain = true)
@TableName(value = "data_dict", autoResultMap = true)
@ApiModel(value = "数据字典", description = "数据字典")
public class DataDict implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "模板ID")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@ApiModelProperty(value = "字典类型")
@TableField("type")
private String type;
@ApiModelProperty(value = "展示")
@TableField("label")
private String label;
@ApiModelProperty(value = "数据值")
@TableField("value")
private String value;
@ApiModelProperty(value = "备注")
@TableField("remarks")
private String remarks;
}
......@@ -4,15 +4,16 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tbyf.his.emport.domain.BaseMp;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tbyf.his.web.dataImport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
/**
* @author lzz
......@@ -22,34 +23,42 @@ import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName(value = "DATA_IMPORT_TEMPLATE", autoResultMap = true)
@TableName(value = "data_import_template", autoResultMap = true)
@ApiModel(value = "数据导入模板表", description = "数据导入模板表")
public class DataImportTemplate extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@TableId(value = "ID", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "模板ID")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@ApiModelProperty(value = "模板名称")
@TableField("TEMPLATE_NAME")
@NotBlank(message = "模板名称不能为空")
private String templateName;
@TableField("name")
private String name;
@ApiModelProperty(value = "模板标题/sheet名称")
@TableField("SHEET_NAME")
private String sheetName;
@ApiModelProperty(value = "机构类型")
@TableField("org_name")
private String orgName;
@ApiModelProperty(value = "模板类型 1-横向普通模板 2-单文档垂直模板")
@TableField("TEMPLATE_TYPE")
private String templateType;
@ApiModelProperty(value = "导入状态 1-已导入 0-未导入")
@TableField("import_status")
private String importStatus;
@ApiModelProperty(value = "数据年份")
@TableField("year")
private String year;
@JsonFormat(pattern = FORMAT, timezone = TIMEZONE)
@ApiModelProperty(value = "上次导入时间")
@TableField("import_time")
private Date importTime;
@ApiModelProperty(value = "数据源ID")
@TableField("DATASOURCE_ID")
@TableField("datasource_id")
private String dataSourceId;
@ApiModelProperty(value = "表名")
@TableField("TABLE_PART_NAME")
private String tablePartName;
@ApiModelProperty(value = "表名")
@TableField("table_name")
private String tableName;
}
package com.tbyf.his.emport.mapper;
package com.tbyf.his.web.dataImport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tbyf.his.emport.entity.ExcelRule;
import com.tbyf.his.web.dataImport.entity.DataDict;
/**
* @author lzz
* @date 2023/1/10 15:46
* @date 2023/2/7 11:22
*/
public interface ExcelRuleMapper extends BaseMapper<ExcelRule> {
public interface DataDictMapper extends BaseMapper<DataDict> {
}
package com.tbyf.his.emport.mapper;
package com.tbyf.his.web.dataImport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tbyf.his.emport.entity.ExcelTemplateField;
import com.tbyf.his.web.dataImport.entity.DataImportTemplate;
/**
* @author lzz
* @date 2023/1/10 15:46
* @date 2023/2/7 11:22
*/
public interface ExcelTemplateFieldMapper extends BaseMapper<ExcelTemplateField> {
public interface DataImportTemplateMapper extends BaseMapper<DataImportTemplate> {
}
package com.tbyf.his.web.dataImport.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tbyf.his.web.dataImport.entity.DataDict;
/**
* @author lzz
* @date 2023/2/7 11:23
*/
public interface DataDictService extends IService<DataDict> {
}
package com.tbyf.his.web.dataImport.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tbyf.his.web.dataImport.entity.DataImportTemplate;
/**
* @author lzz
* @date 2023/2/7 11:23
*/
public interface DataImportTemplateService extends IService<DataImportTemplate> {
}
package com.tbyf.his.web.dataImport.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbyf.his.common.annotation.DataSource;
import com.tbyf.his.common.enums.DataSourceType;
import com.tbyf.his.web.dataImport.entity.DataDict;
import com.tbyf.his.web.dataImport.mapper.DataDictMapper;
import com.tbyf.his.web.dataImport.service.DataDictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @author lzz
* @date 2023/2/7 11:24
*/
@Slf4j
@Service
@DataSource(DataSourceType.MASTER)
public class DataDictServiceImpl extends ServiceImpl<DataDictMapper, DataDict> implements DataDictService {
}
package com.tbyf.his.web.dataImport.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbyf.his.common.annotation.DataSource;
import com.tbyf.his.common.enums.DataSourceType;
import com.tbyf.his.web.dataImport.entity.DataImportTemplate;
import com.tbyf.his.web.dataImport.mapper.DataImportTemplateMapper;
import com.tbyf.his.web.dataImport.service.DataImportTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @author lzz
* @date 2023/2/7 11:24
*/
@Slf4j
@Service
@DataSource(DataSourceType.MASTER)
public class DataImportTemplateServiceImpl extends ServiceImpl<DataImportTemplateMapper, DataImportTemplate> implements DataImportTemplateService {
}
package com.tbyf.his.emport.constant;
/**
* @author lzz
* @date 2023/1/10 17:22
*/
public class EmportConstants {
/**
* 唯一分隔符
*/
public static final String SEPARATOR = ",";
/**
* 验证规则 正则
*/
public static final String SERVICE_PREFIX = "emport_validation_mode_";
/**
* 验证规则 正则
*/
public static final String VALIDATION_MODE_REG = "1";
/**
* 验证规则 非空
*/
public static final String VALIDATION_MODE_NOTNULL = "2";
/**
* 验证规则 区间
*/
public static final String VALIDATION_MODE_SECTION = "3";
/**
* 验证规则 比较
*/
public static final String VALIDATION_MODE_COMPARE = "4";
/**
* 验证规则 插件
*/
public static final String VALIDATION_MODE_PLUGIN = "5";
/**
* 验证规则 值域
*/
public static final String VALIDATION_MODE_RANGE = "6";
/**
* 验证规则 逻辑与
*/
public static final String VALIDATION_MODE_WITH = "11";
/**
* 验证规则 逻辑或
*/
public static final String VALIDATION_MODE_OR = "12";
/**
* 基础规则
*/
public static final String RULE_BASE = "1";
/**
* 组合规则
*/
public static final String RULE_COMBINE = "2";
}
package com.tbyf.his.emport.core;
import com.tbyf.his.emport.constant.EmportConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author lzz
* @date 2023/1/29 13:57
*/
@Configuration
public class EmportConfig {
@Autowired
private ApplicationContext applicationContext;
public static final Map<String, RuleValidator> RULE_VALIDATOR_MAP = new ConcurrentHashMap<>(8);
@PostConstruct
public void init() {
final Map<String, RuleValidator> validatorMap = applicationContext.getBeansOfType(RuleValidator.class);
RULE_VALIDATOR_MAP.putAll(validatorMap);
}
public static RuleValidator getValidator(String mode) {
return RULE_VALIDATOR_MAP.get(EmportConstants.SERVICE_PREFIX + mode);
}
}
package com.tbyf.his.emport.core;
import com.tbyf.his.common.core.text.StrFormatter;
import com.tbyf.his.common.exception.base.BaseException;
import lombok.Getter;
/**
* @author lzz
* @date 2023/1/29 14:23
*/
@Getter
public class EmportException extends BaseException {
private RuleContent ruleContent;
public EmportException() {
super("");
}
public EmportException(String defaultMessage) {
super(defaultMessage);
}
public EmportException(RuleContent content, String message, Object... args) {
super(StrFormatter.format(message, args));
this.ruleContent = content;
}
}
package com.tbyf.his.emport.core;
import com.alibaba.druid.pool.DruidDataSource;
import com.google.common.collect.Lists;
import com.tbyf.his.common.exception.base.BaseException;
import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.emport.domain.vo.FieldInfoVO;
import com.tbyf.his.framework.datasource.DynamicDataSourceContextHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.springframework.util.CollectionUtils;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* 动态数据导入工具类
*
* @author lzz
* @date 2023/2/3 9:31
*/
public class EmportUtils {
/**
* 查询这一行是否包含此数据
*
* @param row
* @param str 支持正则包裹的表达式
* @return
*/
public static boolean findText(Row row, String str) {
final Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
final Cell next = cellIterator.next();
final String value = getValue(next);
if (StringUtils.isNotBlank(value) && Pattern.matches(str, value)) {
return true;
}
}
return false;
}
/**
* 哪一行开始有数据
*
* @param sheet
* @return
*/
public static int hasText(Sheet sheet) {
for (Row row : sheet) {
for (Cell cell : row) {
if (StringUtils.isNotBlank(getValue(cell))) {
return cell.getRowIndex();
}
}
}
return -1;
}
/**
* 从单元格获取数据
*
* @param cell
* @return
*/
public static String getValue(Cell cell) {
final CellType cellType = cell.getCellType();
switch (cellType) {
case STRING:
return cell.getStringCellValue().trim();
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case NUMERIC:
return ((XSSFCell) cell).getCTCell().getV().trim();
default:
return "";
}
}
/**
* 从单元格获取数据
*
* @param cell
* @return
*/
public static String getValue(Cell cell, String type) {
final CellType cellType = cell.getCellType();
switch (cellType) {
case STRING:
return cell.getStringCellValue().trim();
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case NUMERIC:
if ("Number".equals(type)) {
return String.valueOf(cell.getNumericCellValue());
} else if ("Date(YYYY-MM-DD)".equals(type)) {
return cell.getLocalDateTimeCellValue().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
} else if ("Date(YYYY-MM-DD HH:mm:ss)".equals(type)) {
return cell.getLocalDateTimeCellValue().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
return ((XSSFCell) cell).getCTCell().getV();
default:
return "";
}
}
/**
* 生成批量sql
* oracle:
* * INSERT INTO TEST_USER (NAME,AGE)
* * SELECT '1','2' FROM DUAL
* * UNION ALL
* * SELECT '1','2' FROM DUAL
*
* @param tableName
* @param dataSourceId
* @param fieldList
* @param dataList
* @param batchSize
* @return
*/
public static List<String> getBatchSql(String tableName,
String dataSourceId,
List<FieldInfoVO> fieldList,
List<List<String>> dataList,
int batchSize) {
final DruidDataSource dataSource = (DruidDataSource) DynamicDataSourceContextHolder.dataSourcesMap.get(dataSourceId);
List<String> sqlList = new ArrayList<>();
// 计算切分次数
// int limit = (dataList.size() + batchSize - 1) / batchSize;
final List<List<List<String>>> partition = Lists.partition(dataList, batchSize);
if (dataSource.getDriverClassName().toLowerCase().contains("mysql")) {
// INSERT INTO TABLE_NAME(FIELD1,FIELD2)VALUES('1','2'),('3','4')
String sql = "INSERT INTO " + tableName + "("
+ fieldList.stream().map(FieldInfoVO::getDataFieldName).collect(Collectors.joining(","))
+ ") VALUES";
for (List<List<String>> part : partition) {
StringBuilder sb = new StringBuilder(sql);
for (List<String> row : part) {
sb.append("(");
for (int i = 0; i < row.size(); i++) {
sb.append(convertMysqlValue(fieldList.get(i).getDataType(), row.get(i))).append(",");
}
sb.deleteCharAt(sb.length() - 1);
sb.append("),");
}
sb.deleteCharAt(sb.length() - 1);
sqlList.add(sb.toString());
}
} else {
String sql = "INSERT INTO " + tableName + "("
+ fieldList.stream().map(FieldInfoVO::getDataFieldName).collect(Collectors.joining(","))
+ ")";
for (List<List<String>> part : partition) {
StringBuilder sb = new StringBuilder(sql);
for (List<String> row : part) {
sb.append(" SELECT ");
for (int i = 0; i < row.size(); i++) {
sb.append(convertOracleValue(fieldList.get(i).getDataType(), row.get(i))).append(",");
}
sb.deleteCharAt(sb.length() - 1);
sb.append(" FROM DUAL UNION ALL ");
}
sb.deleteCharAt(sb.length() - 1);
sqlList.add(sb.toString());
}
}
return sqlList;
}
/**
* 生成单行数据的插入语句
*
* @param tableName
* @param dataSourceId
* @param fieldList
* @param dataList
* @return
*/
public static String getInsertSql(String tableName,
String dataSourceId,
List<FieldInfoVO> fieldList,
List<String> dataList) {
final DruidDataSource dataSource = (DruidDataSource) DynamicDataSourceContextHolder.dataSourcesMap.get(dataSourceId);
if (dataSource.getDriverClassName().toLowerCase().contains("mysql")) {
StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO ")
.append(tableName)
.append("(")
.append(fieldList.stream().map(FieldInfoVO::getDataFieldName).collect(Collectors.joining(",")))
.append(") VALUES(");
for (int i = 0; i < dataList.size(); i++) {
sb.append(convertMysqlValue(fieldList.get(i).getDataType(), dataList.get(i))).append(",");
}
sb.deleteCharAt(sb.length() - 1);
sb.append(")");
return sb.toString();
} else {
StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO ")
.append(tableName)
.append("(")
.append(fieldList.stream().map(FieldInfoVO::getDataFieldName).collect(Collectors.joining(",")))
.append(") VALUES(");
for (int i = 0; i < dataList.size(); i++) {
sb.append(convertOracleValue(fieldList.get(i).getDataType(), dataList.get(i))).append(",");
}
sb.deleteCharAt(sb.length() - 1);
sb.append(")");
return sb.toString();
}
}
public static String convertOracleValue(String type, String value) {
if (StringUtils.isEmpty(type)) {
return "'" + value + "'";
}
switch (type) {
case "Date(YYYY-MM-DD)":
return "to_date('" + value + "','YYYY-MM-DD')";
case "Date(YYYY-MM-DD HH:mm:ss)":
return "to_date('" + value + "','YYYY-MM-DD HH24:MI:SS')";
default:
return "'" + value + "'";
}
}
public static String convertMysqlValue(String type, String value) {
if (StringUtils.isEmpty(type)) {
return "'" + value + "'";
}
switch (type) {
case "Date(YYYY-MM-DD)":
return "STR_TO_DATE('" + value + "','%Y-%m-%d') ";
case "Date(YYYY-MM-DD HH:mm:ss)":
return "STR_TO_DATE('" + value + "','%Y-%m-%d %H:%i:%s') ";
default:
return "'" + value + "'";
}
}
/**
* 数据批量校验
*
* @param ruleList
* @param value
*/
public static void validate(List<RuleContent> ruleList, String value) {
if (!CollectionUtils.isEmpty(ruleList)) {
if (StringUtils.isBlank(value)) {
throw new BaseException("数据不能为空");
}
for (RuleContent rule : ruleList) {
final RuleValidator validator = EmportConfig.getValidator(rule.getMode());
if (validator == null) {
throw new EmportException(rule, "没有找到对应的规则校验器:{}", rule.getMode());
}
validator.validate(rule);
}
}
}
/**
* 获取横纵坐标
*
* @return
*/
public static Integer getHorizontal(String address) {
final String s = address.split(",")[0];
try {
return Integer.parseInt(s);
} catch (Exception e) {
return letterToNumber(s);
}
}
/**
* 字母转数字
*
* @param letter
* @return
*/
public static int letterToNumber(String letter) {
int length = letter.length();
int num = 0;
int number = 0;
for (int i = 0; i < length; i++) {
char ch = letter.charAt(length - i - 1);
num = (int) (ch - 'A' + 1);
num *= Math.pow(26, i);
number += num;
}
return number;
}
/**
* 获取对应的横纵坐标
* 通过代码与标题
* 代码就是横坐标+1 标题就是+2
*
* @param sheet
* @param fieldInfo
* @return
*/
public static String findAddress(Sheet sheet, FieldInfoVO fieldInfo) {
int allRows = sheet.getLastRowNum() + 1;
for (int a = 0; a < allRows; a++) {
for (Cell cell : sheet.getRow(a)) {
final String value = getValue(cell);
if (StringUtils.isNotBlank(fieldInfo.getFieldName()) && StringUtils.equals(value, fieldInfo.getFieldName())) {
return cell.getColumnIndex() + 2 + "," + cell.getRowIndex();
}
if (StringUtils.isNotBlank(fieldInfo.getFieldTitle()) && StringUtils.equals(value, fieldInfo.getFieldTitle())) {
return cell.getColumnIndex() + 1 + "," + cell.getRowIndex();
}
}
}
return "";
}
}
package com.tbyf.his.emport.core;
import lombok.Data;
/**
* @author lzz
* @date 2023/1/29 14:11
*/
@Data
public class RuleContent {
private String name;
private String id;
private String value;
private String type;
private String mode;
private String content;
}
package com.tbyf.his.emport.core;
/**
* 规则校验接口
*
* @author lzz
* @date 2023/1/29 13:59
*/
public interface RuleValidator {
/**
* 校验方法
*
* @param content
* @return
*/
boolean validate(RuleContent content);
}
package com.tbyf.his.emport.core.validator;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.EmportException;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 比较规则校验
* 目前支持符号为 > >= < <= = !=
*
* @author lzz
* @date 2023/1/29 14:21
*/
@Service(EmportConstants.SERVICE_PREFIX + EmportConstants.VALIDATION_MODE_COMPARE)
public class CompareValidator implements RuleValidator {
public static final String GT = ">";
public static final String GTE = ">=";
public static final String LT = "<";
public static final String LTE = "<=";
public static final String EQ = "=";
public static final String NEQ = "!=";
@Override
public boolean validate(RuleContent content) {
BigDecimal value;
try {
value = new BigDecimal(content.getValue());
} catch (NumberFormatException e) {
throw new EmportException(content, "数据类型异常:{}", content.getValue());
}
if (content.getContent().startsWith(GT)) {
final BigDecimal x = new BigDecimal(getValue(content.getContent(), GT));
if (value.compareTo(x) > 0) {
return true;
}
} else if (content.getContent().startsWith(GTE)) {
final BigDecimal x = new BigDecimal(getValue(content.getContent(), GTE));
if (value.compareTo(x) >= 0) {
return true;
}
} else if (content.getContent().startsWith(LT)) {
final BigDecimal x = new BigDecimal(getValue(content.getContent(), LT));
if (value.compareTo(x) < 0) {
return true;
}
} else if (content.getContent().startsWith(LTE)) {
final BigDecimal x = new BigDecimal(getValue(content.getContent(), LTE));
if (value.compareTo(x) <= 0) {
return true;
}
} else if (content.getContent().startsWith(EQ)) {
final BigDecimal x = new BigDecimal(getValue(content.getContent(), EQ));
if (value.compareTo(x) == 0) {
return true;
}
} else if (content.getContent().startsWith(NEQ)) {
final BigDecimal x = new BigDecimal(getValue(content.getContent(), NEQ));
if (value.compareTo(x) != 0) {
return true;
}
} else {
throw new EmportException(content, "暂不支持的比较符号:[{}]", content.getContent());
}
throw new EmportException(content, "比较规则校验未通过:[{}]", content.getContent());
}
private String getValue(String value, String symbol) {
return value.trim().substring(symbol.length()).trim();
}
}
package com.tbyf.his.emport.core.validator;
import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.EmportException;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import org.springframework.stereotype.Service;
/**
* 非空规则校验
*
* @author lzz
* @date 2023/1/29 14:21
*/
@Service(EmportConstants.SERVICE_PREFIX + EmportConstants.VALIDATION_MODE_NOTNULL)
public class NotNullValidator implements RuleValidator {
@Override
public boolean validate(RuleContent content) {
final String[] badArray = content.getContent().split(EmportConstants.SEPARATOR);
for (String badStr : badArray) {
if (StringUtils.equals(badStr, content.getValue())) {
throw new EmportException(content, "非空规则校验未通过:[{}]", content.getContent());
}
}
return true;
}
}
package com.tbyf.his.emport.core.validator;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.EmportConfig;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import com.tbyf.his.emport.service.ExcelRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 组合规则 逻辑或校验
*
* @author lzz
* @date 2023/1/29 14:21
*/
@Service(EmportConstants.SERVICE_PREFIX + EmportConstants.VALIDATION_MODE_OR)
public class OrValidator implements RuleValidator {
@Autowired
private ExcelRuleService excelRuleService;
@Override
public boolean validate(RuleContent content) {
final String[] split = content.getContent().split(EmportConstants.SEPARATOR);
RuleContent rule1 = excelRuleService.getRuleContent(split[0]);
rule1.setValue(content.getValue());
final RuleValidator validator1 = EmportConfig.getValidator(rule1.getMode());
try {
if (validator1.validate(rule1)) {
return true;
}
} catch (Exception ignore) {
}
RuleContent rule2 = excelRuleService.getRuleContent(split[1]);
rule2.setValue(content.getValue());
final RuleValidator validator2 = EmportConfig.getValidator(rule2.getMode());
return validator2.validate(rule2);
}
}
package com.tbyf.his.emport.core.validator;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import org.springframework.stereotype.Service;
/**
* 插件校验
*
* @author lzz
* @date 2023/1/29 14:21
*/
@Service(EmportConstants.SERVICE_PREFIX + EmportConstants.VALIDATION_MODE_PLUGIN)
public class PluginValidator implements RuleValidator {
@Override
public boolean validate(RuleContent content) {
return true;
}
}
package com.tbyf.his.emport.core.validator;
import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.EmportException;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import org.springframework.stereotype.Service;
/**
* 值域校验
*
* @author lzz
* @date 2023/1/29 14:21
*/
@Service(EmportConstants.SERVICE_PREFIX + EmportConstants.VALIDATION_MODE_RANGE)
public class RangeValidator implements RuleValidator {
@Override
public boolean validate(RuleContent content) {
final String[] arr = content.getContent().split(EmportConstants.SEPARATOR);
for (String value : arr) {
if (StringUtils.equals(value, content.getValue())) {
return true;
}
}
throw new EmportException(content, "值域校验未通过:[{}]", content.getContent());
}
}
package com.tbyf.his.emport.core.validator;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.EmportException;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import org.springframework.stereotype.Service;
import java.util.regex.Pattern;
/**
* @author lzz
* @date 2023/1/29 14:21
*/
@Service(EmportConstants.SERVICE_PREFIX + EmportConstants.VALIDATION_MODE_REG)
public class RegValidator implements RuleValidator {
@Override
public boolean validate(RuleContent content) {
final boolean matches = Pattern.matches(content.getContent(), content.getValue());
if (!matches) {
throw new EmportException(content, "正则表达式校验未通过:[{}]", content.getContent());
}
return true;
}
}
package com.tbyf.his.emport.core.validator;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.EmportException;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 区间规则校验
*
* @author lzz
* @date 2023/1/29 14:21
*/
@Service(EmportConstants.SERVICE_PREFIX + EmportConstants.VALIDATION_MODE_SECTION)
public class SectionValidator implements RuleValidator {
@Override
public boolean validate(RuleContent content) {
final String[] split = content.getContent().split(EmportConstants.SEPARATOR);
final BigDecimal a = new BigDecimal(split[0]);
final BigDecimal b = new BigDecimal(split[1]);
try {
final BigDecimal x = new BigDecimal(content.getValue());
if (x.compareTo(a) >= 0 && b.compareTo(x) >= 0) {
return true;
}
} catch (NumberFormatException e) {
throw new EmportException(content, "数据类型异常:{}", content.getValue());
}
throw new EmportException(content, "区间校验未通过:[{}]", content.getContent());
}
}
package com.tbyf.his.emport.core.validator;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.EmportConfig;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import com.tbyf.his.emport.service.ExcelRuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 组合规则逻辑与校验
*
* @author lzz
* @date 2023/1/29 14:21
*/
@Service(EmportConstants.SERVICE_PREFIX + EmportConstants.VALIDATION_MODE_WITH)
public class WithValidator implements RuleValidator {
@Autowired
private ExcelRuleService excelRuleService;
@Override
public boolean validate(RuleContent content) {
final String[] split = content.getContent().split(EmportConstants.SEPARATOR);
RuleContent rule1 = excelRuleService.getRuleContent(split[0]);
RuleContent rule2 = excelRuleService.getRuleContent(split[1]);
rule1.setValue(content.getValue());
rule2.setValue(content.getValue());
final RuleValidator validator1 = EmportConfig.getValidator(rule1.getMode());
if (validator1.validate(rule1)) {
final RuleValidator validator2 = EmportConfig.getValidator(rule2.getMode());
return validator2.validate(rule2);
}
return false;
}
}
package com.tbyf.his.emport.domain.param;
import com.tbyf.his.emport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "新增基础规则", description = "新增基础规则")
public class AddExcelRuleParam extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "规则名称")
@NotBlank(message = "ruleName不能为空")
private String ruleName;
@ApiModelProperty(value = "规则类型 1-基础规则 2-组合规则")
@NotBlank(message = "ruleType不能为空")
private String ruleType;
@ApiModelProperty(value = "规则验证模式 基础规则有:正则,判空,大小,插件 组合规则有 || &&")
@NotBlank(message = "ruleMode不能为空")
private String ruleMode;
@ApiModelProperty(value = "规则验证内容 基础规则有: 正则表达式 大于小于的值,插件ID 组合规则就是规则ID的集合")
@NotBlank(message = "ruleContent不能为空")
private String ruleContent;
}
package com.tbyf.his.emport.domain.param;
import com.tbyf.his.emport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "新增excel模板字段", description = "新增excel模板字段")
public class AddExcelTemplateFieldParam extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull(message = "templateId不能为空")
@ApiModelProperty(value = "模板ID")
private Long templateId;
@NotBlank(message = "templateFieldName不能为空")
@ApiModelProperty(value = "模板代码名称(提供垂直模板使用)")
private String templateFieldName;
@ApiModelProperty(value = "数据库字段名")
private String tableFieldName;
@ApiModelProperty(value = "数据类型,根据数据库类型与手动选择类型判断,例如String,Number,Date(YYYY-MM-DD)")
private String dataType;
@ApiModelProperty(value = "排序字段,默认为0")
private Long sort = 0L;
@ApiModelProperty(value = "字段说明,例如:登记注册类型代码")
private String fieldTitle;
@ApiModelProperty(value = "计量单位说明")
private String unitTitle;
@ApiModelProperty(value = "字段位置,直接写横纵坐标或者单元格属性 2,3 或者B3")
private String fieldAddress;
@ApiModelProperty(value = "字段单元格合并操作,写明横纵合并大小,默认不合并就是 1,1")
private String fieldLocation;
}
package com.tbyf.his.emport.domain.param;
import com.tbyf.his.emport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "绑定绑定规则参数", description = "绑定绑定规则参数")
public class BindRulesParam extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "字段ID")
@NotNull(message = "id不能为空")
private Long fieldId;
@ApiModelProperty(value = "规则ID集合")
private List<Long> ruleIdList;
}
package com.tbyf.his.emport.domain.param;
import com.tbyf.his.emport.domain.ParamMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author lzz
* @date 2023/1/10 17:01
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "规则查询参数", description = "规则查询参数")
public class QueryExcelRuleParam extends ParamMp {
@ApiModelProperty(value = "规则名称")
private String ruleName;
@ApiModelProperty(value = "规则类型 1-基础规则 2-组合规则")
private String ruleType;
@ApiModelProperty(value = "规则验证模式 基础规则有:正则,判空,大小,插件 组合规则有 || &&")
private String ruleMode;
}
package com.tbyf.his.emport.domain.param;
import com.tbyf.his.emport.domain.ParamMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
/**
* @author lzz
* @date 2023/1/10 17:01
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "模板字段查询参数", description = "模板字段查询参数")
public class QueryTemplateFieldParam extends ParamMp {
@ApiModelProperty(value = "查询关键字,字段名,指标名")
private String keyword;
@ApiModelProperty(value = "模板ID")
@NotNull(message = "templateId不能为空")
private Long templateId;
}
package com.tbyf.his.emport.domain.param;
import com.tbyf.his.emport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "更新基础规则", description = "更新基础规则")
public class UpdateExcelRuleParam extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@NotNull(message = "id不能为空")
private Long id;
@ApiModelProperty(value = "规则名称")
private String ruleName;
@ApiModelProperty(value = "规则类型 1-基础规则 2-组合规则")
private String ruleType;
@ApiModelProperty(value = "规则验证模式 基础规则有:正则,判空,大小,插件 组合规则有 || &&")
private String ruleMode;
@ApiModelProperty(value = "规则验证内容 基础规则有: 正则表达式 大于小于的值,插件ID 组合规则就是规则ID的集合")
private String ruleContent;
}
package com.tbyf.his.emport.domain.param;
import com.tbyf.his.emport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@ApiModel(value = "修改excel模板字段", description = "修改excel模板字段")
public class UpdateExcelTemplateFieldParam extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@NotNull(message = "id不能为空")
private Long id;
@NotNull(message = "templateId不能为空")
@ApiModelProperty(value = "模板ID")
private Long templateId;
@ApiModelProperty(value = "模板代码名称(提供垂直模板使用)")
private String templateFieldName;
@NotBlank(message = "tableFieldName不能为空")
@ApiModelProperty(value = "数据库字段名")
private String tableFieldName;
@ApiModelProperty(value = "排序字段,默认为0")
private Long sort = 0L;
@ApiModelProperty(value = "数据类型,根据数据库类型与手动选择类型判断,例如String,Number,Date(YYYY-MM-DD)")
private String dataType;
@ApiModelProperty(value = "字段说明,例如:登记注册类型代码")
private String fieldTitle;
@ApiModelProperty(value = "计量单位说明")
private String unitTitle;
@ApiModelProperty(value = "字段位置,直接写横纵坐标或者单元格属性 2,3 或者B3")
private String fieldAddress;
@ApiModelProperty(value = "字段单元格合并操作,写明横纵合并大小,默认不合并就是 1,1")
private String fieldLocation;
}
package com.tbyf.his.emport.domain.vo;
import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.emport.core.RuleContent;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author lzz
* @date 2023/1/30 11:49
*/
@Data
public class FieldInfoVO {
@ApiModelProperty(value = "字段ID")
private Long id;
@ApiModelProperty(value = "代码,提供给树形文档使用")
private String fieldName;
@ApiModelProperty(value = "表字段名称")
private String dataFieldName;
@ApiModelProperty(value = "数据类型,根据数据库类型与手动选择类型判断,例如String,Number,Date(YYYY-MM-DD)")
private String dataType;
@ApiModelProperty(value = "字段位置,直接写横纵坐标或者单元格属性 2,3 或者B3")
private String fieldAddress;
@ApiModelProperty(value = "字段单元格合并操作,写明横纵合并大小,默认不合并就是 1,1")
private String fieldLocation;
@ApiModelProperty(value = "排序字段")
private Long sort;
@ApiModelProperty(value = "指标标题 一、机构属性代码")
private String fieldTitle;
@ApiModelProperty(value = "计量单位说明 -")
private String unitTitle;
@ApiModelProperty(value = "绑定的规则列表")
private List<RuleInfoVo> ruleList;
/**
* 初始化单元格合并
*/
public void initFieldLocation() {
if (StringUtils.isBlank(fieldLocation)) {
fieldAddress = "1,1";
}
}
/* ===========功能字段========= */
/**
* 纵坐标
*/
private Integer horizontal;
private List<RuleContent> ruleContentList;
public void initContentList() {
if (CollectionUtils.isEmpty(ruleContentList)) {
if (!CollectionUtils.isEmpty(ruleList)) {
ruleContentList = new ArrayList<>();
ruleList.forEach(rule -> {
RuleContent content = new RuleContent();
content.setId(String.valueOf(rule.getId()));
content.setType(rule.getType());
content.setMode(rule.getMode());
content.setContent(rule.getContent());
content.setName(rule.getName());
ruleContentList.add(content);
});
}
}
}
}
package com.tbyf.his.emport.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author lzz
* @date 2023/1/30 11:53
*/
@Data
public class RuleInfoVo {
@ApiModelProperty(value = "规则ID")
private Long id;
@ApiModelProperty(value = "规则名称")
private String name;
@ApiModelProperty(value = "规则类型 1-基础规则 2-组合规则")
private String type;
@ApiModelProperty(value = "规则验证模式 基础规则有:正则,判空,大小,插件 组合规则有 || &&")
private String mode;
@ApiModelProperty(value = "规则验证内容 基础规则有: 正则表达式 大于小于的值,插件ID 组合规则就是规则ID的集合")
private String content;
}
drop table if exists EXCEL_TEMPLATE;
create table EXCEL_TEMPLATE
(
ID bigint auto_increment comment '主键ID' primary key,
TEMPLATE_NAME varchar(256) null comment '模板名称',
SHEET_NAME varchar(256) null comment '模板标题/sheet名称',
TEMPLATE_TYPE varchar(4) null comment '模板类型 1-横向普通模板 2-单文档垂直模板',
DATASOURCE_ID varchar(256) null comment '数据源ID',
TABLE_PART_NAME varchar(256) null comment '表名称',
CREATE_BY varchar(64) null comment '创建人',
CREATE_TIME timestamp null comment '创建时间',
UPDATE_BY varchar(64) null comment '更新人',
UPDATE_TIME timestamp null comment '更新时间',
REMARK text null comment '备注'
) comment 'Excel模板表';
drop table if exists EXCEL_TEMPLATE_FIELD;
create table EXCEL_TEMPLATE_FIELD
(
ID bigint auto_increment comment '主键ID' primary key,
TEMPLATE_ID bigint null comment '模板ID',
TEMPLATE_FIELD_NAME varchar(64) null comment '模板代码名称(提供垂直模板使用)',
TABLE_FIELD_NAME varchar(64) null comment '数据库字段名',
DATA_TYPE varchar(64) null comment '数据类型,根据数据库类型与手动选择类型判断,例如String,Number,Date(YYYY-MM-DD)',
SORT bigint null comment '排序字段',
FIELD_TITLE varchar(64) null comment '字段说明 登记注册类型代码:',
FIELD_ADDRESS varchar(64) null comment '字段位置,直接写横纵坐标或者单元格属性 2,3 或者B3',
FIELD_LOCATION varchar(64) null comment '字段单元格合并操作,写明横纵合并大小,默认不合并就是 1,1',
UNIT_TITLE varchar(64) null comment '单位说明 人/人次',
CREATE_BY varchar(64) null comment '创建人',
CREATE_TIME timestamp null comment '创建时间',
UPDATE_BY varchar(64) null comment '更新人',
UPDATE_TIME timestamp null comment '更新时间',
REMARK text null comment '备注'
) comment 'Excel模板字段表';
drop table if exists EXCEL_RULE;
create table EXCEL_RULE
(
ID bigint auto_increment comment '主键ID' primary key,
RULE_NAME varchar(64) null comment '规则名称',
RULE_TYPE varchar(64) null comment '规则类型 1-基础规则 2-组合规则',
RULE_MODE varchar(64) null comment '规则验证模式',
RULE_CONTENT varchar(256) null comment '规则验证内容',
CREATE_BY varchar(64) null comment '创建人',
CREATE_TIME timestamp null comment '创建时间',
UPDATE_BY varchar(64) null comment '更新人',
UPDATE_TIME timestamp null comment '更新时间',
REMARK text null comment '备注'
) comment 'Excel基础规则与组合规则表';
drop table if exists EXCEL_FIELD_RULE;
create table EXCEL_FIELD_RULE
(
FIELD_ID bigint null comment '字段ID',
RULE_ID bigint null comment '规则ID'
) comment 'Excel模板字段规则对应表';
\ No newline at end of file
package com.tbyf.his.emport.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@Accessors(chain = true)
@TableName(value = "EXCEL_FIELD_RULE", autoResultMap = true)
@ApiModel(value = "Excel模板字段规则对应表", description = "Excel模板字段规则对应表")
public class ExcelFieldRule implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "字段ID")
@TableField("FIELD_ID")
private Long fieldId;
@ApiModelProperty(value = "规则ID")
@TableField("RULE_ID")
private Long ruleId;
}
package com.tbyf.his.emport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tbyf.his.emport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName(value = "EXCEL_RULE", autoResultMap = true)
@ApiModel(value = "Excel基础规则与组合规则表", description = "Excel基础规则与组合规则表")
public class ExcelRule extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@TableId(value = "ID", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "规则名称")
@TableField("RULE_NAME")
private String ruleName;
@ApiModelProperty(value = "规则类型 1-基础规则 2-组合规则")
@TableField("RULE_TYPE")
private String ruleType;
@ApiModelProperty(value = "规则验证模式 基础规则有:正则,判空,大小,插件 组合规则有 || &&")
@TableField("RULE_MODE")
private String ruleMode;
@ApiModelProperty(value = "规则验证内容 基础规则有: 正则表达式 大于小于的值,插件ID 组合规则就是规则ID的集合")
@TableField("RULE_CONTENT")
private String ruleContent;
}
package com.tbyf.his.emport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tbyf.his.emport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName(value = "EXCEL_TEMPLATE", autoResultMap = true)
@ApiModel(value = "excel模板表", description = "excel模板")
public class ExcelTemplate extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@TableId(value = "ID", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "模板名称")
@TableField("TEMPLATE_NAME")
@NotBlank(message = "模板名称不能为空")
private String templateName;
@ApiModelProperty(value = "模板标题/sheet名称")
@TableField("SHEET_NAME")
private String sheetName;
@ApiModelProperty(value = "模板类型 1-横向普通模板 2-单文档垂直模板")
@TableField("TEMPLATE_TYPE")
private String templateType;
@ApiModelProperty(value = "数据源ID")
@TableField("DATASOURCE_ID")
private String dataSourceId;
@ApiModelProperty(value = "表名称")
@TableField("TABLE_PART_NAME")
private String tablePartName;
}
package com.tbyf.his.emport.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.tbyf.his.emport.domain.BaseMp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author lzz
* @date 2023/1/10 15:36
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName(value = "EXCEL_TEMPLATE_FIELD", autoResultMap = true)
@ApiModel(value = "excel模板字段表", description = "excel模板字段表")
public class ExcelTemplateField extends BaseMp implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@TableId(value = "ID", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "模板ID")
@TableField("TEMPLATE_ID")
private Long templateId;
@ApiModelProperty(value = "模板代码名称(提供垂直模板使用)")
@TableField("TEMPLATE_FIELD_NAME")
private String templateFieldName;
@ApiModelProperty(value = "数据库字段名")
@TableField("TABLE_FIELD_NAME")
private String tableFieldName;
@ApiModelProperty(value = "数据类型,根据数据库类型与手动选择类型判断,例如String,Number,Date(YYYY-MM-DD)")
@TableField("DATA_TYPE")
private String dataType;
@ApiModelProperty(value = "排序字段")
@TableField("SORT")
private Long sort;
@ApiModelProperty(value = "字段说明,例如:登记注册类型代码")
@TableField("FIELD_TITLE")
private String fieldTitle;
@ApiModelProperty(value = "字段位置,直接写横纵坐标或者单元格属性 2,3 或者B3")
@TableField("FIELD_ADDRESS")
private String fieldAddress;
@ApiModelProperty(value = "字段单元格合并操作,写明横纵合并大小,默认不合并就是 1,1")
@TableField("FIELD_LOCATION")
private String fieldLocation;
@ApiModelProperty(value = "计量单位说明")
@TableField("UNIT_TITLE")
private String unitTitle;
}
package com.tbyf.his.emport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tbyf.his.emport.entity.ExcelFieldRule;
import com.tbyf.his.emport.entity.ExcelRule;
import java.util.List;
/**
* @author lzz
* @date 2023/1/10 15:46
*/
public interface ExcelFieldRuleMapper extends BaseMapper<ExcelFieldRule> {
/**
* 查询该字段绑定的所有模板规则
*
* @param fieldId
* @return
*/
List<ExcelRule> listFieldRule(String fieldId);
}
package com.tbyf.his.emport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tbyf.his.emport.domain.vo.FieldInfoVO;
import com.tbyf.his.emport.entity.ExcelTemplate;
import java.util.List;
/**
* @author lzz
* @date 2023/1/10 15:46
*/
public interface ExcelTemplateMapper extends BaseMapper<ExcelTemplate> {
/**
* 查询模板字段信息以及相关规则
*
* @param templateId
* @return
*/
List<FieldInfoVO> getFieldInfoList(String templateId);
}
package com.tbyf.his.emport.service;
import com.tbyf.his.emport.domain.vo.FieldInfoVO;
import com.tbyf.his.emport.entity.ExcelTemplate;
import com.tbyf.his.emport.entity.ExcelTemplateField;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
/**
* @author lzz
* @date 2023/2/3 9:33
*/
public interface EmportService {
/**
* 动态导入普通文档
*
* @param template
* @param list
* @param workbook
*/
void dynamicImportBySimple(ExcelTemplate template, List<FieldInfoVO> list, Workbook workbook);
/**
* 动态导入竖形单文档
*
* @param template
* @param list
* @param workbook
*/
void dynamicImportByVertical(ExcelTemplate template, List<FieldInfoVO> list, Workbook workbook);
/**
* 初始化普通模板
*
* @param template
* @param workbook
* @return
*/
List<ExcelTemplateField> initTemplateBySimple(ExcelTemplate template, Workbook workbook);
/**
* 初始化竖形单文档模板
*
* @param template
* @param workbook
* @return
*/
List<ExcelTemplateField> initTemplateByVertical(ExcelTemplate template, Workbook workbook);
}
package com.tbyf.his.emport.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tbyf.his.emport.domain.param.BindRulesParam;
import com.tbyf.his.emport.entity.ExcelFieldRule;
import com.tbyf.his.emport.entity.ExcelRule;
import java.util.List;
/**
* @author lzz
* @date 2023/1/10 15:53
*/
public interface ExcelFieldRuleService extends IService<ExcelFieldRule> {
/**
* 字段与规则绑定
*
* @param param
* @return
*/
boolean bindRules(BindRulesParam param);
/**
* 查询该字段绑定的所有模板规则
*
* @param fieldId
* @return
*/
List<ExcelRule> listFieldRule(String fieldId);
}
package com.tbyf.his.emport.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tbyf.his.common.core.domain.AjaxResult;
import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.domain.param.AddExcelRuleParam;
import com.tbyf.his.emport.domain.param.QueryExcelRuleParam;
import com.tbyf.his.emport.domain.param.TestRuleParam;
import com.tbyf.his.emport.domain.param.UpdateExcelRuleParam;
import com.tbyf.his.emport.entity.ExcelRule;
import java.util.List;
/**
* @author lzz
* @date 2023/1/10 15:53
*/
public interface ExcelRuleService extends IService<ExcelRule> {
/**
* 分页查询规则信息
*
* @param param
* @return
*/
TableDataInfo queryRule(QueryExcelRuleParam param);
/**
* 删除规则
*
* @param ruleId
* @return
*/
boolean deleteRule(Long ruleId);
/**
* 新增基础规则配置
*
* @param param
* @return
*/
boolean addRule(AddExcelRuleParam param);
/**
* 修改规则配置
*
* @param param
* @return
*/
boolean updateRule(UpdateExcelRuleParam param);
/**
* 查询规则字典
*
* @return
*/
List<ExcelRule> queryRuleDict();
/**
* 测试规则
*
* @param param
* @return
*/
AjaxResult testRule(TestRuleParam param);
/**
* 获取包装后的RoleContent
*
* @param id
* @return
*/
RuleContent getRuleContent(String id);
/**
* 查询规则名称集合
*
* @param ids
* @return
*/
List<String> getRuleNames(String ids);
}
package com.tbyf.his.emport.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tbyf.his.common.core.domain.AjaxResult;
import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.emport.domain.param.AddExcelTemplateFieldParam;
import com.tbyf.his.emport.domain.param.QueryTemplateFieldParam;
import com.tbyf.his.emport.domain.param.UpdateExcelTemplateFieldParam;
import com.tbyf.his.emport.entity.ExcelTemplateField;
/**
* @author lzz
* @date 2023/1/10 15:53
*/
public interface ExcelTemplateFieldService extends IService<ExcelTemplateField> {
/**
* 添加
*
* @param param
* @return
*/
boolean addTemplateField(AddExcelTemplateFieldParam param);
/**
* 更新
*
* @param param
* @return
*/
boolean updateTemplateField(UpdateExcelTemplateFieldParam param);
/**
* 分页查询字段
*
* @param param
* @return
*/
TableDataInfo queryTemplateField(QueryTemplateFieldParam param);
/**
* 删除模板字段
*
* @param templateFieldId
* @return
*/
boolean deleteTemplateField(Long templateFieldId);
/**
* 字段规则测试
*
* @param fieldId
* @param value
* @return
*/
AjaxResult fieldRuleTest(String fieldId, String value);
}
package com.tbyf.his.emport.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.emport.domain.param.QueryTemplateParam;
import com.tbyf.his.emport.domain.param.UploadExcelParam;
import com.tbyf.his.emport.entity.ExcelTemplate;
import com.tbyf.his.emport.entity.ExcelTemplateField;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* @author lzz
* @date 2023/1/10 15:53
*/
public interface ExcelTemplateService extends IService<ExcelTemplate> {
/**
* 新增excel模板
*
* @param template
* @return
*/
boolean addTemplate(ExcelTemplate template);
/**
* 修改excel模板
*
* @param template
* @return
*/
boolean updateTemplate(ExcelTemplate template);
/**
* 分页查询模板
*
* @param param
* @return
*/
TableDataInfo queryTemplate(QueryTemplateParam param);
/**
* 删除模板
* 连带删除字段信息,以及字段信息所有的规则绑定信息
*
* @param templateId
* @return
*/
boolean deleteTemplate(Long templateId);
/**
* 导入excel
*
* @param param
* @return
*/
boolean importExcel(UploadExcelParam param);
/**
* 模板初始化
*
* @param param
*/
void initTemplate(UploadExcelParam param);
/**
* 模板初始化更新字段 (事务)
*
* @param templateId
* @param list
*/
void initTemplateField(Long templateId, List<ExcelTemplateField> list);
/**
* 模板下载
*
* @param templateId
* @param response
*/
void downloadTemplate(Long templateId, HttpServletResponse response);
}
package com.tbyf.his.emport.service.impl;
import com.tbyf.his.common.annotation.DataSource;
import com.tbyf.his.common.enums.DataSourceType;
import com.tbyf.his.common.utils.StringUtils;
import com.tbyf.his.emport.core.EmportUtils;
import com.tbyf.his.emport.domain.vo.FieldInfoVO;
import com.tbyf.his.emport.entity.ExcelTemplate;
import com.tbyf.his.emport.entity.ExcelTemplateField;
import com.tbyf.his.emport.service.EmportService;
import com.tbyf.his.framework.datasource.DataSourceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* @author lzz
* @date 2023/2/3 9:34
*/
@Service
@Slf4j
@DataSource(DataSourceType.MASTER)
public class EmportServiceImpl implements EmportService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private TransactionTemplate transactionTemplate;
@Override
public void dynamicImportBySimple(ExcelTemplate template, List<FieldInfoVO> list, Workbook workbook) {
final Sheet sheet = workbook.getSheetAt(0);
//查询title行,一般是第一行
int startIndex;
int allRows = sheet.getLastRowNum() + 1;
startIndex = IntStream.range(0, allRows)
.filter(a -> EmportUtils.findText(sheet.getRow(a), list.get(0).getFieldTitle()))
.findFirst().orElse(0);
// 提取数据横坐标
final Row titleRow = sheet.getRow(startIndex);
Map<String, Integer> coordinate = new HashMap<>();
titleRow.cellIterator().forEachRemaining(cell -> {
final String value = EmportUtils.getValue(cell);
if (StringUtils.isNotBlank(value)) {
coordinate.put(value, cell.getColumnIndex());
}
});
// 数据坐标清洗
final List<FieldInfoVO> fieldInfoVOList = list.stream().peek(item -> {
if (StringUtils.isBlank(item.getFieldAddress())) {
if (StringUtils.isNotBlank(item.getFieldTitle())) {
final Integer integer = coordinate.get(item.getFieldTitle());
if (integer == null) {
log.info("字段坐标未找到:{}", item);
} else {
item.setHorizontal(integer);
}
}
} else {
item.setHorizontal(EmportUtils.getHorizontal(item.getFieldAddress()));
}
item.initFieldLocation();
item.initContentList();
}).filter(item -> item.getHorizontal() != null)
.collect(Collectors.toList());
// 遍历获取数据,并进行规则判断
List<List<String>> dataList = new ArrayList<>();
for (int a = startIndex + 1; a < allRows; a++) {
final Row row = sheet.getRow(a);
List<String> tempList = new ArrayList<>();
try {
for (FieldInfoVO fieldInfoVO : fieldInfoVOList) {
String tempValue = EmportUtils.getValue(row.getCell(fieldInfoVO.getHorizontal()), fieldInfoVO.getDataType());
// 单位控制
/*if (StringUtils.isNotBlank(fieldInfoVO.getUnitTitle())) {
if (tempValue.endsWith(fieldInfoVO.getUnitTitle())) {
tempValue = tempValue.substring(0, tempValue.length() - fieldInfoVO.getUnitTitle().length()).trim();
}
}*/
// 校验器校验
EmportUtils.validate(fieldInfoVO.getRuleContentList(), tempValue);
tempList.add(tempValue);
}
dataList.add(tempList);
} catch (Exception e) {
log.error("数据清洗异常", e);
throw e;
}
}
// 批量添加数据
final List<String> batchSql = EmportUtils.getBatchSql(template.getTablePartName(),
template.getDataSourceId(),
fieldInfoVOList,
dataList,
100);
if (!CollectionUtils.isEmpty(batchSql)) {
boolean autoCommit = true;
Connection connection = null;
try {
DataSourceUtil.switchDs(template.getDataSourceId());
TransactionSynchronizationManager.initSynchronization();
connection = jdbcTemplate.getDataSource().getConnection();
autoCommit = connection.getAutoCommit();
connection.setAutoCommit(false);
String[] sqls = new String[batchSql.size()];
batchSql.toArray(sqls);
jdbcTemplate.batchUpdate(sqls);
connection.commit();
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
throw new RuntimeException(e);
} finally {
try {
connection.setAutoCommit(autoCommit);
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
DataSourceUtil.switchDefaultDs();
}
}
}
@Override
public void dynamicImportByVertical(ExcelTemplate template, List<FieldInfoVO> list, Workbook workbook) {
final Sheet sheet = workbook.getSheetAt(0);
// 从第一个字段开始解析
List<String> dataList = new ArrayList<>();
list.forEach(fieldInfoVo -> {
// 先判断是否有位置信息
if (StringUtils.isBlank(fieldInfoVo.getFieldAddress())) {
fieldInfoVo.setFieldAddress(EmportUtils.findAddress(sheet, fieldInfoVo));
}
});
final List<FieldInfoVO> fieldList = list.stream()
.filter(item -> StringUtils.isNotBlank(item.getFieldAddress()))
.collect(Collectors.toList());
if (!CollectionUtils.isEmpty(fieldList)) {
fieldList.forEach(item -> {
final String[] address = item.getFieldAddress().split(",");
final Cell cell = sheet.getRow(Integer.parseInt(address[1])).getCell(Integer.parseInt(address[0]));
String value = EmportUtils.getValue(cell, item.getDataType());
// 处理这个值,以便兼容 5人/5
if (StringUtils.isNotBlank(item.getUnitTitle())) {
if (value.endsWith(item.getUnitTitle())) {
value = value.substring(0, value.length() - item.getUnitTitle().length()).trim();
}
}
// 校验器校验
EmportUtils.validate(item.getRuleContentList(), value);
dataList.add(value);
});
// 拼接sql
final String sql = EmportUtils.getInsertSql(template.getTablePartName(), template.getDataSourceId(),
fieldList, dataList);
executeSql(template.getDataSourceId(), sql);
}
}
@Override
public List<ExcelTemplateField> initTemplateBySimple(ExcelTemplate template, Workbook workbook) {
List<ExcelTemplateField> fieldList = new ArrayList<>();
final Sheet sheet = workbook.getSheetAt(0);
// 判断哪一行有数据有数据的就是标题
final int i = EmportUtils.hasText(sheet);
if (i >= 0) {
for (Cell cell : sheet.getRow(i)) {
ExcelTemplateField field = new ExcelTemplateField();
final String value = EmportUtils.getValue(cell);
if (StringUtils.isNotBlank(value)) {
field.setFieldTitle(value);
field.setTemplateId(template.getId())
.setSort((long) cell.getColumnIndex())
.setFieldLocation("1,1")
.setFieldAddress(cell.getColumnIndex() + "," + i);
field.initAdd();
fieldList.add(field);
}
}
}
return fieldList;
}
@Override
public List<ExcelTemplateField> initTemplateByVertical(ExcelTemplate template, Workbook workbook) {
List<ExcelTemplateField> fieldList = new ArrayList<>();
final Sheet sheet = workbook.getSheetAt(0);
int allRows = sheet.getLastRowNum() + 1;
// 排除标题行
root:
for (int i = 0; i < allRows; i++) {
ExcelTemplateField field = new ExcelTemplateField();
final Row row = sheet.getRow(i);
int size = 0;
int x = 0;
for (int y = 1; y < row.getLastCellNum(); y++) {
Cell cell = row.getCell(y);
// 排除标题以及特殊字符
final String value = EmportUtils.getValue(cell);
if (StringUtils.isNotBlank(value)) {
if (StringUtils.equalsAny(value, template.getSheetName(), template.getTemplateName(), "代码", "指标名称", "计量单位")) {
continue root;
}
if (StringUtils.isBlank(field.getTemplateFieldName())) {
field.setTemplateFieldName(value);
size++;
x = cell.getColumnIndex() + 1;
} else if (StringUtils.isBlank(field.getFieldTitle())) {
field.setFieldTitle(value);
size++;
x = cell.getColumnIndex() + 1;
} else {
field.setUnitTitle(value);
size++;
x = cell.getColumnIndex();
break;
}
}
}
// 数据清洗
// 如果一个数据都没有,就跳过
// 如果只有一个数据,就把数据移动到标题上
if (size == 0) {
continue;
} else if (size == 1) {
field.setFieldTitle(field.getTemplateFieldName());
field.setTemplateFieldName(null);
}
field.setTemplateId(template.getId())
.setSort((long) i)
.setFieldLocation("1,1")
.setFieldAddress(x + "," + i);
field.initAdd();
fieldList.add(field);
}
return fieldList;
}
public void executeSql(String dataSourceId, String sql) {
try {
DataSourceUtil.switchDs(dataSourceId);
jdbcTemplate.execute(sql);
} finally {
DataSourceUtil.switchDefaultDs();
}
}
}
package com.tbyf.his.emport.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbyf.his.common.annotation.DataSource;
import com.tbyf.his.common.enums.DataSourceType;
import com.tbyf.his.emport.domain.param.BindRulesParam;
import com.tbyf.his.emport.entity.ExcelFieldRule;
import com.tbyf.his.emport.entity.ExcelRule;
import com.tbyf.his.emport.mapper.ExcelFieldRuleMapper;
import com.tbyf.his.emport.service.ExcelFieldRuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author lzz
* @date 2023/1/10 15:53
*/
@Slf4j
@Service
@DataSource(DataSourceType.MASTER)
public class ExcelFieldRuleServiceImpl extends ServiceImpl<ExcelFieldRuleMapper, ExcelFieldRule> implements ExcelFieldRuleService {
@Autowired
private ExcelFieldRuleMapper excelFieldRuleMapper;
@Autowired
@Lazy
private ExcelFieldRuleService excelFieldRuleService;
@Override
public boolean bindRules(BindRulesParam param) {
final boolean remove = excelFieldRuleService.remove(Wrappers.lambdaQuery(ExcelFieldRule.class).eq(ExcelFieldRule::getFieldId, param.getFieldId()));
if (!CollectionUtils.isEmpty(param.getRuleIdList())) {
final List<ExcelFieldRule> fieldRules = param.getRuleIdList().stream()
.map(item -> {
final ExcelFieldRule fieldRule = new ExcelFieldRule();
fieldRule.setFieldId(param.getFieldId())
.setRuleId(item);
return fieldRule;
}).collect(Collectors.toList());
excelFieldRuleService.saveBatch(fieldRules);
}
return true;
}
@Override
public List<ExcelRule> listFieldRule(String fieldId) {
return excelFieldRuleMapper.listFieldRule(fieldId);
}
}
package com.tbyf.his.emport.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbyf.his.common.annotation.DataSource;
import com.tbyf.his.common.core.domain.AjaxResult;
import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.common.enums.DataSourceType;
import com.tbyf.his.common.exception.base.BaseException;
import com.tbyf.his.emport.constant.EmportConstants;
import com.tbyf.his.emport.core.EmportConfig;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import com.tbyf.his.emport.domain.param.AddExcelRuleParam;
import com.tbyf.his.emport.domain.param.QueryExcelRuleParam;
import com.tbyf.his.emport.domain.param.TestRuleParam;
import com.tbyf.his.emport.domain.param.UpdateExcelRuleParam;
import com.tbyf.his.emport.entity.ExcelFieldRule;
import com.tbyf.his.emport.entity.ExcelRule;
import com.tbyf.his.emport.mapper.ExcelRuleMapper;
import com.tbyf.his.emport.service.ExcelFieldRuleService;
import com.tbyf.his.emport.service.ExcelRuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author lzz
* @date 2023/1/10 15:53
*/
@Slf4j
@Service
@DataSource(DataSourceType.MASTER)
public class ExcelRuleServiceImpl extends ServiceImpl<ExcelRuleMapper, ExcelRule> implements ExcelRuleService {
@Autowired
private ExcelRuleMapper excelRuleMapper;
@Autowired
private ExcelFieldRuleService excelFieldRuleService;
@Autowired
@Lazy
private ExcelRuleService excelRuleService;
@Override
public TableDataInfo queryRule(QueryExcelRuleParam param) {
final Page<ExcelRule> page = Page.of(param.getPageNum(), param.getPageSize());
final LambdaQueryWrapper<ExcelRule> queryWrapper = Wrappers.lambdaQuery(ExcelRule.class);
queryWrapper.like(StringUtils.hasText(param.getRuleName()), ExcelRule::getRuleName, param.getRuleName())
.eq(StringUtils.hasText(param.getRuleMode()), ExcelRule::getRuleMode, param.getRuleMode())
.eq(StringUtils.hasText(param.getRuleType()), ExcelRule::getRuleType, param.getRuleType());
final Page<ExcelRule> templatePage = excelRuleService.page(page, queryWrapper);
return param.convert(templatePage);
}
@Override
public boolean deleteRule(Long ruleId) {
// 需要判断这个规则别人是否使用过
// 第一步是组合规则使用
// 第二部是模板字段绑定规则使用
final LambdaQueryWrapper<ExcelRule> wrapper1 = Wrappers.lambdaQuery(ExcelRule.class)
.eq(ExcelRule::getRuleType, EmportConstants.RULE_COMBINE)
.and(wrapper -> {
wrapper.likeRight(ExcelRule::getRuleContent, ruleId + ",")
.or()
.likeLeft(ExcelRule::getRuleContent, "," + ruleId);
});
final long count1 = excelRuleService.count(wrapper1);
if (count1 > 0) {
throw new BaseException("此规则已被其它组合规则使用");
}
final LambdaQueryWrapper<ExcelFieldRule> wrapper2 = Wrappers.lambdaQuery(ExcelFieldRule.class)
.eq(ExcelFieldRule::getRuleId, ruleId);
final long count2 = excelFieldRuleService.count(wrapper2);
if (count2 > 0) {
throw new BaseException("此规则已被模板字段绑定使用");
}
return excelRuleService.removeById(ruleId);
}
@Override
public boolean addRule(AddExcelRuleParam param) {
// 判断名称不相同
final LambdaQueryWrapper<ExcelRule> queryWrapper = Wrappers.lambdaQuery(ExcelRule.class);
queryWrapper.eq(ExcelRule::getRuleName, param.getRuleName());
final long count = excelRuleService.count(queryWrapper);
if (count > 0) {
throw new BaseException("规则名重复");
}
ExcelRule rule = new ExcelRule();
BeanUtils.copyProperties(param, rule);
rule.initAdd();
return excelRuleService.save(rule);
}
@Override
public boolean updateRule(UpdateExcelRuleParam param) {
// 判断名称不相同
final LambdaQueryWrapper<ExcelRule> queryWrapper = Wrappers.lambdaQuery(ExcelRule.class);
queryWrapper.eq(ExcelRule::getRuleName, param.getRuleName())
.ne(ExcelRule::getId, param.getId());
final long count = excelRuleService.count(queryWrapper);
if (count > 0) {
throw new BaseException("规则名重复");
}
ExcelRule rule = new ExcelRule();
BeanUtils.copyProperties(param, rule);
rule.initUpdate();
return excelRuleService.updateById(rule);
}
@Override
public List<ExcelRule> queryRuleDict() {
final LambdaQueryWrapper<ExcelRule> queryWrapper = Wrappers.lambdaQuery(ExcelRule.class);
queryWrapper.select(ExcelRule::getId, ExcelRule::getRuleName);
return excelRuleService.list(queryWrapper);
}
@Override
public AjaxResult testRule(TestRuleParam param) {
if (!StringUtils.hasText(param.getValue())) {
return AjaxResult.error("值不能为空");
}
RuleContent content = new RuleContent();
content.setContent(param.getRuleContent());
content.setType(param.getRuleType());
content.setMode(param.getRuleMode());
content.setValue(param.getValue());
final RuleValidator validator = EmportConfig.getValidator(content.getMode());
if (Objects.isNull(validator)) {
return AjaxResult.error("校验服务加载异常,请联系管理员");
}
final boolean validate = validator.validate(content);
return validate ? AjaxResult.success() : AjaxResult.error("数据校验不通过");
}
@Override
public RuleContent getRuleContent(String id) {
final ExcelRule rule = excelRuleService.getById(id);
RuleContent content = new RuleContent();
content.setContent(rule.getRuleContent());
content.setId(id);
content.setType(rule.getRuleType());
content.setMode(rule.getRuleMode());
content.setName(rule.getRuleName());
return content;
}
@Override
public List<String> getRuleNames(String ids) {
final String[] idList = ids.split(",");
final LambdaQueryWrapper<ExcelRule> wrapper = Wrappers.lambdaQuery(ExcelRule.class)
.select(ExcelRule::getRuleName)
.in(ExcelRule::getId, idList);
return excelRuleService.list(wrapper).stream().map(ExcelRule::getRuleName).collect(Collectors.toList());
}
}
package com.tbyf.his.emport.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbyf.his.common.annotation.DataSource;
import com.tbyf.his.common.core.domain.AjaxResult;
import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.common.enums.DataSourceType;
import com.tbyf.his.common.exception.base.BaseException;
import com.tbyf.his.emport.core.EmportConfig;
import com.tbyf.his.emport.core.RuleContent;
import com.tbyf.his.emport.core.RuleValidator;
import com.tbyf.his.emport.domain.param.AddExcelTemplateFieldParam;
import com.tbyf.his.emport.domain.param.QueryTemplateFieldParam;
import com.tbyf.his.emport.domain.param.UpdateExcelTemplateFieldParam;
import com.tbyf.his.emport.entity.ExcelFieldRule;
import com.tbyf.his.emport.entity.ExcelTemplateField;
import com.tbyf.his.emport.mapper.ExcelTemplateFieldMapper;
import com.tbyf.his.emport.service.ExcelFieldRuleService;
import com.tbyf.his.emport.service.ExcelRuleService;
import com.tbyf.his.emport.service.ExcelTemplateFieldService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Objects;
/**
* @author lzz
* @date 2023/1/10 15:53
*/
@Slf4j
@Service
@DataSource(DataSourceType.MASTER)
public class ExcelTemplateFieldServiceImpl extends ServiceImpl<ExcelTemplateFieldMapper, ExcelTemplateField> implements ExcelTemplateFieldService {
@Autowired
private ExcelTemplateFieldMapper excelTemplateFieldMapper;
@Autowired
private ExcelFieldRuleService excelFieldRuleService;
@Autowired
private ExcelRuleService excelRuleService;
@Autowired
@Lazy
private ExcelTemplateFieldService excelTemplateFieldService;
@Override
public boolean addTemplateField(AddExcelTemplateFieldParam param) {
// 表字段不能重复
final LambdaQueryWrapper<ExcelTemplateField> queryWrapper = Wrappers.lambdaQuery(ExcelTemplateField.class);
queryWrapper.eq(ExcelTemplateField::getTemplateId, param.getTemplateId())
.eq(ExcelTemplateField::getTableFieldName, param.getTableFieldName());
final long count = excelTemplateFieldService.count(queryWrapper);
if (count > 0) {
throw new BaseException("表字段名已经被使用");
}
ExcelTemplateField field = new ExcelTemplateField();
BeanUtils.copyProperties(param, field);
field.initAdd();
return excelTemplateFieldService.save(field);
}
@Override
public boolean updateTemplateField(UpdateExcelTemplateFieldParam param) {
// 表字段不能重复
final LambdaQueryWrapper<ExcelTemplateField> queryWrapper = Wrappers.lambdaQuery(ExcelTemplateField.class);
queryWrapper.eq(ExcelTemplateField::getTemplateId, param.getTemplateId())
.eq(ExcelTemplateField::getTableFieldName, param.getTableFieldName())
.ne(ExcelTemplateField::getId, param.getId());
final long count = excelTemplateFieldService.count(queryWrapper);
if (count > 0) {
throw new BaseException("表字段名已经被使用");
}
ExcelTemplateField field = new ExcelTemplateField();
BeanUtils.copyProperties(param, field);
field.initUpdate();
return excelTemplateFieldService.updateById(field);
}
@Override
public TableDataInfo queryTemplateField(QueryTemplateFieldParam param) {
final Page<ExcelTemplateField> page = Page.of(param.getPageNum(), param.getPageSize());
final LambdaQueryWrapper<ExcelTemplateField> queryWrapper = Wrappers.lambdaQuery(ExcelTemplateField.class);
queryWrapper.eq(ExcelTemplateField::getTemplateId, param.getTemplateId());
if (StringUtils.hasText(param.getKeyword())) {
queryWrapper.and(wrapper -> {
wrapper.like(ExcelTemplateField::getTemplateFieldName, param.getKeyword())
.or()
.like(ExcelTemplateField::getTableFieldName, param.getKeyword())
.or()
.like(ExcelTemplateField::getFieldTitle, param.getKeyword());
});
}
queryWrapper.orderByAsc(ExcelTemplateField::getSort);
final Page<ExcelTemplateField> templatePage = excelTemplateFieldService.page(page, queryWrapper);
return param.convert(templatePage);
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean deleteTemplateField(Long templateFieldId) {
// 先删除关联规则,再删除本类数据
final LambdaQueryWrapper<ExcelFieldRule> wrapper1 = Wrappers.lambdaQuery(ExcelFieldRule.class);
wrapper1.eq(ExcelFieldRule::getFieldId, templateFieldId);
excelFieldRuleService.remove(wrapper1);
return excelTemplateFieldService.removeById(templateFieldId);
}
@Override
public AjaxResult fieldRuleTest(String fieldId, String value) {
final List<ExcelFieldRule> list = excelFieldRuleService.list(Wrappers.lambdaQuery(ExcelFieldRule.class)
.eq(ExcelFieldRule::getFieldId, fieldId));
list.forEach(obj -> {
final RuleContent ruleContent = excelRuleService.getRuleContent(String.valueOf(obj.getRuleId()));
ruleContent.setValue(value);
final RuleValidator validator = EmportConfig.getValidator(ruleContent.getMode());
if (Objects.isNull(validator)) {
throw new BaseException("校验服务加载异常,请联系管理员");
}
validator.validate(ruleContent);
});
return AjaxResult.success();
}
}
package com.tbyf.his.emport.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbyf.his.common.annotation.DataSource;
import com.tbyf.his.common.core.page.TableDataInfo;
import com.tbyf.his.common.enums.DataSourceType;
import com.tbyf.his.common.exception.base.BaseException;
import com.tbyf.his.emport.domain.param.QueryTemplateParam;
import com.tbyf.his.emport.domain.param.UploadExcelParam;
import com.tbyf.his.emport.domain.vo.FieldInfoVO;
import com.tbyf.his.emport.entity.ExcelFieldRule;
import com.tbyf.his.emport.entity.ExcelTemplate;
import com.tbyf.his.emport.entity.ExcelTemplateField;
import com.tbyf.his.emport.mapper.ExcelTemplateMapper;
import com.tbyf.his.emport.service.EmportService;
import com.tbyf.his.emport.service.ExcelFieldRuleService;
import com.tbyf.his.emport.service.ExcelTemplateFieldService;
import com.tbyf.his.emport.service.ExcelTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author lzz
* @date 2023/1/10 15:53
*/
@Slf4j
@Service
@DataSource(DataSourceType.MASTER)
public class ExcelTemplateServiceImpl extends ServiceImpl<ExcelTemplateMapper, ExcelTemplate> implements ExcelTemplateService {
@Autowired
private ExcelTemplateMapper excelTemplateMapper;
@Autowired
private ExcelTemplateFieldService excelTemplateFieldService;
@Autowired
private ExcelFieldRuleService excelFieldRuleService;
@Autowired
@Lazy
private ExcelTemplateService excelTemplateService;
@Autowired
private EmportService emportService;
@Override
public boolean addTemplate(ExcelTemplate template) {
template.initAdd();
// 判断相同名称模板
final LambdaQueryWrapper<ExcelTemplate> queryWrapper = Wrappers.lambdaQuery(ExcelTemplate.class);
queryWrapper.eq(ExcelTemplate::getTemplateName, template.getTemplateName());
final long count = excelTemplateService.count(queryWrapper);
if (count > 0) {
throw new BaseException("已存在相同的模板名称");
}
return excelTemplateService.save(template);
}
@Override
public boolean updateTemplate(ExcelTemplate template) {
template.initUpdate();
// 判断相同名称模板
final LambdaQueryWrapper<ExcelTemplate> queryWrapper = Wrappers.lambdaQuery(ExcelTemplate.class);
queryWrapper.eq(ExcelTemplate::getTemplateName, template.getTemplateName())
.ne(ExcelTemplate::getId, template.getId());
final long count = excelTemplateService.count(queryWrapper);
if (count > 0) {
throw new BaseException("已存在相同的模板名称");
}
return excelTemplateService.updateById(template);
}
@Override
public TableDataInfo queryTemplate(QueryTemplateParam param) {
final Page<ExcelTemplate> page = Page.of(param.getPageNum(), param.getPageSize());
final LambdaQueryWrapper<ExcelTemplate> queryWrapper = Wrappers.lambdaQuery(ExcelTemplate.class);
queryWrapper.like(StringUtils.hasText(param.getKeyword()), ExcelTemplate::getTemplateName, param.getKeyword());
final Page<ExcelTemplate> templatePage = excelTemplateService.page(page, queryWrapper);
return param.convert(templatePage);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteTemplate(Long templateId) {
// 按照顺序删除,先删除字段规则绑定关系,再删除字段,再删除模板
final ExcelTemplate template = excelTemplateService.getById(templateId);
if (template == null) {
return true;
}
final List<ExcelTemplateField> templateFieldList = excelTemplateFieldService.list(Wrappers.lambdaQuery(ExcelTemplateField.class).eq(ExcelTemplateField::getTemplateId, templateId));
if (!CollectionUtils.isEmpty(templateFieldList)) {
final List<Long> fieldIdList = templateFieldList.stream().map(ExcelTemplateField::getId).collect(Collectors.toList());
excelFieldRuleService.remove(Wrappers.lambdaQuery(ExcelFieldRule.class).in(ExcelFieldRule::getFieldId, fieldIdList));
excelTemplateFieldService.removeByIds(fieldIdList);
}
return excelTemplateService.removeById(templateId);
}
@Override
public boolean importExcel(UploadExcelParam param) {
try (InputStream is = param.getFile().getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
final Sheet sheet = workbook.getSheetAt(0);
// 查询模板信息,与相对应的所有字段信息
final ExcelTemplate template = excelTemplateService.getById(param.getTemplateId());
if (template == null) {
throw new BaseException("模板ID不存在");
}
// 查询字段与模板对应的多对多列表
List<FieldInfoVO> list = excelTemplateMapper.getFieldInfoList(param.getTemplateId());
if (CollectionUtils.isEmpty(list)) {
throw new BaseException("该模板未配置字段");
}
if (com.tbyf.his.common.utils.StringUtils.equals(template.getTemplateType(), "1")) {
emportService.dynamicImportBySimple(template, list, workbook);
} else if (com.tbyf.his.common.utils.StringUtils.equals(template.getTemplateType(), "2")) {
emportService.dynamicImportByVertical(template, list, workbook);
} else {
throw new BaseException("未知的文档类型");
}
return true;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void initTemplate(UploadExcelParam param) {
try (InputStream is = param.getFile().getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
final ExcelTemplate template = excelTemplateService.getById(param.getTemplateId());
if (template == null) {
throw new BaseException("未查询到对应的模板");
}
List<ExcelTemplateField> fieldList;
if (com.tbyf.his.common.utils.StringUtils.equals("1", template.getTemplateType())) {
fieldList = emportService.initTemplateBySimple(template, workbook);
} else {
fieldList = emportService.initTemplateByVertical(template, workbook);
}
if (!CollectionUtils.isEmpty(fieldList)) {
excelTemplateService.initTemplateField(template.getId(), fieldList);
}
final Sheet sheet = workbook.getSheetAt(0);
int rows = sheet.getLastRowNum() + 1;
int x = 0;
// 查询对应的数据的列数
int code = 0, title = 0, unit = 0;
for1:
for (; x < rows; x++) {
// 查找从第几行开始
final Row row = sheet.getRow(x);
int index = 0;
final Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
final Cell cell = cellIterator.next();
final String cellValue = getStringCellValue(cell);
if (index == 0 && com.tbyf.his.common.utils.StringUtils.equals(cellValue, "代码")) {
index++;
code = cell.getColumnIndex();
} else if (index == 1 && com.tbyf.his.common.utils.StringUtils.equals(cellValue, "指标名称")) {
index++;
title = cell.getColumnIndex();
} else if (index == 2 && com.tbyf.his.common.utils.StringUtils.equals(cellValue, "计量单位")) {
unit = cell.getColumnIndex();
break for1;
}
}
}
for (int i = x + 1; i < rows; i++) {
// 查找从第几行开始
final Row row = sheet.getRow(i);
final String fieldName = getStringCellValue(row.getCell(code));
if (StringUtils.hasText(fieldName)) {
ExcelTemplateField field = new ExcelTemplateField();
field.setTemplateId(Long.valueOf(param.getTemplateId()));
field.setTemplateFieldName(fieldName);
field.setSort((long) i);
field.setFieldTitle(getStringCellValue(row.getCell(title)));
final String unitTitle = getStringCellValue(row.getCell(unit));
field.setUnitTitle(com.tbyf.his.common.utils.StringUtils.equals(unitTitle, "-") ? "" : unitTitle);
field.initAdd();
fieldList.add(field);
}
}
excelTemplateService.initTemplateField(Long.valueOf(param.getTemplateId()), fieldList);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void initTemplateField(Long templateId, List<ExcelTemplateField> list) {
final List<ExcelTemplateField> templateFields = excelTemplateFieldService.list(
Wrappers.lambdaQuery(ExcelTemplateField.class)
.eq(ExcelTemplateField::getTemplateId, templateId)
);
templateFields.forEach(field -> {
excelTemplateFieldService.deleteTemplateField(field.getId());
});
excelTemplateFieldService.saveBatch(list);
}
@Override
public void downloadTemplate(Long templateId, HttpServletResponse response) {
final ExcelTemplate template = excelTemplateService.getById(templateId);
if (template == null) {
throw new BaseException("未查询到对应模板");
}
final List<ExcelTemplateField> fieldList = excelTemplateFieldService.list(
Wrappers.lambdaQuery(ExcelTemplateField.class)
.eq(ExcelTemplateField::getTemplateId, template.getId())
.orderByAsc(ExcelTemplateField::getSort)
);
try (Workbook workbook = WorkbookFactory.create(true)) {
final Sheet sheet = workbook.createSheet(template.getRemark());
int index = 0;
final Row titleRow = sheet.createRow(index++);
final Cell titleCell = titleRow.createCell(1);
titleCell.setCellValue(template.getRemark());
final CellStyle titleStyle = workbook.createCellStyle();
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
titleCell.setCellStyle(titleStyle);
// 合并标题单元格
sheet.addMergedRegion(new CellRangeAddress(0, 0, 1, 4));
// 样式
sheet.setColumnWidth(0, 0);
sheet.setColumnWidth(1, 2867);
sheet.setColumnWidth(2, 6400);
sheet.setColumnWidth(3, 7936);
sheet.setColumnWidth(4, 2739);
sheet.setDefaultRowHeight((short) 360);
workbook.write(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public String getStringCellValue(Cell cell) {
final CellType cellType = cell.getCellType();
switch (cellType) {
case STRING:
return cell.getStringCellValue().trim();
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case NUMERIC:
return ((XSSFCell) cell).getCTCell().getV();
default:
return "";
}
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tbyf.his.emport.mapper.ExcelFieldRuleMapper">
<select id="listFieldRule" resultType="com.tbyf.his.emport.entity.ExcelRule">
select ER.ID AS id,
ER.RULE_NAME AS ruleName
from EXCEL_FIELD_RULE EFR
left join EXCEL_RULE ER
on EFR.RULE_ID = ER.ID
where FIELD_ID = #{fieldId}
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tbyf.his.emport.mapper.ExcelTemplateMapper">
<resultMap id="FIELD_WITH_RULE" type="com.tbyf.his.emport.domain.vo.FieldInfoVO">
<id property="id" column="fieldId"/>
<result property="fieldName" column="fieldName"/>
<result property="dataFieldName" column="dataFieldName"/>
<result property="dataType" column="dataType"/>
<result property="fieldAddress" column="fieldAddress"/>
<result property="fieldLocation" column="fieldLocation"/>
<result property="sort" column="sort"/>
<result property="fieldTitle" column="fieldTitle"/>
<result property="unitTitle" column="unitTitle"/>
<collection property="ruleList" ofType="com.tbyf.his.emport.domain.vo.RuleInfoVo">
<id property="id" column="ruleId"/>
<result property="name" column="name"/>
<result property="type" column="type"/>
<result property="mode" column="modeType"/>
<result property="content" column="content"/>
</collection>
</resultMap>
<select id="getFieldInfoList" resultMap="FIELD_WITH_RULE">
SELECT ETF.ID AS fieldId,
ETF.TEMPLATE_FIELD_NAME AS fieldName,
ETF.TABLE_FIELD_NAME AS dataFieldName,
ETF.SORT AS sort,
ETF.FIELD_TITLE AS fieldTitle,
ETF.UNIT_TITLE AS unitTitle,
ETF.DATA_TYPE AS dataType,
ETF.FIELD_ADDRESS AS fieldAddress,
ETF.FIELD_LOCATION AS fieldLocation,
ER.ID AS ruleId,
ER.RULE_NAME AS name,
ER.RULE_TYPE AS type,
ER.RULE_MODE AS modeType,
ER.RULE_CONTENT AS content
FROM EXCEL_TEMPLATE_FIELD ETF
LEFT JOIN EXCEL_FIELD_RULE EFR ON ETF.ID = EFR.FIELD_ID
LEFT JOIN EXCEL_RULE ER ON EFR.RULE_ID = ER.ID
WHERE ETF.TEMPLATE_ID = #{templateId}
AND ETF.TABLE_FIELD_NAME IS NOT NULL
ORDER BY ETF.SORT
</select>
</mapper>
\ No newline at end of file
create table data_dict
(
id varchar(32) not null
primary key,
type varchar(32) null comment '字典类型',
label varchar(256) null comment '标签',
value varchar(64) null comment '数据值',
remarks text null comment '备注'
) comment '数据字典';
create table data_import_template
(
id varchar(32) not null
primary key,
name varchar(256) null comment '模板名称',
org_name varchar(64) null comment '机构类型',
import_status varchar(32) null comment '导入状态 1-已导入 0-未导入',
year varchar(32) null comment '数据年份',
import_time timestamp null comment '上次导入时间',
datasource_id varchar(32) null comment '数据源ID',
table_name varchar(32) null comment '表名',
create_time timestamp null comment '创建时间',
update_time timestamp null comment '更新时间',
remarks text null comment '备注'
) comment '数据导入模板表';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment