代码生成,支持配置前端 UI 类型
This commit is contained in:
parent
c5b6a2a53d
commit
ca9656a40f
@ -37,7 +37,7 @@ public class CodegenUpdateReqVO {
|
||||
@Schema(description = "编号", required = true, example = "1")
|
||||
private Long id;
|
||||
|
||||
@AssertTrue(message = "上级菜单不能为空")
|
||||
@AssertTrue(message = "上级菜单不能为空,请前往 [修改生成配置 -> 生成信息] 界面,设置“上级菜单”字段")
|
||||
public boolean isParentMenuIdValid() {
|
||||
// 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的
|
||||
return ObjectUtil.notEqual(getScene(), CodegenSceneEnum.ADMIN.getScene())
|
||||
@ -57,4 +57,4 @@ public class CodegenUpdateReqVO {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,11 @@ public class CodegenTableBaseVO {
|
||||
@NotNull(message = "模板类型不能为空")
|
||||
private Integer templateType;
|
||||
|
||||
@Schema(description = "前端类型,参见 CodegenFrontTypeEnum 枚举", required = true, example = "20")
|
||||
@NotNull(message = "前端类型不能为空")
|
||||
private Integer frontType;
|
||||
|
||||
@Schema(description = "父菜单编号", example = "1024")
|
||||
private Long parentMenuId;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.dal.dataobject.codegen;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
@ -100,6 +101,12 @@ public class CodegenTableDO extends BaseDO {
|
||||
* 枚举 {@link CodegenTemplateTypeEnum}
|
||||
*/
|
||||
private Integer templateType;
|
||||
/**
|
||||
* 代码生成的前端类型
|
||||
*
|
||||
* 枚举 {@link CodegenFrontTypeEnum}
|
||||
*/
|
||||
private Integer frontType;
|
||||
|
||||
// ========== 菜单相关字段 ==========
|
||||
|
||||
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.infra.enums.codegen;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 代码生成的前端类型枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum CodegenFrontTypeEnum {
|
||||
|
||||
VUE2(10), // Vue2 Element UI 标准模版
|
||||
VUE3(20), // Vue3 Element Plus 标准模版
|
||||
VUE3_SCHEMA(21), // Vue3 Element Plus Schema 模版
|
||||
;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.infra.framework.codegen.config;
|
||||
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -25,4 +26,12 @@ public class CodegenProperties {
|
||||
@NotEmpty(message = "数据库不能为空")
|
||||
private Collection<String> dbSchemas;
|
||||
|
||||
/**
|
||||
* 代码生成的前端类型(默认)
|
||||
*
|
||||
* 枚举 {@link CodegenFrontTypeEnum#getType()}
|
||||
*/
|
||||
@NotNull(message = "代码生成的前端类型不能为空")
|
||||
private Integer frontType;
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;
|
||||
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
|
||||
import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder;
|
||||
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
|
||||
import cn.iocoder.yudao.module.infra.service.db.DatabaseTableService;
|
||||
@ -58,6 +59,9 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
@Resource
|
||||
private CodegenEngine codegenEngine;
|
||||
|
||||
@Resource
|
||||
private CodegenProperties codegenProperties;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<Long> createCodegenList(Long userId, CodegenCreateListReqVO reqVO) {
|
||||
@ -87,6 +91,7 @@ public class CodegenServiceImpl implements CodegenService {
|
||||
CodegenTableDO table = codegenBuilder.buildTable(tableInfo);
|
||||
table.setDataSourceConfigId(dataSourceConfigId);
|
||||
table.setScene(CodegenSceneEnum.ADMIN.getScene()); // 默认配置下,使用管理后台的模板
|
||||
table.setFrontType(codegenProperties.getFrontType());
|
||||
table.setAuthor(userApi.getUser(userId).getCheckedData().getNickname());
|
||||
codegenTableMapper.insert(table);
|
||||
|
||||
|
@ -23,9 +23,12 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
|
||||
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
|
||||
import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Table;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@ -50,11 +53,12 @@ import static cn.hutool.core.text.CharSequenceUtil.*;
|
||||
public class CodegenEngine {
|
||||
|
||||
/**
|
||||
* 模板配置
|
||||
* 后端的模板配置
|
||||
*
|
||||
* key:模板在 resources 的地址
|
||||
* value:生成的路径
|
||||
*/
|
||||
private static final Map<String, String> TEMPLATES = MapUtil.<String, String>builder(new LinkedHashMap<>()) // 有序
|
||||
private static final Map<String, String> SERVER_TEMPLATES = MapUtil.<String, String>builder(new LinkedHashMap<>()) // 有序
|
||||
// Java module-biz Main
|
||||
.put(javaTemplatePath("controller/vo/baseVO"), javaModuleImplVOFilePath("BaseVO"))
|
||||
.put(javaTemplatePath("controller/vo/createReqVO"), javaModuleImplVOFilePath("CreateReqVO"))
|
||||
@ -80,25 +84,40 @@ public class CodegenEngine {
|
||||
javaModuleImplTestFilePath("service/${table.businessName}/${table.className}ServiceImplTest"))
|
||||
// Java module-api Main
|
||||
.put(javaTemplatePath("enums/errorcode"), javaModuleApiMainFilePath("enums/ErrorCodeConstants_手动操作"))
|
||||
// Vue2
|
||||
.put(vueTemplatePath("views/index.vue"),
|
||||
vueFilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
|
||||
.put(vueTemplatePath("api/api.js"),
|
||||
vueFilePath("api/${table.moduleName}/${classNameVar}.js"))
|
||||
// Vue3
|
||||
.put(vue3TemplatePath("views/index.vue"),
|
||||
vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
|
||||
.put(vue3TemplatePath("views/data.ts"),
|
||||
vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts"))
|
||||
.put(vue3TemplatePath("api/api.ts"),
|
||||
vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts"))
|
||||
.put(vue3TemplatePath("api/types.ts"),
|
||||
vue3FilePath("api/${table.moduleName}/${classNameVar}/types.ts"))
|
||||
// SQL
|
||||
.put("codegen/sql/sql.vm", "sql/sql.sql")
|
||||
.put("codegen/sql/h2.vm", "sql/h2.sql")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* 后端的配置模版
|
||||
*
|
||||
* key1:UI 模版的类型 {@link CodegenFrontTypeEnum#getType()}
|
||||
* key2:模板在 resources 的地址
|
||||
* value:生成的路径
|
||||
*/
|
||||
private static final Table<Integer, String, String> FRONT_TEMPLATES = ImmutableTable.<Integer, String, String>builder()
|
||||
// Vue2 标准模版
|
||||
.put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/index.vue"),
|
||||
vueFilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
|
||||
.put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("api/api.js"),
|
||||
vueFilePath("api/${table.moduleName}/${classNameVar}.js"))
|
||||
// Vue3 标准模版
|
||||
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/index.vue"),
|
||||
vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
|
||||
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/form.vue"),
|
||||
vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue"))
|
||||
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("api/api.ts"),
|
||||
vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts"))
|
||||
// Vue3 Schema 模版
|
||||
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"),
|
||||
vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts"))
|
||||
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/index.vue"),
|
||||
vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
|
||||
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/form.vue"),
|
||||
vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue"))
|
||||
.build();
|
||||
|
||||
@Resource
|
||||
private CodegenProperties codegenProperties;
|
||||
|
||||
@ -167,20 +186,32 @@ public class CodegenEngine {
|
||||
bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase);
|
||||
|
||||
// 执行生成
|
||||
final Map<String, String> result = Maps.newLinkedHashMapWithExpectedSize(TEMPLATES.size()); // 有序
|
||||
TEMPLATES.forEach((vmPath, filePath) -> {
|
||||
Map<String, String> templates = getTemplates(table.getFrontType());
|
||||
Map<String, String> result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序
|
||||
templates.forEach((vmPath, filePath) -> {
|
||||
filePath = formatFilePath(filePath, bindingMap);
|
||||
String content = templateEngine.getTemplate(vmPath).render(bindingMap);
|
||||
// 去除字段后面多余的 , 逗号
|
||||
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
|
||||
result.put(filePath, content);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, String> getTemplates(Integer frontType) {
|
||||
Map<String, String> templates = new LinkedHashMap<>();
|
||||
templates.putAll(SERVER_TEMPLATES);
|
||||
templates.putAll(FRONT_TEMPLATES.row(frontType));
|
||||
return templates;
|
||||
}
|
||||
|
||||
private String formatFilePath(String filePath, Map<String, Object> bindingMap) {
|
||||
filePath = StrUtil.replace(filePath, "${basePackage}",
|
||||
getStr(bindingMap, "basePackage").replaceAll("\\.", "/"));
|
||||
filePath = StrUtil.replace(filePath, "${classNameVar}",
|
||||
getStr(bindingMap, "classNameVar"));
|
||||
filePath = StrUtil.replace(filePath, "${simpleClassName}",
|
||||
getStr(bindingMap, "simpleClassName"));
|
||||
// sceneEnum 包含的字段
|
||||
CodegenSceneEnum sceneEnum = (CodegenSceneEnum) bindingMap.get("sceneEnum");
|
||||
filePath = StrUtil.replace(filePath, "${sceneEnum.prefixClass}", sceneEnum.getPrefixClass());
|
||||
@ -239,6 +270,7 @@ public class CodegenEngine {
|
||||
return "yudao-ui-${sceneEnum.basePackage}/" + // 顶级目录
|
||||
"src/" + path;
|
||||
}
|
||||
|
||||
private static String vue3TemplatePath(String path) {
|
||||
return "codegen/vue3/" + path + ".vm";
|
||||
}
|
||||
@ -247,4 +279,8 @@ public class CodegenEngine {
|
||||
return "yudao-ui-${sceneEnum.basePackage}-vue3/" + // 顶级目录
|
||||
"src/" + path;
|
||||
}
|
||||
|
||||
private static String vue3SchemaTemplatePath(String path) {
|
||||
return "codegen/vue3_schema/" + path + ".vm";
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ yudao:
|
||||
codegen:
|
||||
base-package: cn.iocoder.yudao
|
||||
db-schemas: ${spring.datasource.dynamic.datasource.master.name}
|
||||
front-type: 10 # 前端模版的类型,参见 CodegenFrontTypeEnum 枚举类
|
||||
error-code: # 错误码相关配置项
|
||||
constants-class-list:
|
||||
- cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants
|
||||
|
@ -1,17 +1,17 @@
|
||||
## @formatter:off
|
||||
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName};
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
#if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
@ -24,7 +24,6 @@ import ${ExcelUtilsClassName};
|
||||
import ${OperateLogClassName};
|
||||
import static ${OperateTypeEnumClassName}.*;
|
||||
|
||||
import ${basePackage}.framework.operatelog.core.annotations.OperateLog;
|
||||
import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
|
||||
import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
|
||||
import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert;
|
||||
@ -42,18 +41,16 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建${table.classComment}")
|
||||
#if ($sceneEnum.scene == 1)
|
||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")
|
||||
#end
|
||||
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")#end
|
||||
|
||||
public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) {
|
||||
return success(${classNameVar}Service.create${simpleClassName}(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新${table.classComment}")
|
||||
#if ($sceneEnum.scene == 1)
|
||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")
|
||||
#end
|
||||
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")#end
|
||||
|
||||
public CommonResult<Boolean> update${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) {
|
||||
${classNameVar}Service.update${simpleClassName}(updateReqVO);
|
||||
return success(true);
|
||||
@ -62,9 +59,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除${table.classComment}")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
#if ($sceneEnum.scene == 1)
|
||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")
|
||||
#end
|
||||
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")#end
|
||||
|
||||
public CommonResult<Boolean> delete${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
|
||||
${classNameVar}Service.delete${simpleClassName}(id);
|
||||
return success(true);
|
||||
@ -73,9 +69,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得${table.classComment}")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
#if ($sceneEnum.scene == 1)
|
||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
|
||||
#end
|
||||
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end
|
||||
|
||||
public CommonResult<${sceneEnum.prefixClass}${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) {
|
||||
${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id);
|
||||
return success(${table.className}Convert.INSTANCE.convert(${classNameVar}));
|
||||
@ -84,9 +79,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得${table.classComment}列表")
|
||||
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
|
||||
#if ($sceneEnum.scene == 1)
|
||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
|
||||
#end
|
||||
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end
|
||||
|
||||
public CommonResult<List<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) {
|
||||
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(ids);
|
||||
return success(${table.className}Convert.INSTANCE.convertList(list));
|
||||
@ -94,9 +88,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得${table.classComment}分页")
|
||||
#if ($sceneEnum.scene == 1)
|
||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
|
||||
#end
|
||||
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end
|
||||
|
||||
public CommonResult<PageResult<${sceneEnum.prefixClass}${table.className}RespVO>> get${simpleClassName}Page(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageVO) {
|
||||
PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageVO);
|
||||
return success(${table.className}Convert.INSTANCE.convertPage(pageResult));
|
||||
@ -104,16 +97,15 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出${table.classComment} Excel")
|
||||
#if ($sceneEnum.scene == 1)
|
||||
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")
|
||||
#end
|
||||
#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")#end
|
||||
|
||||
@OperateLog(type = EXPORT)
|
||||
public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(exportReqVO);
|
||||
// 导出 Excel
|
||||
List<${sceneEnum.prefixClass}${table.className}ExcelVO> datas = ${table.className}Convert.INSTANCE.convertList02(list);
|
||||
ExcelUtils.write(response, "${table.classComment}.xls","数据", ${sceneEnum.prefixClass}${table.className}ExcelVO.class, datas);
|
||||
ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${sceneEnum.prefixClass}${table.className}ExcelVO.class, datas);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
## @formatter:off
|
||||
## 提供给 baseVO、createVO、updateVO 生成字段
|
||||
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
|
||||
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), required = true#end#if ("$!column.example" != ""), example = "${column.example}"#end)
|
||||
#if (!${column.nullable})## 判断 @NotEmpty 和 @NotNull 注解
|
||||
#if (${field.fieldType} == 'String')
|
||||
@NotEmpty(message = "${column.columnComment}不能为空")
|
||||
@ -11,4 +10,4 @@
|
||||
#if (${column.javaType} == "LocalDateTime")## 时间类型
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
#end
|
||||
private ${column.javaType} ${column.javaField};
|
||||
private ${column.javaType} ${column.javaField};
|
||||
|
@ -1,6 +1,6 @@
|
||||
## @formatter:off
|
||||
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
#foreach ($column in $columns)
|
||||
@ -11,11 +11,11 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
#end
|
||||
#end
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import javax.validation.constraints.*;
|
||||
## 处理 Date 字段的引入
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult} && ${column.javaType} == "LocalDateTime")## 时间类型
|
||||
#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult}
|
||||
&& ${column.javaType} == "LocalDateTime")## 时间类型
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
@ -1,13 +1,13 @@
|
||||
## @formatter:off
|
||||
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import javax.validation.constraints.*;
|
||||
## 处理 Date 字段的引入
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult}) && ${column.javaType} == "LocalDateTime")## 时间类型
|
||||
#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult})
|
||||
&& ${column.javaType} == "LocalDateTime")## 时间类型
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
@ -15,7 +15,7 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
#end
|
||||
#end
|
||||
|
||||
@Schema(name = "${sceneEnum.name} - ${table.classComment}创建 Request VO")
|
||||
@Schema(description = "${sceneEnum.name} - ${table.classComment}创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
@ -1,6 +1,6 @@
|
||||
## @formatter:off
|
||||
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
#foreach ($column in $columns)
|
||||
@ -11,6 +11,7 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
#end
|
||||
#end
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
#foreach ($column in $columns)
|
||||
#if ("$!column.dictType" != "")## 有设置数据字典
|
||||
@ -22,10 +23,10 @@ import ${DictConvertClassName};
|
||||
#end
|
||||
|
||||
/**
|
||||
* ${table.classComment} Excel VO
|
||||
*
|
||||
* @author ${table.author}
|
||||
*/
|
||||
* ${table.classComment} Excel VO
|
||||
*
|
||||
* @author ${table.author}
|
||||
*/
|
||||
@Data
|
||||
public class ${sceneEnum.prefixClass}${table.className}ExcelVO {
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
## @formatter:off
|
||||
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
|
||||
|
||||
import lombok.*;
|
||||
@ -21,7 +20,7 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end;
|
||||
#end
|
||||
|
||||
@Schema(name = "${sceneEnum.name} - ${table.classComment} Excel 导出 Request VO", description = "参数和 ${table.className}PageReqVO 是一致的")
|
||||
@Schema(description = "${sceneEnum.name} - ${table.classComment} Excel 导出 Request VO,参数和 ${table.className}PageReqVO 是一致的")
|
||||
@Data
|
||||
public class ${sceneEnum.prefixClass}${table.className}ExportReqVO {
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
## @formatter:off
|
||||
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
|
||||
|
||||
import lombok.*;
|
||||
@ -21,7 +20,7 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end;
|
||||
#end
|
||||
|
||||
@Schema(name = "${sceneEnum.name} - ${table.classComment}分页 Request VO")
|
||||
@Schema(description = "${sceneEnum.name} - ${table.classComment}分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
@ -1,8 +1,7 @@
|
||||
## @formatter:off
|
||||
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.javaType} == "LocalDateTime")
|
||||
import java.time.LocalDateTime;
|
||||
@ -10,7 +9,7 @@ import java.time.LocalDateTime;
|
||||
#end
|
||||
#end
|
||||
|
||||
@Schema(name = "${sceneEnum.name} - ${table.classComment} Response VO")
|
||||
@Schema(description = "${sceneEnum.name} - ${table.classComment} Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@ -18,7 +17,7 @@ public class ${sceneEnum.prefixClass}${table.className}RespVO extends ${sceneEnu
|
||||
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.listOperationResult} && (!${column.createOperation} || !${column.updateOperation}))##不是通用字段
|
||||
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
|
||||
@Schema(description = "${column.columnComment}"#if (!${column.nullable}), required = true#end#if ("$!column.example" != ""), example = "${column.example}"#end)
|
||||
private ${column.javaType} ${column.javaField};
|
||||
|
||||
#end
|
||||
|
@ -1,13 +1,13 @@
|
||||
## @formatter:off
|
||||
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import javax.validation.constraints.*;
|
||||
## 处理 Date 字段的引入
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult}) && ${column.javaType} == "LocalDateTime")## 时间类型
|
||||
#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult})
|
||||
&& ${column.javaType} == "LocalDateTime")## 时间类型
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
@ -15,7 +15,7 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
#end
|
||||
#end
|
||||
|
||||
@Schema(name = "${sceneEnum.name} - ${table.classComment}更新 Request VO")
|
||||
@Schema(description = "${sceneEnum.name} - ${table.classComment}更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
|
@ -1,11 +1,11 @@
|
||||
-- 菜单 SQL
|
||||
INSERT INTO system_menu(
|
||||
name, permission, type, sort, parent_id,
|
||||
path, icon, component, status
|
||||
path, icon, component, status, component_name
|
||||
)
|
||||
VALUES (
|
||||
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
|
||||
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${classNameVar}/index', 0
|
||||
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${classNameVar}/index', 0, '${table.className}'
|
||||
);
|
||||
|
||||
-- 按钮父菜单ID
|
||||
|
@ -14,61 +14,32 @@ export interface ${simpleClassName}VO {
|
||||
#end
|
||||
}
|
||||
|
||||
export interface ${simpleClassName}PageReqVO extends PageParam {
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.listOperation})##查询操作
|
||||
#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
|
||||
${column.javaField}?: number
|
||||
#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime")
|
||||
${column.javaField}?: Date[]
|
||||
#else
|
||||
${column.javaField}?: ${column.javaType.toLowerCase()}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
export interface ${simpleClassName}ExcelReqVO {
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.listOperation})##查询操作
|
||||
#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
|
||||
${column.javaField}?: number
|
||||
#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime")
|
||||
${column.javaField}?: Date[]
|
||||
#else
|
||||
${column.javaField}?: ${column.javaType.toLowerCase()}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
}
|
||||
#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
|
||||
|
||||
// 查询${table.classComment}列表
|
||||
export const get${simpleClassName}PageApi = async (params: ${simpleClassName}PageReqVO) => {
|
||||
export const get${simpleClassName}Page = async (params: ${simpleClassName}PageReqVO) => {
|
||||
return await request.get({ url: '${baseURL}/page', params })
|
||||
}
|
||||
|
||||
// 查询${table.classComment}详情
|
||||
export const get${simpleClassName}Api = async (id: number) => {
|
||||
export const get${simpleClassName} = async (id: number) => {
|
||||
return await request.get({ url: '${baseURL}/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增${table.classComment}
|
||||
export const create${simpleClassName}Api = async (data: ${simpleClassName}VO) => {
|
||||
export const create${simpleClassName} = async (data: ${simpleClassName}VO) => {
|
||||
return await request.post({ url: '${baseURL}/create', data })
|
||||
}
|
||||
|
||||
// 修改${table.classComment}
|
||||
export const update${simpleClassName}Api = async (data: ${simpleClassName}VO) => {
|
||||
export const update${simpleClassName} = async (data: ${simpleClassName}VO) => {
|
||||
return await request.put({ url: '${baseURL}/update', data })
|
||||
}
|
||||
|
||||
// 删除${table.classComment}
|
||||
export const delete${simpleClassName}Api = async (id: number) => {
|
||||
export const delete${simpleClassName} = async (id: number) => {
|
||||
return await request.delete({ url: '${baseURL}/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 导出${table.classComment} Excel
|
||||
export const export${simpleClassName}Api = async (params: ${simpleClassName}ExcelReqVO) => {
|
||||
export const export${simpleClassName}Api = async (params) => {
|
||||
return await request.download({ url: '${baseURL}/export-excel', params })
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
export type ${simpleClassName}VO = {
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.createOperation || $column.updateOperation)
|
||||
#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
|
||||
${column.javaField}: number
|
||||
#elseif(${column.javaType.toLowerCase()} == "date")
|
||||
${column.javaField}: string
|
||||
#else
|
||||
${column.javaField}: ${column.javaType.toLowerCase()}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
export type ${simpleClassName}PageReqVO = {
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.listOperation})##查询操作
|
||||
#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
|
||||
${column.javaField}: number
|
||||
#elseif(${column.javaType.toLowerCase()} == "date")
|
||||
${column.javaField}: string
|
||||
#else
|
||||
${column.javaField}: ${column.javaType.toLowerCase()}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
export type ${simpleClassName}ExcelReqVO = {
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.listOperation})##查询操作
|
||||
#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
|
||||
${column.javaField}: number
|
||||
#elseif(${column.javaType.toLowerCase()} == "date")
|
||||
${column.javaField}: string
|
||||
#else
|
||||
${column.javaField}: ${column.javaType.toLowerCase()}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
import { reactive } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { required } from '@/utils/formRules'
|
||||
import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
|
||||
const { t } = useI18n() // 国际化
|
||||
// 表单校验
|
||||
export const rules = reactive({
|
||||
#foreach ($column in $columns)
|
||||
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
|
||||
#set($comment=$column.columnComment)
|
||||
$column.javaField: [required],
|
||||
#end
|
||||
#end
|
||||
})
|
||||
// CrudSchema
|
||||
const crudSchemas = reactive<VxeCrudSchema>({
|
||||
primaryKey: 'id', // 默认的主键ID
|
||||
primaryTitle: t('common.index'), // 默认显示的值
|
||||
primaryType: 'seq', // 默认为seq,序号模式
|
||||
action: true,
|
||||
actionWidth: '200', // 3个按钮默认200,如有删减对应增减即可
|
||||
columns: [
|
||||
#foreach($column in $columns)
|
||||
#if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation)
|
||||
#set ($dictType = $column.dictType)
|
||||
#if(!$column.primaryKey)
|
||||
{
|
||||
title: '${column.columnComment}',
|
||||
field: '${column.javaField}',
|
||||
#if (!$column.listOperationResult)
|
||||
isTable: false,
|
||||
#end
|
||||
#if ("" != $dictType)## 有数据字典
|
||||
dictType: DICT_TYPE.$dictType.toUpperCase(),
|
||||
#if (${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
|
||||
dictClass: 'number',
|
||||
#else
|
||||
dictClass: 'string',
|
||||
#end
|
||||
#end
|
||||
#if (!$column.createOperation && !$column.updateOperation)
|
||||
isForm: false,
|
||||
#elseif(!("" != $column.dictType))
|
||||
#if (${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime")
|
||||
form: {
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
type: 'datetime',
|
||||
valueFormat: 'x'
|
||||
}
|
||||
},
|
||||
#elseif($column.htmlType == "editor")## 文本编辑器
|
||||
form: {
|
||||
component: 'Editor',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
componentProps: {
|
||||
valueHtml: ''
|
||||
}
|
||||
},
|
||||
#elseif($column.htmlType == "textarea")## 文本框
|
||||
form: {
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
type: 'textarea',
|
||||
rows: 4
|
||||
},
|
||||
colProps: {
|
||||
span: 24
|
||||
}
|
||||
},
|
||||
#elseif(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")## 数字类型
|
||||
form: {
|
||||
component: 'InputNumber',
|
||||
value: 0
|
||||
},
|
||||
#elseif($column.htmlType == "imageUpload")## 图片上传
|
||||
form: {
|
||||
component: 'UploadImg' // 单图上传,多图为UploadImgs
|
||||
},
|
||||
#elseif($column.htmlType == "fileUpload")## 图片上传
|
||||
form: {
|
||||
component: 'UploadFile'
|
||||
},
|
||||
#end
|
||||
#end
|
||||
#if ($column.listOperation)
|
||||
#if($column.htmlType == "input")
|
||||
isSearch: true,
|
||||
#elseif("" != $dictType)
|
||||
isSearch: true,
|
||||
#elseif($column.htmlType == "datetime")
|
||||
formatter: 'formatDate',
|
||||
search: {
|
||||
show: true,
|
||||
itemRender: {
|
||||
name: 'XDataTimePicker'
|
||||
}
|
||||
},
|
||||
#end
|
||||
#end
|
||||
},
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
]
|
||||
})
|
||||
export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
|
@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
#set ($dictMethods = [])## 使用到的 dict 字典方法
|
||||
#foreach($column in $columns)
|
||||
#if ($column.createOperation || $column.updateOperation)
|
||||
#set ($dictType = $column.dictType)
|
||||
#set ($javaField = $column.javaField)
|
||||
#set ($javaType = $column.javaType)
|
||||
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
#set ($comment = $column.columnComment)
|
||||
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
|
||||
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
|
||||
#set ($dictMethod = "getIntDictOptions")
|
||||
#elseif ($javaType == "String")
|
||||
#set ($dictMethod = "getStrDictOptions")
|
||||
#elseif ($javaType == "Boolean")
|
||||
#set ($dictMethod = "getBoolDictOptions")
|
||||
#end
|
||||
#if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "imageUpload")## 图片上传
|
||||
#set ($hasImageUploadColumn = true)
|
||||
<el-form-item label="${comment}">
|
||||
<UploadImg v-model="formData.${javaField}" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "fileUpload")## 文件上传
|
||||
#set ($hasFileUploadColumn = true)
|
||||
<el-form-item label="${comment}">
|
||||
<UploadFile v-model="formData.${javaField}" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "editor")## 文本编辑器
|
||||
<el-form-item label="${comment}">
|
||||
<Editor :model-value="formData.${javaField}" height="150px" />
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "select")## 下拉框
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
|
||||
#if ("" != $dictType)## 有数据字典
|
||||
#if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import
|
||||
#set($ignore = $dictMethods.add($dictMethod) )
|
||||
#end
|
||||
<el-option
|
||||
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
#else##没数据字典
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
#end
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "checkbox")## 多选框
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-checkbox-group v-model="formData.${javaField}">
|
||||
#if ("" != $dictType)## 有数据字典
|
||||
#if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import
|
||||
#set($ignore = $dictMethods.add($dictMethod) )
|
||||
#end
|
||||
<el-checkbox
|
||||
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-checkbox>
|
||||
#else##没数据字典
|
||||
<el-checkbox>请选择字典生成</el-checkbox>
|
||||
#end
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "radio")## 单选框
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-radio-group v-model="formData.${javaField}">
|
||||
#if ("" != $dictType)## 有数据字典
|
||||
#if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import
|
||||
#set($ignore = $dictMethods.add($dictMethod) )
|
||||
#end
|
||||
<el-radio
|
||||
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
#else##没数据字典
|
||||
<el-radio label="1">请选择字典生成</el-radio>
|
||||
#end
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")## 时间框
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-date-picker
|
||||
v-model="formData.${javaField}"
|
||||
type="date"
|
||||
value-format="timestamp"
|
||||
placeholder="选择${comment}"
|
||||
/>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "textarea")## 文本框
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
|
||||
</el-form-item>
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
#if ($dictMethods.size() > 0)
|
||||
import { DICT_TYPE#foreach ($dictMethod in $dictMethods), ${dictMethod}#end } from '@/utils/dict'
|
||||
#end
|
||||
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
#set ($listOperationLastIndex = -1)## 求最后一个需要 , 的地方
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.createOperation || $column.updateOperation)
|
||||
#set ($listOperationLastIndex = $foreach.index)
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.createOperation || $column.updateOperation)
|
||||
#if ($column.htmlType == "checkbox")
|
||||
$column.javaField: []#if($foreach.index < $listOperationLastIndex),#end
|
||||
#else
|
||||
$column.javaField: undefined#if($foreach.index < $listOperationLastIndex),#end
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
})
|
||||
const formRules = reactive({
|
||||
#set ($listOperationLastIndex = -1)## 求最后一个需要 , 的地方
|
||||
#foreach ($column in $columns)
|
||||
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
|
||||
#set ($listOperationLastIndex = $foreach.index)
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
|
||||
#set($comment=$column.columnComment)
|
||||
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }]#if($foreach.index < $listOperationLastIndex),#end
|
||||
#end
|
||||
#end
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await ${simpleClassName}Api.get${simpleClassName}(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as ${simpleClassName}Api.${simpleClassName}VO
|
||||
if (formType.value === 'create') {
|
||||
await ${simpleClassName}Api.create${simpleClassName}(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await ${simpleClassName}Api.update${simpleClassName}(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
#set ($listOperationLastIndex = -1)## 求最后一个需要 , 的地方
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.createOperation || $column.updateOperation)
|
||||
#set ($listOperationLastIndex = $foreach.index)
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.createOperation || $column.updateOperation)
|
||||
#if ($column.htmlType == "checkbox")
|
||||
$column.javaField: []#if($foreach.index < $listOperationLastIndex),#end
|
||||
#else
|
||||
$column.javaField: undefined#if($foreach.index < $listOperationLastIndex),#end
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
@ -1,177 +1,285 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 列表 -->
|
||||
<vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
|
||||
<template #toolbar_buttons>
|
||||
<!-- 操作:新增 -->
|
||||
<XButton
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
#set ($dictMethods = [])## 使用到的 dict 字典方法
|
||||
#foreach($column in $columns)
|
||||
#if ($column.listOperation)
|
||||
#set ($dictType = $column.dictType)
|
||||
#set ($javaField = $column.javaField)
|
||||
#set ($javaType = $column.javaType)
|
||||
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
#set ($comment = $column.columnComment)
|
||||
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
|
||||
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
|
||||
#set ($dictMethod = "getIntDictOptions")
|
||||
#elseif ($javaType == "String")
|
||||
#set ($dictMethod = "getStrDictOptions")
|
||||
#elseif ($javaType == "Boolean")
|
||||
#set ($dictMethod = "getBoolDictOptions")
|
||||
#end
|
||||
#if ($column.htmlType == "input")
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-input
|
||||
v-model="queryParams.${javaField}"
|
||||
placeholder="请输入${comment}"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
#elseif ($column.htmlType == "select" || $column.htmlType == "radio")
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
#if ($javaField.length() + $comment.length() > 8)
|
||||
<el-select
|
||||
v-model="queryParams.${javaField}"
|
||||
placeholder="请选择${comment}"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
#else
|
||||
<el-select v-model="queryParams.${javaField}" placeholder="请选择${comment}" clearable class="!w-240px">
|
||||
#end
|
||||
#if ("" != $dictType)## 设置了 dictType 数据字典的情况
|
||||
#if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import
|
||||
#set($ignore = $dictMethods.add($dictMethod) )
|
||||
#end
|
||||
<el-option
|
||||
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
#else## 未设置 dictType 数据字典的情况
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
#end
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
#elseif($column.htmlType == "datetime")
|
||||
#if ($column.listOperationCondition != "BETWEEN")## 非范围
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-date-picker
|
||||
v-model="queryParams.${javaField}"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="date"
|
||||
placeholder="选择${comment}"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
#else## 范围
|
||||
<el-form-item label="${comment}" prop="${javaField}">
|
||||
<el-date-picker
|
||||
v-model="queryParams.${javaField}"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
#if ($permissionPrefix.length() <= 12)
|
||||
<el-button type="primary" @click="openForm('create')" v-hasPermi="['${permissionPrefix}:create']">
|
||||
#else
|
||||
<el-button
|
||||
type="primary"
|
||||
preIcon="ep:zoom-in"
|
||||
:title="t('action.add')"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['${permissionPrefix}:create']"
|
||||
@click="handleCreate()"
|
||||
/>
|
||||
<!-- 操作:导出 -->
|
||||
<XButton
|
||||
type="warning"
|
||||
preIcon="ep:download"
|
||||
:title="t('action.export')"
|
||||
>
|
||||
#end
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['${permissionPrefix}:export']"
|
||||
@click="handleExport()"
|
||||
/>
|
||||
</template>
|
||||
<template #actionbtns_default="{ row }">
|
||||
<!-- 操作:修改 -->
|
||||
<XTextButton
|
||||
preIcon="ep:edit"
|
||||
:title="t('action.edit')"
|
||||
v-hasPermi="['${permissionPrefix}:update']"
|
||||
@click="handleUpdate(row.id)"
|
||||
/>
|
||||
<!-- 操作:详情 -->
|
||||
<XTextButton
|
||||
preIcon="ep:view"
|
||||
:title="t('action.detail')"
|
||||
v-hasPermi="['${permissionPrefix}:query']"
|
||||
@click="handleDetail(row.id)"
|
||||
/>
|
||||
<!-- 操作:删除 -->
|
||||
<XTextButton
|
||||
preIcon="ep:delete"
|
||||
:title="t('action.del')"
|
||||
v-hasPermi="['${permissionPrefix}:delete']"
|
||||
@click="handleDelete(row.id)"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
<!-- 弹窗 -->
|
||||
<XModal id="${classNameVar}Model" :loading="modelLoading" v-model="modelVisible" :title="modelTitle">
|
||||
<!-- 表单:添加/修改 -->
|
||||
<Form
|
||||
ref="formRef"
|
||||
v-if="['create', 'update'].includes(actionType)"
|
||||
:schema="allSchemas.formSchema"
|
||||
:rules="rules"
|
||||
/>
|
||||
<!-- 表单:详情 -->
|
||||
<Descriptions
|
||||
v-if="actionType === 'detail'"
|
||||
:schema="allSchemas.detailSchema"
|
||||
:data="detailData"
|
||||
/>
|
||||
<template #footer>
|
||||
<!-- 按钮:保存 -->
|
||||
<XButton
|
||||
v-if="['create', 'update'].includes(actionType)"
|
||||
type="primary"
|
||||
:title="t('action.save')"
|
||||
:loading="actionLoading"
|
||||
@click="submitForm()"
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
#foreach($column in $columns)
|
||||
#if ($column.listOperationResult)
|
||||
#set ($dictType=$column.dictType)
|
||||
#set ($javaField = $column.javaField)
|
||||
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
|
||||
#set ($comment=$column.columnComment)
|
||||
#if ($column.javaType == "LocalDateTime")## 时间类型
|
||||
<el-table-column
|
||||
label="${comment}"
|
||||
align="center"
|
||||
prop="${javaField}"
|
||||
:formatter="dateFormatter"
|
||||
/>
|
||||
<!-- 按钮:关闭 -->
|
||||
<XButton :loading="actionLoading" :title="t('dialog.close')" @click="modelVisible = false" />
|
||||
</template>
|
||||
</XModal>
|
||||
#elseif("" != $column.dictType)## 数据字典
|
||||
<el-table-column label="${comment}" align="center" prop="${javaField}">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
#else
|
||||
<el-table-column label="${comment}" align="center" prop="${javaField}" />
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['${permissionPrefix}:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['${permissionPrefix}:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<${simpleClassName}Form ref="formRef" @success="getList" />
|
||||
</template>
|
||||
<script setup lang="ts" name="${simpleClassName}">
|
||||
// 全局相关的 import
|
||||
import { ref, unref } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { useVxeGrid } from '@/hooks/web/useVxeGrid'
|
||||
import { VxeGridInstance } from 'vxe-table'
|
||||
import { FormExpose } from '@/components/Form'
|
||||
// 业务相关的 import
|
||||
import { rules, allSchemas } from './${classNameVar}.data'
|
||||
|
||||
<script setup lang="ts" name="${table.className}">
|
||||
#if ($dictMethods.size() > 0)
|
||||
import { DICT_TYPE#foreach ($dictMethod in $dictMethods), ${dictMethod}#end } from '@/utils/dict'
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.listOperationResult && $column.htmlType == "datetime")
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
import download from '@/utils/download'
|
||||
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
import ${simpleClassName}Form from './${simpleClassName}Form.vue'
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
// 列表相关的变量
|
||||
const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
|
||||
const { gridOptions, getList, deleteData, exportList } = useVxeGrid<${simpleClassName}Api.${simpleClassName}VO>({
|
||||
allSchemas: allSchemas,
|
||||
getListApi: ${simpleClassName}Api.get${simpleClassName}PageApi,
|
||||
deleteApi: ${simpleClassName}Api.delete${simpleClassName}Api,
|
||||
exportListApi: ${simpleClassName}Api.export${simpleClassName}Api
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
#set ($listOperationLastIndex = -1)## 求最后一个需要 , 的地方
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.listOperation)
|
||||
#set ($listOperationLastIndex = $foreach.index)
|
||||
#end
|
||||
#end
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.listOperation)
|
||||
#if ($column.listOperationCondition != 'BETWEEN')
|
||||
$column.javaField: null#if($foreach.index < $listOperationLastIndex),#end
|
||||
#end
|
||||
#if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
|
||||
$column.javaField: []#if($foreach.index < $listOperationLastIndex),#end
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
// 弹窗相关的变量
|
||||
const modelVisible = ref(false) // 是否显示弹出层
|
||||
const modelTitle = ref('edit') // 弹出层标题
|
||||
const modelLoading = ref(false) // 弹出层loading
|
||||
const actionType = ref('') // 操作按钮的类型
|
||||
const actionLoading = ref(false) // 按钮 Loading
|
||||
const formRef = ref<FormExpose>() // 表单 Ref
|
||||
const detailData = ref() // 详情 Ref
|
||||
|
||||
// 设置标题
|
||||
const setDialogTile = (type: string) => {
|
||||
modelLoading.value = true
|
||||
modelTitle.value = t('action.' + type)
|
||||
actionType.value = type
|
||||
modelVisible.value = true
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await ${simpleClassName}Api.get${simpleClassName}Page(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 新增操作
|
||||
const handleCreate = () => {
|
||||
setDialogTile('create')
|
||||
modelLoading.value = false
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
// 导出操作
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await ${simpleClassName}Api.delete${simpleClassName}(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
await exportList(xGrid, '${table.classComment}.xls')
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await ${simpleClassName}Api.export${simpleClassName}(queryParams)
|
||||
download.excel(data, '${table.classComment}.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 修改操作
|
||||
const handleUpdate = async (rowId: number) => {
|
||||
setDialogTile('update')
|
||||
// 设置数据
|
||||
const res = await ${simpleClassName}Api.get${simpleClassName}Api(rowId)
|
||||
unref(formRef)?.setValues(res)
|
||||
modelLoading.value = false
|
||||
}
|
||||
|
||||
// 详情操作
|
||||
const handleDetail = async (rowId: number) => {
|
||||
setDialogTile('detail')
|
||||
const res = await ${simpleClassName}Api.get${simpleClassName}Api(rowId)
|
||||
detailData.value = res
|
||||
modelLoading.value = false
|
||||
}
|
||||
|
||||
// 删除操作
|
||||
const handleDelete = async (rowId: number) => {
|
||||
await deleteData(xGrid, rowId)
|
||||
}
|
||||
|
||||
// 提交按钮
|
||||
const submitForm = async () => {
|
||||
const elForm = unref(formRef)?.getElFormRef()
|
||||
if (!elForm) return
|
||||
elForm.validate(async (valid) => {
|
||||
if (valid) {
|
||||
actionLoading.value = true
|
||||
// 提交请求
|
||||
try {
|
||||
const data = unref(formRef)?.formModel as ${simpleClassName}Api.${simpleClassName}VO
|
||||
if (actionType.value === 'create') {
|
||||
await ${simpleClassName}Api.create${simpleClassName}Api(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await ${simpleClassName}Api.update${simpleClassName}Api(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
modelVisible.value = false
|
||||
} finally {
|
||||
actionLoading.value = false
|
||||
// 刷新列表
|
||||
await getList(xGrid)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
@ -0,0 +1,45 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface ${simpleClassName}VO {
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.createOperation || $column.updateOperation)
|
||||
#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
|
||||
${column.javaField}: number
|
||||
#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime")
|
||||
${column.javaField}: Date
|
||||
#else
|
||||
${column.javaField}: ${column.javaType.toLowerCase()}
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
// 查询${table.classComment}列表
|
||||
export const get${simpleClassName}Page = async (params: ${simpleClassName}PageReqVO) => {
|
||||
return await request.get({ url: '${baseURL}/page', params })
|
||||
}
|
||||
|
||||
// 查询${table.classComment}详情
|
||||
export const get${simpleClassName} = async (id: number) => {
|
||||
return await request.get({ url: '${baseURL}/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增${table.classComment}
|
||||
export const create${simpleClassName} = async (data: ${simpleClassName}VO) => {
|
||||
return await request.post({ url: '${baseURL}/create', data })
|
||||
}
|
||||
|
||||
// 修改${table.classComment}
|
||||
export const update${simpleClassName} = async (data: ${simpleClassName}VO) => {
|
||||
return await request.put({ url: '${baseURL}/update', data })
|
||||
}
|
||||
|
||||
// 删除${table.classComment}
|
||||
export const delete${simpleClassName} = async (id: number) => {
|
||||
return await request.delete({ url: '${baseURL}/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 导出${table.classComment} Excel
|
||||
export const export${simpleClassName}Api = async (params) => {
|
||||
return await request.download({ url: '${baseURL}/export-excel', params })
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
import type { CrudSchema } from '@/hooks/web/useCrudSchemas'
|
||||
#foreach ($column in $columns)
|
||||
#if ($column.listOperationResult && $column.htmlType == "datetime")
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
|
||||
// 表单校验
|
||||
export const rules = reactive({
|
||||
#foreach ($column in $columns)
|
||||
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
|
||||
#set($comment=$column.columnComment)
|
||||
$column.javaField: [required],
|
||||
#end
|
||||
#end
|
||||
})
|
||||
|
||||
// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/
|
||||
const crudSchemas = reactive<CrudSchema[]>([
|
||||
#foreach($column in $columns)
|
||||
#if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation)
|
||||
#set ($dictType = $column.dictType)
|
||||
#set ($javaField = $column.javaField)
|
||||
#set ($javaType = $column.javaType)
|
||||
{
|
||||
label: '${column.columnComment}',
|
||||
field: '${column.javaField}',
|
||||
## ========= 字典部分 =========
|
||||
#if ("" != $dictType)## 有数据字典
|
||||
dictType: DICT_TYPE.$dictType.toUpperCase(),
|
||||
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
|
||||
dictClass: 'number',
|
||||
#elseif ($javaType == "String")
|
||||
dictClass: 'string',
|
||||
#elseif ($javaType == "Boolean")
|
||||
dictClass: 'boolean',
|
||||
#end
|
||||
#end
|
||||
## ========= Table 表格部分 =========
|
||||
#if (!$column.listOperationResult)
|
||||
isTable: false,
|
||||
#else
|
||||
#if ($column.htmlType == "datetime")
|
||||
formatter: dateFormatter,
|
||||
#end
|
||||
#end
|
||||
## ========= Search 表格部分 =========
|
||||
#if ($column.listOperation)
|
||||
isSearch: true,
|
||||
#if ($column.htmlType == "datetime")
|
||||
search: {
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
type: 'daterange',
|
||||
defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')]
|
||||
}
|
||||
},
|
||||
#end
|
||||
#end
|
||||
## ========= Form 表单部分 =========
|
||||
#if ((!$column.createOperation && !$column.updateOperation) || $column.primaryKey)
|
||||
isForm: false,
|
||||
#else
|
||||
#if($column.htmlType == "imageUpload")## 图片上传
|
||||
form: {
|
||||
component: 'UploadImg'
|
||||
},
|
||||
#elseif($column.htmlType == "fileUpload")## 文件上传
|
||||
form: {
|
||||
component: 'UploadFile'
|
||||
},
|
||||
#elseif($column.htmlType == "editor")## 文本编辑器
|
||||
form: {
|
||||
component: 'Editor',
|
||||
componentProps: {
|
||||
valueHtml: '',
|
||||
height: 200
|
||||
}
|
||||
},
|
||||
#elseif($column.htmlType == "select")## 下拉框
|
||||
form: {
|
||||
component: 'SelectV2'
|
||||
},
|
||||
#elseif($column.htmlType == "checkbox")## 多选框
|
||||
form: {
|
||||
component: 'Checkbox'
|
||||
},
|
||||
#elseif($column.htmlType == "radio")## 单选框
|
||||
form: {
|
||||
component: 'Radio'
|
||||
},
|
||||
#elseif($column.htmlType == "datetime")## 时间框
|
||||
form: {
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
type: 'datetime',
|
||||
valueFormat: 'x'
|
||||
}
|
||||
},
|
||||
#elseif($column.htmlType == "textarea")## 文本框
|
||||
form: {
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
type: 'textarea',
|
||||
rows: 4
|
||||
},
|
||||
colProps: {
|
||||
span: 24
|
||||
}
|
||||
},
|
||||
#elseif(${javaType.toLowerCase()} == "long" || ${javaType.toLowerCase()} == "integer")## 文本框
|
||||
form: {
|
||||
component: 'InputNumber',
|
||||
value: 0
|
||||
},
|
||||
#end
|
||||
#end
|
||||
},
|
||||
#end
|
||||
#end
|
||||
{
|
||||
label: '操作',
|
||||
field: 'action',
|
||||
isForm: false
|
||||
}
|
||||
])
|
||||
export const { allSchemas } = useCrudSchemas(crudSchemas)
|
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<Form ref="formRef" :schema="allSchemas.formSchema" :rules="rules" v-loading="formLoading" />
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
|
||||
import { rules, allSchemas } from './${classNameVar}.data'
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = await ${simpleClassName}Api.get${simpleClassName}(id)
|
||||
formRef.value.setValues(data)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.getElFormRef().validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formRef.value.formModel as ${simpleClassName}Api.${simpleClassName}VO
|
||||
if (formType.value === 'create') {
|
||||
await ${simpleClassName}Api.create${simpleClassName}(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await ${simpleClassName}Api.update${simpleClassName}(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<!-- 搜索工作栏 -->
|
||||
<ContentWrap>
|
||||
<Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams">
|
||||
<!-- 新增等操作按钮 -->
|
||||
<template #actionMore>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['${permissionPrefix}:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
</template>
|
||||
</Search>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<Table
|
||||
:columns="allSchemas.tableColumns"
|
||||
:data="tableObject.tableList"
|
||||
:loading="tableObject.loading"
|
||||
:pagination="{
|
||||
total: tableObject.total
|
||||
}"
|
||||
v-model:pageSize="tableObject.pageSize"
|
||||
v-model:currentPage="tableObject.currentPage"
|
||||
>
|
||||
<template #action="{ row }">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', row.id)"
|
||||
v-hasPermi="['${permissionPrefix}:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
v-hasPermi="['${permissionPrefix}:delete']"
|
||||
@click="handleDelete(row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</Table>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<${simpleClassName}Form ref="formRef" @success="getList" />
|
||||
</template>
|
||||
<script setup lang="ts" name="${table.className}">
|
||||
import { allSchemas } from './${classNameVar}.data'
|
||||
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
|
||||
import ${simpleClassName}Form from './${simpleClassName}Form.vue'
|
||||
|
||||
// tableObject:表格的属性对象,可获得分页大小、条数等属性
|
||||
// tableMethods:表格的操作对象,可进行获得分页、删除记录等操作
|
||||
// 详细可见:https://doc.iocoder.cn/vue3/crud-schema/
|
||||
const { tableObject, tableMethods } = useTable({
|
||||
getListApi: ${simpleClassName}Api.get${simpleClassName}Page, // 分页接口
|
||||
delListApi: ${simpleClassName}Api.delete${simpleClassName} // 删除接口
|
||||
})
|
||||
// 获得表格的各种操作
|
||||
const { getList, setSearchParams } = tableMethods
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = (id: number) => {
|
||||
tableMethods.delList(id, false)
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user