update 重构 将代码生成vm模板替换为fm模板 语法更清晰明了

This commit is contained in:
疯狂的狮子Li
2026-06-18 14:59:06 +08:00
parent 06d4e6d7f1
commit f04197b401
34 changed files with 1671 additions and 1689 deletions
@@ -0,0 +1,63 @@
package ${packageName}.domain.bo;
import ${packageName}.domain.${ClassName};
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import java.io.Serial;
import java.io.Serializable;
<#if hasBetween>
import java.util.HashMap;
import java.util.Map;
</#if>
import lombok.Data;
import jakarta.validation.constraints.*;
<#list importList as import>
import ${import};
</#list>
/**
* ${functionName}业务对象 ${tableName}
*
* @author ${author}
* @date ${datetime}
*/
@Data
@AutoMapper(target = ${ClassName}.class, reverseConvertGenerate = false)
public class ${ClassName}Bo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
<#list columns as column>
<#if !table.isSuperColumn(column.javaField) && (column.query || column.insert || column.edit)>
/**
* ${column.columnComment}
*/
<#if column.insert && column.edit>
<#assign Group = "AddGroup.class, EditGroup.class">
<#elseif column.insert>
<#assign Group = "AddGroup.class">
<#elseif column.edit>
<#assign Group = "EditGroup.class">
</#if>
<#if column.required>
<#if column.javaType == 'String'>
@NotBlank(message = "${column.columnComment}不能为空", groups = { ${Group} })
<#else>
@NotNull(message = "${column.columnComment}不能为空", groups = { ${Group} })
</#if>
</#if>
private ${column.javaType} ${column.javaField};
</#if>
</#list>
<#if hasBetween>
/**
* 查询参数
*/
private Map<String, Object> params = new HashMap<>();
</#if>
}
@@ -0,0 +1,157 @@
package ${packageName}.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
<#if enableExport>
import jakarta.servlet.http.HttpServletResponse;
</#if>
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.redis.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
<#if enableExport>
import org.dromara.common.excel.utils.ExcelBuilder;
</#if>
import ${packageName}.domain.vo.${ClassName}Vo;
import ${packageName}.domain.bo.${ClassName}Bo;
import ${packageName}.service.I${ClassName}Service;
<#if table.crud>
import org.dromara.common.core.domain.PageResult;
<#elseif table.tree>
</#if>
/**
* ${functionName}
*
* @author ${author}
* @date ${datetime}
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/${moduleName}/${businessName}")
public class ${ClassName}Controller extends BaseController {
private final I${ClassName}Service ${className}Service;
/**
* 查询${functionName}列表
*/
@SaCheckPermission("${permissionPrefix}:list")
@GetMapping("/list")
<#if table.crud>
public R<PageResult<${ClassName}Vo>> list(${ClassName}Bo bo, PageQuery pageQuery) {
return R.ok(${className}Service.queryPageList(bo, pageQuery));
}
<#elseif table.tree>
public R<List<${ClassName}Vo>> list(${ClassName}Bo bo) {
List<${ClassName}Vo> list = ${className}Service.queryList(bo);
return R.ok(list);
}
</#if>
/**
* 导出${functionName}列表
*/
<#if enableExport>
@SaCheckPermission("${permissionPrefix}:export")
@Log(title = "${functionName}", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(${ClassName}Bo bo, HttpServletResponse response) {
List<${ClassName}Vo> list = ${className}Service.queryList(bo);
ExcelBuilder.of(list, ${ClassName}Vo.class).sheetName("${functionName}").toResponse(response);
}
</#if>
/**
* 获取${functionName}详细信息
*
* @param ${pkColumn.javaField} 主键
*/
@SaCheckPermission("${permissionPrefix}:query")
@GetMapping("/{${pkColumn.javaField}}")
public R<${ClassName}Vo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable ${pkColumn.javaType} ${pkColumn.javaField}) {
return R.ok(${className}Service.queryById(${pkColumn.javaField}));
}
/**
* 新增${functionName}
*/
@SaCheckPermission("${permissionPrefix}:add")
@Log(title = "${functionName}", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ${ClassName}Bo bo) {
<#if enableUnique>
if (!${className}Service.checkUnique(bo)) {
return R.fail("新增${functionName}失败,组合唯一字段已存在");
}
</#if>
return toAjax(${className}Service.insertByBo(bo));
}
/**
* 修改${functionName}
*/
@SaCheckPermission("${permissionPrefix}:edit")
@Log(title = "${functionName}", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ${ClassName}Bo bo) {
<#if enableUnique>
if (!${className}Service.checkUnique(bo)) {
return R.fail("修改${functionName}失败,组合唯一字段已存在");
}
</#if>
return toAjax(${className}Service.updateByBo(bo));
}
<#if enableStatus>
/**
* 修改${functionName}状态
*/
@SaCheckPermission("${permissionPrefix}:edit")
@Log(title = "${functionName}", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus")
public R<Void> changeStatus(@RequestBody ${ClassName}Bo bo) {
return toAjax(${className}Service.updateStatus(bo.get${pkColumn.capJavaField}(), bo.get${statusColumn.capJavaField}()));
}
</#if>
<#if enableSort>
/**
* 调整${functionName}排序
*/
@SaCheckPermission("${permissionPrefix}:edit")
@Log(title = "${functionName}", businessType = BusinessType.UPDATE)
@PutMapping("/updateSort")
public R<Void> updateSort(@RequestBody ${ClassName}Bo bo) {
return toAjax(${className}Service.updateSort(bo.get${pkColumn.capJavaField}(), bo.get${sortColumn.capJavaField}()));
}
</#if>
/**
* 删除${functionName}
*
* @param ${pkColumn.javaField}s 主键串
*/
@SaCheckPermission("${permissionPrefix}:remove")
@Log(title = "${functionName}", businessType = BusinessType.DELETE)
@DeleteMapping("/{${pkColumn.javaField}s}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) {
return toAjax(${className}Service.deleteWithValidByIds(List.of(${pkColumn.javaField}s), true));
}
}
@@ -0,0 +1,50 @@
package ${packageName}.domain;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
<#list importList as import>
import ${import};
</#list>
import java.io.Serial;
/**
* ${functionName}对象 ${tableName}
*
* @author ${author}
* @date ${datetime}
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("${tableName}")
public class ${ClassName} extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
<#list columns as column>
<#if !table.isSuperColumn(column.javaField)>
/**
* ${column.columnComment}
*/
<#if column.javaField=='delFlag'>
@TableLogic
</#if>
<#if column.javaField=='version'>
@Version
</#if>
<#if column.pk>
@TableId(value = "${column.columnName}")
<#elseif column.needTableField>
@TableField(value = "${column.columnName}")
</#if>
private ${column.javaType} ${column.javaField};
</#if>
</#list>
}
@@ -0,0 +1,18 @@
package ${packageName}.mapper;
import ${packageName}.domain.${ClassName};
import ${packageName}.domain.vo.${ClassName}Vo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* ${functionName}Mapper接口
*
* @author ${author}
* @date ${datetime}
*/
public interface ${ClassName}Mapper extends BaseMapperPlus<${ClassName}, ${ClassName}Vo> {
}
@@ -0,0 +1,107 @@
package ${packageName}.service;
import ${packageName}.domain.vo.${ClassName}Vo;
import ${packageName}.domain.bo.${ClassName}Bo;
<#if table.crud>
import org.dromara.common.core.domain.PageResult;
import org.dromara.common.mybatis.core.page.PageQuery;
</#if>
import java.util.Collection;
import java.util.List;
/**
* ${functionName}Service接口
*
* @author ${author}
* @date ${datetime}
*/
public interface I${ClassName}Service {
/**
* 查询${functionName}
*
* @param ${pkColumn.javaField} 主键
* @return ${functionName}
*/
${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField});
<#if table.crud>
/**
* 分页查询${functionName}列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return ${functionName}分页列表
*/
PageResult<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery);
</#if>
/**
* 查询符合条件的${functionName}列表
*
* @param bo 查询条件
* @return ${functionName}列表
*/
List<${ClassName}Vo> queryList(${ClassName}Bo bo);
<#if enableUnique>
/**
* 校验${functionName}是否满足组合唯一约束
*
* @param bo ${functionName}
* @return 是否唯一
*/
boolean checkUnique(${ClassName}Bo bo);
</#if>
/**
* 新增${functionName}
*
* @param bo ${functionName}
* @return 是否新增成功
*/
Boolean insertByBo(${ClassName}Bo bo);
/**
* 修改${functionName}
*
* @param bo ${functionName}
* @return 是否修改成功
*/
Boolean updateByBo(${ClassName}Bo bo);
<#if enableStatus>
/**
* 修改${functionName}状态
*
* @param ${pkColumn.javaField} 主键
* @param status 状态值
* @return 是否修改成功
*/
Boolean updateStatus(${pkColumn.javaType} ${pkColumn.javaField}, ${statusColumn.javaType} status);
</#if>
<#if enableSort>
/**
* 调整${functionName}排序
*
* @param ${pkColumn.javaField} 主键
* @param sortValue 排序值
* @return 是否修改成功
*/
Boolean updateSort(${pkColumn.javaType} ${pkColumn.javaField}, ${sortColumn.javaType} sortValue);
</#if>
/**
* 校验并批量删除${functionName}信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid);
}
@@ -0,0 +1,347 @@
package ${packageName}.service.impl;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
<#if table.crud>
import org.dromara.common.core.domain.PageResult;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
</#if>
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
<#if enableUnique>
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
</#if>
import org.dromara.common.mybatis.core.query.QueryBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ${packageName}.domain.bo.${ClassName}Bo;
import ${packageName}.domain.vo.${ClassName}Vo;
import ${packageName}.domain.${ClassName};
import ${packageName}.mapper.${ClassName}Mapper;
import ${packageName}.service.I${ClassName}Service;
<#if table.tree>
import org.dromara.common.core.exception.ServiceException;
</#if>
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* ${functionName}Service业务层处理
*
* @author ${author}
* @date ${datetime}
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class ${ClassName}ServiceImpl implements I${ClassName}Service {
private final ${ClassName}Mapper ${className}Mapper;
/**
* 查询${functionName}
*
* @param ${pkColumn.javaField} 主键
* @return ${functionName}
*/
@Override
public ${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField}) {
return ${className}Mapper.selectVoById(${pkColumn.javaField});
}
<#if table.crud>
/**
* 分页查询${functionName}列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return ${functionName}分页列表
*/
@Override
public PageResult<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery) {
LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
Page<${ClassName}Vo> result = ${className}Mapper.selectVoPage(pageQuery.build(), lqw);
return PageResult.build(result.getRecords(), result.getTotal());
}
</#if>
/**
* 查询符合条件的${functionName}列表
*
* @param bo 查询条件
* @return ${functionName}列表
*/
@Override
public List<${ClassName}Vo> queryList(${ClassName}Bo bo) {
LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
return ${className}Mapper.selectVoList(lqw);
}
<#if enableUnique>
/**
* 校验${functionName}是否满足组合唯一约束
*
* @param bo ${functionName}
* @return 是否唯一
*/
@Override
public boolean checkUnique(${ClassName}Bo bo) {
boolean hasUniqueValue = true;
<#list uniqueColumns as column>
<#if column.javaType == 'String'>
hasUniqueValue = hasUniqueValue && StringUtils.isNotBlank(bo.get${column.capJavaField}());
<#else>
hasUniqueValue = hasUniqueValue && bo.get${column.capJavaField}() != null;
</#if>
</#list>
if (!hasUniqueValue) {
return true;
}
LambdaQueryWrapper<${ClassName}> lqw = Wrappers.lambdaQuery();
<#list uniqueColumns as column>
lqw.eq(${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}());
</#list>
lqw.ne(bo.get${pkColumn.capJavaField}() != null, ${ClassName}::get${pkColumn.capJavaField}, bo.get${pkColumn.capJavaField}());
return !${className}Mapper.exists(lqw);
}
</#if>
private LambdaQueryWrapper<${ClassName}> buildQueryWrapper(${ClassName}Bo bo) {
<#if hasBetween>
Map<String, Object> params = bo.getParams();
</#if>
return QueryBuilder.lambda(${ClassName}.class)
<#list columns as column>
<#if column.query>
<#assign queryType = column.queryType>
<#assign javaType = column.javaType>
<#assign AttrName = column.capJavaField>
<#assign mpMethod = column.queryType?lower_case>
<#if queryType != 'BETWEEN'>
<#if javaType == 'String'>
<#assign condition = 'StringUtils.isNotBlank(bo.get'+AttrName+'())'>
<#if queryType == 'LIKE'>
.likeIfText(${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
<#elseif queryType == 'EQ'>
.eqIfText(${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
<#elseif queryType == 'NE'>
.neIfText(${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
<#else>
.${mpMethod}(${condition}, ${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
</#if>
<#else>
<#assign condition = 'bo.get'+AttrName+'() != null'>
<#if queryType == 'EQ'>
.eqIfPresent(${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
<#elseif queryType == 'NE'>
.neIfPresent(${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
<#elseif queryType == 'GT'>
.gtIfPresent(${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
<#elseif queryType == 'LT'>
.ltIfPresent(${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
<#else>
.${mpMethod}(${condition}, ${ClassName}::get${column.capJavaField}, bo.get${column.capJavaField}())
</#if>
</#if>
<#else>
.betweenParams(${ClassName}::get${column.capJavaField}, params, "begin${column.capJavaField}", "end${column.capJavaField}")
</#if>
</#if>
</#list>
<#if table.tree && "" != treeAncestorsField>
.orderByAsc(${ClassName}::get${treeAncestorsCap})
</#if>
<#if table.tree && "" != treeParentCode>
.orderByAsc(${ClassName}::get${treeParentCap})
</#if>
<#if table.tree && "" != treeOrderField>
.orderByAsc(${ClassName}::get${treeOrderCap})
<#elseif enableSort>
.orderByAsc(${ClassName}::get${sortColumn.capJavaField})
</#if>
.orderByAsc(${ClassName}::get${pkColumn.capJavaField})
.build();
}
/**
* 新增${functionName}
*
* @param bo ${functionName}
* @return 是否新增成功
*/
@Override
public Boolean insertByBo(${ClassName}Bo bo) {
${ClassName} add = MapstructUtils.convert(bo, ${ClassName}.class);
<#if table.tree>
fillTreeMetaBeforeSave(add, false);
</#if>
validEntityBeforeSave(add);
boolean flag = ${className}Mapper.insert(add) > 0;
if (flag) {
bo.set${pkColumn.capJavaField}(add.get${pkColumn.capJavaField}());
}
return flag;
}
/**
* 修改${functionName}
*
* @param bo ${functionName}
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(${ClassName}Bo bo) {
${ClassName} update = MapstructUtils.convert(bo, ${ClassName}.class);
<#if table.tree>
fillTreeMetaBeforeSave(update, true);
</#if>
validEntityBeforeSave(update);
return ${className}Mapper.updateById(update) > 0;
}
<#if enableStatus>
/**
* 修改${functionName}状态
*
* @param ${pkColumn.javaField} 主键
* @param status 状态值
* @return 是否修改成功
*/
@Override
public Boolean updateStatus(${pkColumn.javaType} ${pkColumn.javaField}, ${statusColumn.javaType} status) {
return ${className}Mapper.lambda()
.set(${ClassName}::get${statusColumn.capJavaField}, status)
.eq(${ClassName}::get${pkColumn.capJavaField}, ${pkColumn.javaField})
.update();
}
</#if>
<#if enableSort>
/**
* 调整${functionName}排序
*
* @param ${pkColumn.javaField} 主键
* @param sortValue 排序值
* @return 是否修改成功
*/
@Override
public Boolean updateSort(${pkColumn.javaType} ${pkColumn.javaField}, ${sortColumn.javaType} sortValue) {
return ${className}Mapper.lambda()
.set(${ClassName}::get${sortColumn.capJavaField}, sortValue)
.eq(${ClassName}::get${pkColumn.capJavaField}, ${pkColumn.javaField})
.update();
}
</#if>
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(${ClassName} entity) {
// 可在此扩展通用业务校验
}
<#if table.tree>
private void fillTreeMetaBeforeSave(${ClassName} entity, boolean updateMode) {
<#if "" != treeParentCode>
if (entity.get${treeParentCap}() == null) {
entity.set${treeParentCap}(${treeRootValueJavaLiteral});
}
if (ObjectUtil.equal(entity.get${pkColumn.capJavaField}(), entity.get${treeParentCap}())) {
throw new ServiceException("${functionName}父节点不能选择自身");
}
<#if "" != treeAncestorsField>
${ClassName} parent = null;
if (!ObjectUtil.equal(entity.get${treeParentCap}(), ${treeRootValueJavaLiteral})) {
parent = ${className}Mapper.selectById(entity.get${treeParentCap}());
if (ObjectUtil.isNull(parent)) {
throw new ServiceException("${functionName}父节点不存在");
}
}
if (updateMode && entity.get${pkColumn.capJavaField}() != null && ObjectUtil.isNotNull(parent)
&& containsAncestor(parent.get${treeAncestorsCap}(), entity.get${pkColumn.capJavaField}())) {
throw new ServiceException("不能选择当前节点或其子节点作为父节点");
}
String newAncestors = resolveAncestors(entity.get${treeParentCap}(), parent);
if (updateMode && entity.get${pkColumn.capJavaField}() != null) {
${ClassName} oldEntity = ${className}Mapper.selectById(entity.get${pkColumn.capJavaField}());
if (ObjectUtil.isNull(oldEntity)) {
throw new ServiceException("${functionName}不存在,无法修改");
}
String oldAncestors = oldEntity.get${treeAncestorsCap}();
entity.set${treeAncestorsCap}(newAncestors);
if (!StringUtils.equals(oldAncestors, newAncestors)) {
updateChildrenAncestors(entity.get${pkColumn.capJavaField}(), newAncestors, oldAncestors);
}
} else {
entity.set${treeAncestorsCap}(newAncestors);
}
</#if>
</#if>
}
<#if "" != treeAncestorsField>
private String resolveAncestors(${treeParentColumn.javaType} parentId, ${ClassName} parent) {
if (ObjectUtil.equal(parentId, ${treeRootValueJavaLiteral})) {
return "${treeRootValue}";
}
String parentAncestors = parent.get${treeAncestorsCap}();
if (StringUtils.isBlank(parentAncestors)) {
return String.valueOf(parentId);
}
return parentAncestors + StringUtils.SEPARATOR + parentId;
}
private void updateChildrenAncestors(${pkColumn.javaType} currentId, String newAncestors, String oldAncestors) {
List<${ClassName}> children = ${className}Mapper.lambda()
.select(${ClassName}::get${pkColumn.capJavaField}, ${ClassName}::get${treeAncestorsCap})
.findInSet(currentId, ${ClassName}::get${treeAncestorsCap})
.list();
List<${ClassName}> updateList = new ArrayList<>();
for (${ClassName} child : children) {
String ancestors = child.get${treeAncestorsCap}();
if (StringUtils.isBlank(ancestors)) {
continue;
}
${ClassName} update = new ${ClassName}();
update.set${pkColumn.capJavaField}(child.get${pkColumn.capJavaField}());
update.set${treeAncestorsCap}(StringUtils.replaceOnce(ancestors, oldAncestors, newAncestors));
updateList.add(update);
}
if (!updateList.isEmpty()) {
${className}Mapper.updateBatchById(updateList);
}
}
private boolean containsAncestor(String ancestors, ${pkColumn.javaType} nodeId) {
for (String item : StringUtils.splitList(ancestors)) {
if (StringUtils.equals(item, String.valueOf(nodeId))) {
return true;
}
}
return false;
}
</#if>
</#if>
/**
* 校验并批量删除${functionName}信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
public Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid) {
if (isValid) {
// 可在此扩展删除前业务校验
}
return ${className}Mapper.deleteByIds(ids) > 0;
}
}
@@ -0,0 +1,65 @@
package ${packageName}.domain.vo;
<#list importList as import>
import ${import};
</#list>
import ${packageName}.domain.${ClassName};
import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
import org.apache.fesod.sheet.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* ${functionName}视图对象 ${tableName}
*
* @author ${author}
* @date ${datetime}
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ${ClassName}.class)
public class ${ClassName}Vo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
<#list columns as column>
<#if column.list>
/**
* ${column.columnComment}
*/
<#assign parentheseIndex = column.columnComment?index_of("")>
<#if column.dictType?has_content>
@ExcelProperty(value = "${column.columnLabel}", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "${column.dictType}")
<#elseif parentheseIndex != -1>
@ExcelProperty(value = "${column.columnLabel}", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "${column.readConverterExp}()")
<#else>
@ExcelProperty(value = "${column.columnLabel}")
</#if>
private ${column.javaType} ${column.javaField};
<#if column.htmlType == "imageUpload">
/**
* ${column.columnComment}Url
*/
@Translation(type = TransConstant.OSS_ID_TO_URL, mapper = "${column.javaField}")
private String ${column.javaField}Url;
</#if>
</#if>
</#list>
}
@@ -0,0 +1,98 @@
import type { <#if !table.tree>PageResult, </#if> 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></#if>>>({
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</#if>
) {
return request<R>({
url: '/${moduleName}/${businessName}/changeStatus',
method: 'put',
data: {
${pkColumn.javaField},
${statusField}
}
});
}
</#if>
<#if enableSort>
/**
* 调整${functionName}排序
*/
export function update${BusinessName}Sort(
${pkColumn.javaField}: string | number,
${sortField}: <#if sortColumn.javaType == 'LocalDateTime' || sortColumn.javaType == 'String'>string<#else> number</#if>
) {
return request<R>({
url: '/${moduleName}/${businessName}/updateSort',
method: 'put',
data: {
${pkColumn.javaField},
${sortField}
}
});
}
</#if>
/**
* 删除${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,427 @@
import { DeleteOutlined<#if enableExport>, DownloadOutlined</#if>, EditOutlined, PlusOutlined, SortAscendingOutlined } from '@ant-design/icons';
import {
ModalForm,
PageContainer,
<#if needCheckbox>
ProFormCheckbox,
</#if>
<#if needDateField>
ProFormDateTimePicker,
</#if>
<#if needDigit>
ProFormDigit,
</#if>
<#if needSelect>
ProFormSelect,
</#if>
<#if needTextArea>
ProFormTextArea,
</#if>
ProFormText,
ProFormTreeSelect,
ProTable,
type ActionType,
type ProColumns
} from '@ant-design/pro-components';
import { useBoolean } from 'ahooks';
import { Button, Form, message<#if enableStatus || needSwitchField>, Switch</#if><#if enableSort>, InputNumber</#if> } 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,
</#if>
del${BusinessName},
get${BusinessName},
list${BusinessName},
<#if enableSort>
update${BusinessName}Sort,
</#if>
update${BusinessName}
} from '@/api/${moduleName}/${businessName}';
<#if needDict>
import DictTag from '@/components/common/DictTag';
</#if>
<#if needFileUpload>
import FileUpload from '@/components/common/FileUpload';
</#if>
<#if needImagePreview>
import ImagePreview from '@/components/common/ImagePreview';
</#if>
<#if needImageUpload>
import ImageUpload from '@/components/common/ImageUpload';
</#if>
<#if needEditor>
import RichTextEditor from '@/components/common/RichTextEditor';
</#if>
import RowActions from '@/components/common/RowActions';
<#if needDict>
import { useDict } from '@/hooks/useDict';
</#if>
<#if enableExport>
import { useTableExport } from '@/hooks/useTableExport';
</#if>
import { useTreeTableExpand } from '@/hooks/useTreeTableExpand';
import { useUserStore } from '@/stores/userStore';
<#if needDict>
import { dictOptions } from '@/utils/dict';
</#if>
<#if enableStatus>
import { confirmAction } from '@/utils/modal';
</#if>
import { hasPermi } from '@/utils/permission';
import { filterTree<#if needDateField>, formatDateTimeFields</#if>, handleTree<#if needDateField>, toDayjsFields</#if> } from '@/utils/ruoyi';
const default${BusinessName}Form: ${BusinessName}Form = {
${treeParentCode}: ${treeRootValueTsLiteral},
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk && column.htmlType == "checkbox">
${column.javaField}: [],
</#if>
</#list>
};
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
}));
}
<#if enableStatus>
const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'</#if>;
const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'</#if>;
</#if>
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});
</#if>
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();
</#if>
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']);
</#if>
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 }, [
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "datetime">
'${column.javaField}',
</#if>
</#list>
])<#else>{ ...res.data }</#if>;
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "checkbox">
if (typeof data.${column.javaField} === 'string') {
data.${column.javaField} = data.${column.javaField}.split(',');
}
</#if>
</#list>
form.resetFields();
form.setFieldsValue(data);
setModalTitle('修改${functionName}');
openModal();
};
const submitForm = async (values: ${BusinessName}Form) => {
const submitValues = <#if needDateField>formatDateTimeFields({ ...values }, [
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "datetime">
'${column.javaField}',
</#if>
</#list>
])<#else>{ ...values }</#if>;
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "checkbox">
if (Array.isArray(submitValues.${column.javaField})) {
submitValues.${column.javaField} = submitValues.${column.javaField}.join(',');
}
</#if>
</#list>
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(`确认要"${r'${text}'}"吗?`);
await change${BusinessName}Status(row.${pkColumn.javaField}, status);
message.success(`${r'${text}'}成功`);
actionRef.current?.reload();
} catch {
row.${statusField} = previousStatus;
actionRef.current?.reload();
}
};
</#if>
<#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();
};
</#if>
const columns: ProColumns<${BusinessName}VO>[] = [
<#list columns as column>
<#if column.list && !column.pk>
<#if enableStatus && statusField == column.javaField>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
width: 100,
<#if column.dictType?has_content>
fieldProps: { options: dictOptions(dicts.${column.dictType}) },
</#if>
render: (_, row) => (
<Switch
checked={row.${column.javaField} === ${statusField}ActiveValue}
disabled={!canEdit}
onChange={checked => handleStatusChange(row, checked)}
/>
)
},
<#elseif enableSort && sortField == column.javaField>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
search: false,
width: 130,
render: (_, row) => <InputNumber min={0} value={row.${column.javaField} as number} onChange={value => handleSortChange(row, value)} />
},
<#elseif column.htmlType == "datetime">
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}', valueType: 'dateTime', search: <#if column.query>true<#else> false</#if>, width: 170 },
<#elseif column.htmlType == "imageUpload">
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}Url',
search: false,
width: 100,
render: (_, row) => <ImagePreview src={row.${column.javaField}Url || String(row.${column.javaField} || '')} width={50} height={50} />
},
<#elseif column.dictColumn>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
fieldProps: { options: dictOptions(dicts.${column.dictType}) },
render: (_, row) => <DictTag options={dicts.${column.dictType}} value={row.${column.javaField}} />
},
<#elseif column.htmlType == "switch">
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
width: 100,
render: (_, row) => <Switch checked={row.${column.javaField} === ${column.switchActiveValue}} disabled />
},
<#else>
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}'<#if !column.query>, search: false</#if> },
</#if>
</#if>
</#list>
{
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}编号为"${r'${row.'}${pkColumn.javaField}${r'}'}"的数据项?`,
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);
</#if>
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}_${r'${Date.now()}'}.xlsx`)}
>
导出
</Button>
)</#if>
]}
/>
<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 />
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk>
<#assign field = column.javaField>
<#if field == treeParentCode>
<ProFormTreeSelect
name="${column.javaField}"
label="${column.columnLabel}"
<#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>
fieldProps={{
allowClear: true,
treeDefaultExpandAll: true,
treeData: treeSelectData,
placeholder: '请选择${column.columnLabel}'
}}
/>
<#elseif column.htmlType == "input">
<ProFormText name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "textarea">
<ProFormTextArea name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "inputNumber">
<ProFormDigit name="${column.javaField}" label="${column.columnLabel}" min={0} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif (column.htmlType == "select" || column.htmlType == "radio" || column.htmlType == "switch") && column.dictType?has_content>
<ProFormSelect name="${column.javaField}" label="${column.columnLabel}" options={dictOptions(dicts.${column.dictType})} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
<ProFormCheckbox.Group name="${column.javaField}" label="${column.columnLabel}" options={dictOptions(dicts.${column.dictType})} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "switch">
<Form.Item
name="${column.javaField}"
label="${column.columnLabel}"
valuePropName="checked"
getValueProps={value => ({ checked: value === ${column.switchActiveValue} })}
normalize={checked => (checked ? ${column.switchActiveValue} : ${column.switchInactiveValue})}
>
<Switch />
</Form.Item>
<#elseif column.htmlType == "datetime">
<ProFormDateTimePicker name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "imageUpload">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<ImageUpload />
</Form.Item>
<#elseif column.htmlType == "fileUpload">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<FileUpload />
</Form.Item>
<#elseif column.htmlType == "editor">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<RichTextEditor />
</Form.Item>
<#else>
<ProFormText name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
</#if>
</#if>
</#list>
</ModalForm>
</PageContainer>
);
}
@@ -0,0 +1,409 @@
import { DeleteOutlined<#if enableExport>, DownloadOutlined</#if>, EditOutlined, PlusOutlined } from '@ant-design/icons';
import {
ModalForm,
PageContainer,
<#if needCheckbox>
ProFormCheckbox,
</#if>
<#if needDateField>
ProFormDateTimePicker,
</#if>
<#if needDigit>
ProFormDigit,
</#if>
<#if needSelect>
ProFormSelect,
</#if>
<#if needTextArea>
ProFormTextArea,
</#if>
ProFormText,
ProTable,
type ActionType,
type ProColumns
} from '@ant-design/pro-components';
import { useBoolean } from 'ahooks';
import { Button, Form, message, Popconfirm<#if enableStatus || needSwitchField>, Switch</#if><#if enableSort>, InputNumber</#if> } 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,
</#if>
del${BusinessName},
get${BusinessName},
list${BusinessName},
<#if enableSort>
update${BusinessName}Sort,
</#if>
update${BusinessName}
} from '@/api/${moduleName}/${businessName}';
<#if needDict>
import DictTag from '@/components/common/DictTag';
</#if>
<#if needFileUpload>
import FileUpload from '@/components/common/FileUpload';
</#if>
<#if needImagePreview>
import ImagePreview from '@/components/common/ImagePreview';
</#if>
<#if needImageUpload>
import ImageUpload from '@/components/common/ImageUpload';
</#if>
<#if needEditor>
import RichTextEditor from '@/components/common/RichTextEditor';
</#if>
import RowActions from '@/components/common/RowActions';
<#if needDict>
import { useDict } from '@/hooks/useDict';
</#if>
<#if needDateRange>
import { useDateRangeQuery } from '@/hooks/useDateRangeQuery';
</#if>
<#if enableExport>
import { useTableExport } from '@/hooks/useTableExport';
</#if>
import { useTableSelection } from '@/hooks/useTableSelection';
import { useUserStore } from '@/stores/userStore';
<#if needDict>
import { dictOptions } from '@/utils/dict';
</#if>
<#if enableStatus>
import { confirmAction } from '@/utils/modal';
</#if>
import { hasPermi } from '@/utils/permission';
import { <#if needDateField>formatDateTimeFields, toDayjsFields, </#if> toPageQuery, toTableData } from '@/utils/ruoyi';
const default${BusinessName}Form: ${BusinessName}Form = {
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk && column.htmlType == "checkbox">
${column.javaField}: [],
</#if>
</#list>
};
<#if enableStatus>
const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'</#if>;
const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'</#if>;
</#if>
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});
</#if>
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();
</#if>
<#list columns as column>
<#if column.query && column.htmlType == "datetime" && column.queryType == "BETWEEN">
const { applyDateRange: apply${column.capJavaField}DateRange } = useDateRangeQuery('${column.capJavaField}');
</#if>
</#list>
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']);
</#if>
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 }, [
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "datetime">
'${column.javaField}',
</#if>
</#list>
])<#else>{ ...res.data }</#if>;
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "checkbox">
if (typeof data.${column.javaField} === 'string') {
data.${column.javaField} = data.${column.javaField}.split(',');
}
</#if>
</#list>
form.resetFields();
form.setFieldsValue(data);
setModalTitle('修改${functionName}');
openModal();
};
const submitForm = async (values: ${BusinessName}Form) => {
const submitValues = <#if needDateField>formatDateTimeFields({ ...values }, [
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "datetime">
'${column.javaField}',
</#if>
</#list>
])<#else>{ ...values }</#if>;
<#list columns as column>
<#if (column.insert || column.edit) && column.htmlType == "checkbox">
if (Array.isArray(submitValues.${column.javaField})) {
submitValues.${column.javaField} = submitValues.${column.javaField}.join(',');
}
</#if>
</#list>
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(`确认要"${r'${text}'}"吗?`);
await change${BusinessName}Status(row.${pkColumn.javaField}, status);
message.success(`${r'${text}'}成功`);
actionRef.current?.reload();
} catch {
row.${statusField} = previousStatus;
actionRef.current?.reload();
}
};
</#if>
<#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();
};
</#if>
const columns: ProColumns<${BusinessName}VO>[] = [
<#list columns as column>
<#if column.list>
<#if enableStatus && statusField == column.javaField>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
width: 100,
<#if column.dictType?has_content>
fieldProps: { options: dictOptions(dicts.${column.dictType}) },
</#if>
render: (_, row) => (
<Switch
checked={row.${column.javaField} === ${statusField}ActiveValue}
disabled={!canEdit}
onChange={checked => handleStatusChange(row, checked)}
/>
)
},
<#elseif enableSort && sortField == column.javaField>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
search: false,
width: 130,
render: (_, row) => <InputNumber min={0} value={row.${column.javaField} as number} onChange={value => handleSortChange(row, value)} />
},
<#elseif column.htmlType == "datetime">
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}', valueType: 'dateTime', search: <#if column.query && column.queryType != "BETWEEN">true<#else> false</#if>, width: 170 },
<#elseif column.htmlType == "imageUpload">
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}Url',
search: false,
width: 100,
render: (_, row) => <ImagePreview src={row.${column.javaField}Url || String(row.${column.javaField} || '')} width={50} height={50} />
},
<#elseif column.dictColumn>
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
fieldProps: { options: dictOptions(dicts.${column.dictType}) },
render: (_, row) => <DictTag options={dicts.${column.dictType}} value={row.${column.javaField}} />
},
<#elseif column.htmlType == "switch">
{
title: '${column.columnLabel}',
dataIndex: '${column.javaField}',
valueType: 'select',
width: 100,
render: (_, row) => <Switch checked={row.${column.javaField} === ${column.switchActiveValue}} disabled />
},
<#else>
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}'<#if !column.query>, search: false</#if> },
</#if>
</#if>
<#if column.query && column.htmlType == "datetime" && column.queryType == "BETWEEN">
{ title: '${column.columnLabel}', dataIndex: '${column.javaField}Range', valueType: 'dateTimeRange', hideInTable: true },
</#if>
</#list>
{
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}编号为"${r'${row.'}${pkColumn.javaField}${r'}'}"的数据项?`,
onClick: () => remove(row)
}
]}
/>
)
}
];
return (
<PageContainer title="${functionName}">
<ProTable<${BusinessName}VO, ${BusinessName}Query<#if needDateRange> & Record<string, unknown></#if>>
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);
<#list columns as column>
<#if column.query && column.htmlType == "datetime" && column.queryType == "BETWEEN">
query = apply${column.capJavaField}DateRange(query, params.${column.javaField}Range as [string, string] | undefined);
delete query.${column.javaField}Range;
</#if>
</#list>
<#else>
const query = toPageQuery(params);
</#if>
<#if enableExport>
updateExportParams(query);
</#if>
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}编号为"${r'${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}_${r'${Date.now()}'}.xlsx`)}
>
导出
</Button>
)</#if>
]}
/>
<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 />
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk>
<#assign field = column.javaField>
<#if column.htmlType == "input">
<ProFormText name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "textarea">
<ProFormTextArea name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "inputNumber">
<ProFormDigit name="${column.javaField}" label="${column.columnLabel}" min={0} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif (column.htmlType == "select" || column.htmlType == "radio" || column.htmlType == "switch") && column.dictType?has_content>
<ProFormSelect name="${column.javaField}" label="${column.columnLabel}" options={dictOptions(dicts.${column.dictType})} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
<ProFormCheckbox.Group name="${column.javaField}" label="${column.columnLabel}" options={dictOptions(dicts.${column.dictType})} <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "switch">
<Form.Item
name="${column.javaField}"
label="${column.columnLabel}"
valuePropName="checked"
getValueProps={value => ({ checked: value === ${column.switchActiveValue} })}
normalize={checked => (checked ? ${column.switchActiveValue} : ${column.switchInactiveValue})}
>
<Switch />
</Form.Item>
<#elseif column.htmlType == "datetime">
<ProFormDateTimePicker name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
<#elseif column.htmlType == "imageUpload">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<ImageUpload />
</Form.Item>
<#elseif column.htmlType == "fileUpload">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<FileUpload />
</Form.Item>
<#elseif column.htmlType == "editor">
<Form.Item name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if>>
<RichTextEditor />
</Form.Item>
<#else>
<ProFormText name="${column.javaField}" label="${column.columnLabel}" <#if column.required>rules={[{ required: true, message: '${column.columnLabel}不能为空' }]}</#if> />
</#if>
</#if>
</#list>
</ModalForm>
</PageContainer>
);
}
@@ -0,0 +1,57 @@
import type { BaseEntity<#if !table.tree>, PageQuery</#if> } from '@/api/types';
export interface ${BusinessName}VO {
<#list columns as column>
<#if column.list || column.pk>
/**
* ${column.columnComment}
*/
${column.javaField}: ${column.tsType};
<#if column.htmlType == "imageUpload">
/**
* ${column.columnComment}Url
*/
${column.javaField}Url?: string;
</#if>
</#if>
</#list>
<#if table.tree>
/**
* 子对象
*/
children?: ${BusinessName}VO[];
</#if>
}
export interface ${BusinessName}Form extends BaseEntity {
<#list columns as column>
<#if column.insert || column.edit || column.pk>
/**
* ${column.columnComment}
*/
<#if column.htmlType == "checkbox">
${column.javaField}?: string | string[];
<#else>
${column.javaField}?: ${column.tsType};
</#if>
</#if>
</#list>
}
export interface ${BusinessName}Query<#if !table.tree> extends PageQuery</#if> {
<#list columns as column>
<#if column.query>
/**
* ${column.columnComment}
*/
${column.javaField}?: ${column.tsType};
</#if>
</#list>
/**
* 日期范围参数
*/
params?: Record<string, unknown>;
}
@@ -0,0 +1,22 @@
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[0]}, '${functionName}', ${parentMenuId}, 1, '${businessName}', '${moduleName}/${businessName}/index', 'N', 'Y', 'C', '0', '0', '${permissionPrefix}:list', '#', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '${functionName}菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, 1, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:query', '#', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[2]}, '${functionName}新增', ${table.menuIds[0]}, 2, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:add', '#', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[3]}, '${functionName}修改', ${table.menuIds[0]}, 3, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:edit', '#', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[4]}, '${functionName}删除', ${table.menuIds[0]}, 4, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:remove', '#', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, 5, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:export', '#', 1761000000000000103, 1761100000000000001, sysdate(), null, null, '');
@@ -0,0 +1,22 @@
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[0]}, '${functionName}', ${parentMenuId}, 1, '${businessName}', '${moduleName}/${businessName}/index', 'N', 'Y', 'C', '0', '0', '${permissionPrefix}:list', '#', 1761000000000000103, 1761100000000000001, sysdate, null, null, '${functionName}菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, 1, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:query', '#', 1761000000000000103, 1761100000000000001, sysdate, null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[2]}, '${functionName}新增', ${table.menuIds[0]}, 2, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:add', '#', 1761000000000000103, 1761100000000000001, sysdate, null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[3]}, '${functionName}修改', ${table.menuIds[0]}, 3, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:edit', '#', 1761000000000000103, 1761100000000000001, sysdate, null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[4]}, '${functionName}删除', ${table.menuIds[0]}, 4, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:remove', '#', 1761000000000000103, 1761100000000000001, sysdate, null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, 5, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:export', '#', 1761000000000000103, 1761100000000000001, sysdate, null, null, '');
@@ -0,0 +1,23 @@
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[0]}, '${functionName}', ${parentMenuId}, 1, '${businessName}', '${moduleName}/${businessName}/index', 'N', 'Y', 'C', '0', '0', '${permissionPrefix}:list', '#', 1761000000000000103, 1761100000000000001, now(), null, null, '${functionName}菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, 1, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:query', '#', 1761000000000000103, 1761100000000000001, now(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[2]}, '${functionName}新增', ${table.menuIds[0]}, 2, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:add', '#', 1761000000000000103, 1761100000000000001, now(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[3]}, '${functionName}修改', ${table.menuIds[0]}, 3, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:edit', '#', 1761000000000000103, 1761100000000000001, now(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[4]}, '${functionName}删除', ${table.menuIds[0]}, 4, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:remove', '#', 1761000000000000103, 1761100000000000001, now(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, 5, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:export', '#', 1761000000000000103, 1761100000000000001, now(), null, null, '');
@@ -0,0 +1,22 @@
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[0]}, '${functionName}', ${parentMenuId}, 1, '${businessName}', '${moduleName}/${businessName}/index', 'N', 'Y', 'C', '0', '0', '${permissionPrefix}:list', '#', 1761000000000000103, 1761100000000000001, getdate(), null, null, '${functionName}菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[1]}, '${functionName}查询', ${table.menuIds[0]}, 1, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:query', '#', 1761000000000000103, 1761100000000000001, getdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[2]}, '${functionName}新增', ${table.menuIds[0]}, 2, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:add', '#', 1761000000000000103, 1761100000000000001, getdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[3]}, '${functionName}修改', ${table.menuIds[0]}, 3, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:edit', '#', 1761000000000000103, 1761100000000000001, getdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[4]}, '${functionName}删除', ${table.menuIds[0]}, 4, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:remove', '#', 1761000000000000103, 1761100000000000001, getdate(), null, null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark)
values(${table.menuIds[5]}, '${functionName}导出', ${table.menuIds[0]}, 5, '#', '', 'N', 'Y', 'F', '0', '0', '${permissionPrefix}:export', '#', 1761000000000000103, 1761100000000000001, getdate(), null, null, '');
@@ -0,0 +1,103 @@
import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
import type { PageResult } from '@/api/types';
import type { AxiosPromise } from '@/utils/api-types';
import request from '@/utils/request';
/**
* 查询${functionName}列表
* @param query
* @returns {*}
*/
export const list${BusinessName} = (query?: ${BusinessName}Query): AxiosPromise<PageResult<${BusinessName}VO>> => {
return request({
url: '/${moduleName}/${businessName}/list',
method: 'get',
params: query
});
};
/**
* 查询${functionName}详细
* @param ${pkColumn.javaField}
*/
export const get${BusinessName} = (${pkColumn.javaField}: string | number): AxiosPromise<${BusinessName}VO> => {
return request({
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
method: 'get'
});
};
/**
* 新增${functionName}
* @param data
*/
export const add${BusinessName} = (data: ${BusinessName}Form) => {
return request({
url: '/${moduleName}/${businessName}',
method: 'post',
data: data
});
};
/**
* 修改${functionName}
* @param data
*/
export const update${BusinessName} = (data: ${BusinessName}Form) => {
return request({
url: '/${moduleName}/${businessName}',
method: 'put',
data: data
});
};
<#if enableStatus>
/**
* 修改${functionName}状态
* @param ${pkColumn.javaField}
* @param status
*/
export const change${BusinessName}Status = (${pkColumn.javaField}: string | number, status: <#if statusColumn.javaType == 'Boolean'>boolean<#elseif statusColumn.javaType == 'String'>string<#else> number</#if>) => {
return request({
url: '/${moduleName}/${businessName}/changeStatus',
method: 'put',
data: {
${pkColumn.javaField},
${statusField}: status
}
});
};
</#if>
<#if enableSort>
/**
* 调整${functionName}排序
* @param ${pkColumn.javaField}
* @param sortValue
*/
export const update${BusinessName}Sort = (${pkColumn.javaField}: string | number, sortValue: <#if sortColumn.javaType == 'String' || sortColumn.javaType == 'LocalDateTime'>string<#else> number</#if>) => {
return request({
url: '/${moduleName}/${businessName}/updateSort',
method: 'put',
data: {
${pkColumn.javaField},
${sortField}: sortValue
}
});
};
</#if>
/**
* 删除${functionName}
* @param ${pkColumn.javaField}
*/
export const del${BusinessName} = (${pkColumn.javaField}: string | number | Array<string | number>) => {
return request({
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
method: 'delete'
});
};
@@ -0,0 +1,692 @@
<template>
<div class="p-2 page-shell ${moduleName}-${businessName}-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div><h3>筛选条件</h3></div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<#list columns as column>
<#if column.query>
<#if column.htmlType == "input" || column.htmlType == "textarea">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input v-model="queryParams.${column.javaField}" placeholder="请输入${column.columnLabel}" clearable @keyup.enter="handleQuery" />
</el-form-item>
<#elseif column.htmlType == "inputNumber">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input-number v-model="queryParams.${column.javaField}" controls-position="right" />
</el-form-item>
<#elseif (column.htmlType == "select" || column.htmlType == "radio") && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable>
<el-option v-for="dict in ${column.dictType}" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<#elseif column.htmlType == "switch" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable>
<el-option v-for="dict in ${column.dictType}" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<#elseif column.htmlType == "switch">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable>
<#if column.javaType == "Boolean">
<el-option label="是" :value="true" />
<el-option label="否" :value="false" />
<#elseif column.javaType == "Integer" || column.javaType == "Long">
<el-option label="开启" :value="0" />
<el-option label="关闭" :value="1" />
<#else>
<el-option label="开启" value="0" />
<el-option label="关闭" value="1" />
</#if>
</el-select>
</el-form-item>
<#elseif (column.htmlType == "select" || column.htmlType == "radio") && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable>
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<#elseif column.htmlType == "datetime" && column.queryType != "BETWEEN">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-date-picker clearable
v-model="queryParams.${column.javaField}"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择${column.columnLabel}"
/>
</el-form-item>
<#elseif column.htmlType == "datetime" && column.queryType == "BETWEEN">
<el-form-item label="${column.columnLabel}" style="width: 308px">
<el-date-picker
v-model="dateRange${column.capJavaField}"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
/>
</el-form-item>
</#if>
</#if>
</#list>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
<el-card shadow="hover" class="table-panel">
<template #header>
<div class="toolbar-shell">
<div class="table-heading">
<h3>${functionName}列表</h3>
</div>
<div class="toolbar-actions">
<el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button>
<el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
<#if enableExport>
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['${moduleName}:${businessName}:export']">导出</el-button>
</#if>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table
ref="${businessName}TableRef"
v-loading="loading"
class="data-table"
:data="${businessName}List"
row-key="${treeCode}"
border
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<#assign firstTreeListField = "">
<#list columns as tempColumn>
<#if !tempColumn.pk && tempColumn.list && "" != tempColumn.javaField && firstTreeListField == "">
<#assign firstTreeListField = tempColumn.javaField>
</#if>
</#list>
<#list columns as column>
<#if column.pk>
<#elseif enableStatus && statusField == column.javaField>
<#if column.javaField == firstTreeListField>
<el-table-column label="${column.columnLabel}" prop="${column.javaField}">
<#else>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}">
</#if>
<template #default="scope">
<el-switch
v-model="scope.row.${column.javaField}"
:active-value="${statusField}ActiveValue"
:inactive-value="${statusField}InactiveValue"
@change="handleStatusChange(scope.row)"
/>
</template>
</el-table-column>
<#elseif enableSort && sortField == column.javaField>
<#if column.javaField == firstTreeListField>
<el-table-column label="${column.columnLabel}" prop="${column.javaField}" width="160">
<#else>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="160">
</#if>
<template #default="scope">
<#if column.javaType == "LocalDateTime">
<el-date-picker
v-model="scope.row.${column.javaField}"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择${column.columnLabel}"
@change="handleSortChange(scope.row)"
/>
<#else>
<el-input-number v-model="scope.row.${column.javaField}" controls-position="right" :min="0" @change="handleSortChange(scope.row)" />
</#if>
</template>
</el-table-column>
<#elseif column.list && column.htmlType == "switch">
<#if column.javaField == firstTreeListField>
<el-table-column label="${column.columnLabel}" prop="${column.javaField}" width="120">
<#else>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="120">
</#if>
<template #default="scope">
<el-switch
v-model="scope.row.${column.javaField}"
<#if column.javaType == "Boolean">
:active-value="true"
:inactive-value="false"
<#elseif column.javaType == "Integer" || column.javaType == "Long">
:active-value="0"
:inactive-value="1"
<#else>
active-value="0"
inactive-value="1"
</#if>
disabled
/>
</template>
</el-table-column>
<#elseif column.list && column.htmlType == "datetime">
<#if column.javaField == firstTreeListField>
<el-table-column label="${column.columnLabel}" prop="${column.javaField}" width="180">
<#else>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="180">
</#if>
<template #default="scope">
<span>{{ parseTime(scope.row.${column.javaField}, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<#elseif column.list && column.htmlType == "imageUpload">
<#if column.javaField == firstTreeListField>
<el-table-column label="${column.columnLabel}" prop="${column.javaField}Url" width="100">
<#else>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}Url" width="100">
</#if>
<template #default="scope">
<image-preview :src="scope.row.${column.javaField}Url" :width="50" :height="50"/>
</template>
</el-table-column>
<#elseif column.list && column.dictColumn>
<#if column.javaField == firstTreeListField>
<el-table-column label="${column.columnLabel}" prop="${column.javaField}">
<#else>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}">
</#if>
<template #default="scope">
<#if column.htmlType == "checkbox">
<dict-tag :options="${column.dictType}" :value="scope.row.${column.javaField} ? scope.row.${column.javaField}.split(',') : []"/>
<#else>
<dict-tag :options="${column.dictType}" :value="scope.row.${column.javaField}"/>
</#if>
</template>
</el-table-column>
<#elseif column.list && "" != column.javaField>
<#if column.javaField == firstTreeListField>
<el-table-column label="${column.columnLabel}" prop="${column.javaField}" />
<#else>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" />
</#if>
</#if>
</#list>
<#if enableStatus && !statusColumn.list>
<el-table-column label="${statusColumn.columnComment}" align="center" prop="${statusField}">
<template #default="scope">
<el-switch
v-model="scope.row.${statusField}"
:active-value="${statusField}ActiveValue"
:inactive-value="${statusField}InactiveValue"
@change="handleStatusChange(scope.row)"
/>
</template>
</el-table-column>
</#if>
<#if enableSort && !sortColumn.list>
<el-table-column label="${sortColumn.columnComment}" align="center" prop="${sortField}" width="160">
<template #default="scope">
<#if sortColumn.javaType == "LocalDateTime">
<el-date-picker
v-model="scope.row.${sortField}"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择${sortColumn.columnComment}"
@change="handleSortChange(scope.row)"
/>
<#else>
<el-input-number v-model="scope.row.${sortField}" controls-position="right" :min="0" @change="handleSortChange(scope.row)" />
</#if>
</template>
</el-table-column>
</#if>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']" />
</el-tooltip>
<el-tooltip content="新增" placement="top">
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']" />
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 添加或修改${functionName}对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="${businessName}FormRef" :model="form" :rules="rules" label-width="80px">
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk>
<#if "" != treeParentCode && column.javaField == treeParentCode>
<el-form-item label="${column.columnLabel}" prop="${treeParentCode}">
<el-tree-select
v-model="form.${treeParentCode}"
:data="${businessName}Options"
:props="{ value: '${treeCode}', label: '${treeName}', children: 'children' } as any"
value-key="${treeCode}"
placeholder="请选择${column.columnLabel}"
check-strictly
/>
</el-form-item>
<#elseif column.htmlType == "input">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input v-model="form.${column.javaField}" placeholder="请输入${column.columnLabel}" />
</el-form-item>
<#elseif column.htmlType == "inputNumber">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input-number v-model="form.${column.javaField}" controls-position="right" />
</el-form-item>
<#elseif column.htmlType == "imageUpload">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<image-upload v-model="form.${column.javaField}"/>
</el-form-item>
<#elseif column.htmlType == "fileUpload">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<file-upload v-model="form.${column.javaField}"/>
</el-form-item>
<#elseif column.htmlType == "editor">
<el-form-item label="${column.columnLabel}">
<editor v-model="form.${column.javaField}" :min-height="192"/>
</el-form-item>
<#elseif column.htmlType == "select" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="form.${column.javaField}" placeholder="请选择${column.columnLabel}">
<el-option
v-for="dict in ${column.dictType}"
:key="dict.value"
:label="dict.label"
<#if column.javaType == "Integer" || column.javaType == "Long">
:value="parseInt(dict.value)"
<#else>
:value="dict.value"
</#if>
></el-option>
</el-select>
</el-form-item>
<#elseif column.htmlType == "select" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="form.${column.javaField}" placeholder="请选择${column.columnLabel}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-checkbox-group v-model="form.${column.javaField}">
<el-checkbox
v-for="dict in ${column.dictType}"
:key="dict.value"
:label="dict.value">
{{dict.label}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-checkbox-group v-model="form.${column.javaField}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
<#elseif column.htmlType == "radio" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-radio-group v-model="form.${column.javaField}">
<el-radio
v-for="dict in ${column.dictType}"
:key="dict.value"
<#if column.javaType == "Integer" || column.javaType == "Long">
:value="parseInt(dict.value)"
<#else>
:value="dict.value"
</#if>
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<#elseif column.htmlType == "radio" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-radio-group v-model="form.${column.javaField}">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<#elseif column.htmlType == "switch">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-switch
v-model="form.${column.javaField}"
<#if column.javaType == "Boolean">
:active-value="true"
:inactive-value="false"
<#elseif column.javaType == "Integer" || column.javaType == "Long">
:active-value="0"
:inactive-value="1"
<#else>
active-value="0"
inactive-value="1"
</#if>
/>
</el-form-item>
<#elseif column.htmlType == "datetime">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-date-picker clearable
v-model="form.${column.javaField}"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择${column.columnLabel}"
/>
</el-form-item>
<#elseif column.htmlType == "textarea">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input v-model="form.${column.javaField}" type="textarea" placeholder="请输入内容" />
</el-form-item>
</#if>
</#if>
</#list>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="${BusinessName}" lang="ts">
import {
add${BusinessName},
<#if enableStatus>
change${BusinessName}Status,
</#if>
del${BusinessName},
get${BusinessName},
list${BusinessName},
<#if enableSort>
update${BusinessName}Sort,
</#if>
update${BusinessName}
} from '@/api/${moduleName}/${businessName}';
import { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
import { useLoading } from '@/hooks/async/useLoading';
import { useFormDialog } from '@/hooks/dialog/useFormDialog';
<#if needAddDateRange>
import { useDateRangeQuery } from '@/hooks/form/useDateRangeQuery';
</#if>
import { useSearchReset } from '@/hooks/form/useSearchReset';
import { useSearchToggle } from '@/hooks/form/useSearchToggle';
import { useTreeTableExpand } from '@/hooks/tree/useTreeTableExpand';
<#if needDict>
import { useDict } from '@/utils/dict';
</#if>
import modal from '@/plugins/modal';
import { handleTree } from '@/utils/ruoyi';
<#if enableExport>
import { download as requestDownload } from '@/utils/request';
</#if>
<#if needDict>
const { ${dictsNoSymbol} } = toRefs<any>(useDict(${dicts}));
</#if>
<#if enableStatus>
const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'</#if>;
const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'</#if>;
</#if>
type ${BusinessName}Option = {
${treeCode}: <#if treeParentColumn.javaType == 'String'>string<#else> number</#if>;
${treeName}: string;
children?: ${BusinessName}Option[];
};
const ${businessName}List = ref<${BusinessName}VO[]>([]);
const ${businessName}Options = ref<${BusinessName}Option[]>([]);
const all${BusinessName}Options = ref<${BusinessName}Option[]>([]);
const buttonLoading = ref(false);
const { showSearch } = useSearchToggle();
const { loading, setLoading, withLoading } = useLoading();
const queryFormRef = ref<ElFormInstance>();
const ${businessName}FormRef = ref<ElFormInstance>();
const ${businessName}TableRef = ref<ElTableInstance>();
const { isExpandAll, handleToggleExpandAll } = useTreeTableExpand<${BusinessName}VO>({
tableRef: ${businessName}TableRef,
data: ${businessName}List
});
<#list columns as column>
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
const {
dateRange: dateRange${column.capJavaField},
applyDateRange: apply${column.capJavaField}DateRange,
resetDateRange: reset${column.capJavaField}DateRange
} = useDateRangeQuery('${column.capJavaField}');
</#if>
</#list>
const initFormData: ${BusinessName}Form = {
<#list columns as column>
<#if column.insert || column.edit>
<#if column.htmlType == "checkbox">
${column.javaField}: [],
<#else>
${column.javaField}: undefined,
</#if>
</#if>
</#list>
}
const data = reactive<PageData<${BusinessName}Form, ${BusinessName}Query>>({
form: {...initFormData},
queryParams: {
<#list columns as column>
<#if column.query>
<#if column.htmlType != "datetime" || column.queryType != "BETWEEN">
${column.javaField}: undefined,
</#if>
</#if>
</#list>
params: {
<#list columns as column>
<#if column.query>
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
${column.javaField}: undefined,
</#if>
</#if>
</#list>
}
},
rules: {
<#list columns as column>
<#if column.insert || column.edit>
<#if column.required>
${column.javaField}: [
{ required: true, message: "${column.columnLabel}不能为空", trigger: <#if column.htmlType == "select" || column.htmlType == "radio" || column.htmlType == "switch" || column.htmlType == "inputNumber">"change"<#else>"blur"</#if> }
],
</#if>
</#if>
</#list>
}
});
const { queryParams, form, rules } = toRefs(data);
const { dialog, resetForm: reset, openDialog, showDialog, closeDialog } = useFormDialog({
form,
formRef: ${businessName}FormRef,
initialFormData: initFormData
});
/** 查询${functionName}列表 */
const getList = async () => {
await withLoading(async () => {
<#if needAddDateRange>
let params = queryParams.value;
<#list columns as column>
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
params = apply${column.capJavaField}DateRange(params);
</#if>
</#list>
const res = await list${BusinessName}(params);
<#else>
const res = await list${BusinessName}(queryParams.value);
</#if>
const data = handleTree<${BusinessName}VO>(res.data, '${treeCode}', '${treeParentCode}');
if (data) {
${businessName}List.value = data;
}
});
};
/** 查询${functionName}下拉树结构 */
const getTreeselect = async (excludeId?: string | number) => {
const res = await list${BusinessName}();
const data: ${BusinessName}Option = { ${treeCode}: ${treeRootValueTsLiteral}, ${treeName}: '顶级节点', children: [] };
data.children = handleTree<${BusinessName}Option>(res.data, '${treeCode}', '${treeParentCode}');
all${BusinessName}Options.value = [data];
${businessName}Options.value = excludeId != null ? filterTreeOptions(all${BusinessName}Options.value, excludeId) : all${BusinessName}Options.value;
};
/** 取消按钮 */
const cancel = () => {
reset();
closeDialog();
};
/** 搜索按钮操作 */
const handleQuery = () => {
getList();
};
const { resetQuery } = useSearchReset({
queryFormRef,
queryParams,
resetExtras: () => {
<#list columns as column>
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
reset${column.capJavaField}DateRange();
</#if>
</#list>
},
afterReset: () => {
handleQuery();
}
});
/** 新增按钮操作 */
const handleAdd = (row?: Partial<${BusinessName}VO>) => {
openDialog('添加${functionName}');
getTreeselect();
if (row != null && row.${treeCode}) {
form.value.${treeParentCode} = row.${treeCode};
} else {
form.value.${treeParentCode} = ${treeRootValueTsLiteral};
}
};
/** 修改按钮操作 */
const handleUpdate = async (row: Partial<${BusinessName}VO>) => {
reset();
await getTreeselect(row.${treeCode});
if (row != null) {
form.value.${treeParentCode} = row.${treeParentCode};
}
const res = await get${BusinessName}(row.${pkColumn.javaField});
Object.assign(form.value, res.data);
<#list columns as column>
<#if column.htmlType == "checkbox">
form.value.${column.javaField} = form.value.${column.javaField}.split(",");
</#if>
</#list>
showDialog('修改${functionName}');
};
/** 提交按钮 */
const submitForm = () => {
${businessName}FormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
<#list columns as column>
<#if column.htmlType == "checkbox">
form.value.${column.javaField} = form.value.${column.javaField}.join(",");
</#if>
</#list>
if (form.value.${pkColumn.javaField}) {
await update${BusinessName}(form.value).finally(() => (buttonLoading.value = false));
} else {
await add${BusinessName}(form.value).finally(() => (buttonLoading.value = false));
}
modal.msgSuccess('操作成功');
closeDialog();
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row: Partial<${BusinessName}VO>) => {
await modal.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?');
setLoading(true);
await del${BusinessName}(row.${pkColumn.javaField}).finally(() => setLoading(false));
await getList();
modal.msgSuccess('删除成功');
};
const filterTreeOptions = (options: ${BusinessName}Option[], excludeId: string | number): ${BusinessName}Option[] => {
return options
.filter(item => item.${treeCode} !== excludeId)
.map(item => ({
...item,
children: item.children ? filterTreeOptions(item.children, excludeId) : []
}));
};
<#if enableStatus>
/** 状态修改 */
const handleStatusChange = async (row: Partial<${BusinessName}VO>) => {
const text = row.${statusField} === ${statusField}ActiveValue ? '启用' : '停用';
try {
await modal.confirm('确认要"' + text + '"吗?');
await change${BusinessName}Status(row.${pkColumn.javaField}, row.${statusField});
modal.msgSuccess(text + '成功');
} catch (err) {
row.${statusField} = row.${statusField} === ${statusField}ActiveValue ? ${statusField}InactiveValue : ${statusField}ActiveValue;
}
};
</#if>
<#if enableSort>
/** 排序调整 */
const handleSortChange = async (row: Partial<${BusinessName}VO>) => {
try {
await update${BusinessName}Sort(row.${pkColumn.javaField}, row.${sortField});
modal.msgSuccess('排序更新成功');
} catch (err) {
await getList();
}
};
</#if>
<#if enableExport>
/** 导出按钮操作 */
const handleExport = () => {
requestDownload(
'${moduleName}/${businessName}/export',
{
...queryParams.value
},
`${businessName}_${r'${new Date().getTime()}'}.xlsx`
);
};
</#if>
onMounted(() => {
getList();
});
</script>
@@ -0,0 +1,611 @@
<template>
<div class="p-2 page-shell ${moduleName}-${businessName}-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div><h3>筛选条件</h3></div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<#list columns as column>
<#if column.query>
<#if column.htmlType == "input" || column.htmlType == "textarea">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input v-model="queryParams.${column.javaField}" placeholder="请输入${column.columnLabel}" clearable @keyup.enter="handleQuery" />
</el-form-item>
<#elseif column.htmlType == "inputNumber">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input-number v-model="queryParams.${column.javaField}" controls-position="right" />
</el-form-item>
<#elseif (column.htmlType == "select" || column.htmlType == "radio") && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable >
<el-option v-for="dict in ${column.dictType}" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<#elseif column.htmlType == "switch" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable >
<el-option v-for="dict in ${column.dictType}" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<#elseif column.htmlType == "switch">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable >
<#if column.javaType == "Boolean">
<el-option label="是" :value="true" />
<el-option label="否" :value="false" />
<#elseif column.javaType == "Integer" || column.javaType == "Long">
<el-option label="开启" :value="0" />
<el-option label="关闭" :value="1" />
<#else>
<el-option label="开启" value="0" />
<el-option label="关闭" value="1" />
</#if>
</el-select>
</el-form-item>
<#elseif (column.htmlType == "select" || column.htmlType == "radio") && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable >
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<#elseif column.htmlType == "datetime" && column.queryType != "BETWEEN">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-date-picker clearable
v-model="queryParams.${column.javaField}"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择${column.columnLabel}"
/>
</el-form-item>
<#elseif column.htmlType == "datetime" && column.queryType == "BETWEEN">
<el-form-item label="${column.columnLabel}" style="width: 308px">
<el-date-picker
v-model="dateRange${column.capJavaField}"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
/>
</el-form-item>
</#if>
</#if>
</#list>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
<el-card shadow="hover" class="table-panel">
<template #header>
<div class="toolbar-shell">
<div class="table-heading">
<h3>${functionName}列表</h3>
</div>
<div class="toolbar-actions">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button>
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
<#if enableExport>
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['${moduleName}:${businessName}:export']">导出</el-button>
</#if>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table v-loading="loading" border class="data-table" :data="${businessName}List" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<#list columns as column>
<#if column.pk && column.list>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" />
<#elseif enableStatus && statusField == column.javaField>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}">
<template #default="scope">
<el-switch
v-model="scope.row.${column.javaField}"
:active-value="${statusField}ActiveValue"
:inactive-value="${statusField}InactiveValue"
@change="handleStatusChange(scope.row)"
/>
</template>
</el-table-column>
<#elseif enableSort && sortField == column.javaField>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="160">
<template #default="scope">
<#if column.javaType == "LocalDateTime">
<el-date-picker
v-model="scope.row.${column.javaField}"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择${column.columnLabel}"
@change="handleSortChange(scope.row)"
/>
<#else>
<el-input-number v-model="scope.row.${column.javaField}" controls-position="right" :min="0" @change="handleSortChange(scope.row)" />
</#if>
</template>
</el-table-column>
<#elseif column.list && column.htmlType == "switch">
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="120">
<template #default="scope">
<el-switch
v-model="scope.row.${column.javaField}"
<#if column.javaType == "Boolean">
:active-value="true"
:inactive-value="false"
<#elseif column.javaType == "Integer" || column.javaType == "Long">
:active-value="0"
:inactive-value="1"
<#else>
active-value="0"
inactive-value="1"
</#if>
disabled
/>
</template>
</el-table-column>
<#elseif column.list && column.htmlType == "datetime">
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.${column.javaField}, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<#elseif column.list && column.htmlType == "imageUpload">
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}Url" width="100">
<template #default="scope">
<image-preview :src="scope.row.${column.javaField}Url" :width="50" :height="50"/>
</template>
</el-table-column>
<#elseif column.list && column.dictColumn>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}">
<template #default="scope">
<#if column.htmlType == "checkbox">
<dict-tag :options="${column.dictType}" :value="scope.row.${column.javaField} ? scope.row.${column.javaField}.split(',') : []"/>
<#else>
<dict-tag :options="${column.dictType}" :value="scope.row.${column.javaField}"/>
</#if>
</template>
</el-table-column>
<#elseif column.list && "" != column.javaField>
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" />
</#if>
</#list>
<#if enableStatus && !statusColumn.list>
<el-table-column label="${statusColumn.columnComment}" align="center" prop="${statusField}">
<template #default="scope">
<el-switch
v-model="scope.row.${statusField}"
<#if statusColumn.javaType == "Boolean">
:active-value="true"
:inactive-value="false"
<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">
:active-value="0"
:inactive-value="1"
<#else>
active-value="0"
inactive-value="1"
</#if>
@change="handleStatusChange(scope.row)"
/>
</template>
</el-table-column>
</#if>
<#if enableSort && !sortColumn.list>
<el-table-column label="${sortColumn.columnComment}" align="center" prop="${sortField}" width="160">
<template #default="scope">
<#if sortColumn.javaType == "LocalDateTime">
<el-date-picker
v-model="scope.row.${sortField}"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择${sortColumn.columnComment}"
@change="handleSortChange(scope.row)"
/>
<#else>
<el-input-number v-model="scope.row.${sortField}" controls-position="right" :min="0" @change="handleSortChange(scope.row)" />
</#if>
</template>
</el-table-column>
</#if>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改${functionName}对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="${businessName}FormRef" :model="form" :rules="rules" label-width="80px">
<#list columns as column>
<#if (column.insert || column.edit) && !column.pk>`n<#if column.htmlType == "input">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input v-model="form.${column.javaField}" placeholder="请输入${column.columnLabel}" />
</el-form-item>
<#elseif column.htmlType == "inputNumber">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input-number v-model="form.${column.javaField}" controls-position="right" />
</el-form-item>
<#elseif column.htmlType == "imageUpload">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<image-upload v-model="form.${column.javaField}"/>
</el-form-item>
<#elseif column.htmlType == "fileUpload">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<file-upload v-model="form.${column.javaField}"/>
</el-form-item>
<#elseif column.htmlType == "editor">
<el-form-item label="${column.columnLabel}">
<editor v-model="form.${column.javaField}" :min-height="192"/>
</el-form-item>
<#elseif column.htmlType == "select" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="form.${column.javaField}" placeholder="请选择${column.columnLabel}">
<el-option
v-for="dict in ${column.dictType}"
:key="dict.value"
:label="dict.label"
<#if column.javaType == "Integer" || column.javaType == "Long">
:value="parseInt(dict.value)"
<#else>
:value="dict.value"
</#if>
></el-option>
</el-select>
</el-form-item>
<#elseif column.htmlType == "select" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-select v-model="form.${column.javaField}" placeholder="请选择${column.columnLabel}">
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-checkbox-group v-model="form.${column.javaField}">
<el-checkbox
v-for="dict in ${column.dictType}"
:key="dict.value"
:label="dict.value">
{{dict.label}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-checkbox-group v-model="form.${column.javaField}">
<el-checkbox>请选择字典生成</el-checkbox>
</el-checkbox-group>
</el-form-item>
<#elseif column.htmlType == "radio" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-radio-group v-model="form.${column.javaField}">
<el-radio
v-for="dict in ${column.dictType}"
:key="dict.value"
<#if column.javaType == "Integer" || column.javaType == "Long">
:value="parseInt(dict.value)"
<#else>
:value="dict.value"
</#if>
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<#elseif column.htmlType == "radio" && column.dictType?has_content>
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-radio-group v-model="form.${column.javaField}">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<#elseif column.htmlType == "switch">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-switch
v-model="form.${column.javaField}"
<#if column.javaType == "Boolean">
:active-value="true"
:inactive-value="false"
<#elseif column.javaType == "Integer" || column.javaType == "Long">
:active-value="0"
:inactive-value="1"
<#else>
active-value="0"
inactive-value="1"
</#if>
/>
</el-form-item>
<#elseif column.htmlType == "datetime">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-date-picker clearable
v-model="form.${column.javaField}"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择${column.columnLabel}">
</el-date-picker>
</el-form-item>
<#elseif column.htmlType == "textarea">
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
<el-input v-model="form.${column.javaField}" type="textarea" placeholder="请输入内容" />
</el-form-item>
</#if>
</#if>
</#list>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="${BusinessName}" lang="ts">
import {
add${BusinessName},
<#if enableStatus>
change${BusinessName}Status,
</#if>
del${BusinessName},
get${BusinessName},
list${BusinessName},
<#if enableSort>
update${BusinessName}Sort,
</#if>
update${BusinessName}
} from '@/api/${moduleName}/${businessName}';
import { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
import { useLoading } from '@/hooks/async/useLoading';
import { useFormDialog } from '@/hooks/dialog/useFormDialog';
<#if needAddDateRange>
import { useDateRangeQuery } from '@/hooks/form/useDateRangeQuery';
</#if>
import { useSearchReset } from '@/hooks/form/useSearchReset';
import { useSearchToggle } from '@/hooks/form/useSearchToggle';
import { useTableSelection } from '@/hooks/table/useTableSelection';
<#if needDict>
import { useDict } from '@/utils/dict';
</#if>
import modal from '@/plugins/modal';
<#if enableExport>
import { download as requestDownload } from '@/utils/request';
</#if>
<#if needDict>
const { ${dictsNoSymbol} } = toRefs<any>(useDict(${dicts}));
</#if>
<#if enableStatus>
const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'</#if>;
const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'</#if>;
</#if>
const ${businessName}List = ref<${BusinessName}VO[]>([]);
const buttonLoading = ref(false);
const { loading, withLoading } = useLoading(true);
const { showSearch } = useSearchToggle();
const total = ref(0);
<#list columns as column>
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
const {
dateRange: dateRange${column.capJavaField},
applyDateRange: apply${column.capJavaField}DateRange,
resetDateRange: reset${column.capJavaField}DateRange
} = useDateRangeQuery('${column.capJavaField}');
</#if>
</#list>
const queryFormRef = ref<ElFormInstance>();
const ${businessName}FormRef = ref<ElFormInstance>();
const initFormData: ${BusinessName}Form = {
<#list columns as column>
<#if column.insert || column.edit>
<#if column.htmlType == "checkbox">
${column.javaField}: [],
<#else>
${column.javaField}: undefined,
</#if>
</#if>
</#list>
}
const data = reactive<PageData<${BusinessName}Form, ${BusinessName}Query>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
<#list columns as column>
<#if column.query>
<#if column.htmlType != "datetime" || column.queryType != "BETWEEN">
${column.javaField}: undefined,
</#if>
</#if>
</#list>
params: {
<#list columns as column>
<#if column.query>
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
${column.javaField}: undefined,
</#if>
</#if>
</#list>
}
},
rules: {
<#list columns as column>
<#if column.insert || column.edit>
<#if column.required>
${column.javaField}: [
{ required: true, message: "${column.columnLabel}不能为空", trigger: <#if column.htmlType == "select" || column.htmlType == "radio" || column.htmlType == "switch" || column.htmlType == "inputNumber">"change"<#else>"blur"</#if> }
],
</#if>
</#if>
</#list>
}
});
const { queryParams, form, rules } = toRefs(data);
const { ids, single, multiple, handleSelectionChange } = useTableSelection<${BusinessName}VO>(item => item.${pkColumn.javaField});
const { dialog, resetForm: reset, openDialog, showDialog, closeDialog } = useFormDialog({
form,
formRef: ${businessName}FormRef,
initialFormData: initFormData
});
/** 查询${functionName}列表 */
const getList = async () => {
await withLoading(async () => {
<#if needAddDateRange>
let params = queryParams.value;
<#list columns as column>
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
params = apply${column.capJavaField}DateRange(params);
</#if>
</#list>
const res = await list${BusinessName}(params);
<#else>
const res = await list${BusinessName}(queryParams.value);
</#if>
${businessName}List.value = res.data?.rows;
total.value = res.data?.total;
});
};
/** 取消按钮 */
const cancel = () => {
reset();
closeDialog();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
const { resetQuery } = useSearchReset({
queryFormRef,
queryParams,
pageNumKey: 'pageNum',
pageSizeKey: 'pageSize',
initialPageSize: 10,
resetExtras: () => {
<#list columns as column>
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
reset${column.capJavaField}DateRange();
</#if>
</#list>
},
afterReset: () => {
handleQuery();
}
});
/** 新增按钮操作 */
const handleAdd = () => {
openDialog('添加${functionName}');
};
/** 修改按钮操作 */
const handleUpdate = async (row?: Partial<${BusinessName}VO>) => {
reset();
const _${pkColumn.javaField} = row?.${pkColumn.javaField} || ids.value[0];
const res = await get${BusinessName}(_${pkColumn.javaField});
Object.assign(form.value, res.data);
<#list columns as column>
<#if column.htmlType == "checkbox">
form.value.${column.javaField} = form.value.${column.javaField}.split(",");
</#if>
</#list>
showDialog('修改${functionName}');
};
/** 提交按钮 */
const submitForm = () => {
${businessName}FormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
<#list columns as column>
<#if column.htmlType == "checkbox">
form.value.${column.javaField} = form.value.${column.javaField}.join(",");
</#if>
</#list>
if (form.value.${pkColumn.javaField}) {
await update${BusinessName}(form.value).finally(() => (buttonLoading.value = false));
} else {
await add${BusinessName}(form.value).finally(() => (buttonLoading.value = false));
}
modal.msgSuccess('操作成功');
closeDialog();
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: Partial<${BusinessName}VO>) => {
const _${pkColumn.javaField}s = row?.${pkColumn.javaField} || ids.value;
await modal.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?');
await del${BusinessName}(_${pkColumn.javaField}s);
modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
<#if enableExport>
const handleExport = () => {
requestDownload(
'${moduleName}/${businessName}/export',
{
...queryParams.value
},
`${businessName}_${r'${new Date().getTime()}'}.xlsx`
);
};
</#if>
<#if enableStatus>
/** 状态修改 */
const handleStatusChange = async (row: Partial<${BusinessName}VO>) => {
const text = row.${statusField} === ${statusField}ActiveValue ? '启用' : '停用';
try {
await modal.confirm('确认要"' + text + '"吗?');
await change${BusinessName}Status(row.${pkColumn.javaField}, row.${statusField});
modal.msgSuccess(text + '成功');
} catch (err) {
row.${statusField} = row.${statusField} === ${statusField}ActiveValue ? ${statusField}InactiveValue : ${statusField}ActiveValue;
}
};
</#if>
<#if enableSort>
/** 排序调整 */
const handleSortChange = async (row: Partial<${BusinessName}VO>) => {
try {
await update${BusinessName}Sort(row.${pkColumn.javaField}, row.${sortField});
modal.msgSuccess('排序更新成功');
} catch (err) {
await getList();
}
};
</#if>
onMounted(() => {
getList();
});
</script>
@@ -0,0 +1,50 @@
import type { BaseEntity<#if !table.tree>, PageQuery</#if> } from '@/api/types';
export interface ${BusinessName}VO {
<#list columns as column>
<#if column.list>
/**
* ${column.columnComment}
*/
${column.javaField}: ${column.tsType};
<#if column.htmlType == "imageUpload">
/**
* ${column.columnComment}Url
*/
${column.javaField}Url: string;
</#if>
</#if>
</#list>
<#if table.tree>
/**
* 子对象
*/
children: ${BusinessName}VO[];
</#if>
}
export interface ${BusinessName}Form extends BaseEntity {
<#list columns as column>
<#if column.insert || column.edit>
/**
* ${column.columnComment}
*/
${column.javaField}?: ${column.tsType};
</#if>
</#list>
}
export interface ${BusinessName}Query<#if !table.tree> extends PageQuery</#if> {
<#list columns as column>
<#if column.query>
/**
* ${column.columnComment}
*/
${column.javaField}?: ${column.tsType};
</#if>
</#list>
/**
* 日期范围参数
*/
params?: any;
}
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${packageName}.mapper.${ClassName}Mapper">
</mapper>