yshop1.7发布,后台升級eladmin2.4(前端,后台权限,代码生成器等重构),修复商品分类等一些问题

This commit is contained in:
hupeng
2020-01-07 23:24:01 +08:00
parent b5c4386963
commit 2c9816d57d
490 changed files with 14611 additions and 7104 deletions

View File

@ -0,0 +1,77 @@
package co.yixiang.domain;
import co.yixiang.utils.GenUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
/**
* 列的数据信息
* @author Zheng Jie
* @date 2019-01-02
*/
@Data
@Entity
@NoArgsConstructor
@Table(name = "column_config")
public class ColumnInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
private String tableName;
/** 数据库字段名称 */
private String columnName;
/** 数据库字段类型 */
private String columnType;
/** 数据库字段键类型 */
private String keyType;
/** 字段额外的参数 */
private String extra;
/** 数据库字段描述 */
private String remark;
/** 必填 */
private Boolean notNull;
/** 是否在列表显示 */
private Boolean listShow;
/** 是否表单显示 */
private Boolean formShow;
/** 表单类型 */
private String formType;
/** 查询 1:模糊 2精确 */
private String queryType;
/** 字典名称 */
private String dictName;
/** 日期注解 */
private String dateAnnotation;
public ColumnInfo(String tableName, String columnName, Boolean notNull, String columnType, String remark, String keyType, String extra) {
this.tableName = tableName;
this.columnName = columnName;
this.columnType = columnType;
this.keyType = keyType;
this.extra = extra;
this.notNull = notNull;
if(GenUtil.PK.equalsIgnoreCase(keyType) && GenUtil.EXTRA.equalsIgnoreCase(extra)){
this.notNull = false;
}
this.remark = remark;
this.listShow = true;
this.formShow = true;
}
}

View File

@ -1,8 +1,9 @@
package co.yixiang.domain;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
import javax.validation.constraints.NotBlank;
/**
* 代码生成配置
@ -11,32 +12,50 @@ import java.io.Serializable;
*/
@Data
@Entity
@NoArgsConstructor
@Table(name = "gen_config")
public class GenConfig implements Serializable {
public class GenConfig {
public GenConfig(String tableName) {
this.cover = false;
this.moduleName = "yshop-system";
this.tableName = tableName;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
/** 包路径 **/
@NotBlank
private String tableName;
/** 接口名称 **/
private String apiAlias;
/** 包路径 */
@NotBlank
private String pack;
/** 模块名 **/
/** 模块名 */
@Column(name = "module_name")
@NotBlank
private String moduleName;
/** 前端文件路径 **/
/** 前端文件路径 */
@NotBlank
private String path;
/** 前端文件路径 **/
/** 前端文件路径 */
@Column(name = "api_path")
private String apiPath;
/** 作者 **/
/** 作者 */
private String author;
/** 表前缀 **/
/** 表前缀 */
private String prefix;
/** 是否覆盖 **/
/** 是否覆盖 */
private Boolean cover;
}

View File

@ -14,19 +14,19 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
public class TableInfo {
/** 表名称 **/
/** 表名称 */
private Object tableName;
/** 创建日期 **/
/** 创建日期 */
private Object createTime;
// 数据库引擎
/** 数据库引擎 */
private Object engine;
// 编码集
/** 编码集 */
private Object coding;
// 备注
/** 备注 */
private Object remark;

View File

@ -0,0 +1,19 @@
package co.yixiang.repository;
import co.yixiang.domain.ColumnInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-01-14
*/
public interface ColumnInfoRepository extends JpaRepository<ColumnInfo,Long> {
/**
* 查询表信息
* @param tableName 表格名
* @return 表信息
*/
List<ColumnInfo> findByTableNameOrderByIdAsc(String tableName);
}

View File

@ -8,4 +8,11 @@ import org.springframework.data.jpa.repository.JpaRepository;
* @date 2019-01-14
*/
public interface GenConfigRepository extends JpaRepository<GenConfig,Long> {
/**
* 查询表配置
* @param tableName 表名
* @return /
*/
GenConfig findByTableName(String tableName);
}

View File

@ -1,8 +1,9 @@
package co.yixiang.rest;
import co.yixiang.service.GenConfigService;
import co.yixiang.domain.GenConfig;
import org.springframework.beans.factory.annotation.Autowired;
import co.yixiang.service.GenConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
@ -13,23 +14,25 @@ import org.springframework.web.bind.annotation.*;
* @date 2019-01-14
*/
@RestController
@RequestMapping("api")
@RequestMapping("/api/genConfig")
@Api(tags = "系统:代码生成器配置管理")
public class GenConfigController {
@Autowired
private GenConfigService genConfigService;
private final GenConfigService genConfigService;
/**
* 查询生成器配置
* @return
*/
@GetMapping(value = "/genConfig")
public ResponseEntity get(){
return new ResponseEntity(genConfigService.find(), HttpStatus.OK);
public GenConfigController(GenConfigService genConfigService) {
this.genConfigService = genConfigService;
}
@PutMapping(value = "/genConfig")
public ResponseEntity emailConfig(@Validated @RequestBody GenConfig genConfig){
return new ResponseEntity(genConfigService.update(genConfig),HttpStatus.OK);
@ApiOperation("查询")
@GetMapping(value = "/{tableName}")
public ResponseEntity<Object> get(@PathVariable String tableName){
return new ResponseEntity<>(genConfigService.find(tableName), HttpStatus.OK);
}
@ApiOperation("修改")
@PutMapping
public ResponseEntity<Object> emailConfig(@Validated @RequestBody GenConfig genConfig){
return new ResponseEntity<>(genConfigService.update(genConfig.getTableName(), genConfig),HttpStatus.OK);
}
}

View File

@ -1,15 +1,18 @@
package co.yixiang.rest;
import cn.hutool.core.util.PageUtil;
import co.yixiang.domain.vo.ColumnInfo;
import co.yixiang.domain.ColumnInfo;
import co.yixiang.service.GenConfigService;
import co.yixiang.service.GeneratorService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import co.yixiang.exception.BadRequestException;
import org.springframework.beans.factory.annotation.Autowired;
import co.yixiang.utils.PageUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@ -17,54 +20,77 @@ import java.util.List;
* @date 2019-01-02
*/
@RestController
@RequestMapping("api")
@RequestMapping("/api/generator")
@Api(tags = "系统:代码生成管理")
public class GeneratorController {
@Autowired
private GeneratorService generatorService;
private final GeneratorService generatorService;
@Autowired
private GenConfigService genConfigService;
private final GenConfigService genConfigService;
@Value("${generator.enabled}")
private Boolean generatorEnabled;
/**
* 查询数据库元数据
* @param name
* @param page
* @param size
* @return
*/
@GetMapping(value = "/generator/tables")
public ResponseEntity getTables(@RequestParam(defaultValue = "") String name,
@RequestParam(defaultValue = "0")Integer page,
@RequestParam(defaultValue = "10")Integer size){
public GeneratorController(GeneratorService generatorService, GenConfigService genConfigService) {
this.generatorService = generatorService;
this.genConfigService = genConfigService;
}
@ApiOperation("查询数据库数据")
@GetMapping(value = "/tables/all")
public ResponseEntity<Object> getTables(){
return new ResponseEntity<>(generatorService.getTables(), HttpStatus.OK);
}
@ApiOperation("查询数据库数据")
@GetMapping(value = "/tables")
public ResponseEntity<Object> getTables(@RequestParam(defaultValue = "") String name,
@RequestParam(defaultValue = "0")Integer page,
@RequestParam(defaultValue = "10")Integer size){
int[] startEnd = PageUtil.transToStartEnd(page+1, size);
return new ResponseEntity(generatorService.getTables(name,startEnd), HttpStatus.OK);
return new ResponseEntity<>(generatorService.getTables(name,startEnd), HttpStatus.OK);
}
/**
* 查询表内元数据
* @param tableName
* @return
*/
@GetMapping(value = "/generator/columns")
public ResponseEntity getTables(@RequestParam String tableName){
return new ResponseEntity(generatorService.getColumns(tableName), HttpStatus.OK);
@ApiOperation("查询字段数据")
@GetMapping(value = "/columns")
public ResponseEntity<Object> getTables(@RequestParam String tableName){
List<ColumnInfo> columnInfos = generatorService.getColumns(tableName);
return new ResponseEntity<>(PageUtil.toPage(columnInfos,columnInfos.size()), HttpStatus.OK);
}
/**
* 生成代码
* @param columnInfos
* @return
*/
@PostMapping(value = "/generator")
public ResponseEntity generator(@RequestBody List<ColumnInfo> columnInfos, @RequestParam String tableName){
if(!generatorEnabled){
throw new BadRequestException("此环境不允许生成代码!");
@ApiOperation("保存字段数据")
@PutMapping
public ResponseEntity<HttpStatus> save(@RequestBody List<ColumnInfo> columnInfos){
generatorService.save(columnInfos);
return new ResponseEntity<>(HttpStatus.OK);
}
@ApiOperation("同步字段数据")
@PostMapping(value = "sync")
public ResponseEntity<HttpStatus> sync(@RequestBody List<String> tables){
for (String table : tables) {
generatorService.sync(generatorService.getColumns(table), generatorService.query(table));
}
generatorService.generator(columnInfos,genConfigService.find(),tableName);
return new ResponseEntity(HttpStatus.OK);
return new ResponseEntity<>(HttpStatus.OK);
}
@ApiOperation("生成代码")
@PostMapping(value = "/{tableName}/{type}")
public ResponseEntity<Object> generator(@PathVariable String tableName, @PathVariable Integer type, HttpServletRequest request, HttpServletResponse response){
if(!generatorEnabled && type == 0){
throw new BadRequestException("此环境不允许生成代码,请选择预览或者下载查看!");
}
switch (type){
// 生成代码
case 0: generatorService.generator(genConfigService.find(tableName), generatorService.getColumns(tableName));
break;
// 预览
case 1: return generatorService.preview(genConfigService.find(tableName), generatorService.getColumns(tableName));
// 打包
case 2: generatorService.download(genConfigService.find(tableName), generatorService.getColumns(tableName), request, response);
break;
default: throw new BadRequestException("没有这个选项");
}
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -1,29 +1,25 @@
package co.yixiang.service;
import co.yixiang.domain.GenConfig;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
/**
* @author Zheng Jie
* @date 2019-01-14
*/
@CacheConfig(cacheNames = "genConfig")
public interface GenConfigService {
/**
* find
* @return
* 查询表配置
* @param tableName 表名
* @return 表配置
*/
@Cacheable(key = "'1'")
GenConfig find();
GenConfig find(String tableName);
/**
* update
* @param genConfig
* @return
* 更新表配置
* @param tableName 表名
* @param genConfig 表配置
* @return 表配置
*/
@CacheEvict(allEntries = true)
GenConfig update(GenConfig genConfig);
GenConfig update(String tableName, GenConfig genConfig);
}

View File

@ -1,7 +1,11 @@
package co.yixiang.service;
import co.yixiang.domain.ColumnInfo;
import co.yixiang.domain.GenConfig;
import co.yixiang.domain.vo.ColumnInfo;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
@ -12,24 +16,67 @@ public interface GeneratorService {
/**
* 查询数据库元数据
* @param name
* @param startEnd
* @return
* @param name 表名
* @param startEnd 分页参数
* @return /
*/
Object getTables(String name, int[] startEnd);
/**
* 得到数据表的元数据
* @param name
* @return
* @param name 表名
* @return /
*/
Object getColumns(String name);
List<ColumnInfo> getColumns(String name);
/**
* 生成代码
* @param columnInfos
* @param genConfig
* @param tableName
* 同步表数据
* @param columnInfos /
* @param columnInfoList
*/
void generator(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName);
@Async
void sync(List<ColumnInfo> columnInfos, List<ColumnInfo> columnInfoList);
/**
* 保持数据
* @param columnInfos /
*/
void save(List<ColumnInfo> columnInfos);
/**
* 获取所有table
* @return /
*/
Object getTables();
/**
* 代码生成
* @param genConfig 配置信息
* @param columns 字段信息
*/
void generator(GenConfig genConfig, List<ColumnInfo> columns);
/**
* 预览
* @param genConfig 配置信息
* @param columns 字段信息
* @return /
*/
ResponseEntity<Object> preview(GenConfig genConfig, List<ColumnInfo> columns);
/**
* 打包下载
* @param genConfig 配置信息
* @param columns 字段信息
* @param request /
* @param response /
*/
void download(GenConfig genConfig, List<ColumnInfo> columns, HttpServletRequest request, HttpServletResponse response);
/**
* 查询数据库的表字段数据数据
* @param table /
* @return /
*/
List<ColumnInfo> query(String table);
}

View File

@ -1,53 +1,63 @@
package co.yixiang.service.impl;
import co.yixiang.domain.GenConfig;
import co.yixiang.repository.GenConfigRepository;
import co.yixiang.service.GenConfigService;
import co.yixiang.domain.GenConfig;
import org.springframework.beans.factory.annotation.Autowired;
import co.yixiang.utils.StringUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.Optional;
/**
* @author Zheng Jie
* @date 2019-01-14
*/
@Service
@CacheConfig(cacheNames = "genConfig")
public class GenConfigServiceImpl implements GenConfigService {
@Autowired
private GenConfigRepository genConfigRepository;
private final GenConfigRepository genConfigRepository;
@Override
public GenConfig find() {
Optional<GenConfig> genConfig = genConfigRepository.findById(1L);
if(genConfig.isPresent()){
return genConfig.get();
} else {
return new GenConfig();
}
public GenConfigServiceImpl(GenConfigRepository genConfigRepository) {
this.genConfigRepository = genConfigRepository;
}
@Override
public GenConfig update(GenConfig genConfig) {
genConfig.setId(1L);
// 自动设置Api路径注释掉前需要同步取消前端的注释
String separator = File.separator;
String[] paths = null;
if (separator.equals("\\")) {
paths = genConfig.getPath().split("\\\\");
} else paths = genConfig.getPath().split(File.separator);
StringBuffer api = new StringBuffer();
for (int i = 0; i < paths.length; i++) {
api.append(paths[i]);
api.append(separator);
if(paths[i].equals("src")){
api.append("api");
break;
}
@Cacheable(key = "#p0")
public GenConfig find(String tableName) {
GenConfig genConfig = genConfigRepository.findByTableName(tableName);
if(genConfig == null){
return new GenConfig(tableName);
}
return genConfig;
}
@Override
@CachePut(key = "#p0")
public GenConfig update(String tableName, GenConfig genConfig) {
// 如果 api 路径为空,则自动生成路径
if(StringUtils.isBlank(genConfig.getApiPath())){
String separator = File.separator;
String[] paths;
String symbol = "\\";
if (symbol.equals(separator)) {
paths = genConfig.getPath().split("\\\\");
} else {
paths = genConfig.getPath().split(File.separator);
}
StringBuilder api = new StringBuilder();
for (String path : paths) {
api.append(path);
api.append(separator);
if ("src".equals(path)) {
api.append("api");
break;
}
}
genConfig.setApiPath(api.toString());
}
genConfig.setApiPath(api.toString());
return genConfigRepository.save(genConfig);
}
}

View File

@ -1,32 +1,60 @@
package co.yixiang.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import co.yixiang.domain.vo.ColumnInfo;
import co.yixiang.service.GeneratorService;
import cn.hutool.core.util.ZipUtil;
import co.yixiang.domain.ColumnInfo;
import co.yixiang.domain.GenConfig;
import co.yixiang.utils.GenUtil;
import co.yixiang.domain.vo.TableInfo;
import co.yixiang.exception.BadRequestException;
import co.yixiang.utils.GenUtil;
import co.yixiang.repository.ColumnInfoRepository;
import co.yixiang.service.GeneratorService;
import co.yixiang.utils.FileUtil;
import co.yixiang.utils.PageUtil;
import co.yixiang.utils.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2019-01-02
*/
@Service
@SuppressWarnings({"unchecked","all"})
public class GeneratorServiceImpl implements GeneratorService {
@PersistenceContext
private EntityManager em;
private final ColumnInfoRepository columnInfoRepository;
public GeneratorServiceImpl(ColumnInfoRepository columnInfoRepository) {
this.columnInfoRepository = columnInfoRepository;
}
@Override
public Object getTables() {
// 使用预编译防止sql注入
String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " +
"where table_schema = (select database()) " +
"order by create_time desc";
Query query = em.createNativeQuery(sql);
return query.getResultList();
}
@Override
public Object getTables(String name, int[] startEnd) {
// 使用预编译防止sql注入
@ -37,10 +65,11 @@ public class GeneratorServiceImpl implements GeneratorService {
query.setFirstResult(startEnd[0]);
query.setMaxResults(startEnd[1]-startEnd[0]);
query.setParameter(1, StringUtils.isNotBlank(name) ? ("%" + name + "%") : "%%");
List<Object[]> result = query.getResultList();
List result = query.getResultList();
List<TableInfo> tableInfos = new ArrayList<>();
for (Object[] obj : result) {
tableInfos.add(new TableInfo(obj[0],obj[1],obj[2],obj[3], ObjectUtil.isNotEmpty(obj[4])? obj[4] : "-"));
for (Object obj : result) {
Object[] arr = (Object[]) obj;
tableInfos.add(new TableInfo(arr[0],arr[1],arr[2],arr[3], ObjectUtil.isNotEmpty(arr[4])? arr[4] : "-"));
}
Query query1 = em.createNativeQuery("SELECT COUNT(*) from information_schema.tables where table_schema = (select database())");
Object totalElements = query1.getSingleResult();
@ -48,30 +77,112 @@ public class GeneratorServiceImpl implements GeneratorService {
}
@Override
public Object getColumns(String name) {
public List<ColumnInfo> getColumns(String tableName) {
List<ColumnInfo> columnInfos = columnInfoRepository.findByTableNameOrderByIdAsc(tableName);
if(CollectionUtil.isNotEmpty(columnInfos)){
return columnInfos;
} else {
columnInfos = query(tableName);
return columnInfoRepository.saveAll(columnInfos);
}
}
@Override
public List<ColumnInfo> query(String tableName){
// 使用预编译防止sql注入
String sql = "select column_name, is_nullable, data_type, column_comment, column_key, extra from information_schema.columns " +
"where table_name = ? and table_schema = (select database()) order by ordinal_position";
Query query = em.createNativeQuery(sql);
query.setParameter(1, StringUtils.isNotBlank(name) ? name : null);
List<Object[]> result = query.getResultList();
query.setParameter(1,tableName);
List result = query.getResultList();
List<ColumnInfo> columnInfos = new ArrayList<>();
for (Object[] obj : result) {
columnInfos.add(new ColumnInfo(obj[0],obj[1],obj[2],obj[3],obj[4],obj[5],null,"true"));
for (Object obj : result) {
Object[] arr = (Object[]) obj;
columnInfos.add(
new ColumnInfo(
tableName,
arr[0].toString(),
"NO".equals(arr[1]),
arr[2].toString(),
ObjectUtil.isNotNull(arr[3]) ? arr[3].toString() : null,
ObjectUtil.isNotNull(arr[4]) ? arr[4].toString() : null,
ObjectUtil.isNotNull(arr[5]) ? arr[5].toString() : null)
);
}
return PageUtil.toPage(columnInfos,columnInfos.size());
return columnInfos;
}
@Override
public void generator(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName) {
public void sync(List<ColumnInfo> columnInfos, List<ColumnInfo> columnInfoList) {
// 第一种情况,数据库类字段改变或者新增字段
for (ColumnInfo columnInfo : columnInfoList) {
// 根据字段名称查找
List<ColumnInfo> columns = new ArrayList<ColumnInfo>(columnInfos.stream().filter(c-> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList()));
// 如果能找到,就修改部分可能被字段
if(CollectionUtil.isNotEmpty(columns)){
ColumnInfo column = columns.get(0);
column.setColumnType(columnInfo.getColumnType());
column.setExtra(columnInfo.getExtra());
column.setKeyType(columnInfo.getKeyType());
if(StringUtils.isBlank(column.getRemark())){
column.setRemark(columnInfo.getRemark());
}
columnInfoRepository.save(column);
} else {
// 如果找不到,则保存新字段信息
columnInfoRepository.save(columnInfo);
}
}
// 第二种情况,数据库字段删除了
for (ColumnInfo columnInfo : columnInfos) {
// 根据字段名称查找
List<ColumnInfo> columns = new ArrayList<ColumnInfo>(columnInfoList.stream().filter(c-> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList()));
// 如果找不到,就代表字段被删除了,则需要删除该字段
if(CollectionUtil.isEmpty(columns)){
columnInfoRepository.delete(columnInfo);
}
}
}
@Override
public void save(List<ColumnInfo> columnInfos) {
columnInfoRepository.saveAll(columnInfos);
}
@Override
public void generator(GenConfig genConfig, List<ColumnInfo> columns) {
if(genConfig.getId() == null){
throw new BadRequestException("请先配置生成器");
}
try {
GenUtil.generatorCode(columnInfos,genConfig,tableName);
GenUtil.generatorCode(columns, genConfig);
} catch (IOException e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
e.printStackTrace();
throw new BadRequestException("生成失败,请手动处理已生成的文件");
}
}
@Override
public ResponseEntity<Object> preview(GenConfig genConfig, List<ColumnInfo> columns) {
if(genConfig.getId() == null){
throw new BadRequestException("请先配置生成器");
}
List<Map<String,Object>> genList = GenUtil.preview(columns, genConfig);
return new ResponseEntity<>(genList, HttpStatus.OK);
}
@Override
public void download(GenConfig genConfig, List<ColumnInfo> columns, HttpServletRequest request, HttpServletResponse response) {
if(genConfig.getId() == null){
throw new BadRequestException("请先配置生成器");
}
try {
File file = new File(GenUtil.download(columns, genConfig));
String zipPath = file.getPath() + ".zip";
ZipUtil.zip(file.getPath(), zipPath);
FileUtil.downloadFile(request, response, new File(zipPath), true);
} catch (IOException e) {
throw new BadRequestException("打包失败");
}
}
}

View File

@ -12,11 +12,12 @@ public class ColUtil {
/**
* 转换mysql数据类型为java数据类型
* @param type
* @return
* @param type 数据库字段类型
* @return String
*/
public static String cloToJava(String type){
static String cloToJava(String type){
Configuration config = getConfig();
assert config != null;
return config.getString(type,"unknowType");
}

View File

@ -2,19 +2,16 @@ package co.yixiang.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.template.*;
import co.yixiang.domain.GenConfig;
import co.yixiang.domain.vo.ColumnInfo;
import lombok.extern.slf4j.Slf4j;
import co.yixiang.domain.GenConfig;
import co.yixiang.domain.ColumnInfo;
import org.springframework.util.ObjectUtils;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* 代码生成
@ -22,122 +19,119 @@ import java.util.Map;
* @date 2019-01-02
*/
@Slf4j
@SuppressWarnings("all")
public class GenUtil {
private static final String TIMESTAMP = "Timestamp";
private static final String BIGDECIMAL = "BigDecimal";
private static final String PK = "PRI";
public static final String PK = "PRI";
private static final String EXTRA = "auto_increment";
public static final String EXTRA = "auto_increment";
/**
* 获取后端代码模板名称
* @return
* @return List
*/
public static List<String> getAdminTemplateNames() {
private static List<String> getAdminTemplateNames() {
List<String> templateNames = new ArrayList<>();
templateNames.add("Entity");
templateNames.add("Dto");
templateNames.add("Mapper");
templateNames.add("Repository");
templateNames.add("Controller");
templateNames.add("QueryCriteria");
templateNames.add("Service");
templateNames.add("ServiceImpl");
templateNames.add("QueryCriteria");
templateNames.add("Controller");
templateNames.add("Repository");
return templateNames;
}
/**
* 获取前端代码模板名称
* @return
* @return List
*/
public static List<String> getFrontTemplateNames() {
private static List<String> getFrontTemplateNames() {
List<String> templateNames = new ArrayList<>();
templateNames.add("api");
templateNames.add("index");
templateNames.add("eForm");
templateNames.add("api");
return templateNames;
}
/**
* 生成代码
* @param columnInfos 表元数据
* @param genConfig 生成代码的参数配置,如包路径,作者
*/
public static void generatorCode(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName) throws IOException {
Map<String,Object> map = new HashMap();
map.put("package",genConfig.getPack());
map.put("moduleName",genConfig.getModuleName());
map.put("author",genConfig.getAuthor());
map.put("date", LocalDate.now().toString());
map.put("tableName",tableName);
String className = StringUtils.toCapitalizeCamelCase(tableName);
String changeClassName = StringUtils.toCamelCase(tableName);
// 判断是否去除表前缀
if (StringUtils.isNotEmpty(genConfig.getPrefix())) {
className = StringUtils.toCapitalizeCamelCase(StrUtil.removePrefix(tableName,genConfig.getPrefix()));
changeClassName = StringUtils.toCamelCase(StrUtil.removePrefix(tableName,genConfig.getPrefix()));
}
map.put("className", className);
map.put("upperCaseClassName", className.toUpperCase());
map.put("changeClassName", changeClassName);
map.put("hasTimestamp",false);
map.put("hasBigDecimal",false);
map.put("hasQuery",false);
map.put("auto",false);
List<Map<String,Object>> columns = new ArrayList<>();
List<Map<String,Object>> queryColumns = new ArrayList<>();
for (ColumnInfo column : columnInfos) {
Map<String,Object> listMap = new HashMap();
listMap.put("columnComment",column.getColumnComment());
listMap.put("columnKey",column.getColumnKey());
String colType = ColUtil.cloToJava(column.getColumnType().toString());
String changeColumnName = StringUtils.toCamelCase(column.getColumnName().toString());
String capitalColumnName = StringUtils.toCapitalizeCamelCase(column.getColumnName().toString());
if(PK.equals(column.getColumnKey())){
map.put("pkColumnType",colType);
map.put("pkChangeColName",changeColumnName);
map.put("pkCapitalColName",capitalColumnName);
}
if(TIMESTAMP.equals(colType)){
map.put("hasTimestamp",true);
}
if(BIGDECIMAL.equals(colType)){
map.put("hasBigDecimal",true);
}
if(EXTRA.equals(column.getExtra())){
map.put("auto",true);
}
listMap.put("columnType",colType);
listMap.put("columnName",column.getColumnName());
listMap.put("isNullable",column.getIsNullable());
listMap.put("columnShow",column.getColumnShow());
listMap.put("changeColumnName",changeColumnName);
listMap.put("capitalColumnName",capitalColumnName);
// 判断是否有查询如有则把查询的字段set进columnQuery
if(!StringUtils.isBlank(column.getColumnQuery())){
listMap.put("columnQuery",column.getColumnQuery());
map.put("hasQuery",true);
queryColumns.add(listMap);
}
columns.add(listMap);
}
map.put("columns",columns);
map.put("queryColumns",queryColumns);
public static List<Map<String, Object>> preview(List<ColumnInfo> columns, GenConfig genConfig) {
Map<String,Object> genMap = getGenMap(columns, genConfig);
List<Map<String,Object>> genList = new ArrayList<>();
// 获取后端模版
List<String> templates = getAdminTemplateNames();
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
for (String templateName : templates) {
Map<String,Object> map = new HashMap<>(1);
Template template = engine.getTemplate("generator/admin/"+templateName+".ftl");
map.put("content", template.render(genMap));
map.put("name", templateName);
genList.add(map);
}
// 获取前端模版
templates = getFrontTemplateNames();
for (String templateName : templates) {
Map<String,Object> map = new HashMap<>(1);
Template template = engine.getTemplate("generator/front/"+templateName+".ftl");
map.put(templateName, template.render(genMap));
map.put("content", template.render(genMap));
map.put("name", templateName);
genList.add(map);
}
return genList;
}
public static String download(List<ColumnInfo> columns, GenConfig genConfig) throws IOException {
String tempPath =System.getProperty("java.io.tmpdir") + "yshop-gen-temp" + File.separator + genConfig.getTableName() + File.separator;
Map<String,Object> genMap = getGenMap(columns, genConfig);
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
// 生成后端代码
List<String> templates = getAdminTemplateNames();
for (String templateName : templates) {
Template template = engine.getTemplate("generator/admin/"+templateName+".ftl");
String filePath = getAdminFilePath(templateName,genConfig,className);
String filePath = getAdminFilePath(templateName,genConfig,genMap.get("className").toString(),tempPath + "yshop" + File.separator);
assert filePath != null;
File file = new File(filePath);
// 如果非覆盖生成
if(!genConfig.getCover() && FileUtil.exist(file)){
continue;
}
// 生成代码
genFile(file, template, genMap);
}
// 生成前端代码
templates = getFrontTemplateNames();
for (String templateName : templates) {
Template template = engine.getTemplate("generator/front/"+templateName+".ftl");
String path = tempPath + "yshop-web" + File.separator;
String apiPath = path + "src" + File.separator + "api" + File.separator;
String srcPath = path + "src" + File.separator + "views" + File.separator + genMap.get("changeClassName").toString() + File.separator;
String filePath = getFrontFilePath(templateName, apiPath, srcPath, genMap.get("changeClassName").toString());
assert filePath != null;
File file = new File(filePath);
// 如果非覆盖生成
if(!genConfig.getCover() && FileUtil.exist(file)){
continue;
}
// 生成代码
genFile(file, template, genMap);
}
return tempPath;
}
public static void generatorCode(List<ColumnInfo> columnInfos, GenConfig genConfig) throws IOException {
Map<String,Object> genMap = getGenMap(columnInfos, genConfig);
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
// 生成后端代码
List<String> templates = getAdminTemplateNames();
for (String templateName : templates) {
Template template = engine.getTemplate("generator/admin/"+templateName+".ftl");
String filePath = getAdminFilePath(templateName,genConfig,genMap.get("className").toString(),System.getProperty("user.dir"));
assert filePath != null;
File file = new File(filePath);
// 如果非覆盖生成
@ -145,15 +139,16 @@ public class GenUtil {
continue;
}
// 生成代码
genFile(file, template, map);
genFile(file, template, genMap);
}
// 生成前端代码
templates = getFrontTemplateNames();
for (String templateName : templates) {
Template template = engine.getTemplate("generator/front/"+templateName+".ftl");
String filePath = getFrontFilePath(templateName,genConfig,map.get("changeClassName").toString());
String filePath = getFrontFilePath(templateName,genConfig.getApiPath(),genConfig.getPath(),genMap.get("changeClassName").toString());
assert filePath != null;
File file = new File(filePath);
// 如果非覆盖生成
@ -161,15 +156,173 @@ public class GenUtil {
continue;
}
// 生成代码
genFile(file, template, map);
genFile(file, template, genMap);
}
}
// 获取模版数据
private static Map<String,Object> getGenMap(List<ColumnInfo> columnInfos, GenConfig genConfig) {
// 存储模版字段数据
Map<String,Object> genMap = new HashMap<>(16);
// 接口别名
genMap.put("apiAlias",genConfig.getApiAlias());
// 包名称
genMap.put("package",genConfig.getPack());
// 模块名称
genMap.put("moduleName",genConfig.getModuleName());
// 作者
genMap.put("author",genConfig.getAuthor());
// 创建日期
genMap.put("date", LocalDate.now().toString());
// 表名
genMap.put("tableName",genConfig.getTableName());
// 大写开头的类名
String className = StringUtils.toCapitalizeCamelCase(genConfig.getTableName());
// 小写开头的类名
String changeClassName = StringUtils.toCamelCase(genConfig.getTableName());
// 判断是否去除表前缀
if (StringUtils.isNotEmpty(genConfig.getPrefix())) {
className = StringUtils.toCapitalizeCamelCase(StrUtil.removePrefix(genConfig.getTableName(),genConfig.getPrefix()));
changeClassName = StringUtils.toCamelCase(StrUtil.removePrefix(genConfig.getTableName(),genConfig.getPrefix()));
}
// 保存类名
genMap.put("className", className);
// 保存小写开头的类名
genMap.put("changeClassName", changeClassName);
// 存在 Timestamp 字段
genMap.put("hasTimestamp",false);
// 查询类中存在 Timestamp 字段
genMap.put("queryHasTimestamp",false);
// 存在 BigDecimal 字段
genMap.put("hasBigDecimal",false);
// 查询类中存在 BigDecimal 字段
genMap.put("queryHasBigDecimal",false);
// 是否需要创建查询
genMap.put("hasQuery",false);
// 自增主键
genMap.put("auto",false);
// 存在字典
genMap.put("hasDict",false);
// 存在日期注解
genMap.put("hasDateAnnotation",false);
// 保存字段信息
List<Map<String,Object>> columns = new ArrayList<>();
// 保存查询字段的信息
List<Map<String,Object>> queryColumns = new ArrayList<>();
// 存储字典信息
List<String> dicts = new ArrayList<>();
// 存储 between 信息
List<Map<String,Object>> betweens = new ArrayList<>();
// 存储不为空的字段信息
List<Map<String,Object>> isNotNullColumns = new ArrayList<>();
for (ColumnInfo column : columnInfos) {
Map<String,Object> listMap = new HashMap<>(16);
// 字段描述
listMap.put("remark",column.getRemark());
// 字段类型
listMap.put("columnKey",column.getKeyType());
// 主键类型
String colType = ColUtil.cloToJava(column.getColumnType());
// 小写开头的字段名
String changeColumnName = StringUtils.toCamelCase(column.getColumnName().toString());
// 大写开头的字段名
String capitalColumnName = StringUtils.toCapitalizeCamelCase(column.getColumnName().toString());
if(PK.equals(column.getKeyType())){
// 存储主键类型
genMap.put("pkColumnType",colType);
// 存储小写开头的字段名
genMap.put("pkChangeColName",changeColumnName);
// 存储大写开头的字段名
genMap.put("pkCapitalColName",capitalColumnName);
}
// 是否存在 Timestamp 类型的字段
if(TIMESTAMP.equals(colType)){
genMap.put("hasTimestamp",true);
}
// 是否存在 BigDecimal 类型的字段
if(BIGDECIMAL.equals(colType)){
genMap.put("hasBigDecimal",true);
}
// 主键是否自增
if(EXTRA.equals(column.getExtra())){
genMap.put("auto",true);
}
// 主键存在字典
if(StringUtils.isNotBlank(column.getDictName())){
genMap.put("hasDict",true);
dicts.add(column.getDictName());
}
// 存储字段类型
listMap.put("columnType",colType);
// 存储字原始段名称
listMap.put("columnName",column.getColumnName());
// 不为空
listMap.put("istNotNull",column.getNotNull());
// 字段列表显示
listMap.put("columnShow",column.getListShow());
// 表单显示
listMap.put("formShow",column.getFormShow());
// 表单组件类型
listMap.put("formType", StringUtils.isNotBlank(column.getFormType()) ? column.getFormType() : "Input");
// 小写开头的字段名称
listMap.put("changeColumnName",changeColumnName);
//大写开头的字段名称
listMap.put("capitalColumnName",capitalColumnName);
// 字典名称
listMap.put("dictName",column.getDictName());
// 日期注解
listMap.put("dateAnnotation",column.getDateAnnotation());
if(StringUtils.isNotBlank(column.getDateAnnotation())){
genMap.put("hasDateAnnotation",true);
}
// 添加非空字段信息
if(column.getNotNull()){
isNotNullColumns.add(listMap);
}
// 判断是否有查询如有则把查询的字段set进columnQuery
if(!StringUtils.isBlank(column.getQueryType())){
// 查询类型
listMap.put("queryType",column.getQueryType());
// 是否存在查询
genMap.put("hasQuery",true);
if(TIMESTAMP.equals(colType)){
// 查询中存储 Timestamp 类型
genMap.put("queryHasTimestamp",true);
}
if(BIGDECIMAL.equals(colType)){
// 查询中存储 BigDecimal 类型
genMap.put("queryHasBigDecimal",true);
}
if("between".equalsIgnoreCase(column.getQueryType())){
betweens.add(listMap);
} else {
// 添加到查询列表中
queryColumns.add(listMap);
}
}
// 添加到字段列表中
columns.add(listMap);
}
// 保存字段列表
genMap.put("columns",columns);
// 保存查询列表
genMap.put("queryColumns",queryColumns);
// 保存字段列表
genMap.put("dicts",dicts);
// 保存查询列表
genMap.put("betweens",betweens);
// 保存非空字段信息
genMap.put("isNotNullColumns",isNotNullColumns);
return genMap;
}
/**
* 定义后端文件路径以及名称
*/
public static String getAdminFilePath(String templateName, GenConfig genConfig, String className) {
String projectPath = System.getProperty("user.dir") + File.separator + genConfig.getModuleName();
private static String getAdminFilePath(String templateName, GenConfig genConfig, String className, String rootPath) {
String projectPath = rootPath + File.separator + genConfig.getModuleName();
String packagePath = projectPath + File.separator + "src" +File.separator+ "main" + File.separator + "java" + File.separator;
if (!ObjectUtils.isEmpty(genConfig.getPack())) {
packagePath += genConfig.getPack().replace(".", File.separator) + File.separator;
@ -192,7 +345,7 @@ public class GenUtil {
}
if ("Dto".equals(templateName)) {
return packagePath + "service" + File.separator + "dto" + File.separator + className + "DTO.java";
return packagePath + "service" + File.separator + "dto" + File.separator + className + "Dto.java";
}
if ("QueryCriteria".equals(templateName)) {
@ -213,35 +366,30 @@ public class GenUtil {
/**
* 定义前端文件路径以及名称
*/
public static String getFrontFilePath(String templateName, GenConfig genConfig, String apiName) {
String path = genConfig.getPath();
private static String getFrontFilePath(String templateName, String apiPath, String path, String apiName) {
if ("api".equals(templateName)) {
return genConfig.getApiPath() + File.separator + apiName + ".js";
return apiPath + File.separator + apiName + ".js";
}
if ("index".equals(templateName)) {
return path + File.separator + "index.vue";
}
if ("eForm".equals(templateName)) {
return path + File.separator + File.separator + "form.vue";
}
return null;
}
public static void genFile(File file,Template template,Map<String,Object> map) throws IOException {
private static void genFile(File file, Template template, Map<String, Object> map) throws IOException {
// 生成目标文件
Writer writer = null;
try {
FileUtil.touch(file);
writer = new FileWriter(file);
template.render(map, writer);
} catch (TemplateException e) {
throw new RuntimeException(e);
} catch (IOException e) {
} catch (TemplateException | IOException e) {
throw new RuntimeException(e);
} finally {
assert writer != null;
writer.close();
}
}