feat: 新增查询列映射信息列表接口

提取 QueryTypeEnum 枚举
This commit is contained in:
Charles7c 2023-08-06 23:32:01 +08:00
parent 1b06a96cfb
commit f4c6d83ff5
27 changed files with 977 additions and 89 deletions

View File

@ -18,6 +18,8 @@ package top.charles7c.cnadmin.common.annotation;
import java.lang.annotation.*;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
/**
* 查询注解
*
@ -38,7 +40,7 @@ public @interface Query {
/**
* 查询类型等值查询模糊查询范围查询等
*/
Type type() default Type.EQUAL;
QueryTypeEnum type() default QueryTypeEnum.EQUAL;
/**
* 多属性模糊查询仅支持 String 类型属性多个属性之间用逗号分隔
@ -47,66 +49,4 @@ public @interface Query {
* </p>
*/
String blurry() default "";
/**
* 查询类型
*/
enum Type {
/**
* 等值查询例如WHERE `age` = 18
*/
EQUAL,
/**
* 非等值查询例如WHERE `age` != 18
*/
NOT_EQUAL,
/**
* 大于查询例如WHERE `age` > 18
*/
GREATER_THAN,
/**
* 小于查询例如WHERE `age` < 18
*/
LESS_THAN,
/**
* 大于等于查询例如WHERE `age` >= 18
*/
GREATER_THAN_OR_EQUAL,
/**
* 小于等于查询例如WHERE `age` <= 18
*/
LESS_THAN_OR_EQUAL,
/**
* 范围查询例如WHERE `age` BETWEEN 10 AND 18
*/
BETWEEN,
/**
* 左模糊查询例如WHERE `nickname` LIKE '%'
*/
LEFT_LIKE,
/**
* 中模糊查询例如WHERE `nickname` LIKE '%%'
*/
INNER_LIKE,
/**
* 右模糊查询例如WHERE `nickname` LIKE '%'
*/
RIGHT_LIKE,
/**
* 包含查询例如WHERE `age` IN (10, 20, 30)
*/
IN,
/**
* 不包含查询例如WHERE `age` NOT IN (20, 30)
*/
NOT_IN,
/**
* 空查询例如WHERE `email` IS NULL
*/
IS_NULL,
/**
* 非空查询例如WHERE `email` IS NOT NULL
*/
IS_NOT_NULL,;
}
}

View File

@ -35,6 +35,11 @@ public class StringConsts implements StrPool {
*/
public static final String EMPTY = "";
/**
* 空格
*/
public static final String SPACE = " ";
/**
* 分号
*/

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import top.charles7c.cnadmin.common.base.BaseEnum;
/**
* 查询类型枚举
*
* @author Charles7c
* @since 2023/4/12 22:56
*/
@Getter
@RequiredArgsConstructor
public enum QueryTypeEnum implements BaseEnum<Integer, String> {
/**
* 等值查询例如WHERE `age` = 18
*/
EQUAL(1, "="),
/**
* 非等值查询例如WHERE `age` != 18
*/
NOT_EQUAL(2, "!="),
/**
* 大于查询例如WHERE `age` > 18
*/
GREATER_THAN(3, ">"),
/**
* 小于查询例如WHERE `age` < 18
*/
LESS_THAN(4, "<"),
/**
* 大于等于查询例如WHERE `age` >= 18
*/
GREATER_THAN_OR_EQUAL(5, ">="),
/**
* 小于等于查询例如WHERE `age` <= 18
*/
LESS_THAN_OR_EQUAL(6, "<="),
/**
* 范围查询例如WHERE `age` BETWEEN 10 AND 18
*/
BETWEEN(7, "BETWEEN"),
/**
* 左模糊查询例如WHERE `nickname` LIKE '%s'
*/
LEFT_LIKE(8, "LIKE '%s'"),
/**
* 中模糊查询例如WHERE `nickname` LIKE '%s%'
*/
INNER_LIKE(9, "LIKE '%s%'"),
/**
* 右模糊查询例如WHERE `nickname` LIKE 's%'
*/
RIGHT_LIKE(10, "LIKE 's%'"),
/**
* 包含查询例如WHERE `age` IN (10, 20, 30)
*/
IN(11, "IN"),
/**
* 不包含查询例如WHERE `age` NOT IN (20, 30)
*/
NOT_IN(12, "NOT IN"),
/**
* 空查询例如WHERE `email` IS NULL
*/
IS_NULL(13, "IS NULL"),
/**
* 非空查询例如WHERE `email` IS NOT NULL
*/
IS_NOT_NULL(14, "IS NOT NULL"),;
private final Integer value;
private final String description;
}

View File

@ -30,6 +30,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import top.charles7c.cnadmin.common.annotation.Query;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
import top.charles7c.cnadmin.common.exception.BadRequestException;
import top.charles7c.cnadmin.common.util.ReflectUtils;
import top.charles7c.cnadmin.common.util.validate.ValidationUtils;
@ -146,7 +147,7 @@ public class QueryHelper {
// 注意数据库规范中列采用下划线连接法命名程序规范中变量采用驼峰法命名
String property = queryAnnotation.property();
String columnName = StrUtil.toUnderlineCase(StrUtil.blankToDefault(property, fieldName));
Query.Type queryType = queryAnnotation.type();
QueryTypeEnum queryType = queryAnnotation.type();
switch (queryType) {
case EQUAL:
queryWrapper.eq(columnName, fieldValue);

View File

@ -46,7 +46,7 @@ public class LogProperties {
private Boolean includeInnerIp;
/**
* 哪些请求方式不记录系统日志
* 排除请求方式哪些请求方式不记录系统日志
*/
private List<String> excludeMethods = new ArrayList<>();

View File

@ -28,6 +28,7 @@ import org.springframework.format.annotation.DateTimeFormat;
import top.charles7c.cnadmin.common.annotation.Query;
import top.charles7c.cnadmin.common.constant.StringConsts;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
/**
* 登录日志查询条件
@ -52,7 +53,7 @@ public class LoginLogQuery implements Serializable {
* 登录时间
*/
@Schema(description = "登录时间")
@Query(type = Query.Type.BETWEEN)
@Query(type = QueryTypeEnum.BETWEEN)
@DateTimeFormat(pattern = StringConsts.NORM_DATE_TIME_PATTERN)
private List<Date> createTime;
}

View File

@ -28,6 +28,7 @@ import org.springframework.format.annotation.DateTimeFormat;
import top.charles7c.cnadmin.common.annotation.Query;
import top.charles7c.cnadmin.common.constant.StringConsts;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
/**
* 操作日志查询条件
@ -45,7 +46,7 @@ public class OperationLogQuery implements Serializable {
* 操作内容
*/
@Schema(description = "操作内容")
@Query(type = Query.Type.INNER_LIKE)
@Query(type = QueryTypeEnum.INNER_LIKE)
private String description;
/**
@ -59,7 +60,7 @@ public class OperationLogQuery implements Serializable {
* 操作时间
*/
@Schema(description = "操作时间")
@Query(type = Query.Type.BETWEEN)
@Query(type = QueryTypeEnum.BETWEEN)
@DateTimeFormat(pattern = StringConsts.NORM_DATE_TIME_PATTERN)
private List<Date> createTime;

View File

@ -28,6 +28,7 @@ import org.springframework.format.annotation.DateTimeFormat;
import top.charles7c.cnadmin.common.annotation.Query;
import top.charles7c.cnadmin.common.constant.StringConsts;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
/**
* 系统日志查询条件
@ -45,7 +46,7 @@ public class SystemLogQuery implements Serializable {
* 创建时间
*/
@Schema(description = "创建时间")
@Query(type = Query.Type.BETWEEN)
@Query(type = QueryTypeEnum.BETWEEN)
@DateTimeFormat(pattern = StringConsts.NORM_DATE_TIME_PATTERN)
private List<Date> createTime;
}

View File

@ -23,6 +23,7 @@ import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import top.charles7c.cnadmin.common.annotation.Query;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
/**
* 部门查询条件
@ -40,7 +41,7 @@ public class DeptQuery implements Serializable {
* 部门名称
*/
@Schema(description = "部门名称")
@Query(type = Query.Type.INNER_LIKE)
@Query(type = QueryTypeEnum.INNER_LIKE)
private String name;
/**

View File

@ -23,6 +23,7 @@ import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import top.charles7c.cnadmin.common.annotation.Query;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
/**
* 菜单查询条件
@ -40,7 +41,7 @@ public class MenuQuery implements Serializable {
* 菜单标题
*/
@Schema(description = "菜单标题")
@Query(type = Query.Type.INNER_LIKE)
@Query(type = QueryTypeEnum.INNER_LIKE)
private String title;
/**

View File

@ -28,6 +28,7 @@ import org.springframework.format.annotation.DateTimeFormat;
import top.charles7c.cnadmin.common.annotation.Query;
import top.charles7c.cnadmin.common.constant.StringConsts;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
/**
* 用户查询条件
@ -59,7 +60,7 @@ public class UserQuery implements Serializable {
* 创建时间
*/
@Schema(description = "创建时间")
@Query(type = Query.Type.BETWEEN)
@Query(type = QueryTypeEnum.BETWEEN)
@DateTimeFormat(pattern = StringConsts.NORM_DATE_TIME_PATTERN)
private List<Date> createTime;

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.tool.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 代码生成器配置属性
*
* @author Charles7c
* @since 2023/8/5 11:08
*/
@Data
@Component
@ConfigurationProperties(prefix = "generator")
public class GeneratorProperties {
/**
* 排除数据表哪些数据表不展示在代码生成中
*/
private String[] excludeTables;
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.tool.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import top.charles7c.cnadmin.common.base.BaseEnum;
/**
* 表单类型枚举
*
* @author Charles7c
* @since 2023/8/6 10:49
*/
@Getter
@RequiredArgsConstructor
public enum FormTypeEnum implements BaseEnum<Integer, String> {
/**
* 文本框
*/
TEXT(1, "文本框"),
/**
* 文本域
*/
TEXT_AREA(2, "文本域"),
/**
* 下拉框
*/
SELECT(3, "下拉框"),
/**
* 单选框
*/
RADIO(4, "单选框"),
/**
* 日期框
*/
DATE(5, "日期框"),
/**
* 日期时间框
*/
DATE_TIME(6, "日期时间框"),;
private final Integer value;
private final String description;
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.tool.mapper;
import top.charles7c.cnadmin.common.base.BaseMapper;
import top.charles7c.cnadmin.tool.model.entity.ColumnMappingDO;
/**
* 列映射 Mapper
*
* @author Charles7c
* @since 2023/4/12 23:56
*/
public interface ColumnMappingMapper extends BaseMapper<ColumnMappingDO> {}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.tool.mapper;
import top.charles7c.cnadmin.common.base.BaseMapper;
import top.charles7c.cnadmin.tool.model.entity.GenConfigDO;
/**
* 生成配置 Mapper
*
* @author Charles7c
* @since 2023/4/12 23:56
*/
public interface GenConfigMapper extends BaseMapper<GenConfigDO> {}

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.tool.model.entity;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import cn.hutool.setting.dialect.PropsUtil;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
import top.charles7c.cnadmin.tool.enums.FormTypeEnum;
/**
* 列映射实体
*
* @author Charles7c
* @since 2023/4/12 20:21
*/
@Data
@TableName("gen_column_mapping")
@Accessors(chain = true)
@Schema(description = "列映射信息")
public class ColumnMappingDO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId
@Schema(description = "ID")
private Long id;
/**
* 表名称
*/
@Schema(description = "表名称")
private String tableName;
/**
* 列名称
*/
@Schema(description = "列名称")
private String columnName;
/**
* 列类型
*/
@Schema(description = "列类型")
private String columnType;
/**
* 字段名称
*/
@Schema(description = "字段名称")
private String fieldName;
/**
* 字段类型
*/
@Schema(description = "字段类型")
private String fieldType;
/**
* 注释
*/
@Schema(description = "注释")
private String comment;
/**
* 排序
*/
@Schema(description = "排序")
private Integer sort;
/**
* 是否必填
*/
@Schema(description = "是否必填")
private Boolean isRequired;
/**
* 是否在列表中显示
*/
@Schema(description = "是否在列表中显示")
private Boolean showInList;
/**
* 是否在新增中显示
*/
@Schema(description = "是否在新增中显示")
private Boolean showInAdd;
/**
* 是否在修改中显示
*/
@Schema(description = "是否在修改中显示")
private Boolean showInUpdate;
/**
* 是否在查询中显示
*/
@Schema(description = "是否在查询中显示")
private Boolean showInQuery;
/**
* 表单类型
*/
@Schema(description = "表单类型")
private FormTypeEnum formType;
/**
* 查询方式
*/
@Schema(description = "查询方式")
private QueryTypeEnum queryType;
/**
* 创建时间
*/
@Schema(description = "创建时间")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 修改时间
*/
@Schema(description = "修改时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
public ColumnMappingDO setColumnName(String columnName) {
this.columnName = columnName;
this.fieldName = StrUtil.toCamelCase(this.columnName);
return this;
}
public ColumnMappingDO setColumnType(String columnType) {
this.columnType = columnType;
Props generatorProp = PropsUtil.get("generator");
this.fieldType = generatorProp.getStr(columnType);
return this;
}
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.tool.model.entity;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 生成配置实体
*
* @author Charles7c
* @since 2023/4/12 20:21
*/
@Data
@TableName("gen_config")
public class GenConfigDO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId
private Long id;
/**
* 表名称
*/
private String tableName;
/**
* 模块名称
*/
private String moduleName;
/**
* 包名称
*/
private String packageName;
/**
* 业务名称
*/
private String businessName;
/**
* 作者
*/
private String author;
/**
* 前端路径
*/
private String frontendPath;
/**
* 表前缀
*/
private String tablePrefix;
/**
* 是否覆盖
*/
private Boolean isOverride;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}

View File

@ -44,9 +44,9 @@ public class TableVO implements Serializable {
private String tableName;
/**
* 注释
* 描述
*/
@Schema(description = "注释")
@Schema(description = "描述")
private String comment;
/**

View File

@ -17,9 +17,11 @@
package top.charles7c.cnadmin.tool.service;
import java.sql.SQLException;
import java.util.List;
import top.charles7c.cnadmin.common.model.query.PageQuery;
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
import top.charles7c.cnadmin.tool.model.entity.ColumnMappingDO;
import top.charles7c.cnadmin.tool.model.query.TableQuery;
import top.charles7c.cnadmin.tool.model.vo.TableVO;
@ -32,13 +34,22 @@ import top.charles7c.cnadmin.tool.model.vo.TableVO;
public interface GeneratorService {
/**
* 分页查询列表
* 分页查询表信息列表
*
* @param query
* 查询条件
* @param pageQuery
* 分页查询条件
* @return 分页列表信息
* @return 表信息分页列表
*/
PageDataVO<TableVO> pageTable(TableQuery query, PageQuery pageQuery) throws SQLException;
/**
* 查询列映射信息列表
*
* @param tableName
* 表名称
* @return 列映射信息列表
*/
List<ColumnMappingDO> listColumnMapping(String tableName);
}

View File

@ -17,6 +17,8 @@
package top.charles7c.cnadmin.tool.service.impl;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.sql.DataSource;
@ -26,11 +28,21 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.meta.Column;
import top.charles7c.cnadmin.common.constant.StringConsts;
import top.charles7c.cnadmin.common.enums.QueryTypeEnum;
import top.charles7c.cnadmin.common.model.query.PageQuery;
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
import top.charles7c.cnadmin.tool.config.properties.GeneratorProperties;
import top.charles7c.cnadmin.tool.enums.FormTypeEnum;
import top.charles7c.cnadmin.tool.mapper.ColumnMappingMapper;
import top.charles7c.cnadmin.tool.model.entity.ColumnMappingDO;
import top.charles7c.cnadmin.tool.model.query.TableQuery;
import top.charles7c.cnadmin.tool.model.vo.TableVO;
import top.charles7c.cnadmin.tool.service.GeneratorService;
@ -49,6 +61,8 @@ import top.charles7c.cnadmin.tool.util.Table;
public class GeneratorServiceImpl implements GeneratorService {
private final DataSource dataSource;
private final GeneratorProperties generatorProperties;
private final ColumnMappingMapper columnMappingMapper;
@Override
public PageDataVO<TableVO> pageTable(TableQuery query, PageQuery pageQuery) throws SQLException {
@ -57,9 +71,29 @@ public class GeneratorServiceImpl implements GeneratorService {
if (StrUtil.isNotBlank(tableName)) {
tableList.removeIf(table -> !StrUtil.containsAny(table.getTableName(), tableName));
}
tableList
.removeIf(table -> StrUtil.equalsAny(table.getTableName(), "DATABASECHANGELOG", "DATABASECHANGELOGLOCK"));
tableList.removeIf(table -> StrUtil.equalsAny(table.getTableName(), generatorProperties.getExcludeTables()));
List<TableVO> tableVOList = BeanUtil.copyToList(tableList, TableVO.class);
return PageDataVO.build(pageQuery.getPage(), pageQuery.getSize(), tableVOList);
}
@Override
public List<ColumnMappingDO> listColumnMapping(String tableName) {
List<ColumnMappingDO> columnMappingList = columnMappingMapper
.selectList(Wrappers.lambdaQuery(ColumnMappingDO.class).eq(ColumnMappingDO::getTableName, tableName));
if (CollUtil.isEmpty(columnMappingList)) {
Collection<Column> columnList = MetaUtils.getColumns(dataSource, tableName);
columnMappingList = new ArrayList<>(columnList.size());
for (Column column : columnList) {
String columnType = StrUtil.splitToArray(column.getTypeName(), StringConsts.SPACE)[0];
boolean isRequired = !column.isPk() && !column.isNullable();
ColumnMappingDO columnMapping = new ColumnMappingDO().setTableName(tableName)
.setColumnName(column.getName()).setColumnType(columnType.toLowerCase())
.setComment(column.getComment()).setIsRequired(isRequired).setShowInList(true)
.setShowInAdd(isRequired).setShowInUpdate(isRequired).setShowInQuery(isRequired)
.setFormType(FormTypeEnum.TEXT).setQueryType(QueryTypeEnum.EQUAL);
columnMappingList.add(columnMapping);
}
}
return columnMappingList;
}
}

View File

@ -18,6 +18,7 @@ package top.charles7c.cnadmin.tool.util;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.sql.DataSource;
@ -28,6 +29,8 @@ import lombok.NoArgsConstructor;
import cn.hutool.core.date.DateUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.db.meta.Column;
import cn.hutool.db.meta.MetaUtil;
/**
* 数据库元数据信息工具类
@ -59,4 +62,18 @@ public class MetaUtils {
}
return tableList;
}
/**
* 获取所有列信息
*
* @param dataSource
* 数据源
* @param tableName
* 表名称
* @return 列信息列表
*/
public static Collection<Column> getColumns(DataSource dataSource, String tableName) {
cn.hutool.db.meta.Table table = MetaUtil.getTableMeta(dataSource, tableName);
return table.getColumns();
}
}

View File

@ -0,0 +1,27 @@
# Database type to Java typeELADMIN
tinyint=Integer
smallint=Integer
mediumint=Integer
int=Integer
integer=Integer
bigint=Long
float=Float
double=Double
decimal=BigDecimal
bit=Boolean
char=String
varchar=String
tinytext=String
text=String
mediumtext=String
longtext=String
date=LocalDate
datetime=LocalDateTime
timestamp=LocalDateTime

View File

@ -28,3 +28,41 @@ export function listTable(params: TableParam) {
},
});
}
export interface ColumnMappingRecord {
id: string;
tableName: string;
columnName: string;
columnType: string;
fieldName: string;
fieldType: string;
comment: string;
sort: number;
isRequired: boolean;
showInList: boolean;
showInAdd: boolean;
showInUpdate: boolean;
showInQuery: boolean;
formType: string;
queryType: string;
createTime: string;
updateTime: string;
}
export interface GenConfigRecord {
id: string;
tableName: string;
moduleName: string;
packageName: string;
frontendPath: string;
businessName: string;
author: string;
tablePrefix: string;
isOverride: boolean;
createTime: string;
updateTime: string;
}
export function listColumnMapping(tableName: string) {
return axios.get<ColumnMappingRecord[]>(`${BASE_URL}/column/${tableName}`);
}

View File

@ -51,7 +51,9 @@
<!-- 列表区域 -->
<a-table
ref="tableRef"
row-key="tableName"
:data="tableList"
:loading="loading"
:row-selection="{
type: 'checkbox',
showCheckedAll: true,
@ -63,10 +65,9 @@
total: total,
current: queryParams.page,
}"
row-key="tableName"
:bordered="false"
:stripe="true"
:loading="loading"
column-resizable
stripe
size="large"
@page-change="handlePageChange"
@page-size-change="handlePageSizeChange"
@ -84,12 +85,20 @@
:width="200"
tooltip
/>
<a-table-column title="注释" data-index="comment" tooltip />
<a-table-column title="描述" data-index="comment" tooltip />
<a-table-column title="存储引擎" data-index="engine" align="center" />
<a-table-column title="字符集" data-index="charset" />
<a-table-column title="创建时间" data-index="createTime" />
<a-table-column title="操作" align="center">
<template #cell="{ record }">
<a-button
type="text"
size="small"
title="配置"
@click="toConfig(record.tableName)"
>
<template #icon><icon-settings /></template>配置
</a-button>
<a-button
type="text"
size="small"
@ -102,23 +111,198 @@
</a-table-column>
</template>
</a-table>
<!-- 表单区域 -->
<a-drawer
:title="title"
:visible="visible"
:width="1000"
:mask-closable="false"
:esc-to-close="false"
unmount-on-close
render-to-body
@ok="handleOk"
@cancel="handleCancel"
>
<a-card title="字段配置" class="field-config">
<a-table
ref="columnMappingRef"
:data="columnMappingList"
:loading="columnMappingLoading"
:pagination="false"
:bordered="false"
size="large"
:scroll="{
y: 400,
}"
>
<template #columns>
<a-table-column
title="名称"
data-index="fieldName"
:width="130"
ellipsis
tooltip
/>
<a-table-column
title="类型"
data-index="fieldType"
:width="90"
ellipsis
tooltip
/>
<a-table-column title="描述" data-index="comment" :width="170">
<template #cell="{ record }">
<a-input v-model="record.comment" />
</template>
</a-table-column>
<a-table-column
title="必填"
data-index="isRequired"
:width="60"
align="center"
>
<template #cell="{ record }">
<a-checkbox v-model="record.isRequired" value="true" />
</template>
</a-table-column>
<a-table-column
title="列表"
data-index="showInList"
:width="60"
align="center"
>
<template #cell="{ record }">
<a-checkbox v-model="record.showInList" value="true" />
</template>
</a-table-column>
<a-table-column
title="新增"
data-index="showInAdd"
:width="60"
align="center"
>
<template #cell="{ record }">
<a-checkbox v-model="record.showInAdd" value="true" />
</template>
</a-table-column>
<a-table-column
title="修改"
data-index="showInUpdate"
:width="60"
align="center"
>
<template #cell="{ record }">
<a-checkbox v-model="record.showInUpdate" value="true" />
</template>
</a-table-column>
<a-table-column
title="表单类型"
data-index="formType"
:width="150"
>
<template #cell="{ record }">
<a-select
v-model="record.formType"
:options="FormTypeEnum"
placeholder="请选择表单类型"
/>
</template>
</a-table-column>
<a-table-column title="查询方式" data-index="queryType">
<template #cell="{ record }">
<a-select
v-model="record.queryType"
:options="QueryTypeEnum"
placeholder="请选择查询方式"
/>
</template>
</a-table-column>
</template>
</a-table>
</a-card>
<a-card title="生成配置" style="margin-top: 10px">
<a-form
ref="formRef"
:model="form"
:rules="rules"
class="gen-config"
size="large"
>
<a-form-item label="作者名称" field="author">
<a-input v-model="form.author" placeholder="请输入作者名称" />
</a-form-item>
<a-form-item label="业务名称" field="businessName">
<a-input
v-model="form.businessName"
placeholder="自定义业务名称,例如:用户"
/>
</a-form-item>
<a-form-item label="所属模块" field="moduleName">
<a-input
v-model="form.moduleName"
placeholder="项目模块名称例如continew-admin-system"
/>
</a-form-item>
<a-form-item label="模块包名" field="packageName">
<a-input
v-model="form.packageName"
placeholder="项目模块包名例如top.charles7c.cnadmin.system"
/>
</a-form-item>
<a-form-item label="前端路径" field="frontendPath">
<a-input
v-model="form.frontendPath"
placeholder="前端项目 views 目录地址"
/>
</a-form-item>
<a-form-item label="去表前缀" field="tablePrefix">
<a-input
v-model="form.tablePrefix"
placeholder="数据库表前缀例如sys_"
/>
</a-form-item>
<a-form-item label="是否覆盖" field="isOverride">
<a-radio-group v-model="form.isOverride" type="button">
<a-radio :value="true"></a-radio>
<a-radio :value="false"></a-radio>
</a-radio-group>
</a-form-item>
</a-form>
</a-card>
</a-drawer>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { getCurrentInstance, ref, toRefs, reactive } from 'vue';
import { TableRecord, TableParam, listTable } from '@/api/tool/generator';
import {
TableRecord,
TableParam,
ColumnMappingRecord,
GenConfigRecord,
listTable,
listColumnMapping,
} from '@/api/tool/generator';
const { proxy } = getCurrentInstance() as any;
const { FormTypeEnum, QueryTypeEnum } = proxy.useDict(
'FormTypeEnum',
'QueryTypeEnum'
);
const tableList = ref<TableRecord[]>([]);
const columnMappingList = ref<ColumnMappingRecord[]>([]);
const total = ref(0);
const ids = ref<Array<string>>([]);
const title = ref('');
const single = ref(true);
const multiple = ref(true);
const showQuery = ref(true);
const loading = ref(false);
const visible = ref(false);
const columnMappingLoading = ref(false);
const data = reactive({
//
@ -128,8 +312,17 @@
size: 10,
sort: ['createTime,desc', 'updateTime,desc'],
},
//
form: {} as GenConfigRecord,
//
rules: {
author: [{ required: true, message: '请输入作者名称' }],
moduleName: [{ required: true, message: '请输入模块名称' }],
packageName: [{ required: true, message: '请输入包名称' }],
businessName: [{ required: true, message: '请输入业务名称' }],
},
});
const { queryParams } = toRefs(data);
const { queryParams, form, rules } = toRefs(data);
/**
* 查询列表
@ -149,6 +342,41 @@
};
getList();
/**
* 打开配置对话框
*
* @param tableName 表名称
*/
const toConfig = (tableName: string) => {
title.value = `${tableName} 配置`;
form.value.isOverride = false;
visible.value = true;
//
columnMappingLoading.value = true;
listColumnMapping(tableName)
.then((res) => {
columnMappingList.value = res.data;
})
.finally(() => {
columnMappingLoading.value = false;
});
};
/**
* 确定
*/
const handleOk = () => {
visible.value = false;
proxy.$message.info('功能尚在开发中');
};
/**
* 关闭配置
*/
const handleCancel = () => {
visible.value = false;
};
/**
* 代码生成
*
@ -207,8 +435,16 @@
<script lang="ts">
export default {
name: 'Role',
name: 'Generator',
};
</script>
<style scoped lang="less"></style>
<style scoped lang="less">
.field-config :deep(.arco-card-body) {
padding: 0;
}
:deep(.gen-config.arco-form) {
width: 50%;
}
</style>

View File

@ -17,6 +17,7 @@
package top.charles7c.cnadmin.webapi.controller.tool;
import java.sql.SQLException;
import java.util.List;
import lombok.RequiredArgsConstructor;
@ -25,12 +26,14 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.charles7c.cnadmin.common.model.query.PageQuery;
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
import top.charles7c.cnadmin.common.model.vo.R;
import top.charles7c.cnadmin.tool.model.entity.ColumnMappingDO;
import top.charles7c.cnadmin.tool.model.query.TableQuery;
import top.charles7c.cnadmin.tool.model.vo.TableVO;
import top.charles7c.cnadmin.tool.service.GeneratorService;
@ -55,4 +58,10 @@ public class GeneratorController {
public R<PageDataVO<TableVO>> pageTable(TableQuery query, @Validated PageQuery pageQuery) throws SQLException {
return R.ok(generatorService.pageTable(query, pageQuery));
}
@Operation(summary = "查询列映射信息列表", description = "查询列映射信息列表")
@GetMapping("/column/{tableName}")
public R<List<ColumnMappingDO>> listColumnMapping(@PathVariable String tableName) {
return R.ok(generatorService.listColumnMapping(tableName));
}
}

View File

@ -37,7 +37,7 @@ logging:
enabled: true
# 是否记录内网 IP 操作
includeInnerIp: true
# 哪些请求方式不记录系统日志
# 排除请求方式
#excludeMethods:
# - GET
# 脱敏字段
@ -45,6 +45,15 @@ logging:
- password
- Authorization
--- ### 代码生成器配置
generator:
# 排除数据表
excludeTables:
- DATABASECHANGELOG
- DATABASECHANGELOGLOCK
- gen_config
- gen_column_mapping
--- ### 接口文档配置
springdoc:
# 设置对象型参数的展示形式(设为 true 表示将对象型参数平展开,即对象内的属性直接作为参数展示而不是嵌套在对象内,默认为 false

View File

@ -1,2 +1,40 @@
-- liquibase formatted sql
-- changeset Charles7c:1
CREATE TABLE IF NOT EXISTS `gen_config` (
`id` bigint(20) UNSIGNED AUTO_INCREMENT COMMENT 'ID',
`table_name` varchar(100) NOT NULL COMMENT '表名称',
`module_name` varchar(50) NOT NULL COMMENT '模块名称',
`package_name` varchar(50) NOT NULL COMMENT '包名称',
`frontend_path` varchar(255) NOT NULL COMMENT '前端路径',
`business_name` varchar(50) NOT NULL COMMENT '业务名称',
`author` varchar(100) NOT NULL COMMENT '作者',
`table_prefix` varchar(20) DEFAULT NULL COMMENT '表前缀',
`is_override` bit(1) DEFAULT b'0' COMMENT '是否覆盖',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_table_name`(`table_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='生成配置表';
CREATE TABLE IF NOT EXISTS `gen_column_mapping` (
`id` bigint(20) UNSIGNED AUTO_INCREMENT COMMENT 'ID',
`table_name` varchar(100) NOT NULL COMMENT '表名称',
`column_name` varchar(50) NOT NULL COMMENT '列名称',
`column_type` varchar(25) NOT NULL COMMENT '列类型',
`field_name` varchar(50) NOT NULL COMMENT '字段名称',
`field_type` varchar(25) NOT NULL COMMENT '字段类型',
`comment` varchar(512) DEFAULT NULL COMMENT '注释',
`sort` int(11) UNSIGNED DEFAULT 999 COMMENT '排序',
`is_required` bit(1) DEFAULT b'1' COMMENT '是否必填',
`show_in_list` bit(1) DEFAULT b'1' COMMENT '是否在列表中显示',
`show_in_add` bit(1) DEFAULT b'1' COMMENT '是否在新增中显示',
`show_in_update` bit(1) DEFAULT b'1' COMMENT '是否在修改中显示',
`show_in_query` bit(1) DEFAULT b'1' COMMENT '是否在查询中显示',
`form_type` tinyint(1) UNSIGNED DEFAULT NULL COMMENT '表单类型',
`query_type` tinyint(1) UNSIGNED DEFAULT NULL COMMENT '查询方式',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_table_name`(`table_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='列映射表';