添加前端代码生成器.

This commit is contained in:
lijiahang
2023-08-10 14:11:06 +08:00
parent 0f739f01e9
commit 4d32bbc10f
12 changed files with 277 additions and 50 deletions

View File

@@ -41,10 +41,10 @@ public class CodeGenerator {
// 生成的表
GenTable[] tables = {
new GenTable("system_user", "用户", "user")
.vue("user/user", "user", "user")
.vue("user", "user")
.enums(UserStatusEnum.class),
new GenTable("system_role", "角色", "role")
.vue("user/role", "user", "role")
.vue("user", "role")
.enums(RoleStatusEnum.class),
new GenTable("system_menu", "菜单", "menu"),
};
@@ -129,6 +129,7 @@ public class CodeGenerator {
private static GlobalConfig getGlobalConfig(String outputDir, String author) {
// 全局配置
GlobalConfig gbConfig = new GlobalConfig.Builder()
.disableOpenDir()
// 设置作者
.author(author)
// 生成路径
@@ -313,19 +314,21 @@ public class CodeGenerator {
// convert provider 文件
new String[]{"/templates/orion-server-convert-provider.java.vm", "%sProviderConvert.java", "convert"},
// vue api 文件
new String[]{"/templates/orion-vue-api.ts.vm", "${feature}.ts", "vue/api/${apiPath}"},
new String[]{"/templates/orion-vue-api.ts.vm", "${feature}.ts", "vue/api/${module}"},
// vue router 文件
new String[]{"/templates/orion-vue-router.ts.vm", "${module}.${feature}.ts", "vue/router/routes/modules"},
// vue views index.ts 文件
new String[]{"/templates/orion-vue-views-index.vue.vm", "index.vue", "vue/views/${viewsPath}"},
new String[]{"/templates/orion-vue-views-index.vue.vm", "index.vue", "vue/views/${module}/${feature}"},
// vue form-modal.vue 文件
new String[]{"/templates/orion-vue-views-components-form-modal.vue.vm", "${feature}-form-modal.vue", "vue/views/${viewsPath}/components"},
new String[]{"/templates/orion-vue-views-components-form-modal.vue.vm", "${feature}-form-modal.vue", "vue/views/${module}/${feature}/components"},
// vue table.vue 文件
new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${viewsPath}/components"},
new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${module}/${feature}/components"},
// vue enum.types.ts 文件
new String[]{"/templates/orion-vue-views-types-enum.types.ts.vm", "enum.types.ts", "vue/views/${viewsPath}/types"},
new String[]{"/templates/orion-vue-views-types-enum.types.ts.vm", "enum.types.ts", "vue/views/${module}/${feature}/types"},
// vue form.rules.ts 文件
new String[]{"/templates/orion-vue-views-types-form.rules.ts.vm", "form.rules.ts", "vue/views/${viewsPath}/types"},
new String[]{"/templates/orion-vue-views-types-form.rules.ts.vm", "form.rules.ts", "vue/views/${module}/${feature}/types"},
// vue table.vue 文件
new String[]{"/templates/orion-vue-views-types-table.columns.ts.vm", "table.columns.ts", "vue/views/${viewsPath}/types"},
new String[]{"/templates/orion-vue-views-types-table.columns.ts.vm", "table.columns.ts", "vue/views/${module}/${feature}/types"},
};
// 构建文件

View File

@@ -39,14 +39,9 @@ public class GenTable {
private boolean genVue;
/**
* views 父目录
* 模块 用于文件名称生成
*/
private String viewsPath;
/**
* api 文件目录
*/
private String apiPath;
private String module;
/**
* 功能 用于文件名称生成
@@ -68,15 +63,13 @@ public class GenTable {
/**
* 生成 vue 模板
*
* @param viewsPath viewsPath
* @param apiPath apiPath
* @param feature feature
* @param module module
* @param feature feature
* @return this
*/
public GenTable vue(String viewsPath, String apiPath, String feature) {
public GenTable vue(String module, String feature) {
this.genVue = true;
this.viewsPath = viewsPath;
this.apiPath = apiPath;
this.module = module;
this.feature = feature;
return this;
}

View File

@@ -22,7 +22,10 @@ import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.orion.lang.define.collect.MultiLinkedHashMap;
import com.orion.lang.utils.Enums;
import com.orion.lang.utils.Strings;
import com.orion.lang.utils.VariableStyles;
import com.orion.lang.utils.io.Files1;
import com.orion.lang.utils.reflect.BeanMap;
import com.orion.lang.utils.reflect.Fields;
@@ -253,6 +256,15 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine {
String outPath = getConfigBuilder().getGlobalConfig().getOutputDir();
GenTable table = tables.get(tableInfo.getName());
BeanMap beanMap = BeanMap.create(table, "enums");
// 功能名称首字母大写
beanMap.put("featureFirstUpper", Strings.firstUpper(table.getFeature()));
// 功能名称全大写
beanMap.put("featureAllUpper", table.getFeature().toUpperCase());
// 枚举
beanMap.put("enums", this.getEnumMap(table));
System.out.println( this.getEnumMap(table));
objectMap.put("vue", beanMap);
// 生成文件
customFiles.forEach(file -> {
@@ -276,4 +288,22 @@ public class VelocityTemplateEngine extends AbstractTemplateEngine {
templatePath.endsWith(".vue.vm");
}
/**
* 获取枚举 map
*
* @param table table
* @return enums
*/
private Object getEnumMap(GenTable table) {
List<Class<? extends Enum<?>>> enums = table.getEnums();
Map<String, MultiLinkedHashMap<String, String, Object>> enumMap = new LinkedHashMap<>();
for (Class<? extends Enum<?>> e : enums) {
// 大驼峰文件名称转为蛇形大写
String enumTypeName = VariableStyles.BIG_HUMP.toSerpentine(e.getSimpleName()).toUpperCase();
MultiLinkedHashMap<String, String, Object> fieldValueMap = Enums.getFieldValueMap(e);
enumMap.put(enumTypeName, fieldValueMap);
}
return enumMap;
}
}

View File

@@ -57,5 +57,3 @@ Authorization: {{token}}
${httpComment}

View File

@@ -1 +1,126 @@
api
import axios from 'axios';
import qs from 'query-string';
import { DataGrid, Pagination } from '@/types/global';
/**
* ${table.comment}创建请求
*/
export interface ${vue.featureFirstUpper}CreateRequest {
#foreach($field in ${table.fields})
#if("$!field.propertyName" != "id")
#if("$field.propertyType" == "String" || "$field.propertyType" == "Date")
${field.propertyName}?: string;
#elseif("$field.propertyType" == "Integer" || "$field.propertyType" == "Long")
${field.propertyName}?: number;
#elseif("$field.propertyType" == "Boolean")
${field.propertyName}?: boolean;
#else
${field.propertyName}?: any;
#end
#end
#end
}
/**
* ${table.comment}更新请求
*/
export interface ${vue.featureFirstUpper}UpdateRequest extends ${vue.featureFirstUpper}CreateRequest {
id: number;
}
/**
* ${table.comment}查询请求
*/
export interface ${vue.featureFirstUpper}QueryRequest extends Pagination {
#foreach($field in ${table.fields})
#if("$field.propertyType" == "String" || "$field.propertyType" == "Date")
${field.propertyName}?: string;
#elseif("$field.propertyType" == "Integer" || "$field.propertyType" == "Long")
${field.propertyName}?: number;
#elseif("$field.propertyType" == "Boolean")
${field.propertyName}?: boolean;
#else
${field.propertyName}?: any;
#end
#end
}
/**
* ${table.comment}查询响应
*/
export interface ${vue.featureFirstUpper}QueryResponse {
#foreach($field in ${table.fields})
#if("$field.propertyType" == "String")
${field.propertyName}?: string;
#elseif("$field.propertyType" == "Integer" || "$field.propertyType" == "Long" || "$field.propertyType" == "Date")
${field.propertyName}?: number;
#elseif("$field.propertyType" == "Boolean")
${field.propertyName}?: boolean;
#else
${field.propertyName}?: any;
#end
#end
createTime: number;
updateTime: number;
creator: string;
updater: string;
}
/**
* $apiComment.create
*/
export function create${vue.featureFirstUpper}(request: ${vue.featureFirstUpper}CreateRequest) {
return axios.post('/${package.ModuleName}/${typeHyphen}/create', request);
}
/**
* $apiComment.update
*/
export function update${vue.featureFirstUpper}(request: ${vue.featureFirstUpper}UpdateRequest) {
return axios.put('/${package.ModuleName}/${typeHyphen}/update', request);
}
/**
* $apiComment.get
*/
export function get${vue.featureFirstUpper}(id: number) {
return axios.get<${vue.featureFirstUpper}QueryResponse>('/${package.ModuleName}/${typeHyphen}/get', { params: { id } });
}
/**
* $apiComment.list
*/
export function get${vue.featureFirstUpper}List(idList: Array<number>) {
return axios.get<${vue.featureFirstUpper}QueryResponse[]>('/${package.ModuleName}/${typeHyphen}/list', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
}
});
}
/**
* $apiComment.query
*/
export function get${vue.featureFirstUpper}Page(request: ${vue.featureFirstUpper}QueryRequest) {
return axios.post<DataGrid<${vue.featureFirstUpper}QueryResponse>>('/${package.ModuleName}/${typeHyphen}/query', request);
}
/**
* $apiComment.delete
*/
export function delete${vue.featureFirstUpper}(id: number) {
return axios.delete('/${package.ModuleName}/${typeHyphen}/delete', { params: { id } });
}
/**
* $apiComment.batchDelete
*/
export function batchDelete${vue.featureFirstUpper}(idList: Array<number>) {
return axios.delete('/${package.ModuleName}/${typeHyphen}/delete-batch', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
}
});
}

View File

@@ -0,0 +1,17 @@
import { DEFAULT_LAYOUT } from '../base';
import { AppRouteRecordRaw } from '../types';
const $vue.featureAllUpper: AppRouteRecordRaw = {
name: '$vue.module',
path: '/$vue.module',
component: DEFAULT_LAYOUT,
children: [
{
name: '$vue.module$vue.featureFirstUpper',
path: '/$vue.module/$vue.featureFirstUpper',
component: () => import('@/views/$vue.module/$vue.feature/index.vue'),
},
],
};
export default $vue.featureAllUpper;

View File

@@ -1 +1,18 @@
e.types.ts
#foreach($enumEntity in ${vue.enums.entrySet()})
/**
*
*/
export const $enumEntity.key = {
#foreach($enumEntityItem in $enumEntity.value.entrySet())
$enumEntityItem.key: {
value: null,
label: '',
color: '',
#foreach($enumEntityItemFields in $enumEntityItem.value.entrySet())
$enumEntityItemFields.key: '$enumEntityItemFields.value',
#end
}
#end
}
#end

View File

@@ -1 +1,24 @@
orion-vue-views-types-form.rules.ts
import { FieldRule } from '@arco-design/web-vue';
#foreach($field in ${table.fields})
#if(${field.propertyType} == 'String')
export const ${field.propertyName} = [{
required: true,
message: '请输入${field.comment}'
}, {
maxLength: $field.metaInfo.length,
message: '${field.comment}长度不能大于$field.metaInfo.length位'
}] as FieldRule[];
#else
export const ${field.propertyName} = [{
required: true,
message: '请输入${field.comment}'
}] as FieldRule[];
#end
#end
export default {
#foreach($field in ${table.fields})
${field.propertyName},
#end
} as Record<string, FieldRule | FieldRule[]>;

View File

@@ -1 +1,44 @@
orion-vue-views-types-table.columns.ts.vm
import { TableColumnData } from '@arco-design/web-vue/es/table/interface';
const columns = [
{
title: 'id',
dataIndex: 'id',
slotName: 'id',
width: 70,
fixed: 'left',
}, #foreach($field in ${table.fields}){
title: '${field.comment}',
dataIndex: '${field.propertyName}',
slotName: '${field.propertyName}',
align: 'center',
width: 100,
#if(${field.propertyType} == 'String')
ellipsis: true,
tooltip: true,
#end
}, #end{
title: '创建时间',
dataIndex: 'createTime',
slotName: 'createTime',
}, {
title: '修改时间',
dataIndex: 'updateTime',
slotName: 'updateTime',
}, {
title: '创建人',
dataIndex: 'creator',
slotName: 'creator',
}, {
title: '修改人',
dataIndex: 'updater',
slotName: 'updater',
}, {
title: '操作',
slotName: 'option',
width: 158,
fixed: 'right',
}
] as TableColumnData[];
export default columns;

View File

@@ -71,10 +71,3 @@ Authorization: {{token}}
DELETE {{baseUrl}}/infra/system-menu/delete?id=1
Authorization: {{token}}
### 通过 id 批量删除菜单
DELETE {{baseUrl}}/infra/system-menu/delete-batch?idList=1,2,3
Authorization: {{token}}

View File

@@ -60,11 +60,3 @@ Authorization: {{token}}
### 通过 id 删除角色
DELETE {{baseUrl}}/infra/system-role/delete?id=1
Authorization: {{token}}
### 通过 id 批量删除角色
DELETE {{baseUrl}}/infra/system-role/delete-batch?idList=1,2,3
Authorization: {{token}}

View File

@@ -65,10 +65,3 @@ Authorization: {{token}}
DELETE {{baseUrl}}/infra/system-user/delete?id=1
Authorization: {{token}}
### 通过 id 批量删除用户
DELETE {{baseUrl}}/infra/system-user/delete-batch?idList=1,2,3
Authorization: {{token}}