mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2026-06-19 04:04:29 +00:00
update 优化 代码生成支持接入各种不同前端 只需要将模板放到vm文件夹下 前端传对应的文件夹名即可
This commit is contained in:
@@ -2,11 +2,19 @@
|
||||
|
||||
## 优先参考的代码来源
|
||||
|
||||
- `ruoyi-modules/ruoyi-gen/src/main/resources/vm/vue/*.vm`
|
||||
- `ruoyi-modules/ruoyi-gen/src/main/resources/vm/<frontendType>/*.vm`
|
||||
- 默认 Vue 模板在 `vm/vue`,React 模板在 `vm/react`
|
||||
- 前端工程中与目标模块最接近的现有页面
|
||||
|
||||
当前 boot4 仓库通常只含后端与 generator 前端模板;如果前端工程不在当前 root,先以 generator 模板约定为准,再对照用户提供的前端目录或相邻仓库。
|
||||
|
||||
## 前端模板选择规则
|
||||
|
||||
- `gen_table.frontend_type` 存字符串,值直接对应 `vm` 下的模板目录,例如 `vue`、`react`。
|
||||
- 生成器按 `vm/<frontendType>/api.ts.vm`、`types.ts.vm`、`index.*.vm`、`index-tree.*.vm` 查找模板。
|
||||
- 页面输出后缀由页面模板文件名决定:`index.vue.vm` 输出 `index.vue`,`index.tsx.vm` 输出 `index.tsx`。
|
||||
- 新增其他前端时优先只新增 `vm/<frontendType>` 目录和对应 VM 文件,不在 Java 代码里增加数字枚举或硬编码分支。
|
||||
|
||||
## API 文件规则
|
||||
|
||||
- 从 `@/utils/request` 引入 `request`。
|
||||
|
||||
@@ -80,6 +80,11 @@ public interface GenConstants {
|
||||
*/
|
||||
String SORT_FIELD = "sortField";
|
||||
|
||||
/**
|
||||
* 默认前端模板类型,对应 vm/vue 目录。
|
||||
*/
|
||||
String FRONTEND_TYPE_VUE = "vue";
|
||||
|
||||
/**
|
||||
* 树根节点值
|
||||
*/
|
||||
@@ -268,10 +273,10 @@ public interface GenConstants {
|
||||
// MyBatis MapperXML 模板
|
||||
String XML_MAPPER_TEMPLATE_PATH = "vm/xml/mapper.xml.vm";
|
||||
// 前端源码模板
|
||||
String TS_API_TEMPLATE_PATH = "vm/vue/api.ts.vm";
|
||||
String TS_TYPES_TEMPLATE_PATH = "vm/vue/types.ts.vm";
|
||||
String VUE_INDEX_TEMPLATE_PATH = "vm/vue/index.vue.vm";
|
||||
String VUE_INDEX_TREE_TEMPLATE_PATH = "vm/vue/index-tree.vue.vm";
|
||||
String FRONTEND_API_TEMPLATE_NAME = "api.ts.vm";
|
||||
String FRONTEND_TYPES_TEMPLATE_NAME = "types.ts.vm";
|
||||
String FRONTEND_INDEX_TEMPLATE_PREFIX = "index";
|
||||
String FRONTEND_INDEX_TREE_TEMPLATE_PREFIX = "index-tree";
|
||||
// 数据库SQL模板
|
||||
String SQL_ORACLE_TEMPLATE_PATH = "vm/sql/oracle.sql.vm";
|
||||
String SQL_POSTGRES_TEMPLATE_PATH = "vm/sql/postgres.sql.vm";
|
||||
@@ -290,10 +295,14 @@ public interface GenConstants {
|
||||
, JAVA_SERVICE_IMPL_TEMPLATE_PATH
|
||||
, JAVA_CONTROLLER_TEMPLATE_PATH
|
||||
, XML_MAPPER_TEMPLATE_PATH
|
||||
, TS_API_TEMPLATE_PATH
|
||||
, TS_TYPES_TEMPLATE_PATH
|
||||
, VUE_INDEX_TEMPLATE_PATH
|
||||
, VUE_INDEX_TREE_TEMPLATE_PATH
|
||||
, "vm/vue/api.ts.vm"
|
||||
, "vm/vue/types.ts.vm"
|
||||
, "vm/vue/index.vue.vm"
|
||||
, "vm/vue/index-tree.vue.vm"
|
||||
, "vm/react/api.ts.vm"
|
||||
, "vm/react/types.ts.vm"
|
||||
, "vm/react/index.tsx.vm"
|
||||
, "vm/react/index-tree.tsx.vm"
|
||||
, SQL_ORACLE_TEMPLATE_PATH
|
||||
, SQL_POSTGRES_TEMPLATE_PATH
|
||||
, SQL_SQLSERVER_TEMPLATE_PATH
|
||||
|
||||
@@ -61,6 +61,11 @@ public class GenTable extends BaseEntity {
|
||||
*/
|
||||
private String tplCategory;
|
||||
|
||||
/**
|
||||
* 前端模板类型,对应 vm 下的模板目录
|
||||
*/
|
||||
private String frontendType;
|
||||
|
||||
/**
|
||||
* 生成包路径
|
||||
*/
|
||||
|
||||
+1
-1
@@ -453,7 +453,7 @@ public class GenTableServiceImpl implements IGenTableService {
|
||||
table.setMenuIds(menuIds);
|
||||
setPkColumn(table);
|
||||
Dict context = TemplateEngineUtils.buildContext(table);
|
||||
List<PathNamedTemplate> templates = TemplateEngineUtils.getTemplateList(table.getTplCategory(), table.getDataName());
|
||||
List<PathNamedTemplate> templates = TemplateEngineUtils.getTemplateList(table.getTplCategory(), table.getDataName(), table.getFrontendType());
|
||||
return new RenderContext(table, context, templates);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ public class GenUtils {
|
||||
genTable.setBusinessName(getBusinessName(genTable.getTableName()));
|
||||
genTable.setFunctionName(replaceText(genTable.getTableComment()));
|
||||
genTable.setFunctionAuthor(PROPERTIES.getAuthor());
|
||||
genTable.setFrontendType(GenConstants.FRONTEND_TYPE_VUE);
|
||||
genTable.setCreateTime(null);
|
||||
genTable.setUpdateTime(null);
|
||||
}
|
||||
|
||||
+139
-11
@@ -9,6 +9,7 @@ import cn.hutool.extra.template.TemplateUtil;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.DateUtils;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
@@ -20,7 +21,11 @@ import org.dromara.gen.constant.GenConstants;
|
||||
import org.dromara.gen.domain.GenTable;
|
||||
import org.dromara.gen.domain.GenTableColumn;
|
||||
import org.dromara.gen.util.template.PathNamedTemplate;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -49,6 +54,7 @@ public class TemplateEngineUtils {
|
||||
// 模板引擎
|
||||
private static final TemplateEngine TEMPLATE_ENGINE;
|
||||
private static final Map<String, PathNamedTemplate> TEMPLATE_MAPPER;
|
||||
private static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER = new PathMatchingResourcePatternResolver();
|
||||
|
||||
static {
|
||||
// 模板引擎初始化
|
||||
@@ -85,6 +91,7 @@ public class TemplateEngineUtils {
|
||||
String functionName = genTable.getFunctionName();
|
||||
|
||||
context.put("tplCategory", genTable.getTplCategory());
|
||||
context.put("frontendType", resolveFrontendType(genTable.getFrontendType()));
|
||||
context.put("tableName", genTable.getTableName());
|
||||
context.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】");
|
||||
context.put("ClassName", genTable.getClassName());
|
||||
@@ -186,6 +193,18 @@ public class TemplateEngineUtils {
|
||||
* @return 模板列表
|
||||
*/
|
||||
public static List<PathNamedTemplate> getTemplateList(String tplCategory, String dsName) {
|
||||
return getTemplateList(tplCategory, dsName, GenConstants.FRONTEND_TYPE_VUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模板信息
|
||||
*
|
||||
* @param tplCategory 前端页面模板分类
|
||||
* @param dsName 数据源名称
|
||||
* @param frontendType 前端模板类型
|
||||
* @return 模板列表
|
||||
*/
|
||||
public static List<PathNamedTemplate> getTemplateList(String tplCategory, String dsName, String frontendType) {
|
||||
List<PathNamedTemplate> templates = new ArrayList<>();
|
||||
// 后端源码模板
|
||||
templates.add(TEMPLATE_MAPPER.get(GenConstants.JAVA_DOMAIN_TEMPLATE_PATH));
|
||||
@@ -198,8 +217,8 @@ public class TemplateEngineUtils {
|
||||
// MyBatis MapperXML 模板
|
||||
templates.add(TEMPLATE_MAPPER.get(GenConstants.XML_MAPPER_TEMPLATE_PATH));
|
||||
// 前端 API 与类型模板
|
||||
templates.add(TEMPLATE_MAPPER.get(GenConstants.TS_API_TEMPLATE_PATH));
|
||||
templates.add(TEMPLATE_MAPPER.get(GenConstants.TS_TYPES_TEMPLATE_PATH));
|
||||
templates.add(getTemplate(getFrontendApiTemplatePath(frontendType)));
|
||||
templates.add(getTemplate(getFrontendTypesTemplatePath(frontendType)));
|
||||
// 数据库模板
|
||||
DataBaseType dataBaseType = DataBaseHelper.getDataBaseType(dsName);
|
||||
if (dataBaseType.isOracle()) {
|
||||
@@ -214,13 +233,27 @@ public class TemplateEngineUtils {
|
||||
}
|
||||
// 前端页面模板
|
||||
if (GenConstants.TPL_CRUD.equals(tplCategory)) {
|
||||
templates.add(TEMPLATE_MAPPER.get(GenConstants.VUE_INDEX_TEMPLATE_PATH));
|
||||
templates.add(getTemplate(getFrontendIndexTemplatePath(frontendType)));
|
||||
} else if (GenConstants.TPL_TREE.equals(tplCategory)) {
|
||||
templates.add(TEMPLATE_MAPPER.get(GenConstants.VUE_INDEX_TREE_TEMPLATE_PATH));
|
||||
templates.add(getTemplate(getFrontendIndexTreeTemplatePath(frontendType)));
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模板,支持按前端模板类型动态加载 vm/{frontendType} 下的模板。
|
||||
*
|
||||
* @param templatePath 模板路径
|
||||
* @return 带路径名的模板
|
||||
*/
|
||||
private static PathNamedTemplate getTemplate(String templatePath) {
|
||||
PathNamedTemplate template = TEMPLATE_MAPPER.get(templatePath);
|
||||
if (ObjectUtil.isNotNull(template)) {
|
||||
return template;
|
||||
}
|
||||
return PathNamedTemplate.form(TEMPLATE_ENGINE, templatePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件名
|
||||
*
|
||||
@@ -242,7 +275,7 @@ public class TemplateEngineUtils {
|
||||
|
||||
String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
|
||||
String mybatisPath = MYBATIS_PATH + "/" + moduleName;
|
||||
String vuePath = "vue";
|
||||
String frontendPath = getFrontendPath(genTable.getFrontendType());
|
||||
// templatePath
|
||||
// genFilePathFormat
|
||||
if (template.contains("domain.java.vm")) {
|
||||
@@ -264,17 +297,112 @@ public class TemplateEngineUtils {
|
||||
} else if (template.contains("sql.vm")) {
|
||||
fileName = businessName + "Menu.sql";
|
||||
} else if (template.contains("api.ts.vm")) {
|
||||
fileName = StringUtils.format("{}/api/{}/{}/index.ts", vuePath, moduleName, businessName);
|
||||
fileName = StringUtils.format("{}/api/{}/{}/index.ts", frontendPath, moduleName, businessName);
|
||||
} else if (template.contains("types.ts.vm")) {
|
||||
fileName = StringUtils.format("{}/api/{}/{}/types.ts", vuePath, moduleName, businessName);
|
||||
} else if (template.contains("index.vue.vm")) {
|
||||
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
|
||||
} else if (template.contains("index-tree.vue.vm")) {
|
||||
fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
|
||||
fileName = StringUtils.format("{}/api/{}/{}/types.ts", frontendPath, moduleName, businessName);
|
||||
} else if (isFrontendPageTemplate(template, GenConstants.FRONTEND_INDEX_TEMPLATE_PREFIX)) {
|
||||
fileName = StringUtils.format("{}/views/{}/{}/index.{}", frontendPath, moduleName, businessName,
|
||||
getFrontendPageExtension(template, GenConstants.FRONTEND_INDEX_TEMPLATE_PREFIX));
|
||||
} else if (isFrontendPageTemplate(template, GenConstants.FRONTEND_INDEX_TREE_TEMPLATE_PREFIX)) {
|
||||
fileName = StringUtils.format("{}/views/{}/{}/index.{}", frontendPath, moduleName, businessName,
|
||||
getFrontendPageExtension(template, GenConstants.FRONTEND_INDEX_TREE_TEMPLATE_PREFIX));
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取前端输出目录。
|
||||
*
|
||||
* @param frontendType 前端模板类型
|
||||
* @return 前端输出目录
|
||||
*/
|
||||
private static String getFrontendPath(String frontendType) {
|
||||
return resolveFrontendType(frontendType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取前端页面文件扩展名。
|
||||
*
|
||||
* @param template 模板路径
|
||||
* @param templatePrefix 模板文件名前缀
|
||||
* @return 文件扩展名
|
||||
*/
|
||||
private static String getFrontendPageExtension(String template, String templatePrefix) {
|
||||
String fileName = getTemplateFileName(template);
|
||||
return fileName.substring((templatePrefix + ".").length(), fileName.length() - ".vm".length());
|
||||
}
|
||||
|
||||
private static String getFrontendApiTemplatePath(String frontendType) {
|
||||
return getFrontendTemplatePath(frontendType, GenConstants.FRONTEND_API_TEMPLATE_NAME);
|
||||
}
|
||||
|
||||
private static String getFrontendTypesTemplatePath(String frontendType) {
|
||||
return getFrontendTemplatePath(frontendType, GenConstants.FRONTEND_TYPES_TEMPLATE_NAME);
|
||||
}
|
||||
|
||||
private static String getFrontendIndexTemplatePath(String frontendType) {
|
||||
return getFrontendPageTemplatePath(frontendType, GenConstants.FRONTEND_INDEX_TEMPLATE_PREFIX);
|
||||
}
|
||||
|
||||
private static String getFrontendIndexTreeTemplatePath(String frontendType) {
|
||||
return getFrontendPageTemplatePath(frontendType, GenConstants.FRONTEND_INDEX_TREE_TEMPLATE_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析前端模板类型。
|
||||
*
|
||||
* @param frontendType 前端模板类型
|
||||
* @return 已规范化的模板目录名
|
||||
*/
|
||||
private static String resolveFrontendType(String frontendType) {
|
||||
String type = StringUtils.blankToDefault(frontendType, GenConstants.FRONTEND_TYPE_VUE);
|
||||
if (!type.matches("[A-Za-z0-9_-]+")) {
|
||||
throw new ServiceException("前端模板类型仅支持字母、数字、下划线和中划线");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static String getFrontendTemplatePath(String frontendType, String templateName) {
|
||||
return StringUtils.format("vm/{}/{}", resolveFrontendType(frontendType), templateName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取前端页面模板路径,页面输出扩展名由模板文件名决定。
|
||||
*
|
||||
* @param frontendType 前端模板类型
|
||||
* @param templatePrefix 页面模板文件名前缀
|
||||
* @return 页面模板路径
|
||||
*/
|
||||
private static String getFrontendPageTemplatePath(String frontendType, String templatePrefix) {
|
||||
String type = resolveFrontendType(frontendType);
|
||||
String pattern = StringUtils.format("classpath*:vm/{}/{}.*.vm", type, templatePrefix);
|
||||
try {
|
||||
Resource[] resources = RESOURCE_PATTERN_RESOLVER.getResources(pattern);
|
||||
if (resources.length == 0) {
|
||||
throw new ServiceException(StringUtils.format("未找到前端模板: vm/{}/{}.*.vm", type, templatePrefix));
|
||||
}
|
||||
return Arrays.stream(resources)
|
||||
.map(Resource::getFilename)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.sorted()
|
||||
.findFirst()
|
||||
.map(fileName -> StringUtils.format("vm/{}/{}", type, fileName))
|
||||
.orElseThrow(() -> new ServiceException(StringUtils.format("未找到前端模板: vm/{}/{}.*.vm", type, templatePrefix)));
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException(StringUtils.format("读取前端模板失败: vm/{}/{}.*.vm", type, templatePrefix), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isFrontendPageTemplate(String template, String templatePrefix) {
|
||||
String fileName = getTemplateFileName(template);
|
||||
return fileName.startsWith(templatePrefix + ".") && fileName.endsWith(".vm");
|
||||
}
|
||||
|
||||
private static String getTemplateFileName(String template) {
|
||||
int index = Math.max(template.lastIndexOf('/'), template.lastIndexOf('\\'));
|
||||
return index >= 0 ? template.substring(index + 1) : template;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取包前缀
|
||||
*
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import type { #if(!$table.tree)PageResult, #end R } from '@/api/types';
|
||||
import request from '@/api/request';
|
||||
import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from './types';
|
||||
|
||||
/**
|
||||
* 查询${functionName}列表
|
||||
*/
|
||||
export function list${BusinessName}(query?: ${BusinessName}Query) {
|
||||
return request<R<#if($table.tree)${BusinessName}VO[]#else PageResult<${BusinessName}VO>#end>>({
|
||||
url: '/${moduleName}/${businessName}/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询${functionName}详细
|
||||
*/
|
||||
export function get${BusinessName}(${pkColumn.javaField}: string | number) {
|
||||
return request<R<${BusinessName}VO>>({
|
||||
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增${functionName}
|
||||
*/
|
||||
export function add${BusinessName}(data: ${BusinessName}Form) {
|
||||
return request<R>({
|
||||
url: '/${moduleName}/${businessName}',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改${functionName}
|
||||
*/
|
||||
export function update${BusinessName}(data: ${BusinessName}Form) {
|
||||
return request<R>({
|
||||
url: '/${moduleName}/${businessName}',
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
#if($enableStatus)
|
||||
/**
|
||||
* 修改${functionName}状态
|
||||
*/
|
||||
export function change${BusinessName}Status(
|
||||
${pkColumn.javaField}: string | number,
|
||||
${statusField}: #if($statusColumn.javaType == 'Boolean')boolean#elseif($statusColumn.javaType == 'Integer' || $statusColumn.javaType == 'Long')number#else string#end
|
||||
) {
|
||||
return request<R>({
|
||||
url: '/${moduleName}/${businessName}/changeStatus',
|
||||
method: 'put',
|
||||
data: {
|
||||
${pkColumn.javaField},
|
||||
${statusField}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#end
|
||||
#if($enableSort)
|
||||
/**
|
||||
* 调整${functionName}排序
|
||||
*/
|
||||
export function update${BusinessName}Sort(
|
||||
${pkColumn.javaField}: string | number,
|
||||
${sortField}: #if($sortColumn.javaType == 'LocalDateTime' || $sortColumn.javaType == 'String')string#else number#end
|
||||
) {
|
||||
return request<R>({
|
||||
url: '/${moduleName}/${businessName}/updateSort',
|
||||
method: 'put',
|
||||
data: {
|
||||
${pkColumn.javaField},
|
||||
${sortField}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#end
|
||||
/**
|
||||
* 删除${functionName}
|
||||
*/
|
||||
export function del${BusinessName}(${pkColumn.javaField}: string | number | Array<string | number>) {
|
||||
return request<R>({
|
||||
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
#set($needDict = $dicts != '')
|
||||
#set($needImagePreview = false)
|
||||
#set($needImageUpload = false)
|
||||
#set($needFileUpload = false)
|
||||
#set($needEditor = false)
|
||||
#set($needCheckbox = false)
|
||||
#set($needSelect = false)
|
||||
#set($needTextArea = false)
|
||||
#set($needDigit = false)
|
||||
#set($needDateField = false)
|
||||
#set($needSwitchField = false)
|
||||
#foreach($column in $columns)
|
||||
#if($column.list && $column.htmlType == "imageUpload")
|
||||
#set($needImagePreview = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "imageUpload")
|
||||
#set($needImageUpload = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "fileUpload")
|
||||
#set($needFileUpload = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "editor")
|
||||
#set($needEditor = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "checkbox")
|
||||
#set($needCheckbox = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit || $column.query) && ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "switch"))
|
||||
#set($needSelect = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "textarea")
|
||||
#set($needTextArea = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "inputNumber")
|
||||
#set($needDigit = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "datetime")
|
||||
#set($needDateField = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit || $column.list) && $column.htmlType == "switch")
|
||||
#set($needSwitchField = true)
|
||||
#end
|
||||
#end
|
||||
#macro(comment $column)#set($idx=$column.columnComment.indexOf("("))#if($idx != -1)$column.columnComment.substring(0, $idx)#else$column.columnComment#end#end
|
||||
import { DeleteOutlined#if($enableExport), DownloadOutlined#end, EditOutlined, PlusOutlined, SortAscendingOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
ModalForm,
|
||||
PageContainer,
|
||||
#if($needCheckbox)
|
||||
ProFormCheckbox,
|
||||
#end
|
||||
#if($needDateField)
|
||||
ProFormDateTimePicker,
|
||||
#end
|
||||
#if($needDigit)
|
||||
ProFormDigit,
|
||||
#end
|
||||
#if($needSelect)
|
||||
ProFormSelect,
|
||||
#end
|
||||
#if($needTextArea)
|
||||
ProFormTextArea,
|
||||
#end
|
||||
ProFormText,
|
||||
ProFormTreeSelect,
|
||||
ProTable,
|
||||
type ActionType,
|
||||
type ProColumns
|
||||
} from '@ant-design/pro-components';
|
||||
import { useBoolean } from 'ahooks';
|
||||
import { Button, Form, message#if($enableStatus || $needSwitchField), Switch#end#if($enableSort), InputNumber#end } from 'antd';
|
||||
import { useMemo, useRef, useState } from 'react';
|
||||
import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
|
||||
import {
|
||||
add${BusinessName},
|
||||
#if($enableStatus)
|
||||
change${BusinessName}Status,
|
||||
#end
|
||||
del${BusinessName},
|
||||
get${BusinessName},
|
||||
list${BusinessName},
|
||||
#if($enableSort)
|
||||
update${BusinessName}Sort,
|
||||
#end
|
||||
update${BusinessName}
|
||||
} from '@/api/${moduleName}/${businessName}';
|
||||
#if($needDict)
|
||||
import DictTag from '@/components/common/DictTag';
|
||||
#end
|
||||
#if($needFileUpload)
|
||||
import FileUpload from '@/components/common/FileUpload';
|
||||
#end
|
||||
#if($needImagePreview)
|
||||
import ImagePreview from '@/components/common/ImagePreview';
|
||||
#end
|
||||
#if($needImageUpload)
|
||||
import ImageUpload from '@/components/common/ImageUpload';
|
||||
#end
|
||||
#if($needEditor)
|
||||
import RichTextEditor from '@/components/common/RichTextEditor';
|
||||
#end
|
||||
import RowActions from '@/components/common/RowActions';
|
||||
#if($needDict)
|
||||
import { useDict } from '@/hooks/useDict';
|
||||
#end
|
||||
#if($enableExport)
|
||||
import { useTableExport } from '@/hooks/useTableExport';
|
||||
#end
|
||||
import { useTreeTableExpand } from '@/hooks/useTreeTableExpand';
|
||||
import { useUserStore } from '@/stores/userStore';
|
||||
#if($needDict)
|
||||
import { dictOptions } from '@/utils/dict';
|
||||
#end
|
||||
#if($enableStatus)
|
||||
import { confirmAction } from '@/utils/modal';
|
||||
#end
|
||||
import { hasPermi } from '@/utils/permission';
|
||||
import { filterTree#if($needDateField), formatDateTimeFields#end, handleTree#if($needDateField), toDayjsFields#end } from '@/utils/ruoyi';
|
||||
|
||||
const default${BusinessName}Form: ${BusinessName}Form = {
|
||||
${treeParentCode}: ${treeRootValueTsLiteral},
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && !$column.pk && $column.htmlType == "checkbox")
|
||||
${column.javaField}: [],
|
||||
#end
|
||||
#end
|
||||
};
|
||||
|
||||
interface ${BusinessName}SelectNode {
|
||||
title: string;
|
||||
value: string | number;
|
||||
children?: ${BusinessName}SelectNode[];
|
||||
}
|
||||
|
||||
function toTreeSelectData(nodes: ${BusinessName}VO[]): ${BusinessName}SelectNode[] {
|
||||
return nodes.map(node => ({
|
||||
title: String(node.${treeName} || ''),
|
||||
value: node.${treeCode},
|
||||
children: node.children ? toTreeSelectData(node.children) : undefined
|
||||
}));
|
||||
}
|
||||
|
||||
#macro(switchActiveValue $column)#if($column.javaType == "Boolean")true#elseif($column.javaType == "Integer" || $column.javaType == "Long")0#else'0'#end#end
|
||||
#macro(switchInactiveValue $column)#if($column.javaType == "Boolean")false#elseif($column.javaType == "Integer" || $column.javaType == "Long")1#else'1'#end#end
|
||||
#if($enableStatus)
|
||||
const ${statusField}ActiveValue = #if($statusColumn.javaType == "Boolean")true#elseif($statusColumn.javaType == "Integer" || $statusColumn.javaType == "Long")0#else'0'#end;
|
||||
const ${statusField}InactiveValue = #if($statusColumn.javaType == "Boolean")false#elseif($statusColumn.javaType == "Integer" || $statusColumn.javaType == "Long")1#else'1'#end;
|
||||
|
||||
#end
|
||||
export default function ${BusinessName}Page() {
|
||||
const actionRef = useRef<ActionType | undefined>(undefined);
|
||||
const [form] = Form.useForm<${BusinessName}Form>();
|
||||
const userInfo = useUserStore(state => state.userInfo);
|
||||
#if($needDict)
|
||||
const dicts = useDict(${dicts});
|
||||
#end
|
||||
const [treeOptions, setTreeOptions] = useState<${BusinessName}VO[]>([]);
|
||||
const [tableRows, setTableRows] = useState<${BusinessName}VO[]>([]);
|
||||
const { expandAll, expandedRowKeys, onExpandedRowsChange, syncExpandedRows, toggleExpandAll } =
|
||||
useTreeTableExpand<${BusinessName}VO>(row => row.${treeCode});
|
||||
const [modalOpen, { setTrue: openModal, setFalse: closeModal }] = useBoolean(false);
|
||||
const [modalTitle, setModalTitle] = useState('');
|
||||
#if($enableExport)
|
||||
const { updateExportParams, exportFile } = useTableExport();
|
||||
#end
|
||||
|
||||
const canAdd = hasPermi(userInfo, ['${permissionPrefix}:add']);
|
||||
const canEdit = hasPermi(userInfo, ['${permissionPrefix}:edit']);
|
||||
const canRemove = hasPermi(userInfo, ['${permissionPrefix}:remove']);
|
||||
#if($enableExport)
|
||||
const canExport = hasPermi(userInfo, ['${permissionPrefix}:export']);
|
||||
#end
|
||||
const treeSelectData = useMemo(
|
||||
() => [{ title: '顶级节点', value: ${treeRootValueTsLiteral}, children: toTreeSelectData(treeOptions) }],
|
||||
[treeOptions]
|
||||
);
|
||||
|
||||
const loadTreeOptions = async (excludeId?: string | number) => {
|
||||
const res = await list${BusinessName}();
|
||||
const rows = handleTree<${BusinessName}VO>(res.data || [], '${treeCode}', '${treeParentCode}');
|
||||
setTreeOptions(excludeId ? filterTree(rows, node => node.${treeCode} !== excludeId) : rows);
|
||||
};
|
||||
|
||||
const openAdd = async (row?: ${BusinessName}VO) => {
|
||||
await loadTreeOptions();
|
||||
form.resetFields();
|
||||
form.setFieldsValue({ ...default${BusinessName}Form, ${treeParentCode}: row?.${treeCode} || ${treeRootValueTsLiteral} });
|
||||
setModalTitle('添加${functionName}');
|
||||
openModal();
|
||||
};
|
||||
|
||||
const openEdit = async (row: ${BusinessName}VO) => {
|
||||
await loadTreeOptions(row.${treeCode});
|
||||
const res = await get${BusinessName}(row.${pkColumn.javaField});
|
||||
const data = #if($needDateField)toDayjsFields({ ...res.data }, [
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "datetime")
|
||||
'${column.javaField}',
|
||||
#end
|
||||
#end
|
||||
])#else{ ...res.data }#end;
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "checkbox")
|
||||
if (typeof data.${column.javaField} === 'string') {
|
||||
data.${column.javaField} = data.${column.javaField}.split(',');
|
||||
}
|
||||
#end
|
||||
#end
|
||||
form.resetFields();
|
||||
form.setFieldsValue(data);
|
||||
setModalTitle('修改${functionName}');
|
||||
openModal();
|
||||
};
|
||||
|
||||
const submitForm = async (values: ${BusinessName}Form) => {
|
||||
const submitValues = #if($needDateField)formatDateTimeFields({ ...values }, [
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "datetime")
|
||||
'${column.javaField}',
|
||||
#end
|
||||
#end
|
||||
])#else{ ...values }#end;
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "checkbox")
|
||||
if (Array.isArray(submitValues.${column.javaField})) {
|
||||
submitValues.${column.javaField} = submitValues.${column.javaField}.join(',');
|
||||
}
|
||||
#end
|
||||
#end
|
||||
submitValues.${pkColumn.javaField} ? await update${BusinessName}(submitValues) : await add${BusinessName}(submitValues);
|
||||
message.success('操作成功');
|
||||
form.resetFields();
|
||||
actionRef.current?.reload();
|
||||
return true;
|
||||
};
|
||||
|
||||
const remove = async (row: ${BusinessName}VO) => {
|
||||
await del${BusinessName}(row.${pkColumn.javaField});
|
||||
message.success('删除成功');
|
||||
actionRef.current?.reload();
|
||||
};
|
||||
|
||||
#if($enableStatus)
|
||||
const handleStatusChange = async (row: ${BusinessName}VO, checked: boolean) => {
|
||||
const previousStatus = row.${statusField};
|
||||
const status = checked ? ${statusField}ActiveValue : ${statusField}InactiveValue;
|
||||
const text = checked ? '启用' : '停用';
|
||||
try {
|
||||
await confirmAction(`确认要"${text}"吗?`);
|
||||
await change${BusinessName}Status(row.${pkColumn.javaField}, status);
|
||||
message.success(`${text}成功`);
|
||||
actionRef.current?.reload();
|
||||
} catch {
|
||||
row.${statusField} = previousStatus;
|
||||
actionRef.current?.reload();
|
||||
}
|
||||
};
|
||||
|
||||
#end
|
||||
#if($enableSort)
|
||||
const handleSortChange = async (row: ${BusinessName}VO, value?: number | null) => {
|
||||
await update${BusinessName}Sort(row.${pkColumn.javaField}, value || 0);
|
||||
message.success('排序更新成功');
|
||||
actionRef.current?.reload();
|
||||
};
|
||||
|
||||
#end
|
||||
const columns: ProColumns<${BusinessName}VO>[] = [
|
||||
#foreach($column in $columns)
|
||||
#set($javaField=$column.javaField)
|
||||
#set($dictType=$column.dictType)
|
||||
#if($column.list && !$column.pk)
|
||||
#if($enableStatus && $statusField == $javaField)
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}',
|
||||
valueType: 'select',
|
||||
width: 100,
|
||||
#if("" != $dictType)
|
||||
fieldProps: { options: dictOptions(dicts.${dictType}) },
|
||||
#end
|
||||
render: (_, row) => (
|
||||
<Switch
|
||||
checked={row.${javaField} === ${statusField}ActiveValue}
|
||||
disabled={!canEdit}
|
||||
onChange={checked => handleStatusChange(row, checked)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
#elseif($enableSort && $sortField == $javaField)
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}',
|
||||
search: false,
|
||||
width: 130,
|
||||
render: (_, row) => <InputNumber min={0} value={row.${javaField} as number} onChange={value => handleSortChange(row, value)} />
|
||||
},
|
||||
#elseif($column.htmlType == "datetime")
|
||||
{ title: '#comment($column)', dataIndex: '${javaField}', valueType: 'dateTime', search: #if($column.query)true#else false#end, width: 170 },
|
||||
#elseif($column.htmlType == "imageUpload")
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}Url',
|
||||
search: false,
|
||||
width: 100,
|
||||
render: (_, row) => <ImagePreview src={row.${javaField}Url || String(row.${javaField} || '')} width={50} height={50} />
|
||||
},
|
||||
#elseif($column.dictColumn)
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}',
|
||||
valueType: 'select',
|
||||
fieldProps: { options: dictOptions(dicts.${dictType}) },
|
||||
render: (_, row) => <DictTag options={dicts.${dictType}} value={row.${javaField}} />
|
||||
},
|
||||
#elseif($column.htmlType == "switch")
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}',
|
||||
valueType: 'select',
|
||||
width: 100,
|
||||
render: (_, row) => <Switch checked={row.${javaField} === #switchActiveValue($column)} disabled />
|
||||
},
|
||||
#else
|
||||
{ title: '#comment($column)', dataIndex: '${javaField}'#if(!$column.query), search: false#end },
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
{
|
||||
title: '操作',
|
||||
valueType: 'option',
|
||||
width: 130,
|
||||
fixed: 'right',
|
||||
render: (_, row) => (
|
||||
<RowActions
|
||||
actions={[
|
||||
canEdit && { key: 'edit', label: '修改', icon: <EditOutlined />, onClick: () => openEdit(row) },
|
||||
canAdd && { key: 'add', label: '新增', icon: <PlusOutlined />, onClick: () => openAdd(row) },
|
||||
canRemove && {
|
||||
key: 'delete',
|
||||
label: '删除',
|
||||
icon: <DeleteOutlined />,
|
||||
danger: true,
|
||||
confirm: `是否确认删除${functionName}编号为"#[[${row.]]#${pkColumn.javaField}#[[}]]#"的数据项?`,
|
||||
onClick: () => remove(row)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<PageContainer title="${functionName}">
|
||||
<ProTable<${BusinessName}VO, ${BusinessName}Query>
|
||||
actionRef={actionRef}
|
||||
rowKey="${treeCode}"
|
||||
columns={columns}
|
||||
scroll={{ x: 1000 }}
|
||||
pagination={false}
|
||||
search={{ labelWidth: 90 }}
|
||||
expandable={{
|
||||
expandedRowKeys,
|
||||
onExpandedRowsChange
|
||||
}}
|
||||
request={async params => {
|
||||
const res = await list${BusinessName}(params);
|
||||
const rows = handleTree<${BusinessName}VO>(res.data || [], '${treeCode}', '${treeParentCode}');
|
||||
setTableRows(rows);
|
||||
syncExpandedRows(rows, expandAll);
|
||||
#if($enableExport)
|
||||
updateExportParams(params);
|
||||
#end
|
||||
return { data: rows, total: rows.length, success: true };
|
||||
}}
|
||||
toolbar={{ title: '${functionName}列表' }}
|
||||
toolBarRender={() => [
|
||||
canAdd && (
|
||||
<Button key="add" type="primary" icon={<PlusOutlined />} onClick={() => openAdd()}>
|
||||
新增
|
||||
</Button>
|
||||
),
|
||||
<Button
|
||||
key="expand"
|
||||
icon={<SortAscendingOutlined />}
|
||||
onClick={() => toggleExpandAll(tableRows)}
|
||||
>
|
||||
展开/折叠
|
||||
</Button>#if($enableExport),
|
||||
canExport && (
|
||||
<Button
|
||||
key="export"
|
||||
icon={<DownloadOutlined />}
|
||||
onClick={() => exportFile('/${moduleName}/${businessName}/export', () => `${businessName}_#[[${Date.now()}]]#.xlsx`)}
|
||||
>
|
||||
导出
|
||||
</Button>
|
||||
)#end
|
||||
]}
|
||||
/>
|
||||
|
||||
<ModalForm<${BusinessName}Form>
|
||||
title={modalTitle}
|
||||
open={modalOpen}
|
||||
width={560}
|
||||
form={form}
|
||||
layout="vertical"
|
||||
initialValues={default${BusinessName}Form}
|
||||
modalProps={{ destroyOnHidden: true, onCancel: closeModal }}
|
||||
onOpenChange={open => !open && closeModal()}
|
||||
onFinish={submitForm}
|
||||
>
|
||||
<ProFormText name="${pkColumn.javaField}" hidden />
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && !$column.pk)
|
||||
#set($field=$column.javaField)
|
||||
#set($dictType=$column.dictType)
|
||||
#if($field == $treeParentCode)
|
||||
<ProFormTreeSelect
|
||||
name="${field}"
|
||||
label="#comment($column)"
|
||||
#if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end
|
||||
fieldProps={{
|
||||
allowClear: true,
|
||||
treeDefaultExpandAll: true,
|
||||
treeData: treeSelectData,
|
||||
placeholder: '请选择#comment($column)'
|
||||
}}
|
||||
/>
|
||||
#elseif($column.htmlType == "input")
|
||||
<ProFormText name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "textarea")
|
||||
<ProFormTextArea name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "inputNumber")
|
||||
<ProFormDigit name="${field}" label="#comment($column)" min={0} #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif(($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "switch") && "" != $dictType)
|
||||
<ProFormSelect name="${field}" label="#comment($column)" options={dictOptions(dicts.${dictType})} #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||
<ProFormCheckbox.Group name="${field}" label="#comment($column)" options={dictOptions(dicts.${dictType})} #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "switch")
|
||||
<Form.Item
|
||||
name="${field}"
|
||||
label="#comment($column)"
|
||||
valuePropName="checked"
|
||||
getValueProps={value => ({ checked: value === #switchActiveValue($column) })}
|
||||
normalize={checked => (checked ? #switchActiveValue($column) : #switchInactiveValue($column))}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
<ProFormDateTimePicker name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "imageUpload")
|
||||
<Form.Item name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end>
|
||||
<ImageUpload />
|
||||
</Form.Item>
|
||||
#elseif($column.htmlType == "fileUpload")
|
||||
<Form.Item name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end>
|
||||
<FileUpload />
|
||||
</Form.Item>
|
||||
#elseif($column.htmlType == "editor")
|
||||
<Form.Item name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end>
|
||||
<RichTextEditor />
|
||||
</Form.Item>
|
||||
#else
|
||||
<ProFormText name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
</ModalForm>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
#set($needDict = $dicts != '')
|
||||
#set($needDateRange = false)
|
||||
#set($needImagePreview = false)
|
||||
#set($needImageUpload = false)
|
||||
#set($needFileUpload = false)
|
||||
#set($needEditor = false)
|
||||
#set($needCheckbox = false)
|
||||
#set($needSelect = false)
|
||||
#set($needTextArea = false)
|
||||
#set($needDigit = false)
|
||||
#set($needDateField = false)
|
||||
#set($needSwitchField = false)
|
||||
#foreach($column in $columns)
|
||||
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($needDateRange = true)
|
||||
#end
|
||||
#if($column.list && $column.htmlType == "imageUpload")
|
||||
#set($needImagePreview = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "imageUpload")
|
||||
#set($needImageUpload = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "fileUpload")
|
||||
#set($needFileUpload = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "editor")
|
||||
#set($needEditor = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "checkbox")
|
||||
#set($needCheckbox = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit || $column.query) && ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "switch"))
|
||||
#set($needSelect = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "textarea")
|
||||
#set($needTextArea = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "inputNumber")
|
||||
#set($needDigit = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "datetime")
|
||||
#set($needDateField = true)
|
||||
#end
|
||||
#if(($column.insert || $column.edit || $column.list) && $column.htmlType == "switch")
|
||||
#set($needSwitchField = true)
|
||||
#end
|
||||
#end
|
||||
#macro(comment $column)#set($idx=$column.columnComment.indexOf("("))#if($idx != -1)$column.columnComment.substring(0, $idx)#else$column.columnComment#end#end
|
||||
import { DeleteOutlined#if($enableExport), DownloadOutlined#end, EditOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
ModalForm,
|
||||
PageContainer,
|
||||
#if($needCheckbox)
|
||||
ProFormCheckbox,
|
||||
#end
|
||||
#if($needDateField)
|
||||
ProFormDateTimePicker,
|
||||
#end
|
||||
#if($needDigit)
|
||||
ProFormDigit,
|
||||
#end
|
||||
#if($needSelect)
|
||||
ProFormSelect,
|
||||
#end
|
||||
#if($needTextArea)
|
||||
ProFormTextArea,
|
||||
#end
|
||||
ProFormText,
|
||||
ProTable,
|
||||
type ActionType,
|
||||
type ProColumns
|
||||
} from '@ant-design/pro-components';
|
||||
import { useBoolean } from 'ahooks';
|
||||
import { Button, Form, message, Popconfirm#if($enableStatus || $needSwitchField), Switch#end#if($enableSort), InputNumber#end } from 'antd';
|
||||
import { useRef, useState } from 'react';
|
||||
import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
|
||||
import {
|
||||
add${BusinessName},
|
||||
#if($enableStatus)
|
||||
change${BusinessName}Status,
|
||||
#end
|
||||
del${BusinessName},
|
||||
get${BusinessName},
|
||||
list${BusinessName},
|
||||
#if($enableSort)
|
||||
update${BusinessName}Sort,
|
||||
#end
|
||||
update${BusinessName}
|
||||
} from '@/api/${moduleName}/${businessName}';
|
||||
#if($needDict)
|
||||
import DictTag from '@/components/common/DictTag';
|
||||
#end
|
||||
#if($needFileUpload)
|
||||
import FileUpload from '@/components/common/FileUpload';
|
||||
#end
|
||||
#if($needImagePreview)
|
||||
import ImagePreview from '@/components/common/ImagePreview';
|
||||
#end
|
||||
#if($needImageUpload)
|
||||
import ImageUpload from '@/components/common/ImageUpload';
|
||||
#end
|
||||
#if($needEditor)
|
||||
import RichTextEditor from '@/components/common/RichTextEditor';
|
||||
#end
|
||||
import RowActions from '@/components/common/RowActions';
|
||||
#if($needDict)
|
||||
import { useDict } from '@/hooks/useDict';
|
||||
#end
|
||||
#if($needDateRange)
|
||||
import { useDateRangeQuery } from '@/hooks/useDateRangeQuery';
|
||||
#end
|
||||
#if($enableExport)
|
||||
import { useTableExport } from '@/hooks/useTableExport';
|
||||
#end
|
||||
import { useTableSelection } from '@/hooks/useTableSelection';
|
||||
import { useUserStore } from '@/stores/userStore';
|
||||
#if($needDict)
|
||||
import { dictOptions } from '@/utils/dict';
|
||||
#end
|
||||
#if($enableStatus)
|
||||
import { confirmAction } from '@/utils/modal';
|
||||
#end
|
||||
import { hasPermi } from '@/utils/permission';
|
||||
import { #if($needDateField)formatDateTimeFields, toDayjsFields, #end toPageQuery, toTableData } from '@/utils/ruoyi';
|
||||
|
||||
const default${BusinessName}Form: ${BusinessName}Form = {
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && !$column.pk && $column.htmlType == "checkbox")
|
||||
${column.javaField}: [],
|
||||
#end
|
||||
#end
|
||||
};
|
||||
|
||||
#macro(switchActiveValue $column)#if($column.javaType == "Boolean")true#elseif($column.javaType == "Integer" || $column.javaType == "Long")0#else'0'#end#end
|
||||
#macro(switchInactiveValue $column)#if($column.javaType == "Boolean")false#elseif($column.javaType == "Integer" || $column.javaType == "Long")1#else'1'#end#end
|
||||
#if($enableStatus)
|
||||
const ${statusField}ActiveValue = #if($statusColumn.javaType == "Boolean")true#elseif($statusColumn.javaType == "Integer" || $statusColumn.javaType == "Long")0#else'0'#end;
|
||||
const ${statusField}InactiveValue = #if($statusColumn.javaType == "Boolean")false#elseif($statusColumn.javaType == "Integer" || $statusColumn.javaType == "Long")1#else'1'#end;
|
||||
|
||||
#end
|
||||
export default function ${BusinessName}Page() {
|
||||
const actionRef = useRef<ActionType | undefined>(undefined);
|
||||
const [form] = Form.useForm<${BusinessName}Form>();
|
||||
const userInfo = useUserStore(state => state.userInfo);
|
||||
#if($needDict)
|
||||
const dicts = useDict(${dicts});
|
||||
#end
|
||||
const { ids, selectedOne, handleSelectionChange, clearSelection } = useTableSelection<${BusinessName}VO>(
|
||||
row => row.${pkColumn.javaField}
|
||||
);
|
||||
const [modalOpen, { setTrue: openModal, setFalse: closeModal }] = useBoolean(false);
|
||||
const [modalTitle, setModalTitle] = useState('');
|
||||
#if($enableExport)
|
||||
const { updateExportParams, exportFile } = useTableExport();
|
||||
#end
|
||||
#foreach($column in $columns)
|
||||
#if($column.query && $column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
const { applyDateRange: apply${AttrName}DateRange } = useDateRangeQuery('${AttrName}');
|
||||
#end
|
||||
#end
|
||||
|
||||
const canAdd = hasPermi(userInfo, ['${permissionPrefix}:add']);
|
||||
const canEdit = hasPermi(userInfo, ['${permissionPrefix}:edit']);
|
||||
const canRemove = hasPermi(userInfo, ['${permissionPrefix}:remove']);
|
||||
#if($enableExport)
|
||||
const canExport = hasPermi(userInfo, ['${permissionPrefix}:export']);
|
||||
#end
|
||||
|
||||
const openAdd = () => {
|
||||
form.resetFields();
|
||||
form.setFieldsValue(default${BusinessName}Form);
|
||||
setModalTitle('添加${functionName}');
|
||||
openModal();
|
||||
};
|
||||
|
||||
const openEdit = async (row?: ${BusinessName}VO) => {
|
||||
const target = row || selectedOne;
|
||||
if (!target?.${pkColumn.javaField}) return;
|
||||
const res = await get${BusinessName}(target.${pkColumn.javaField});
|
||||
const data = #if($needDateField)toDayjsFields({ ...res.data }, [
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "datetime")
|
||||
'${column.javaField}',
|
||||
#end
|
||||
#end
|
||||
])#else{ ...res.data }#end;
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "checkbox")
|
||||
if (typeof data.${column.javaField} === 'string') {
|
||||
data.${column.javaField} = data.${column.javaField}.split(',');
|
||||
}
|
||||
#end
|
||||
#end
|
||||
form.resetFields();
|
||||
form.setFieldsValue(data);
|
||||
setModalTitle('修改${functionName}');
|
||||
openModal();
|
||||
};
|
||||
|
||||
const submitForm = async (values: ${BusinessName}Form) => {
|
||||
const submitValues = #if($needDateField)formatDateTimeFields({ ...values }, [
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "datetime")
|
||||
'${column.javaField}',
|
||||
#end
|
||||
#end
|
||||
])#else{ ...values }#end;
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && $column.htmlType == "checkbox")
|
||||
if (Array.isArray(submitValues.${column.javaField})) {
|
||||
submitValues.${column.javaField} = submitValues.${column.javaField}.join(',');
|
||||
}
|
||||
#end
|
||||
#end
|
||||
submitValues.${pkColumn.javaField} ? await update${BusinessName}(submitValues) : await add${BusinessName}(submitValues);
|
||||
message.success('操作成功');
|
||||
form.resetFields();
|
||||
actionRef.current?.reload();
|
||||
return true;
|
||||
};
|
||||
|
||||
const remove = async (row?: ${BusinessName}VO) => {
|
||||
await del${BusinessName}(row?.${pkColumn.javaField} || ids);
|
||||
message.success('删除成功');
|
||||
clearSelection();
|
||||
actionRef.current?.reloadAndRest?.();
|
||||
};
|
||||
|
||||
#if($enableStatus)
|
||||
const handleStatusChange = async (row: ${BusinessName}VO, checked: boolean) => {
|
||||
const previousStatus = row.${statusField};
|
||||
const status = checked ? ${statusField}ActiveValue : ${statusField}InactiveValue;
|
||||
const text = checked ? '启用' : '停用';
|
||||
try {
|
||||
await confirmAction(`确认要"${text}"吗?`);
|
||||
await change${BusinessName}Status(row.${pkColumn.javaField}, status);
|
||||
message.success(`${text}成功`);
|
||||
actionRef.current?.reload();
|
||||
} catch {
|
||||
row.${statusField} = previousStatus;
|
||||
actionRef.current?.reload();
|
||||
}
|
||||
};
|
||||
|
||||
#end
|
||||
#if($enableSort)
|
||||
const handleSortChange = async (row: ${BusinessName}VO, value?: number | null) => {
|
||||
await update${BusinessName}Sort(row.${pkColumn.javaField}, value || 0);
|
||||
message.success('排序更新成功');
|
||||
actionRef.current?.reload();
|
||||
};
|
||||
|
||||
#end
|
||||
const columns: ProColumns<${BusinessName}VO>[] = [
|
||||
#foreach($column in $columns)
|
||||
#set($javaField=$column.javaField)
|
||||
#set($dictType=$column.dictType)
|
||||
#if($column.list)
|
||||
#if($enableStatus && $statusField == $javaField)
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}',
|
||||
valueType: 'select',
|
||||
width: 100,
|
||||
#if("" != $dictType)
|
||||
fieldProps: { options: dictOptions(dicts.${dictType}) },
|
||||
#end
|
||||
render: (_, row) => (
|
||||
<Switch
|
||||
checked={row.${javaField} === ${statusField}ActiveValue}
|
||||
disabled={!canEdit}
|
||||
onChange={checked => handleStatusChange(row, checked)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
#elseif($enableSort && $sortField == $javaField)
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}',
|
||||
search: false,
|
||||
width: 130,
|
||||
render: (_, row) => <InputNumber min={0} value={row.${javaField} as number} onChange={value => handleSortChange(row, value)} />
|
||||
},
|
||||
#elseif($column.htmlType == "datetime")
|
||||
{ title: '#comment($column)', dataIndex: '${javaField}', valueType: 'dateTime', search: #if($column.query && $column.queryType != "BETWEEN")true#else false#end, width: 170 },
|
||||
#elseif($column.htmlType == "imageUpload")
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}Url',
|
||||
search: false,
|
||||
width: 100,
|
||||
render: (_, row) => <ImagePreview src={row.${javaField}Url || String(row.${javaField} || '')} width={50} height={50} />
|
||||
},
|
||||
#elseif($column.dictColumn)
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}',
|
||||
valueType: 'select',
|
||||
fieldProps: { options: dictOptions(dicts.${dictType}) },
|
||||
render: (_, row) => <DictTag options={dicts.${dictType}} value={row.${javaField}} />
|
||||
},
|
||||
#elseif($column.htmlType == "switch")
|
||||
{
|
||||
title: '#comment($column)',
|
||||
dataIndex: '${javaField}',
|
||||
valueType: 'select',
|
||||
width: 100,
|
||||
render: (_, row) => <Switch checked={row.${javaField} === #switchActiveValue($column)} disabled />
|
||||
},
|
||||
#else
|
||||
{ title: '#comment($column)', dataIndex: '${javaField}'#if(!$column.query), search: false#end },
|
||||
#end
|
||||
#end
|
||||
#if($column.query && $column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
{ title: '#comment($column)', dataIndex: '${javaField}Range', valueType: 'dateTimeRange', hideInTable: true },
|
||||
#end
|
||||
#end
|
||||
{
|
||||
title: '操作',
|
||||
valueType: 'option',
|
||||
width: 92,
|
||||
fixed: 'right',
|
||||
render: (_, row) => (
|
||||
<RowActions
|
||||
actions={[
|
||||
canEdit && { key: 'edit', label: '修改', icon: <EditOutlined />, onClick: () => openEdit(row) },
|
||||
canRemove && {
|
||||
key: 'delete',
|
||||
label: '删除',
|
||||
icon: <DeleteOutlined />,
|
||||
danger: true,
|
||||
confirm: `是否确认删除${functionName}编号为"#[[${row.]]#${pkColumn.javaField}#[[}]]#"的数据项?`,
|
||||
onClick: () => remove(row)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<PageContainer title="${functionName}">
|
||||
<ProTable<${BusinessName}VO, ${BusinessName}Query#if($needDateRange) & Record<string, unknown>#end>
|
||||
actionRef={actionRef}
|
||||
rowKey="${pkColumn.javaField}"
|
||||
columns={columns}
|
||||
scroll={{ x: 1000 }}
|
||||
search={{ labelWidth: 90 }}
|
||||
pagination={{ defaultPageSize: 10, showSizeChanger: true }}
|
||||
rowSelection={{ selectedRowKeys: ids, onChange: handleSelectionChange }}
|
||||
request={async params => {
|
||||
#if($needDateRange)
|
||||
let query = toPageQuery(params);
|
||||
#foreach($column in $columns)
|
||||
#if($column.query && $column.htmlType == "datetime" && $column.queryType == "BETWEEN")
|
||||
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
query = apply${AttrName}DateRange(query, params.${column.javaField}Range as [string, string] | undefined);
|
||||
delete query.${column.javaField}Range;
|
||||
#end
|
||||
#end
|
||||
#else
|
||||
const query = toPageQuery(params);
|
||||
#end
|
||||
#if($enableExport)
|
||||
updateExportParams(query);
|
||||
#end
|
||||
const res = await list${BusinessName}(query);
|
||||
return toTableData(res);
|
||||
}}
|
||||
toolbar={{ title: '${functionName}列表' }}
|
||||
toolBarRender={() => [
|
||||
canAdd && (
|
||||
<Button key="add" type="primary" icon={<PlusOutlined />} onClick={openAdd}>
|
||||
新增
|
||||
</Button>
|
||||
),
|
||||
canEdit && (
|
||||
<Button key="edit" disabled={!selectedOne} icon={<EditOutlined />} onClick={() => openEdit()}>
|
||||
修改
|
||||
</Button>
|
||||
),
|
||||
canRemove && (
|
||||
<Popconfirm key="delete" title={`是否确认删除${functionName}编号为"#[[${ids}]]#"的数据项?`} onConfirm={() => remove()}>
|
||||
<Button danger disabled={!ids.length} icon={<DeleteOutlined />}>
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
)#if($enableExport),
|
||||
canExport && (
|
||||
<Button
|
||||
key="export"
|
||||
icon={<DownloadOutlined />}
|
||||
onClick={() => exportFile('/${moduleName}/${businessName}/export', () => `${businessName}_#[[${Date.now()}]]#.xlsx`)}
|
||||
>
|
||||
导出
|
||||
</Button>
|
||||
)#end
|
||||
]}
|
||||
/>
|
||||
|
||||
<ModalForm<${BusinessName}Form>
|
||||
title={modalTitle}
|
||||
open={modalOpen}
|
||||
width={560}
|
||||
form={form}
|
||||
layout="vertical"
|
||||
initialValues={default${BusinessName}Form}
|
||||
modalProps={{ destroyOnHidden: true, onCancel: closeModal }}
|
||||
onOpenChange={open => !open && closeModal()}
|
||||
onFinish={submitForm}
|
||||
>
|
||||
<ProFormText name="${pkColumn.javaField}" hidden />
|
||||
#foreach($column in $columns)
|
||||
#if(($column.insert || $column.edit) && !$column.pk)
|
||||
#set($field=$column.javaField)
|
||||
#set($dictType=$column.dictType)
|
||||
#if($column.htmlType == "input")
|
||||
<ProFormText name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "textarea")
|
||||
<ProFormTextArea name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "inputNumber")
|
||||
<ProFormDigit name="${field}" label="#comment($column)" min={0} #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif(($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "switch") && "" != $dictType)
|
||||
<ProFormSelect name="${field}" label="#comment($column)" options={dictOptions(dicts.${dictType})} #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "checkbox" && "" != $dictType)
|
||||
<ProFormCheckbox.Group name="${field}" label="#comment($column)" options={dictOptions(dicts.${dictType})} #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "switch")
|
||||
<Form.Item
|
||||
name="${field}"
|
||||
label="#comment($column)"
|
||||
valuePropName="checked"
|
||||
getValueProps={value => ({ checked: value === #switchActiveValue($column) })}
|
||||
normalize={checked => (checked ? #switchActiveValue($column) : #switchInactiveValue($column))}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
<ProFormDateTimePicker name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#elseif($column.htmlType == "imageUpload")
|
||||
<Form.Item name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end>
|
||||
<ImageUpload />
|
||||
</Form.Item>
|
||||
#elseif($column.htmlType == "fileUpload")
|
||||
<Form.Item name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end>
|
||||
<FileUpload />
|
||||
</Form.Item>
|
||||
#elseif($column.htmlType == "editor")
|
||||
<Form.Item name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end>
|
||||
<RichTextEditor />
|
||||
</Form.Item>
|
||||
#else
|
||||
<ProFormText name="${field}" label="#comment($column)" #if($column.required)rules={[{ required: true, message: '#comment($column)不能为空' }]}#end />
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
</ModalForm>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import type { BaseEntity#if(!$table.tree), PageQuery#end } from '@/api/types';
|
||||
|
||||
#macro(tsType $column)#if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1)string | number#elseif($column.javaType == 'Long' || $column.javaType == 'Integer' || $column.javaType == 'Double' || $column.javaType == 'Float' || $column.javaType == 'BigDecimal')number#elseif($column.javaType == 'Boolean')boolean#else string#end#end
|
||||
|
||||
export interface ${BusinessName}VO {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.list || $column.pk)
|
||||
/**
|
||||
* $column.columnComment
|
||||
*/
|
||||
$column.javaField: #tsType($column);
|
||||
#if($column.htmlType == "imageUpload")
|
||||
/**
|
||||
* ${column.columnComment}Url
|
||||
*/
|
||||
${column.javaField}Url?: string;
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
#if($table.tree)
|
||||
/**
|
||||
* 子对象
|
||||
*/
|
||||
children?: ${BusinessName}VO[];
|
||||
#end
|
||||
}
|
||||
|
||||
export interface ${BusinessName}Form extends BaseEntity {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.insert || $column.edit || $column.pk)
|
||||
/**
|
||||
* $column.columnComment
|
||||
*/
|
||||
#if($column.htmlType == "checkbox")
|
||||
$column.javaField?: string | string[];
|
||||
#else
|
||||
$column.javaField?: #tsType($column);
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
export interface ${BusinessName}Query#if(!$table.tree) extends PageQuery#end {
|
||||
#foreach ($column in $columns)
|
||||
#if($column.query)
|
||||
/**
|
||||
* $column.columnComment
|
||||
*/
|
||||
$column.javaField?: #tsType($column);
|
||||
#end
|
||||
#end
|
||||
/**
|
||||
* 日期范围参数
|
||||
*/
|
||||
params?: Record<string, unknown>;
|
||||
}
|
||||
@@ -1005,10 +1005,9 @@ create table gen_table (
|
||||
data_name varchar2(200) default '',
|
||||
table_name varchar2(200) default '',
|
||||
table_comment varchar2(500) default '',
|
||||
sub_table_name varchar2(64) default null,
|
||||
sub_table_fk_name varchar2(64) default null,
|
||||
class_name varchar2(100) default '',
|
||||
tpl_category varchar2(200) default 'crud',
|
||||
frontend_type varchar2(50) default 'vue',
|
||||
package_name varchar2(100),
|
||||
module_name varchar2(30),
|
||||
business_name varchar2(30),
|
||||
@@ -1032,10 +1031,9 @@ comment on column gen_table.table_id is '编号';
|
||||
comment on column gen_table.data_name is '数据源名称';
|
||||
comment on column gen_table.table_name is '表名称';
|
||||
comment on column gen_table.table_comment is '表描述';
|
||||
comment on column gen_table.sub_table_name is '关联子表的表名';
|
||||
comment on column gen_table.sub_table_fk_name is '子表关联的外键名';
|
||||
comment on column gen_table.class_name is '实体类名称';
|
||||
comment on column gen_table.tpl_category is '使用的模板(crud单表操作 tree树表操作)';
|
||||
comment on column gen_table.frontend_type is '前端模板类型,对应 vm 下的模板目录';
|
||||
comment on column gen_table.package_name is '生成包路径';
|
||||
comment on column gen_table.module_name is '生成模块名';
|
||||
comment on column gen_table.business_name is '生成业务名';
|
||||
|
||||
@@ -1004,10 +1004,9 @@ create table if not exists gen_table
|
||||
data_name varchar(200) default ''::varchar,
|
||||
table_name varchar(200) default ''::varchar,
|
||||
table_comment varchar(500) default ''::varchar,
|
||||
sub_table_name varchar(64) default ''::varchar,
|
||||
sub_table_fk_name varchar(64) default ''::varchar,
|
||||
class_name varchar(100) default ''::varchar,
|
||||
tpl_category varchar(200) default 'crud'::varchar,
|
||||
frontend_type varchar(50) default 'vue'::varchar,
|
||||
package_name varchar(100) default null::varchar,
|
||||
module_name varchar(30) default null::varchar,
|
||||
business_name varchar(30) default null::varchar,
|
||||
@@ -1030,10 +1029,9 @@ comment on column gen_table.table_id is '编号';
|
||||
comment on column gen_table.data_name is '数据源名称';
|
||||
comment on column gen_table.table_name is '表名称';
|
||||
comment on column gen_table.table_comment is '表描述';
|
||||
comment on column gen_table.sub_table_name is '关联子表的表名';
|
||||
comment on column gen_table.sub_table_fk_name is '子表关联的外键名';
|
||||
comment on column gen_table.class_name is '实体类名称';
|
||||
comment on column gen_table.tpl_category is '使用的模板(CRUD单表操作 TREE树表操作)';
|
||||
comment on column gen_table.frontend_type is '前端模板类型,对应 vm 下的模板目录';
|
||||
comment on column gen_table.package_name is '生成包路径';
|
||||
comment on column gen_table.module_name is '生成模块名';
|
||||
comment on column gen_table.business_name is '生成业务名';
|
||||
|
||||
@@ -736,10 +736,9 @@ create table gen_table (
|
||||
data_name varchar(200) default '' comment '数据源名称',
|
||||
table_name varchar(200) default '' comment '表名称',
|
||||
table_comment varchar(500) default '' comment '表描述',
|
||||
sub_table_name varchar(64) default null comment '关联子表的表名',
|
||||
sub_table_fk_name varchar(64) default null comment '子表关联的外键名',
|
||||
class_name varchar(100) default '' comment '实体类名称',
|
||||
tpl_category varchar(200) default 'crud' comment '使用的模板(crud单表操作 tree树表操作)',
|
||||
frontend_type varchar(50) default 'vue' comment '前端模板类型,对应 vm 下的模板目录',
|
||||
package_name varchar(100) comment '生成包路径',
|
||||
module_name varchar(30) comment '生成模块名',
|
||||
business_name varchar(30) comment '生成业务名',
|
||||
|
||||
@@ -216,10 +216,9 @@ CREATE TABLE gen_table
|
||||
data_name nvarchar(200) DEFAULT '' NULL,
|
||||
table_name nvarchar(200) DEFAULT '' NULL,
|
||||
table_comment nvarchar(500) DEFAULT '' NULL,
|
||||
sub_table_name nvarchar(64) NULL,
|
||||
sub_table_fk_name nvarchar(64) NULL,
|
||||
class_name nvarchar(100) DEFAULT '' NULL,
|
||||
tpl_category nvarchar(200) DEFAULT ('crud') NULL,
|
||||
frontend_type nvarchar(50) DEFAULT ('vue') NULL,
|
||||
package_name nvarchar(100) NULL,
|
||||
module_name nvarchar(30) NULL,
|
||||
business_name nvarchar(30) NULL,
|
||||
@@ -265,18 +264,6 @@ EXEC sys.sp_addextendedproperty
|
||||
'TABLE', N'gen_table',
|
||||
'COLUMN', N'table_comment'
|
||||
GO
|
||||
EXEC sys.sp_addextendedproperty
|
||||
'MS_Description', N'关联子表的表名' ,
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'gen_table',
|
||||
'COLUMN', N'sub_table_name'
|
||||
GO
|
||||
EXEC sys.sp_addextendedproperty
|
||||
'MS_Description', N'子表关联的外键名' ,
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'gen_table',
|
||||
'COLUMN', N'sub_table_fk_name'
|
||||
GO
|
||||
EXEC sys.sp_addextendedproperty
|
||||
'MS_Description', N'实体类名称' ,
|
||||
'SCHEMA', N'dbo',
|
||||
@@ -289,6 +276,12 @@ EXEC sys.sp_addextendedproperty
|
||||
'TABLE', N'gen_table',
|
||||
'COLUMN', N'tpl_category'
|
||||
GO
|
||||
EXEC sys.sp_addextendedproperty
|
||||
'MS_Description', N'前端模板类型,对应 vm 下的模板目录' ,
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'gen_table',
|
||||
'COLUMN', N'frontend_type'
|
||||
GO
|
||||
EXEC sys.sp_addextendedproperty
|
||||
'MS_Description', N'生成包路径' ,
|
||||
'SCHEMA', N'dbo',
|
||||
|
||||
Reference in New Issue
Block a user