Commit c2f9bad3ad745713a665b718501cb7b3c75922ce

Authored by jason
2 parents 8be3a3f8 e7be2a03

Merge remote-tracking branch 'origin/develop' into develop

Showing 39 changed files with 923 additions and 852 deletions
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/enums/DbTypeEnum.java
... ... @@ -60,6 +60,12 @@ public enum DbTypeEnum {
60 60 * 人大金仓
61 61 */
62 62 KINGBASE_ES(DbType.KINGBASE_ES, "KingbaseES", "POSITION('#{value}' IN #{column}) <> 0"),
  63 +
  64 + /**
  65 + * OceanBase
  66 + */
  67 + OCEAN_BASE(DbType.OCEAN_BASE, "OceanBase", "FIND_IN_SET('#{value}', #{column}) <> 0")
  68 +
63 69 ;
64 70  
65 71 public static final Map<String, DbTypeEnum> MAP_BY_NAME = Arrays.stream(values())
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java
... ... @@ -100,6 +100,10 @@ public class BpmModelMetaInfoVO {
100 100 @Schema(description = "任务后置通知设置", example = "{}")
101 101 private HttpRequestSetting taskAfterTriggerSetting;
102 102  
  103 + @Schema(description = "自定义打印模板设置", example = "{}")
  104 + @Valid
  105 + private PrintTemplateSetting printTemplateSetting;
  106 +
103 107 @Schema(description = "流程 ID 规则")
104 108 @Data
105 109 @Valid
... ... @@ -180,4 +184,17 @@ public class BpmModelMetaInfoVO {
180 184  
181 185 }
182 186  
  187 + @Schema(description = "自定义打印模板设置")
  188 + @Data
  189 + public static class PrintTemplateSetting {
  190 +
  191 + @Schema(description = "是否自定义打印模板", example = "false")
  192 + @NotNull(message = "是否自定义打印模板不能为空")
  193 + private Boolean enable;
  194 +
  195 + @Schema(description = "打印模板", example = "<p></p>")
  196 + private String template;
  197 +
  198 + }
  199 +
183 200 }
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
... ... @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
8 8 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
  9 +import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
9 10 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
10 11 import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
11 12 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
... ... @@ -26,6 +27,7 @@ import jakarta.validation.Valid;
26 27 import org.flowable.engine.history.HistoricProcessInstance;
27 28 import org.flowable.engine.repository.ProcessDefinition;
28 29 import org.flowable.task.api.Task;
  30 +import org.flowable.task.api.history.HistoricTaskInstance;
29 31 import org.springframework.security.access.prepost.PreAuthorize;
30 32 import org.springframework.validation.annotation.Validated;
31 33 import org.springframework.web.bind.annotation.*;
... ... @@ -34,9 +36,11 @@ import java.util.List;
34 36 import java.util.Map;
35 37 import java.util.Set;
36 38  
  39 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37 40 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
38 41 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
39 42 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  43 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS;
40 44  
41 45 @Tag(name = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请”
42 46 @RestController
... ... @@ -192,8 +196,30 @@ public class BpmProcessInstanceController {
192 196 @GetMapping("/get-bpmn-model-view")
193 197 @Operation(summary = "获取流程实例的 BPMN 模型视图", description = "在【流程详细】界面中,进行调用")
194 198 @Parameter(name = "id", description = "流程实例的编号", required = true)
195   - public CommonResult<BpmProcessInstanceBpmnModelViewRespVO> getProcessInstanceBpmnModelView(@RequestParam(value = "id") String id) {
  199 + public CommonResult<BpmProcessInstanceBpmnModelViewRespVO> getProcessInstanceBpmnModelView(
  200 + @RequestParam(value = "id") String id) {
196 201 return success(processInstanceService.getProcessInstanceBpmnModelView(id));
197 202 }
198 203  
  204 + @GetMapping("/get-print-data")
  205 + @Operation(summary = "获得流程实例的打印数据")
  206 + @Parameter(name = "id", description = "流程实例的编号", required = true)
  207 + @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
  208 + public CommonResult<BpmProcessPrintDataRespVO> getProcessInstancePrintData(
  209 + @RequestParam("processInstanceId") String processInstanceId) {
  210 + HistoricProcessInstance historicProcessInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
  211 + if (historicProcessInstance == null) {
  212 + throw exception(PROCESS_INSTANCE_NOT_EXISTS);
  213 + }
  214 + AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(historicProcessInstance.getStartUserId()));
  215 + DeptRespDTO dept = deptApi.getDept(startUser.getDeptId());
  216 + List<HistoricTaskInstance> tasks = taskService.getFinishedTaskListByProcessInstanceIdWithoutCancel(processInstanceId);
  217 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  218 + convertSet(tasks, item -> Long.valueOf(item.getAssignee())));
  219 + return success(BpmProcessInstanceConvert.INSTANCE.buildProcessInstancePrintData(historicProcessInstance,
  220 + processDefinitionService.getProcessDefinitionInfo(historicProcessInstance.getProcessDefinitionId()),
  221 + tasks, userMap,
  222 + new UserSimpleBaseVO().setNickname(startUser.getNickname()).setDeptName(dept.getName())));
  223 + }
  224 +
199 225 }
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessPrintDataRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +@Schema(description = "管理后台 - 流程实例的打印数据 Response VO")
  9 +@Data
  10 +public class BpmProcessPrintDataRespVO {
  11 +
  12 + @Schema(description = "流程实例数据")
  13 + private BpmProcessInstanceRespVO processInstance;
  14 +
  15 + @Schema(description = "是否开启自定义打印模板", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  16 + private Boolean printTemplateEnable;
  17 +
  18 + @Schema(description = "自定义打印模板 HTML")
  19 + private String printTemplateHtml;
  20 +
  21 + @Schema(description = "审批任务列表")
  22 + private List<Task> tasks;
  23 +
  24 + @Schema(description = "流程任务")
  25 + @Data
  26 + public static class Task {
  27 +
  28 + @Schema(description = "流程任务的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  29 + private String id;
  30 +
  31 + @Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
  32 + private String name;
  33 +
  34 + @Schema(description = "签名 URL", example = "https://www.iocoder.cn/sign.png")
  35 + private String signPicUrl;
  36 +
  37 + @Schema(description = "任务描述", requiredMode = Schema.RequiredMode.REQUIRED)
  38 + private String description; // 该字段由后端拼接
  39 +
  40 + }
  41 +
  42 +}
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
1 1 package cn.iocoder.yudao.module.bpm.convert.task;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.date.DateUtil;
4 5 import cn.hutool.core.util.StrUtil;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 7 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
7 8 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
  9 +import cn.iocoder.yudao.framework.common.util.date.DateUtils;
8 10 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
9 11 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 12 import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
  13 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO;
11 14 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
12 15 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
13 16 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO;
14 17 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceBpmnModelViewRespVO;
15 18 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
  19 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessPrintDataRespVO;
16 20 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
17 21 import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
18 22 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
19 23 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
20 24 import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
  25 +import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
  26 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
21 27 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
22 28 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
23 29 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
... ... @@ -35,10 +41,7 @@ import org.mapstruct.Mapping;
35 41 import org.mapstruct.MappingTarget;
36 42 import org.mapstruct.factory.Mappers;
37 43  
38   -import java.util.HashSet;
39   -import java.util.List;
40   -import java.util.Map;
41   -import java.util.Set;
  44 +import java.util.*;
42 45  
43 46 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
44 47 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
... ... @@ -292,4 +295,47 @@ public interface BpmProcessInstanceConvert {
292 295 .setActivityNodes(activityNodes);
293 296 }
294 297  
  298 + default BpmProcessPrintDataRespVO buildProcessInstancePrintData(HistoricProcessInstance historicProcessInstance,
  299 + BpmProcessDefinitionInfoDO processDefinitionInfo,
  300 + List<HistoricTaskInstance> tasks,
  301 + Map<Long, AdminUserRespDTO> userMap,
  302 + UserSimpleBaseVO startUser) {
  303 + BpmModelMetaInfoVO.PrintTemplateSetting printTemplateSetting = processDefinitionInfo.getPrintTemplateSetting();
  304 + BpmProcessPrintDataRespVO printData = new BpmProcessPrintDataRespVO();
  305 + // 打印模板是否开启
  306 + printData.setPrintTemplateEnable(printTemplateSetting != null && Boolean.TRUE.equals(printTemplateSetting.getEnable()));
  307 + // 流程相关数据
  308 + BpmProcessInstanceRespVO processInstance = new BpmProcessInstanceRespVO()
  309 + .setId(historicProcessInstance.getId()).setName(historicProcessInstance.getName())
  310 + .setBusinessKey(historicProcessInstance.getBusinessKey())
  311 + .setStartTime(DateUtils.of(historicProcessInstance.getStartTime()))
  312 + .setEndTime(DateUtils.of(historicProcessInstance.getEndTime()))
  313 + .setStartUser(startUser).setStatus(FlowableUtils.getProcessInstanceStatus(historicProcessInstance))
  314 + .setFormVariables(historicProcessInstance.getProcessVariables())
  315 + .setProcessDefinition(BeanUtils.toBean(processDefinitionInfo, BpmProcessDefinitionRespVO.class));
  316 + printData.setProcessInstance(processInstance);
  317 + // 审批历史
  318 + List<BpmProcessPrintDataRespVO.Task> approveTasks = new ArrayList<>(tasks.size());
  319 + tasks.forEach(item -> {
  320 + Map<String, Object> taskLocalVariables = item.getTaskLocalVariables();
  321 + BpmProcessPrintDataRespVO.Task approveTask = new BpmProcessPrintDataRespVO.Task();
  322 + approveTask.setName(item.getName());
  323 + approveTask.setId(item.getId());
  324 + approveTask.setSignPicUrl((String) taskLocalVariables.get(BpmnVariableConstants.TASK_SIGN_PIC_URL));
  325 + approveTask.setDescription(StrUtil.format("{} / {} / {} / {} / {}",
  326 + userMap.get(Long.valueOf(item.getAssignee())).getNickname(),
  327 + item.getName(),
  328 + DateUtil.formatDateTime(item.getEndTime()),
  329 + BpmTaskStatusEnum.valueOf((Integer) taskLocalVariables.get(BpmnVariableConstants.TASK_VARIABLE_STATUS)).getName(),
  330 + taskLocalVariables.get(BpmnVariableConstants.TASK_VARIABLE_REASON)));
  331 + approveTasks.add(approveTask);
  332 + });
  333 + printData.setTasks(approveTasks);
  334 + // 自定义模板
  335 + if (printData.getPrintTemplateEnable() && printTemplateSetting != null) {
  336 + printData.setPrintTemplateHtml(printTemplateSetting.getTemplate());
  337 + }
  338 + return printData;
  339 + }
  340 +
295 341 }
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java
... ... @@ -224,4 +224,10 @@ public class BpmProcessDefinitionInfoDO extends BaseDO {
224 224 @TableField(typeHandler = JacksonTypeHandler.class)
225 225 private BpmModelMetaInfoVO.HttpRequestSetting taskAfterTriggerSetting;
226 226  
  227 + /**
  228 + * 自定义打印模板设置
  229 + */
  230 + @TableField(typeHandler = JacksonTypeHandler.class)
  231 + private BpmModelMetaInfoVO.PrintTemplateSetting printTemplateSetting;
  232 +
227 233 }
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
1 1 package cn.iocoder.yudao.module.bpm.enums.task;
2 2  
  3 +import cn.hutool.core.util.ArrayUtil;
3 4 import cn.iocoder.yudao.framework.common.core.ArrayValuable;
4 5 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
5 6 import lombok.AllArgsConstructor;
... ... @@ -47,4 +48,8 @@ public enum BpmProcessInstanceStatusEnum implements ArrayValuable&lt;Integer&gt; {
47 48 APPROVE.getStatus(), REJECT.getStatus(), CANCEL.getStatus());
48 49 }
49 50  
  51 + public static BpmProcessInstanceStatusEnum valueOf(Integer status) {
  52 + return ArrayUtil.firstMatch(item -> item.getStatus().equals(status), values());
  53 + }
  54 +
50 55 }
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java
1 1 package cn.iocoder.yudao.module.bpm.enums.task;
2 2  
  3 +import cn.hutool.core.util.ArrayUtil;
3 4 import cn.hutool.core.util.ObjUtil;
4 5 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
5 6 import lombok.AllArgsConstructor;
... ... @@ -68,4 +69,8 @@ public enum BpmTaskStatusEnum {
68 69 return ObjUtil.equal(status, CANCEL.getStatus());
69 70 }
70 71  
  72 + public static BpmTaskStatusEnum valueOf(Integer status) {
  73 + return ArrayUtil.firstMatch(item -> item.getStatus().equals(status), values());
  74 + }
  75 +
71 76 }
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.task;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.collection.ListUtil;
  5 +import cn.hutool.core.date.DatePattern;
5 6 import cn.hutool.core.date.DateUtil;
6 7 import cn.hutool.core.lang.Assert;
7 8 import cn.hutool.core.map.MapUtil;
... ... @@ -13,6 +14,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
13 14 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
14 15 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
15 16 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
  17 +import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
16 18 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO;
17 19 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
18 20 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
... ... @@ -974,7 +976,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
974 976 status);
975 977 }
976 978  
977   - // 1.3 如果子流程拒绝, 设置其父流程也为拒绝状态且结束父流程
  979 + // 1.3 如果子流程拒绝,设置其父流程也为拒绝状态,且结束父流程
  980 + // 相关问题链接:https://t.zsxq.com/kZhyb
978 981 if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())
979 982 && StrUtil.isNotBlank(instance.getSuperExecutionId())) {
980 983 // 1.3.1 获取父流程实例 并标记为不通过
... ... @@ -984,6 +987,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
984 987  
985 988 // 1.3.2 结束父流程。需要在子流程结束事务提交后执行
986 989 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  990 +
987 991 @Override
988 992 public void afterCompletion(int transactionStatus) {
989 993 // 回滚情况,直接返回
... ... @@ -1043,7 +1047,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
1043 1047 runtimeService.setProcessInstanceName(instance.getProcessInstanceId(), name);
1044 1048 }
1045 1049  
1046   - // 流程前置通知:需要在流程启动后(事务提交后)。variables 已设置。或者放在 PROCESS_STARTED 事件中处理,先放这里。
  1050 + // 流程前置通知:需要在流程启动后(事务提交后),保证 variables 已设置
  1051 + // 相关问题链接:https://t.zsxq.com/DF7Kq
1047 1052 if (ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
1048 1053 return;
1049 1054 }
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
... ... @@ -176,6 +176,14 @@ public interface BpmTaskService {
176 176 */
177 177 List<HistoricActivityInstance> getHistoricActivityListByExecutionId(String executionId);
178 178  
  179 + /**
  180 + * 获得指定流程实例的已完成的流程任务列表,不包含取消状态
  181 + *
  182 + * @param processInstanceId 流程实例的编号
  183 + * @return 流程任务列表
  184 + */
  185 + List<HistoricTaskInstance> getFinishedTaskListByProcessInstanceIdWithoutCancel(String processInstanceId);
  186 +
179 187 // ========== Update 写入相关方法 ==========
180 188  
181 189 /**
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
... ... @@ -492,6 +492,17 @@ public class BpmTaskServiceImpl implements BpmTaskService {
492 492 return historyService.createHistoricActivityInstanceQuery().executionId(executionId).list();
493 493 }
494 494  
  495 + @Override
  496 + public List<HistoricTaskInstance> getFinishedTaskListByProcessInstanceIdWithoutCancel(String processInstanceId) {
  497 + return historyService.createHistoricTaskInstanceQuery()
  498 + .finished()
  499 + .includeTaskLocalVariables()
  500 + .processInstanceId(processInstanceId)
  501 + .taskVariableValueNotEquals(BpmnVariableConstants.TASK_VARIABLE_STATUS,
  502 + BpmTaskStatusEnum.CANCEL.getStatus())
  503 + .orderByHistoricTaskInstanceStartTime().asc().list();
  504 + }
  505 +
495 506 /**
496 507 * 判断指定用户,是否是当前任务的审批人
497 508 *
... ...
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java
... ... @@ -21,9 +21,8 @@ public enum CodegenFrontTypeEnum {
21 21 VUE3_VBEN5_ANTD_SCHEMA(40), // Vue3 VBEN5 + ANTD + schema 模版
22 22 VUE3_VBEN5_ANTD_GENERAL(41), // Vue3 VBEN5 + ANTD 标准模版
23 23  
24   - // TODO @puhui999::50、51 会好点;
25   - VUE3_VBEN5_EP_SCHEMA(42), // Vue3 VBEN5 + EP + schema 模版
26   - VUE3_VBEN5_EP_GENERAL(43), // Vue3 VBEN5 + EP 标准模版
  24 + VUE3_VBEN5_EP_SCHEMA(50), // Vue3 VBEN5 + EP + schema 模版
  25 + VUE3_VBEN5_EP_GENERAL(51), // Vue3 VBEN5 + EP 标准模版
27 26 ;
28 27  
29 28 /**
... ...
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
... ... @@ -343,7 +343,7 @@ public class CodegenEngine {
343 343 filePath = formatFilePath(filePath, bindingMap);
344 344 String content = templateEngine.getTemplate(vmPath).render(bindingMap);
345 345 // 格式化代码
346   - content = prettyCode(content);
  346 + content = prettyCode(content, vmPath);
347 347 result.put(filePath, content);
348 348 }
349 349  
... ... @@ -383,11 +383,14 @@ public class CodegenEngine {
383 383 * 如果不处理,Vue 的 Pretty 格式校验可能会报错
384 384 *
385 385 * @param content 格式化前的代码
  386 + * @param vmPath 模板路径
386 387 * @return 格式化后的代码
387 388 */
388   - private String prettyCode(String content) {
389   - // Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错
390   - content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
  389 + private String prettyCode(String content, String vmPath) {
  390 + // Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错(需要排除 vben5)
  391 + if (!StrUtil.contains(vmPath, "vben5")) {
  392 + content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
  393 + }
391 394 // Vue 界面:去除多的 dateFormatter,只有一个的情况下,说明没使用到
392 395 if (StrUtil.count(content, "dateFormatter") == 1) {
393 396 content = StrUtils.removeLineContains(content, "dateFormatter");
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/api/api.ts.vm
... ... @@ -98,7 +98,7 @@ export function delete${simpleClassName}List(ids: number[]) {
98 98  
99 99 /** 导出${table.classComment} */
100 100 export function export${simpleClassName}(params: any) {
101   - return requestClient.download('${baseURL}/export-excel', params);
  101 + return requestClient.download('${baseURL}/export-excel', { params });
102 102 }
103 103  
104 104 ## 特殊:主子表专属逻辑
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/form.vue.vm
1 1 <script lang="ts" setup>
2   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
3 2 import type { Rule } from 'ant-design-vue/es/form';
  3 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  4 +
  5 +import { computed, ref } from 'vue';
4 6  
5 7 import { useVbenModal } from '@vben/common-ui';
  8 +import { DICT_TYPE } from '@vben/constants';
  9 +import { getDictOptions } from '@vben/hooks';
6 10 import { Tinymce as RichTextarea } from '#/components/tinymce';
7 11 import { ImageUpload, FileUpload } from "#/components/upload";
8 12 import { message, Tabs, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker, TreeSelect } from 'ant-design-vue';
9   -import { DICT_TYPE, getDictOptions } from '#/utils';
10 13 #if($table.templateType == 2)## 树表需要导入这些
11 14 import { get${simpleClassName}List } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
12 15 import { handleTree } from '@vben/utils'
... ... @@ -20,7 +23,6 @@ import { handleTree } from &#39;@vben/utils&#39;
20 23 #end
21 24 #end
22 25  
23   -import { computed, ref } from 'vue';
24 26 import { $t } from '#/locales';
25 27 import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
26 28  
... ... @@ -70,7 +72,7 @@ const getTitle = computed(() =&gt; {
70 72 #end
71 73  
72 74 /** 重置表单 */
73   -const resetForm = () => {
  75 +function resetForm() {
74 76 formData.value = {
75 77 #foreach ($column in $columns)
76 78 #if ($column.createOperation || $column.updateOperation)
... ... @@ -88,7 +90,7 @@ const resetForm = () =&gt; {
88 90 ## 特殊:树表专属逻辑
89 91 #if ( $table.templateType == 2 )
90 92 /** 获得${table.classComment}树 */
91   -const get${simpleClassName}Tree = async () => {
  93 +async function get${simpleClassName}Tree() {
92 94 ${classNameVar}Tree.value = []
93 95 const data = await get${simpleClassName}List({});
94 96 data.unshift({
... ... @@ -147,7 +149,6 @@ const [Modal, modalApi] = useVbenModal({
147 149 emit('success');
148 150 message.success({
149 151 content: $t('ui.actionMessage.operationSuccess'),
150   - key: 'action_process_msg',
151 152 });
152 153 } finally {
153 154 modalApi.unlock();
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm
1 1 <script lang="ts" setup>
2 2 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
3   -import type { VxeTableInstance } from '#/adapter/vxe-table';
  3 +
  4 +import { ref, h, reactive, onMounted, nextTick } from 'vue';
4 5  
5 6 import { Page, useVbenModal } from '@vben/common-ui';
6   -import { cloneDeep, formatDateTime } from '@vben/utils';
  7 +import { DICT_TYPE } from '@vben/constants';
  8 +import { getDictOptions } from '@vben/hooks';
  9 +import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
  10 +import { cloneDeep, downloadFileFromBlobPart, formatDateTime } from '@vben/utils';
7 11 import { Button, message,Tabs,Pagination,Form,RangePicker,DatePicker,Select,Input } from 'ant-design-vue';
8   -import { DictTag } from '#/components/dict-tag';
9   -import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
10 12 import ${simpleClassName}Form from './modules/form.vue';
11 13 import { Download, Plus, RefreshCw, Search, Trash2 } from '@vben/icons';
12 14 import { ContentWrap } from '#/components/content-wrap';
13 15 import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
14   -import { TableToolbar } from '#/components/table-toolbar';
15   -import { useTableToolbar } from '#/hooks';
16 16  
17 17 ## 特殊:主子表专属逻辑
18 18 #if ( $table.templateType == 11 || $table.templateType == 12 )
... ... @@ -23,7 +23,6 @@ import { useTableToolbar } from &#39;#/hooks&#39;;
23 23 #end
24 24 #end
25 25  
26   -import { ref, h, reactive,onMounted,nextTick } from 'vue';
27 26 import { $t } from '#/locales';
28 27 #if (${table.templateType} == 2)## 树表接口
29 28 import { handleTree,isEmpty } from '@vben/utils'
... ... @@ -77,7 +76,7 @@ const queryFormRef = ref() // 搜索的表单
77 76 const exportLoading = ref(false) // 导出的加载中
78 77  
79 78 /** 查询列表 */
80   -const getList = async () => {
  79 +async function getList() {
81 80 loading.value = true
82 81 try {
83 82 const params = cloneDeep(queryParams) as any;
... ... @@ -104,7 +103,7 @@ const getList = async () =&gt; {
104 103 }
105 104  
106 105 /** 搜索按钮操作 */
107   -const handleQuery = () => {
  106 +function handleQuery() {
108 107 #if ( $table.templateType != 2 )
109 108 queryParams.pageNo = 1
110 109 #end
... ... @@ -112,7 +111,7 @@ const handleQuery = () =&gt; {
112 111 }
113 112  
114 113 /** 重置按钮操作 */
115   -const resetQuery = () => {
  114 +function resetQuery() {
116 115 queryFormRef.value.resetFields()
117 116 handleQuery()
118 117 }
... ... @@ -144,14 +143,10 @@ async function handleDelete(row: ${simpleClassName}Api.${simpleClassName}) {
144 143 const hideLoading = message.loading({
145 144 content: $t('ui.actionMessage.deleting', [row.id]),
146 145 duration: 0,
147   - key: 'action_process_msg',
148 146 });
149 147 try {
150   - await delete${simpleClassName}(row.id as number);
151   - message.success({
152   - content: $t('ui.actionMessage.deleteSuccess', [row.id]),
153   - key: 'action_process_msg',
154   - });
  148 + await delete${simpleClassName}(row.id!);
  149 + message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
155 150 await getList();
156 151 } finally {
157 152 hideLoading();
... ... @@ -164,12 +159,11 @@ async function handleDeleteBatch() {
164 159 const hideLoading = message.loading({
165 160 content: $t('ui.actionMessage.deleting'),
166 161 duration: 0,
167   - key: 'action_process_msg',
168 162 });
169 163 try {
170 164 await delete${simpleClassName}List(checkedIds.value);
171 165 checkedIds.value = [];
172   - message.success( $t('ui.actionMessage.deleteSuccess') );
  166 + message.success($t('ui.actionMessage.deleteSuccess'));
173 167 await getList();
174 168 } finally {
175 169 hideLoading();
... ... @@ -187,7 +181,7 @@ function handleRowCheckboxChange({
187 181 #end
188 182  
189 183 /** 导出表格 */
190   -async function onExport() {
  184 +async function handleExport() {
191 185 try {
192 186 exportLoading.value = true;
193 187 const data = await export${simpleClassName}(queryParams);
... ... @@ -200,7 +194,7 @@ try {
200 194 #if (${table.templateType} == 2)
201 195 /** 切换树形展开/收缩状态 */
202 196 const isExpanded = ref(true);
203   -function toggleExpand() {
  197 +function handleExpand() {
204 198 isExpanded.value = !isExpanded.value;
205 199 tableRef.value?.setAllTreeExpand(isExpanded.value);
206 200 }
... ... @@ -303,12 +297,12 @@ onMounted(() =&gt; {
303 297 <!-- 列表 -->
304 298 <ContentWrap title="${table.classComment}">
305 299 <template #extra>
306   - <TableToolbar
  300 + <VbenVxeTableToolbar
307 301 ref="tableToolbarRef"
308 302 v-model:hidden-search="hiddenSearchBar"
309 303 >
310 304 #if (${table.templateType} == 2)
311   - <Button @click="toggleExpand" class="mr-2">
  305 + <Button @click="handleExpand" class="mr-2">
312 306 {{ isExpanded ? '收缩' : '展开' }}
313 307 </Button>
314 308 #end
... ... @@ -326,7 +320,7 @@ onMounted(() =&gt; {
326 320 type="primary"
327 321 class="ml-2"
328 322 :loading="exportLoading"
329   - @click="onExport"
  323 + @click="handleExport"
330 324 v-access:code="['${permissionPrefix}:export']"
331 325 >
332 326 {{ $t('ui.actionTitle.export') }}
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/form_sub_erp.vue.vm
... ... @@ -3,107 +3,109 @@
3 3 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
4 4 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
5 5 <script lang="ts" setup>
6   - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
7   - import type { Rule } from 'ant-design-vue/es/form';
  6 +import type { Rule } from 'ant-design-vue/es/form';
  7 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
8 8  
9   - import { useVbenModal } from '@vben/common-ui';
10   - import { Tinymce as RichTextarea } from '#/components/tinymce';
11   - import { ImageUpload, FileUpload } from "#/components/upload";
12   - import { message, Tabs, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker, TreeSelect } from 'ant-design-vue';
13   - import { DICT_TYPE, getDictOptions } from '#/utils';
  9 +import { computed, ref } from 'vue';
14 10  
15   - import { computed, ref } from 'vue';
16   - import { $t } from '#/locales';
  11 +import { useVbenModal } from '@vben/common-ui';
  12 +import { DICT_TYPE } from '@vben/constants';
  13 +import { getDictOptions } from '@vben/hooks';
  14 +import { cloneDeep, formatDateTime } from '@vben/utils';
  15 +import { Tinymce as RichTextarea } from '#/components/tinymce';
  16 +import { ImageUpload, FileUpload } from "#/components/upload";
  17 +import { message, Tabs, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker, TreeSelect } from 'ant-design-vue';
17 18  
18   - import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  19 +import { $t } from '#/locales';
19 20  
20   - const emit = defineEmits(['success']);
21   - const getTitle = computed(() => {
22   - return formData.value?.id
23   - ? $t('ui.actionTitle.edit', ['${subTable.classComment}'])
24   - : $t('ui.actionTitle.create', ['${subTable.classComment}']);
25   - });
  21 +import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
26 22  
27   - const formRef = ref();
28   - const formData = ref<Partial<${simpleClassName}Api.${subSimpleClassName}>>({
29   - #foreach ($column in $subColumns)
30   - #if ($column.createOperation || $column.updateOperation)
31   - #if ($column.htmlType == "checkbox")
32   - $column.javaField: [],
33   - #else
34   - $column.javaField: undefined,
35   - #end
  23 +const emit = defineEmits(['success']);
  24 +const getTitle = computed(() => {
  25 + return formData.value?.id
  26 + ? $t('ui.actionTitle.edit', ['${subTable.classComment}'])
  27 + : $t('ui.actionTitle.create', ['${subTable.classComment}']);
  28 +});
  29 +
  30 +const formRef = ref();
  31 +const formData = ref<Partial<${simpleClassName}Api.${subSimpleClassName}>>({
  32 + #foreach ($column in $subColumns)
  33 + #if ($column.createOperation || $column.updateOperation)
  34 + #if ($column.htmlType == "checkbox")
  35 + $column.javaField: [],
  36 + #else
  37 + $column.javaField: undefined,
36 38 #end
37 39 #end
38   - });
39   - const rules: Record<string, Rule[]> = {
40   - #foreach ($column in $subColumns)
41   - #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
42   - #set($comment=$column.columnComment)
43   - $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
44   - #end
  40 + #end
  41 +});
  42 +const rules: Record<string, Rule[]> = {
  43 + #foreach ($column in $subColumns)
  44 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  45 + #set($comment=$column.columnComment)
  46 + $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
45 47 #end
46   - };
  48 + #end
  49 +};
  50 +
  51 +const [Modal, modalApi] = useVbenModal({
  52 + async onConfirm() {
  53 + await formRef.value?.validate();
47 54  
48   - const [Modal, modalApi] = useVbenModal({
49   - async onConfirm() {
50   - await formRef.value?.validate();
  55 + modalApi.lock();
  56 + // 提交表单
  57 + const data = formData.value as ${simpleClassName}Api.${subSimpleClassName};
  58 + try {
  59 + await (formData.value?.id ? update${subSimpleClassName}(data) : create${subSimpleClassName}(data));
  60 + // 关闭并提示
  61 + await modalApi.close();
  62 + emit('success');
  63 + message.success({
  64 + content: $t('ui.actionMessage.operationSuccess'),
  65 + });
  66 + } finally {
  67 + modalApi.unlock();
  68 + }
  69 + },
  70 + async onOpenChange(isOpen: boolean) {
  71 + if (!isOpen) {
  72 + resetForm()
  73 + return;
  74 + }
51 75  
  76 + // 加载数据
  77 + let data = modalApi.getData<${simpleClassName}Api.${subSimpleClassName}>();
  78 + if (!data) {
  79 + return;
  80 + }
  81 + if (data.id) {
52 82 modalApi.lock();
53   - // 提交表单
54   - const data = formData.value as ${simpleClassName}Api.${subSimpleClassName};
55 83 try {
56   - await (formData.value?.id ? update${subSimpleClassName}(data) : create${subSimpleClassName}(data));
57   - // 关闭并提示
58   - await modalApi.close();
59   - emit('success');
60   - message.success({
61   - content: $t('ui.actionMessage.operationSuccess'),
62   - key: 'action_process_msg',
63   - });
  84 + data = await get${subSimpleClassName}(data.id);
64 85 } finally {
65 86 modalApi.unlock();
66 87 }
67   - },
68   - async onOpenChange(isOpen: boolean) {
69   - if (!isOpen) {
70   - resetForm()
71   - return;
72   - }
  88 + }
  89 + // 设置到 values
  90 + formData.value = data;
  91 + },
  92 +});
73 93  
74   - // 加载数据
75   - let data = modalApi.getData<${simpleClassName}Api.${subSimpleClassName}>();
76   - if (!data) {
77   - return;
78   - }
79   - if (data.id) {
80   - modalApi.lock();
81   - try {
82   - data = await get${subSimpleClassName}(data.id);
83   - } finally {
84   - modalApi.unlock();
85   - }
86   - }
87   - // 设置到 values
88   - formData.value = data;
89   - },
90   - });
91   -
92   - /** 重置表单 */
93   - const resetForm = () => {
94   - formData.value = {
95   - #foreach ($column in $subColumns)
96   - #if ($column.createOperation || $column.updateOperation)
97   - #if ($column.htmlType == "checkbox")
98   - $column.javaField: [],
99   - #else
100   - $column.javaField: undefined,
101   - #end
  94 +/** 重置表单 */
  95 +function resetForm(){
  96 + formData.value = {
  97 + #foreach ($column in $subColumns)
  98 + #if ($column.createOperation || $column.updateOperation)
  99 + #if ($column.htmlType == "checkbox")
  100 + $column.javaField: [],
  101 + #else
  102 + $column.javaField: undefined,
102 103 #end
103 104 #end
104   - };
105   - formRef.value?.resetFields();
106   - }
  105 + #end
  106 + };
  107 + formRef.value?.resetFields();
  108 +}
107 109 </script>
108 110  
109 111 <template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/form_sub_normal.vue.vm
... ... @@ -5,12 +5,15 @@
5 5 #set ($subClassNameVar = $subClassNameVars.get($subIndex))
6 6 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
7 7 <script lang="ts" setup>
8   - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  8 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
9 9  
10   - import { message, Tabs, Form, Input, Textarea,Button, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker } from 'ant-design-vue';
11   - import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
12   - import { $t } from '#/locales';
13   - import { DICT_TYPE, getDictOptions } from '#/utils';
  10 +import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
  11 +
  12 +import { DICT_TYPE } from '@vben/constants';
  13 +import { getDictOptions } from '@vben/hooks';
  14 +
  15 +import { message, Tabs, Form, Input, Textarea,Button, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker } from 'ant-design-vue';
  16 +import { $t } from '#/locales';
14 17  
15 18 #if ($subTable.subJoinMany) ## 一对多
16 19 import type { VxeTableInstance } from '#/adapter/vxe-table';
... ... @@ -30,13 +33,14 @@ const props = defineProps&lt;{
30 33 #if ($subTable.subJoinMany) ## 一对多
31 34 const list = ref<${simpleClassName}Api.${subSimpleClassName}[]>([]) // 列表的数据
32 35 const tableRef = ref<VxeTableInstance>();
  36 +
33 37 /** 添加${subTable.classComment} */
34   -const onAdd = async () => {
  38 +async function handleAdd() {
35 39 await tableRef.value?.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
36 40 }
37 41  
38 42 /** 删除${subTable.classComment} */
39   -const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  43 +async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
40 44 await tableRef.value?.remove(row);
41 45 }
42 46  
... ... @@ -46,9 +50,11 @@ defineExpose({
46 50 const data = list.value as ${simpleClassName}Api.${subSimpleClassName}[];
47 51 const removeRecords = tableRef.value?.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
48 52 const insertRecords = tableRef.value?.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
49   - return data
50   - .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
51   - ?.concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
  53 + return [
  54 + ...data.filter(
  55 + (row) => !removeRecords.some((removed) => removed.id === row.id),
  56 + ),
  57 + ...insertRecords.map((row: any) => ({ ...row, id: undefined })),
52 58 },
53 59 });
54 60  
... ... @@ -123,25 +129,25 @@ watch(
123 129 #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
124 130 #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
125 131 <vxe-column field="${javaField}" title="${comment}" align="center">
126   - <template #default="{row}">
  132 + <template #default="{ row }">
127 133 <Input v-model:value="row.${javaField}" />
128 134 </template>
129 135 </vxe-column>
130 136 #elseif($column.htmlType == "imageUpload")## 图片上传
131 137 <vxe-column field="${javaField}" title="${comment}" align="center">
132   - <template #default="{row}">
  138 + <template #default="{ row }">
133 139 <ImageUpload v-model:value="row.${javaField}" />
134 140 </template>
135 141 </vxe-column>
136 142 #elseif($column.htmlType == "fileUpload")## 文件上传
137 143 <vxe-column field="${javaField}" title="${comment}" align="center">
138   - <template #default="{row}">
  144 + <template #default="{ row }">
139 145 <FileUpload v-model:value="row.${javaField}" />
140 146 </template>
141 147 </vxe-column>
142 148 #elseif($column.htmlType == "select")## 下拉框
143 149 <vxe-column field="${javaField}" title="${comment}" align="center">
144   - <template #default="{row}">
  150 + <template #default="{ row }">
145 151 <Select v-model:value="row.${javaField}" placeholder="请选择${comment}">
146 152 #if ("" != $dictType)## 有数据字典
147 153 <Select.Option
... ... @@ -159,7 +165,7 @@ watch(
159 165 </vxe-column>
160 166 #elseif($column.htmlType == "checkbox")## 多选框
161 167 <vxe-column field="${javaField}" title="${comment}" align="center">
162   - <template #default="{row}">
  168 + <template #default="{ row }">
163 169 <CheckboxGroup v-model:value="row.${javaField}">
164 170 #if ("" != $dictType)## 有数据字典
165 171 <Checkbox
... ... @@ -177,7 +183,7 @@ watch(
177 183 </vxe-column>
178 184 #elseif($column.htmlType == "radio")## 单选框
179 185 <vxe-column field="${javaField}" title="${comment}" align="center">
180   - <template #default="{row}">
  186 + <template #default="{ row }">
181 187 <RadioGroup v-model:value="row.${javaField}">
182 188 #if ("" != $dictType)## 有数据字典
183 189 <Radio
... ... @@ -195,7 +201,7 @@ watch(
195 201 </vxe-column>
196 202 #elseif($column.htmlType == "datetime")## 时间框
197 203 <vxe-column field="${javaField}" title="${comment}" align="center">
198   - <template #default="{row}">
  204 + <template #default="{ row }">
199 205 <DatePicker
200 206 v-model:value="row.${javaField}"
201 207 :showTime="true"
... ... @@ -206,7 +212,7 @@ watch(
206 212 </vxe-column>
207 213 #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框
208 214 <vxe-column field="${javaField}" title="${comment}" align="center">
209   - <template #default="{row}">
  215 + <template #default="{ row }">
210 216 <Textarea v-model:value="row.${javaField}" />
211 217 </template>
212 218 </vxe-column>
... ... @@ -214,12 +220,12 @@ watch(
214 220 #end
215 221 #end
216 222 <vxe-column field="operation" title="操作" align="center">
217   - <template #default="{row}">
  223 + <template #default="{ row }">
218 224 <Button
219 225 size="small"
220 226 type="link"
221 227 danger
222   - @click="onDelete(row as any)"
  228 + @click="handleDelect(row)"
223 229 v-access:code="['${permissionPrefix}:delete']"
224 230 >
225 231 {{ $t('ui.actionTitle.delete') }}
... ... @@ -228,7 +234,7 @@ watch(
228 234 </vxe-column>
229 235 </vxe-table>
230 236 <div class="flex justify-center mt-4">
231   - <Button :icon="h(Plus)" type="primary" ghost @click="onAdd" v-access:code="['${permissionPrefix}:create']">
  237 + <Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${permissionPrefix}:create']">
232 238 {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
233 239 </Button>
234 240 </div>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/list_sub_erp.vue.vm
... ... @@ -6,48 +6,50 @@
6 6 #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex))
7 7 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
8 8 <script lang="ts" setup>
9   - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
10   - import type { VxeTableInstance } from '#/adapter/vxe-table';
  9 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  10 +import type { VxeTableInstance } from '#/adapter/vxe-table';
11 11  
12   - import { DictTag } from '#/components/dict-tag';
13   - import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
14   - import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
15   - import { reactive,ref, h, nextTick,watch,onMounted } from 'vue';
16   - import { cloneDeep, formatDateTime } from '@vben/utils';
17   - import { ContentWrap } from '#/components/content-wrap';
  12 +import { reactive,ref, h, nextTick,watch,onMounted } from 'vue';
  13 +
  14 +import { DICT_TYPE } from '@vben/constants';
  15 +import { getDictOptions } from '@vben/hooks';
  16 +
  17 +import { DictTag } from '#/components/dict-tag';
  18 +import { getRangePickerDefaultProps } from '#/utils';
  19 +import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
  20 +import { ContentWrap } from '#/components/content-wrap';
18 21  
19 22 #if ($table.templateType == 11) ## erp
20   - import { useVbenModal } from '@vben/common-ui';
21   - import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
22   - import { Tinymce as RichTextarea } from '#/components/tinymce';
23   - import { ImageUpload, FileUpload } from "#/components/upload";
24   - import { message,Button, Tabs,Pagination, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox,RangePicker, DatePicker, TreeSelect } from 'ant-design-vue';
25   - import { Plus, Trash2 } from '@vben/icons';
26   - import { $t } from '#/locales';
27   - import { TableToolbar } from '#/components/table-toolbar';
28   - import { useTableToolbar } from '#/hooks';
  23 +import { useVbenModal } from '@vben/common-ui';
  24 +import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
  25 +import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
  26 +import { Tinymce as RichTextarea } from '#/components/tinymce';
  27 +import { ImageUpload, FileUpload } from "#/components/upload";
  28 +import { message,Button, Tabs,Pagination, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox,RangePicker, DatePicker, TreeSelect } from 'ant-design-vue';
  29 +import { Plus, Trash2 } from '@vben/icons';
  30 +import { $t } from '#/locales';
29 31 #end
30 32  
31 33 #if ($table.templateType == 11) ## erp
32   - import { delete${subSimpleClassName},#if ($deleteBatchEnable) delete${subSimpleClassName}List,#end get${subSimpleClassName}Page } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
33   - import { isEmpty } from '@vben/utils';
34   - #else
35   - #if ($subTable.subJoinMany) ## 一对多
36   - import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
37   - #else
38   - import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
39   - #end
  34 +import { delete${subSimpleClassName},#if ($deleteBatchEnable) delete${subSimpleClassName}List,#end get${subSimpleClassName}Page } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  35 +import { isEmpty } from '@vben/utils';
  36 +#else
  37 +#if ($subTable.subJoinMany) ## 一对多
  38 +import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  39 +#else
  40 +import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  41 +#end
40 42 #end
41 43  
42 44 const props = defineProps<{
43   - ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
  45 + ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
44 46 }>()
45 47  
46 48 #if ($table.templateType == 11) ## erp
47   - const [FormModal, formModalApi] = useVbenModal({
48   - connectedComponent: ${subSimpleClassName}Form,
49   - destroyOnClose: true,
50   - });
  49 +const [FormModal, formModalApi] = useVbenModal({
  50 + connectedComponent: ${subSimpleClassName}Form,
  51 + destroyOnClose: true,
  52 +});
51 53  
52 54 /** 创建${subTable.classComment} */
53 55 function handleCreate() {
... ... @@ -68,14 +70,10 @@ async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
68 70 const hideLoading = message.loading({
69 71 content: $t('ui.actionMessage.deleting', [row.id]),
70 72 duration: 0,
71   - key: 'action_process_msg',
72 73 });
73 74 try {
74   - await delete${subSimpleClassName}(row.id as number);
75   - message.success({
76   - content: $t('ui.actionMessage.deleteSuccess', [row.id]),
77   - key: 'action_process_msg',
78   - });
  75 + await delete${subSimpleClassName}(row.id!);
  76 + message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
79 77 await getList();
80 78 } finally {
81 79 hideLoading();
... ... @@ -88,12 +86,11 @@ async function handleDeleteBatch() {
88 86 const hideLoading = message.loading({
89 87 content: $t('ui.actionMessage.deleting'),
90 88 duration: 0,
91   - key: 'action_process_msg',
92 89 });
93 90 try {
94 91 await delete${subSimpleClassName}List(checkedIds.value);
95 92 checkedIds.value = [];
96   - message.success( $t('ui.actionMessage.deleteSuccess') );
  93 + message.success($t('ui.actionMessage.deleteSuccess'));
97 94 await getList();
98 95 } finally {
99 96 hideLoading();
... ... @@ -111,87 +108,87 @@ function handleRowCheckboxChange({
111 108 #end
112 109 #end
113 110  
114   - const loading = ref(true) // 列表的加载中
115   - const list = ref<${simpleClassName}Api.${subSimpleClassName}[]>([]) // 列表的数据
  111 +const loading = ref(true) // 列表的加载中
  112 +const list = ref<${simpleClassName}Api.${subSimpleClassName}[]>([]) // 列表的数据
116 113 #if ($table.templateType == 11) ## erp
117   - const total = ref(0) // 列表的总页数
  114 +const total = ref(0) // 列表的总页数
118 115 #end
119 116 #if ($table.templateType == 11) ## erp
120   - const queryFormRef = ref() // 搜索的表单
121   - const queryParams = reactive({
122   - pageNo: 1,
123   - pageSize: 10,
124   - #foreach ($column in $subColumns)
125   - #if ($column.listOperation)
126   - #if ($column.listOperationCondition != 'BETWEEN')
127   - $column.javaField: undefined,
128   - #end
129   - #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
130   - $column.javaField: undefined,
131   - #end
132   - #end
  117 +const queryFormRef = ref() // 搜索的表单
  118 +const queryParams = reactive({
  119 + pageNo: 1,
  120 + pageSize: 10,
  121 + #foreach ($column in $subColumns)
  122 + #if ($column.listOperation)
  123 + #if ($column.listOperationCondition != 'BETWEEN')
  124 + $column.javaField: undefined,
133 125 #end
134   - })
  126 + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
  127 + $column.javaField: undefined,
  128 + #end
  129 + #end
  130 + #end
  131 +})
135 132  
136 133 /** 搜索按钮操作 */
137   -const handleQuery = () => {
  134 +function handleQuery() {
138 135 queryParams.pageNo = 1
139 136 getList()
140 137 }
141 138  
142 139 /** 重置按钮操作 */
143   -const resetQuery = () => {
  140 +function resetQuery() {
144 141 queryFormRef.value.resetFields()
145 142 handleQuery()
146 143 }
147 144 #end
148 145 /** 查询列表 */
149   - const getList = async () => {
150   - loading.value = true
151   - try {
152   - if (!props.${subJoinColumn.javaField}){
153   - return []
154   - }
155   - ## 特殊:树表专属逻辑(树不需要分页接口)
156   - #if ($table.templateType == 11) ## erp
157   - const params = cloneDeep(queryParams) as any;
158   - #foreach ($column in $columns)
159   - #if ($column.listOperation)
160   - #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
161   - if (params.${column.javaField} && Array.isArray(params.${column.javaField})) {
162   - params.${column.javaField} = (params.${column.javaField} as string[]).join(',');
163   - }
164   - #end
165   - #end
166   - #end
167   - params.${subJoinColumn.javaField} = props.${subJoinColumn.javaField};
168   - const data = await get${subSimpleClassName}Page(params)
169   - list.value = data.list
170   - total.value = data.total
171   - #else
172   - #if ($subTable.subJoinMany) ## 一对多
173   - list.value = await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
174   - #else
175   - list.value = [await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)];
176   - #end
177   - #end
178   - } finally {
179   - loading.value = false
  146 +async function getList() {
  147 + loading.value = true
  148 + try {
  149 + if (!props.${subJoinColumn.javaField}){
  150 + return []
180 151 }
  152 + ## 特殊:树表专属逻辑(树不需要分页接口)
  153 + #if ($table.templateType == 11) ## erp
  154 + const params = cloneDeep(queryParams) as any;
  155 + #foreach ($column in $columns)
  156 + #if ($column.listOperation)
  157 + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
  158 + if (params.${column.javaField} && Array.isArray(params.${column.javaField})) {
  159 + params.${column.javaField} = (params.${column.javaField} as string[]).join(',');
  160 + }
  161 + #end
  162 + #end
  163 + #end
  164 + params.${subJoinColumn.javaField} = props.${subJoinColumn.javaField};
  165 + const data = await get${subSimpleClassName}Page(params)
  166 + list.value = data.list
  167 + total.value = data.total
  168 + #else
  169 + #if ($subTable.subJoinMany) ## 一对多
  170 + list.value = await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
  171 + #else
  172 + list.value = [await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)];
  173 + #end
  174 + #end
  175 + } finally {
  176 + loading.value = false
181 177 }
  178 +}
182 179  
183   - /** 监听主表的关联字段的变化,加载对应的子表数据 */
184   - watch(
185   - () => props.${subJoinColumn.javaField},
186   - async (val) => {
187   - if (!val) {
188   - return;
189   - }
190   - await nextTick();
191   - await getList()
192   - },
193   - { immediate: true },
194   - );
  180 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  181 +watch(
  182 + () => props.${subJoinColumn.javaField},
  183 + async (val) => {
  184 + if (!val) {
  185 + return;
  186 + }
  187 + await nextTick();
  188 + await getList()
  189 + },
  190 + { immediate: true },
  191 +);
195 192  
196 193 #if ($table.templateType == 11) ## erp
197 194 /** 初始化 */
... ... @@ -292,7 +289,7 @@ onMounted(() =&gt; {
292 289 <!-- 列表 -->
293 290 <ContentWrap title="${table.classComment}">
294 291 <template #extra>
295   - <TableToolbar
  292 + <VbenVxeTableToolbar
296 293 ref="tableToolbarRef"
297 294 v-model:hidden-search="hiddenSearchBar"
298 295 >
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/api/api.ts.vm
1   -import type { PageParam, PageResult } from '@vben/request';
2   -import type { Dayjs } from 'dayjs';
3   -
4   -import { requestClient } from '#/api/request';
5   -#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
6   -
7   -export namespace ${simpleClassName}Api {
8   -## 特殊:主子表专属逻辑
9   -#foreach ($subTable in $subTables)
10   - #set ($index = $foreach.count - 1)
11   - #set ($subSimpleClassName = $subSimpleClassNames.get($index))
12   - #set ($subColumns = $subColumnsList.get($index))##当前字段数组
13   - /** ${subTable.classComment}信息 */
14   - export interface ${subSimpleClassName} {
15   - #foreach ($column in $subColumns)
16   - #if ($column.createOperation || $column.updateOperation)
17   - #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
18   - ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment}
19   - #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
20   - ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: string | Dayjs; // ${column.columnComment}
21   - #else
22   - ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment}
23   - #end
24   - #end
25   - #end
26   - }
27   -
28   -#end
29   - /** ${table.classComment}信息 */
30   - export interface ${simpleClassName} {
31   -#foreach ($column in $columns)
32   -#if ($column.createOperation || $column.updateOperation)
33   -#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
34   - ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment}
35   -#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
36   - ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: string | Dayjs; // ${column.columnComment}
37   -#else
38   - ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment}
39   -#end
40   -#end
41   -#end
42   -#if ( $table.templateType == 2 )
43   - children?: ${simpleClassName}[];
44   -#end
45   -## 特殊:主子表专属逻辑
46   -#if ( $table.templateType == 10 || $table.templateType == 12 )
47   - #foreach ($subTable in $subTables)
48   - #set ($index = $foreach.count - 1)
49   - #set ($subSimpleClassName = $subSimpleClassNames.get($index))
50   - #if ( $subTable.subJoinMany )
51   - ${subSimpleClassName.toLowerCase()}s?: ${subSimpleClassName}[]
52   - #else
53   - ${subSimpleClassName.toLowerCase()}?: ${subSimpleClassName}
54   - #end
55   - #end
56   -#end
57   - }
58   -}
59   -
60   -#if ( $table.templateType != 2 )
61   -/** 查询${table.classComment}分页 */
62   -export function get${simpleClassName}Page(params: PageParam) {
63   - return requestClient.get<PageResult<${simpleClassName}Api.${simpleClassName}>>('${baseURL}/page', { params });
64   -}
65   -#else
66   -/** 查询${table.classComment}列表 */
67   -export function get${simpleClassName}List(params: any) {
68   - return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>('${baseURL}/list', { params });
69   -}
70   -#end
71   -
72   -/** 查询${table.classComment}详情 */
73   -export function get${simpleClassName}(id: number) {
74   - return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/get?id=${id}`);
75   -}
76   -
77   -/** 新增${table.classComment} */
78   -export function create${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
79   - return requestClient.post('${baseURL}/create', data);
80   -}
81   -
82   -/** 修改${table.classComment} */
83   -export function update${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
84   - return requestClient.put('${baseURL}/update', data);
85   -}
86   -
87   -/** 删除${table.classComment} */
88   -export function delete${simpleClassName}(id: number) {
89   - return requestClient.delete(`${baseURL}/delete?id=${id}`);
90   -}
91   -
92   -#if ( $table.templateType != 2 && $deleteBatchEnable)
93   -/** 批量删除${table.classComment} */
94   -export function delete${simpleClassName}List(ids: number[]) {
95   - return requestClient.delete(`${baseURL}/delete-list?ids=${ids.join(',')}`)
96   -}
97   -#end
98   -
99   -/** 导出${table.classComment} */
100   -export function export${simpleClassName}(params: any) {
101   - return requestClient.download('${baseURL}/export-excel', params);
102   -}
103   -
104   -## 特殊:主子表专属逻辑
105   -#foreach ($subTable in $subTables)
106   -#set ($index = $foreach.count - 1)
107   -#set ($subSimpleClassName = $subSimpleClassNames.get($index))
108   -#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
109   -#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
110   -#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
111   -#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
112   -#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
113   -#set ($subClassNameVar = $subClassNameVars.get($index))
114   -
115   -// ==================== 子表($subTable.classComment) ====================
116   -
117   -## 情况一:MASTER_ERP 时,需要分查询页子表
118   -#if ( $table.templateType == 11 )
119   -/** 获得${subTable.classComment}分页 */
120   -export function get${subSimpleClassName}Page(params: PageParam) {
121   - return requestClient.get<PageResult<${simpleClassName}Api.${subSimpleClassName}>>(`${baseURL}/${subSimpleClassName_strikeCase}/page`, { params });
122   -}
123   -## 情况二:非 MASTER_ERP 时,需要列表查询子表
124   -#else
125   - #if ( $subTable.subJoinMany )
126   -/** 获得${subTable.classComment}列表 */
127   -export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
128   - return requestClient.get<${simpleClassName}Api.${subSimpleClassName}[]>(`${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
129   -}
130   - #else
131   -/** 获得${subTable.classComment} */
132   -export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
133   - return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
134   -}
135   - #end
136   -#end
137   -## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作
138   -#if ( $table.templateType == 11 )
139   -/** 新增${subTable.classComment} */
140   -export function create${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
141   - return requestClient.post(`${baseURL}/${subSimpleClassName_strikeCase}/create`, data);
142   -}
143   -
144   -/** 修改${subTable.classComment} */
145   -export function update${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
146   - return requestClient.put(`${baseURL}/${subSimpleClassName_strikeCase}/update`, data);
147   -}
148   -
149   -/** 删除${subTable.classComment} */
150   -export function delete${subSimpleClassName}(id: number) {
151   - return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete?id=${id}`);
152   -}
153   -
154   -#if ($deleteBatchEnable)
155   -/** 批量删除${subTable.classComment} */
156   -export function delete${subSimpleClassName}List(ids: number[]) {
157   - return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete-list?ids=${ids.join(',')}`)
158   -}
159   -#end
160   -
161   -/** 获得${subTable.classComment} */
162   -export function get${subSimpleClassName}(id: number) {
163   - return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`);
164   -}
165   -#end
166   -#end
167   -
  1 +#parse("codegen/vue3_vben5_ele/schema/api/api.ts.vm")
168 2 \ No newline at end of file
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/data.ts.vm
  1 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
1 2 import type { VbenFormSchema } from '#/adapter/form';
2 3 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
3   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  4 +import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
4 5  
5   -import { z } from '#/adapter/form';
6   -import {
7   - DICT_TYPE,
8   - getDictOptions,
9   - getRangePickerDefaultProps,
10   -} from '#/utils';
  6 +import { DICT_TYPE } from '@vben/constants';
  7 +import { getDictOptions } from '@vben/hooks';
11 8 #if(${table.templateType} == 2)## 树表需要导入这些
12 9 import { get${simpleClassName}List } from '#/api/${table.moduleName}/${table.businessName}';
13 10 import { handleTree } from '@vben/utils';
14 11 #end
15 12  
  13 +import { getRangePickerDefaultProps } from '#/utils';
  14 +
16 15 /** 新增/修改的表单 */
17 16 export function useFormSchema(): VbenFormSchema[] {
18 17 return [
... ... @@ -186,7 +185,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
186 185 }
187 186  
188 187 /** 列表的字段 */
189   -export function useGridColumns(): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] {
  188 +export function useGridColumns(): VxeTableGridOptions<${apiName}.${simpleClassName}>['columns'] {
190 189 return [
191 190 #if ($table.templateType != 2 && $deleteBatchEnable)
192 191 { type: 'checkbox', width: 40 },
... ... @@ -389,7 +388,7 @@ export function use${subSimpleClassName}GridFormSchema(): VbenFormSchema[] {
389 388 }
390 389  
391 390 /** 列表的字段 */
392   -export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  391 +export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${apiName}.${subSimpleClassName}>['columns'] {
393 392 return [
394 393 #if ($table.templateType != 2 && $deleteBatchEnable)
395 394 { type: 'checkbox', width: 40 },
... ... @@ -426,7 +425,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions&lt;${sim
426 425 #else
427 426 #if ($subTable.subJoinMany) ## 一对多
428 427 /** 新增/修改列表的字段 */
429   - export function use${subSimpleClassName}GridEditColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  428 + export function use${subSimpleClassName}GridEditColumns(): VxeTableGridOptions<${apiName}.${subSimpleClassName}>['columns'] {
430 429 return [
431 430 #foreach($column in $subColumns)
432 431 #if ($column.createOperation || $column.updateOperation)
... ... @@ -602,4 +601,4 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions&lt;${sim
602 601 }
603 602 #end
604 603 #end
605 604 -#end
  605 +#end
606 606 \ No newline at end of file
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/form.vue.vm
  1 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
1 2 <script lang="ts" setup>
2   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  3 +import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
  4 +
  5 +import { computed, ref } from 'vue';
3 6  
4 7 import { useVbenModal } from '@vben/common-ui';
5   -import { message, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
  8 +
  9 +import { message#if ($table.templateType == 11), Tabs#end } from 'ant-design-vue';
  10 +
  11 +import { useVbenForm } from '#/adapter/form';
  12 +import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  13 +import { $t } from '#/locales';
6 14 ## 特殊:主子表专属逻辑
7 15 #if ( $table.templateType == 10 || $table.templateType == 12 )
8 16 #foreach ($subSimpleClassName in $subSimpleClassNames)
... ... @@ -12,21 +20,15 @@ import { message, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGro
12 20 #end
13 21 #end
14 22  
15   -import { computed, ref } from 'vue';
16   -import { $t } from '#/locales';
17   -import { useVbenForm } from '#/adapter/form';
18   -import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
19   -
20 23 import { useFormSchema } from '../data';
21 24  
22 25 const emit = defineEmits(['success']);
23   -const formData = ref<${simpleClassName}Api.${simpleClassName}>();
  26 +const formData = ref<${apiName}.${simpleClassName}>();
24 27 const getTitle = computed(() => {
25 28 return formData.value?.id
26 29 ? $t('ui.actionTitle.edit', ['${table.classComment}'])
27 30 : $t('ui.actionTitle.create', ['${table.classComment}']);
28 31 });
29   -
30 32 ## 特殊:主子表专属逻辑
31 33 #if ( $table.templateType == 10 || $table.templateType == 12 )
32 34 #if ( $subTables && $subTables.size() > 0 )
... ... @@ -51,7 +53,7 @@ const [Form, formApi] = useVbenForm({
51 53 },
52 54 layout: 'horizontal',
53 55 schema: useFormSchema(),
54   - showDefaultActions: false
  56 + showDefaultActions: false,
55 57 });
56 58  
57 59 const [Modal, modalApi] = useVbenModal({
... ... @@ -60,8 +62,8 @@ const [Modal, modalApi] = useVbenModal({
60 62 if (!valid) {
61 63 return;
62 64 }
63   - ## 特殊:主子表专属逻辑
64   - #if ( $table.templateType == 10 || $table.templateType == 12 )
  65 +## 特殊:主子表专属逻辑
  66 +#if ( $table.templateType == 10 || $table.templateType == 12 )
65 67 #if ( $subTables && $subTables.size() > 0 )
66 68 // 校验子表单
67 69 #foreach ($subTable in $subTables)
... ... @@ -78,12 +80,12 @@ const [Modal, modalApi] = useVbenModal({
78 80 #end
79 81 #end
80 82 #end
81   - #end
  83 +#end
82 84 modalApi.lock();
83 85 // 提交表单
84   - const data = (await formApi.getValues()) as ${simpleClassName}Api.${simpleClassName};
85   - ## 特殊:主子表专属逻辑
86   - #if ( $table.templateType == 10 || $table.templateType == 12 )
  86 + const data = (await formApi.getValues()) as ${apiName}.${simpleClassName};
  87 +## 特殊:主子表专属逻辑
  88 +#if ( $table.templateType == 10 || $table.templateType == 12 )
87 89 #if ( $subTables && $subTables.size() > 0 )
88 90 // 拼接子表的数据
89 91 #foreach ($subTable in $subTables)
... ... @@ -96,13 +98,13 @@ const [Modal, modalApi] = useVbenModal({
96 98 #end
97 99 #end
98 100 #end
99   - #end
  101 +#end
100 102 try {
101 103 await (formData.value?.id ? update${simpleClassName}(data) : create${simpleClassName}(data));
102 104 // 关闭并提示
103 105 await modalApi.close();
104 106 emit('success');
105   - message.success( $t('ui.actionMessage.operationSuccess') );
  107 + message.success($t('ui.actionMessage.operationSuccess'));
106 108 } finally {
107 109 modalApi.unlock();
108 110 }
... ... @@ -113,21 +115,24 @@ const [Modal, modalApi] = useVbenModal({
113 115 return;
114 116 }
115 117 // 加载数据
116   - let data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>();
117   - if (!data) {
  118 + const data = modalApi.getData<${apiName}.${simpleClassName}>();
  119 + if (!data || !data.id) {
  120 +#if (${table.templateType} == 2)## 树表特有
  121 + // 设置上级
  122 + await formApi.setValues(data);
  123 +#end
118 124 return;
119 125 }
120   - if (data.id) {
121   - modalApi.lock();
122   - try {
123   - data = await get${simpleClassName}(data.id);
124   - } finally {
125   - modalApi.unlock();
  126 + modalApi.lock();
  127 + try {
  128 + formData.value = await get${simpleClassName}(data.id);
  129 + // 设置到 values
  130 + if (formData.value) {
  131 + await formApi.setValues(formData.value);
126 132 }
  133 + } finally {
  134 + modalApi.unlock();
127 135 }
128   - // 设置到 values
129   - formData.value = data;
130   - await formApi.setValues(formData.value);
131 136 },
132 137 });
133 138 </script>
... ... @@ -135,8 +140,8 @@ const [Modal, modalApi] = useVbenModal({
135 140 <template>
136 141 <Modal :title="getTitle">
137 142 <Form class="mx-4" />
138   - ## 特殊:主子表专属逻辑
139   - #if ( $table.templateType == 10 || $table.templateType == 12 )
  143 +## 特殊:主子表专属逻辑
  144 +#if ( $table.templateType == 10 || $table.templateType == 12 )
140 145 <!-- 子表的表单 -->
141 146 <Tabs v-model:active-key="subTabsName">
142 147 #foreach ($subTable in $subTables)
... ... @@ -149,6 +154,6 @@ const [Modal, modalApi] = useVbenModal({
149 154 </Tabs.TabPane>
150 155 #end
151 156 </Tabs>
152   - #end
  157 +#end
153 158 </Modal>
154 159 </template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm
  1 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
1 2 <script lang="ts" setup>
2 3 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
3   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  4 +import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
4 5  
5   -import { Page, useVbenModal } from '@vben/common-ui';
6   -import { message,Tabs } from 'ant-design-vue';
7   -import Form from './modules/form.vue';
  6 +import { ref } from 'vue';
8 7  
9   -## 特殊:主子表专属逻辑
10   -#if ( $table.templateType == 11 || $table.templateType == 12 )
11   - #foreach ($subSimpleClassName in $subSimpleClassNames)
12   - #set ($index = $foreach.count - 1)
13   - #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
14   -import ${subSimpleClassName}List from './modules/${subSimpleClassName_strikeCase}-list.vue'
15   - #end
16   -#end
  8 +import {#if ($table.templateType != 2 && $deleteBatchEnable) confirm,#end Page, useVbenModal } from '@vben/common-ui';
  9 +import { downloadFileFromBlobPart#if ($table.templateType != 2 && $deleteBatchEnable), isEmpty#end } from '@vben/utils';
  10 +
  11 +import { message#if ($table.templateType == 11), Tabs#end } from 'ant-design-vue';
17 12  
18   -import { ref, computed } from 'vue';
19   -import { $t } from '#/locales';
20 13 import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
21 14 #if (${table.templateType} == 2)## 树表接口
22   -import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  15 +import {
  16 + delete${simpleClassName},
  17 + export${simpleClassName},
  18 + get${simpleClassName}List,
  19 +} from '#/api/${table.moduleName}/${table.businessName}';
23 20 #else## 标准表接口
24   -import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  21 +import {
  22 + delete${simpleClassName},#if ($deleteBatchEnable)
  23 +
  24 + delete${simpleClassName}List,#end
  25 + export${simpleClassName},
  26 + get${simpleClassName}Page,
  27 +} from '#/api/${table.moduleName}/${table.businessName}';
25 28 #end
26   -import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
  29 +import { $t } from '#/locales';
27 30  
28 31 import { useGridColumns, useGridFormSchema } from './data';
  32 +import Form from './modules/form.vue';
  33 +## 特殊:主子表专属逻辑
  34 +#if ( $table.templateType == 11 || $table.templateType == 12 )
  35 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  36 + #set ($index = $foreach.count - 1)
  37 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  38 +import ${subSimpleClassName}List from './modules/${subSimpleClassName_strikeCase}-list.vue';
  39 + #end
  40 +#end
29 41  
30 42 #if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况
31 43 /** 子表的列表 */
32 44 const subTabsName = ref('$subClassNameVars.get(0)')
33 45 #if ($table.templateType == 11)
34   -const select${simpleClassName} = ref<${simpleClassName}Api.${simpleClassName}>();
  46 +const select${simpleClassName} = ref<${apiName}.${simpleClassName}>();
35 47 #end
36 48 #end
37   -
38 49 const [FormModal, formModalApi] = useVbenModal({
39 50 connectedComponent: Form,
40 51 destroyOnClose: true,
41 52 });
42   -
43 53 #if (${table.templateType} == 2)## 树表特有:控制表格展开收缩
  54 +
44 55 /** 切换树形展开/收缩状态 */
45 56 const isExpanded = ref(true);
46   -function toggleExpand() {
  57 +function handleExpand() {
47 58 isExpanded.value = !isExpanded.value;
48 59 gridApi.grid.setAllTreeExpand(isExpanded.value);
49 60 }
50 61 #end
51 62  
52 63 /** 刷新表格 */
53   -function onRefresh() {
  64 +function handleRefresh() {
54 65 #if ($table.templateType == 12) ## 内嵌情况
55 66 gridApi.reload();
56 67 #else
... ... @@ -60,34 +71,31 @@ function onRefresh() {
60 71  
61 72 /** 创建${table.classComment} */
62 73 function handleCreate() {
63   - formModalApi.setData({}).open();
  74 + formModalApi.setData(null).open();
64 75 }
65   -
66   -/** 编辑${table.classComment} */
67   -function handleEdit(row: ${simpleClassName}Api.${simpleClassName}) {
68   - formModalApi.setData(row).open();
69   -}
70   -
71 76 #if (${table.templateType} == 2)## 树表特有:新增下级
72   -/** 新增下级${table.classComment} */
73   -function handleAppend(row: ${simpleClassName}Api.${simpleClassName}) {
  77 +
  78 +/** 添加下级${table.classComment} */
  79 +function handleAppend(row: ${apiName}.${simpleClassName}) {
74 80 formModalApi.setData({ ${treeParentColumn.javaField}: row.id }).open();
75 81 }
76 82 #end
77 83  
  84 +/** 编辑${table.classComment} */
  85 +function handleEdit(row: ${apiName}.${simpleClassName}) {
  86 + formModalApi.setData(row).open();
  87 +}
  88 +
78 89 /** 删除${table.classComment} */
79   -async function handleDelete(row: ${simpleClassName}Api.${simpleClassName}) {
  90 +async function handleDelete(row: ${apiName}.${simpleClassName}) {
80 91 const hideLoading = message.loading({
81 92 content: $t('ui.actionMessage.deleting', [row.id]),
82   - key: 'action_key_msg',
  93 + duration: 0,
83 94 });
84 95 try {
85   - await delete${simpleClassName}(row.id as number);
86   - message.success({
87   - content: $t('ui.actionMessage.deleteSuccess', [row.id]),
88   - key: 'action_key_msg',
89   - });
90   - onRefresh();
  96 + await delete${simpleClassName}(row.id!);
  97 + message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
  98 + handleRefresh();
91 99 } finally {
92 100 hideLoading();
93 101 }
... ... @@ -96,30 +104,28 @@ async function handleDelete(row: ${simpleClassName}Api.${simpleClassName}) {
96 104 #if ($table.templateType != 2 && $deleteBatchEnable)
97 105 /** 批量删除${table.classComment} */
98 106 async function handleDeleteBatch() {
  107 + await confirm($t('ui.actionMessage.deleteBatchConfirm'));
99 108 const hideLoading = message.loading({
100   - content: $t('ui.actionMessage.deleting'),
101   - key: 'action_key_msg',
  109 + content: $t('ui.actionMessage.deletingBatch'),
  110 + duration: 0,
102 111 });
103 112 try {
104 113 await delete${simpleClassName}List(checkedIds.value);
105 114 checkedIds.value = [];
106   - message.success({
107   - content: $t('ui.actionMessage.deleteSuccess'),
108   - key: 'action_key_msg',
109   - });
110   - onRefresh();
  115 + message.success($t('ui.actionMessage.deleteSuccess'));
  116 + handleRefresh();
111 117 } finally {
112 118 hideLoading();
113 119 }
114 120 }
115 121  
116   -const checkedIds = ref<number[]>([])
  122 +const checkedIds = ref<number[]>([]);
117 123 function handleRowCheckboxChange({
118 124 records,
119 125 }: {
120   - records: ${simpleClassName}Api.${simpleClassName}[];
  126 + records: ${apiName}.${simpleClassName}[];
121 127 }) {
122   - checkedIds.value = records.map((item) => item.id);
  128 + checkedIds.value = records.map((item) => item.id!);
123 129 }
124 130 #end
125 131  
... ... @@ -141,20 +147,11 @@ const [Grid, gridApi] = useVbenVxeGrid({
141 147 height: 'auto',
142 148 #end
143 149 #if (${table.templateType} == 2)## 树表设置
144   - treeConfig: {
145   - parentField: '${treeParentColumn.javaField}',
146   - rowField: 'id',
147   - transform: true,
148   - expandAll: true,
149   - reserve: true,
150   - },
151   - pagerConfig: {
152   - enabled: false,
153   - },
154   -#else## 标准表设置
155 150 pagerConfig: {
156   - enabled: true,
  151 + enabled: false,
157 152 },
  153 +#else## 标准表设置
  154 + keepSource: true,
158 155 #end
159 156 proxyConfig: {
160 157 ajax: {
... ... @@ -184,27 +181,35 @@ const [Grid, gridApi] = useVbenVxeGrid({
184 181 refresh: true,
185 182 search: true,
186 183 },
187   - } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
188   -#if (${table.templateType} == 11 || $deleteBatchEnable)
189   - gridEvents:{
190   - #if(${table.templateType} == 11)
191   - cellClick: ({ row }: { row: ${simpleClassName}Api.${simpleClassName}}) => {
  184 +#if (${table.templateType} == 2)## 树表设置
  185 + treeConfig: {
  186 + parentField: '${treeParentColumn.javaField}',
  187 + rowField: 'id',
  188 + transform: true,
  189 + expandAll: true,
  190 + reserve: true,
  191 + },
  192 +#end
  193 + } as VxeTableGridOptions<${apiName}.${simpleClassName}>,
  194 +#if (${table.templateType} == 11 || (${table.templateType} != 2 && $deleteBatchEnable))
  195 + gridEvents: {
  196 + #if(${table.templateType} == 11)
  197 + cellClick: ({ row }: { row: ${apiName}.${simpleClassName}}) => {
192 198 select${simpleClassName}.value = row;
193 199 },
194   - #end
195   - #if(${table.templateType} != 2 && $deleteBatchEnable)
196   - checkboxAll: handleRowCheckboxChange,
197   - checkboxChange: handleRowCheckboxChange,
198   - #end
199   - }
  200 + #end
  201 + #if (${table.templateType} != 2 && $deleteBatchEnable)
  202 + checkboxAll: handleRowCheckboxChange,
  203 + checkboxChange: handleRowCheckboxChange,
  204 + #end
  205 + },
200 206 #end
201 207 });
202 208 </script>
203 209  
204 210 <template>
205 211 <Page auto-content-height>
206   - <FormModal @success="onRefresh" />
207   -
  212 + <FormModal @success="handleRefresh" />
208 213 #if ($table.templateType == 11) ## erp情况
209 214 <div>
210 215 #end
... ... @@ -228,13 +233,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
228 233 <template #toolbar-tools>
229 234 <TableAction
230 235 :actions="[
231   - #if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
232   - {
233   - label: isExpanded ? '收缩' : '展开',
234   - type: 'primary',
235   - onClick: toggleExpand,
236   - },
237   - #end
238 236 {
239 237 label: $t('ui.actionTitle.create', ['${table.classComment}']),
240 238 type: 'primary',
... ... @@ -242,6 +240,13 @@ const [Grid, gridApi] = useVbenVxeGrid({
242 240 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:create'],
243 241 onClick: handleCreate,
244 242 },
  243 + #if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
  244 + {
  245 + label: isExpanded ? '收缩' : '展开',
  246 + type: 'primary',
  247 + onClick: handleExpand,
  248 + },
  249 + #end
245 250 {
246 251 label: $t('ui.actionTitle.export'),
247 252 type: 'primary',
... ... @@ -255,8 +260,8 @@ const [Grid, gridApi] = useVbenVxeGrid({
255 260 type: 'primary',
256 261 danger: true,
257 262 icon: ACTION_ICON.DELETE,
258   - disabled: isEmpty(checkedIds),
259 263 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:delete'],
  264 + disabled: isEmpty(checkedIds),
260 265 onClick: handleDeleteBatch,
261 266 },
262 267 #end
... ... @@ -297,7 +302,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
297 302 />
298 303 </template>
299 304 </Grid>
300   -
301 305 #if ($table.templateType == 11) ## erp情况
302 306 <!-- 子表的表单 -->
303 307 <Tabs v-model:active-key="subTabsName" class="mt-2">
... ... @@ -314,4 +318,4 @@ const [Grid, gridApi] = useVbenVxeGrid({
314 318 </div>
315 319 #end
316 320 </Page>
317 321 -</template>
  322 +</template>
318 323 \ No newline at end of file
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_erp.vue.vm
... ... @@ -2,8 +2,9 @@
2 2 #set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
3 3 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
4 4 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
5 6 <script lang="ts" setup>
6   - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  7 + import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
7 8  
8 9 import { useVbenModal } from '@vben/common-ui';
9 10 import { message } from 'ant-design-vue';
... ... @@ -16,7 +17,7 @@
16 17 import { use${subSimpleClassName}FormSchema } from '../data';
17 18  
18 19 const emit = defineEmits(['success']);
19   - const formData = ref<${simpleClassName}Api.${subSimpleClassName}>();
  20 + const formData = ref<${apiName}.${subSimpleClassName}>();
20 21 const getTitle = computed(() => {
21 22 return formData.value?.id
22 23 ? $t('ui.actionTitle.edit', ['${subTable.classComment}'])
... ... @@ -45,7 +46,7 @@
45 46  
46 47 modalApi.lock();
47 48 // 提交表单
48   - const data = (await formApi.getValues()) as ${simpleClassName}Api.${subSimpleClassName};
  49 + const data = (await formApi.getValues()) as ${apiName}.${subSimpleClassName};
49 50 data.${subJoinColumn.javaField} = formData.value?.${subJoinColumn.javaField};
50 51 try {
51 52 await (formData.value?.id ? update${subSimpleClassName}(data) : create${subSimpleClassName}(data));
... ... @@ -64,7 +65,7 @@
64 65 }
65 66  
66 67 // 加载数据
67   - let data = modalApi.getData<${simpleClassName}Api.${subSimpleClassName}>();
  68 + let data = modalApi.getData<${apiName}.${subSimpleClassName}>();
68 69 if (!data) {
69 70 return;
70 71 }
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm
... ... @@ -4,10 +4,12 @@
4 4 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
5 5 #set ($subClassNameVar = $subClassNameVars.get($subIndex))
6 6 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  7 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
7 8 <script lang="ts" setup>
8   - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  9 + import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
9 10  
10 11 import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
  12 +
11 13 import { $t } from '#/locales';
12 14  
13 15 #if ($subTable.subJoinMany) ## 一对多
... ... @@ -33,7 +35,7 @@ const props = defineProps&lt;{
33 35 function onActionClick({
34 36 code,
35 37 row,
36   -}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
  38 +}: OnActionClickParams<${apiName}.${subSimpleClassName}>) {
37 39 switch (code) {
38 40 case 'delete': {
39 41 onDelete(row);
... ... @@ -63,20 +65,20 @@ gridOptions: {
63 65  
64 66 /** 添加${subTable.classComment} */
65 67 const onAdd = async () => {
66   - await gridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
  68 + await gridApi.grid.insertAt({} as ${apiName}.${subSimpleClassName}, -1);
67 69 }
68 70  
69 71 /** 删除${subTable.classComment} */
70   -const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  72 +const onDelete = async (row: ${apiName}.${subSimpleClassName}) => {
71 73 await gridApi.grid.remove(row);
72 74 }
73 75  
74 76 /** 提供获取表格数据的方法供父组件调用 */
75 77 defineExpose({
76   - getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
77   - const data = gridApi.grid.getData() as ${simpleClassName}Api.${subSimpleClassName}[];
78   - const removeRecords = gridApi.grid.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
79   - const insertRecords = gridApi.grid.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  78 + getData: (): ${apiName}.${subSimpleClassName}[] => {
  79 + const data = gridApi.grid.getData() as ${apiName}.${subSimpleClassName}[];
  80 + const removeRecords = gridApi.grid.getRemoveRecords() as ${apiName}.${subSimpleClassName}[];
  81 + const insertRecords = gridApi.grid.getInsertRecords() as ${apiName}.${subSimpleClassName}[];
80 82 return data
81 83 .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
82 84 .concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm
... ... @@ -5,9 +5,10 @@
5 5 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
6 6 #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex))
7 7 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  8 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
8 9 <script lang="ts" setup>
9 10 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
10   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  11 +import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
11 12  
12 13 #if ($table.templateType == 11) ## erp
13 14 import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
... ... @@ -51,23 +52,20 @@ function handleCreate() {
51 52 }
52 53  
53 54 /** 编辑${subTable.classComment} */
54   -function handleEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
  55 +function handleEdit(row: ${apiName}.${subSimpleClassName}) {
55 56 formModalApi.setData(row).open();
56 57 }
57 58  
58 59 /** 删除${subTable.classComment} */
59   -async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
  60 +async function handleDelete(row: ${apiName}.${subSimpleClassName}) {
60 61 const hideLoading = message.loading({
61 62 content: $t('ui.actionMessage.deleting', [row.id]),
62   - key: 'action_process_msg',
  63 + duration: 0,
63 64 });
64 65 try {
65   - await delete${subSimpleClassName}(row.id as number);
66   - message.success({
67   - content: $t('ui.actionMessage.deleteSuccess', [row.id]),
68   - key: 'action_key_msg',
69   - });
70   - onRefresh();
  66 + await delete${subSimpleClassName}(row.id!);
  67 + message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
  68 + handleRefresh();
71 69 } finally {
72 70 hideLoading();
73 71 }
... ... @@ -78,16 +76,13 @@ async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
78 76 async function handleDeleteBatch() {
79 77 const hideLoading = message.loading({
80 78 content: $t('ui.actionMessage.deleting'),
81   - key: 'action_key_msg',
  79 + duration: 0,
82 80 });
83 81 try {
84 82 await delete${subSimpleClassName}List(checkedIds.value);
85 83 checkedIds.value = [];
86   - message.success({
87   - content: $t('ui.actionMessage.deleteSuccess', [row.id]),
88   - key: 'action_key_msg',
89   - });
90   - onRefresh();
  84 + message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
  85 + handleRefresh();
91 86 } finally {
92 87 hideLoading();
93 88 }
... ... @@ -97,7 +92,7 @@ const checkedIds = ref&lt;number[]&gt;([])
97 92 function handleRowCheckboxChange({
98 93 records,
99 94 }: {
100   - records: ${simpleClassName}Api.${subSimpleClassName}[];
  95 + records: ${apiName}.${subSimpleClassName}[];
101 96 }) {
102 97 checkedIds.value = records.map((item) => item.id);
103 98 }
... ... @@ -149,7 +144,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
149 144 keyField: 'id',
150 145 isHover: true,
151 146 },
152   - } as VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>,
  147 + } as VxeTableGridOptions<${apiName}.${subSimpleClassName}>,
153 148 #if (${table.templateType} == 11 && $deleteBatchEnable)
154 149 gridEvents:{
155 150 checkboxAll: handleRowCheckboxChange,
... ... @@ -159,7 +154,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
159 154 });
160 155  
161 156 /** 刷新表格 */
162   -async function onRefresh() {
  157 +async function handleRefresh() {
163 158 #if ($table.templateType == 11) ## erp
164 159 await gridApi.query();
165 160 #else
... ... @@ -179,7 +174,7 @@ watch(
179 174 return;
180 175 }
181 176 await nextTick();
182   - await onRefresh()
  177 + await handleRefresh()
183 178 },
184 179 { immediate: true },
185 180 );
... ... @@ -187,7 +182,7 @@ watch(
187 182  
188 183 <template>
189 184 #if ($table.templateType == 11) ## erp
190   - <FormModal @success="onRefresh" />
  185 + <FormModal @success="handleRefresh" />
191 186 <Grid table-title="${subTable.classComment}列表">
192 187 <template #toolbar-tools>
193 188 <TableAction
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/api/api.ts.vm
... ... @@ -98,7 +98,7 @@ export function delete${simpleClassName}List(ids: number[]) {
98 98  
99 99 /** 导出${table.classComment} */
100 100 export function export${simpleClassName}(params: any) {
101   - return requestClient.download('${baseURL}/export-excel', params);
  101 + return requestClient.download('${baseURL}/export-excel', { params });
102 102 }
103 103  
104 104 ## 特殊:主子表专属逻辑
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/form.vue.vm
... ... @@ -3,10 +3,11 @@ import type { ${simpleClassName}Api } from &#39;#/api/${table.moduleName}/${simpleCl
3 3 import type { FormRules } from 'element-plus';
4 4  
5 5 import { useVbenModal } from '@vben/common-ui';
  6 +import { DICT_TYPE } from '@vben/constants';
  7 +import { getDictOptions } from '@vben/hooks';
6 8 import { Tinymce as RichTextarea } from '#/components/tinymce';
7 9 import { ImageUpload, FileUpload } from "#/components/upload";
8 10 import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker, ElTreeSelect } from 'element-plus';
9   -import { DICT_TYPE, getDictOptions } from '#/utils';
10 11 #if($table.templateType == 2)## 树表需要导入这些
11 12 import { get${simpleClassName}List } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
12 13 import { handleTree } from '@vben/utils'
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/index.vue.vm
1 1 <script lang="ts" setup>
2 2 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
3   -import type { VxeTableInstance } from '#/adapter/vxe-table';
  3 +
  4 +import { ref, h, reactive, onMounted, nextTick } from 'vue';
4 5  
5 6 import { Page, useVbenModal } from '@vben/common-ui';
6   -import { cloneDeep, formatDateTime } from '@vben/utils';
  7 +import { DICT_TYPE } from '@vben/constants';
  8 +import { getDictOptions } from '@vben/hooks';
  9 +import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
  10 +import { cloneDeep, downloadFileFromBlobPart, formatDateTime } from '@vben/utils';
7 11 import { ElButton, ElMessage, ElLoading, ElTabs, ElTabPane, ElPagination, ElForm, ElFormItem, ElDatePicker, ElSelect, ElOption, ElInput } from 'element-plus';
8   -import { DictTag } from '#/components/dict-tag';
9   -import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
10 12 import ${simpleClassName}Form from './modules/form.vue';
11 13 import { Download, Plus, RefreshCw, Search, Trash2 } from '@vben/icons';
12 14 import { ContentWrap } from '#/components/content-wrap';
13 15 import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
14   -import { TableToolbar } from '#/components/table-toolbar';
15   -import { useTableToolbar } from '#/hooks';
16 16  
17 17 ## 特殊:主子表专属逻辑
18 18 #if ( $table.templateType == 11 || $table.templateType == 12 )
... ... @@ -23,7 +23,6 @@ import { useTableToolbar } from &#39;#/hooks&#39;;
23 23 #end
24 24 #end
25 25  
26   -import { ref, h, reactive,onMounted,nextTick } from 'vue';
27 26 import { $t } from '#/locales';
28 27 #if (${table.templateType} == 2)## 树表接口
29 28 import { handleTree,isEmpty } from '@vben/utils'
... ... @@ -104,7 +103,7 @@ const getList = async () =&gt; {
104 103 }
105 104  
106 105 /** 搜索按钮操作 */
107   -const handleQuery = () => {
  106 +function handleQuery() {
108 107 #if ( $table.templateType != 2 )
109 108 queryParams.pageNo = 1
110 109 #end
... ... @@ -112,7 +111,7 @@ const handleQuery = () =&gt; {
112 111 }
113 112  
114 113 /** 重置按钮操作 */
115   -const resetQuery = () => {
  114 +function resetQuery() {
116 115 queryFormRef.value.resetFields()
117 116 handleQuery()
118 117 }
... ... @@ -182,7 +181,7 @@ function handleRowCheckboxChange({
182 181 #end
183 182  
184 183 /** 导出表格 */
185   -async function onExport() {
  184 +async function handleExport() {
186 185 try {
187 186 exportLoading.value = true;
188 187 const data = await export${simpleClassName}(queryParams);
... ... @@ -195,7 +194,7 @@ try {
195 194 #if (${table.templateType} == 2)
196 195 /** 切换树形展开/收缩状态 */
197 196 const isExpanded = ref(true);
198   -function toggleExpand() {
  197 +function handleExpand() {
199 198 isExpanded.value = !isExpanded.value;
200 199 tableRef.value?.setAllTreeExpand(isExpanded.value);
201 200 }
... ... @@ -306,7 +305,7 @@ onMounted(() =&gt; {
306 305 v-model:hidden-search="hiddenSearchBar"
307 306 >
308 307 #if (${table.templateType} == 2)
309   - <el-button @click="toggleExpand" class="mr-2">
  308 + <el-button @click="handleExpand" class="mr-2">
310 309 {{ isExpanded ? '收缩' : '展开' }}
311 310 </el-button>
312 311 #end
... ... @@ -324,7 +323,7 @@ onMounted(() =&gt; {
324 323 type="primary"
325 324 class="ml-2"
326 325 :loading="exportLoading"
327   - @click="onExport"
  326 + @click="handleExport"
328 327 v-access:code="['${permissionPrefix}:export']"
329 328 >
330 329 {{ $t('ui.actionTitle.export') }}
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/form_sub_erp.vue.vm
... ... @@ -6,13 +6,15 @@
6 6 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
7 7 import type { FormRules } from 'element-plus';
8 8  
  9 + import { computed, ref, reactive } from 'vue';
  10 +
9 11 import { useVbenModal } from '@vben/common-ui';
  12 + import { DICT_TYPE } from '@vben/constants';
  13 + import { getDictOptions } from '@vben/hooks';
10 14 import { Tinymce as RichTextarea } from '#/components/tinymce';
11 15 import { ImageUpload, FileUpload } from "#/components/upload";
12 16 import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker, ElTreeSelect } from 'element-plus';
13   - import { DICT_TYPE, getDictOptions } from '#/utils';
14 17  
15   - import { computed, ref, reactive } from 'vue';
16 18 import { $t } from '#/locales';
17 19  
18 20 import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/form_sub_normal.vue.vm
... ... @@ -5,12 +5,15 @@
5 5 #set ($subClassNameVar = $subClassNameVars.get($subIndex))
6 6 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
7 7 <script lang="ts" setup>
8   - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  8 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
9 9  
10   - import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElButton, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker } from 'element-plus';
11   - import { computed, ref, reactive, h, onMounted,watch,nextTick } from 'vue';
12   - import { $t } from '#/locales';
13   - import { DICT_TYPE, getDictOptions } from '#/utils';
  10 +import { computed, ref, reactive, h, onMounted,watch,nextTick } from 'vue';
  11 +
  12 +import { DICT_TYPE } from '@vben/constants';
  13 +import { getDictOptions } from '@vben/hooks';
  14 +
  15 +import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElButton, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker } from 'element-plus';
  16 +import { $t } from '#/locales';
14 17  
15 18 #if ($subTable.subJoinMany) ## 一对多
16 19 import type { VxeTableInstance } from '#/adapter/vxe-table';
... ... @@ -31,12 +34,12 @@ const props = defineProps&lt;{
31 34 const list = ref<${simpleClassName}Api.${subSimpleClassName}[]>([]) // 列表的数据
32 35 const tableRef = ref<VxeTableInstance>();
33 36 /** 添加${subTable.classComment} */
34   -const onAdd = async () => {
  37 +async function handleAdd() {
35 38 await tableRef.value?.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
36 39 }
37 40  
38 41 /** 删除${subTable.classComment} */
39   -const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  42 +async function onDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
40 43 await tableRef.value?.remove(row);
41 44 }
42 45  
... ... @@ -46,9 +49,11 @@ defineExpose({
46 49 const data = list.value as ${simpleClassName}Api.${subSimpleClassName}[];
47 50 const removeRecords = tableRef.value?.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
48 51 const insertRecords = tableRef.value?.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
49   - return data
50   - .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
51   - ?.concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
  52 + return [
  53 + ...data.filter(
  54 + (row) => !removeRecords.some((removed) => removed.id === row.id),
  55 + ),
  56 + ...insertRecords.map((row: any) => ({ ...row, id: undefined })),
52 57 },
53 58 });
54 59  
... ... @@ -227,7 +232,7 @@ watch(
227 232 </vxe-column>
228 233 </vxe-table>
229 234 <div class="flex justify-center mt-4">
230   - <el-button :icon="h(Plus)" type="primary" plain @click="onAdd" v-access:code="['${permissionPrefix}:create']">
  235 + <el-button :icon="h(Plus)" type="primary" plain @click="handleAdd" v-access:code="['${permissionPrefix}:create']">
231 236 {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
232 237 </el-button>
233 238 </div>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/list_sub_erp.vue.vm
... ... @@ -9,23 +9,25 @@
9 9 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
10 10 import type { VxeTableInstance } from '#/adapter/vxe-table';
11 11  
  12 + import { reactive,ref, h, nextTick,watch,onMounted } from 'vue';
  13 +
  14 + import { DICT_TYPE } from '@vben/constants';
  15 + import { getDictOptions } from '@vben/hooks';
  16 +
12 17 import { DictTag } from '#/components/dict-tag';
13   - import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
  18 + import { getRangePickerDefaultProps } from '#/utils';
14 19 import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
15   - import { reactive,ref, h, nextTick,watch,onMounted } from 'vue';
16   - import { cloneDeep, formatDateTime } from '@vben/utils';
17 20 import { ContentWrap } from '#/components/content-wrap';
18 21  
19 22 #if ($table.templateType == 11) ## erp
20 23 import { useVbenModal } from '@vben/common-ui';
  24 + import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
21 25 import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
22 26 import { Tinymce as RichTextarea } from '#/components/tinymce';
23 27 import { ImageUpload, FileUpload } from "#/components/upload";
24 28 import { ElMessage, ElLoading, ElButton, ElTabs, ElTabPane, ElPagination, ElForm, ElFormItem, ElDatePicker, ElSelect, ElOption, ElInput } from 'element-plus';
25 29 import { Plus, Trash2 } from '@vben/icons';
26 30 import { $t } from '#/locales';
27   - import { TableToolbar } from '#/components/table-toolbar';
28   - import { useTableToolbar } from '#/hooks';
29 31 #end
30 32  
31 33 #if ($table.templateType == 11) ## erp
... ... @@ -129,64 +131,64 @@ function handleRowCheckboxChange({
129 131 })
130 132  
131 133 /** 搜索按钮操作 */
132   -const handleQuery = () => {
  134 +function handleQuery() {
133 135 queryParams.pageNo = 1
134 136 getList()
135 137 }
136 138  
137 139 /** 重置按钮操作 */
138   -const resetQuery = () => {
  140 +function resetQuery() {
139 141 queryFormRef.value.resetFields()
140 142 handleQuery()
141 143 }
142 144 #end
143   - /** 查询列表 */
144   - const getList = async () => {
145   - loading.value = true
146   - try {
147   - if (!props.${subJoinColumn.javaField}){
148   - return []
149   - }
150   - ## 特殊:树表专属逻辑(树不需要分页接口)
151   - #if ($table.templateType == 11) ## erp
152   - const params = cloneDeep(queryParams) as any;
153   - #foreach ($column in $columns)
154   - #if ($column.listOperation)
155   - #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
156   - if (params.${column.javaField} && Array.isArray(params.${column.javaField})) {
157   - params.${column.javaField} = (params.${column.javaField} as string[]).join(',');
158   - }
159   - #end
160   - #end
161   - #end
162   - params.${subJoinColumn.javaField} = props.${subJoinColumn.javaField};
163   - const data = await get${subSimpleClassName}Page(params)
164   - list.value = data.list
165   - total.value = data.total
166   - #else
167   - #if ($subTable.subJoinMany) ## 一对多
168   - list.value = await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
169   - #else
170   - list.value = [await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)];
171   - #end
172   - #end
173   - } finally {
174   - loading.value = false
  145 +/** 查询列表 */
  146 +async function getList() {
  147 + loading.value = true
  148 + try {
  149 + if (!props.${subJoinColumn.javaField}){
  150 + return []
175 151 }
  152 + ## 特殊:树表专属逻辑(树不需要分页接口)
  153 + #if ($table.templateType == 11) ## erp
  154 + const params = cloneDeep(queryParams) as any;
  155 + #foreach ($column in $columns)
  156 + #if ($column.listOperation)
  157 + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
  158 + if (params.${column.javaField} && Array.isArray(params.${column.javaField})) {
  159 + params.${column.javaField} = (params.${column.javaField} as string[]).join(',');
  160 + }
  161 + #end
  162 + #end
  163 + #end
  164 + params.${subJoinColumn.javaField} = props.${subJoinColumn.javaField};
  165 + const data = await get${subSimpleClassName}Page(params)
  166 + list.value = data.list
  167 + total.value = data.total
  168 + #else
  169 + #if ($subTable.subJoinMany) ## 一对多
  170 + list.value = await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
  171 + #else
  172 + list.value = [await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)];
  173 + #end
  174 + #end
  175 + } finally {
  176 + loading.value = false
176 177 }
  178 +}
177 179  
178   - /** 监听主表的关联字段的变化,加载对应的子表数据 */
179   - watch(
180   - () => props.${subJoinColumn.javaField},
181   - async (val) => {
182   - if (!val) {
183   - return;
184   - }
185   - await nextTick();
186   - await getList()
187   - },
188   - { immediate: true },
189   - );
  180 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  181 +watch(
  182 + () => props.${subJoinColumn.javaField},
  183 + async (val) => {
  184 + if (!val) {
  185 + return;
  186 + }
  187 + await nextTick();
  188 + await getList()
  189 + },
  190 + { immediate: true },
  191 +);
190 192  
191 193 #if ($table.templateType == 11) ## erp
192 194 /** 初始化 */
... ... @@ -290,7 +292,7 @@ onMounted(() =&gt; {
290 292 <!-- 列表 -->
291 293 <ContentWrap title="${table.classComment}">
292 294 <template #extra>
293   - <TableToolbar
  295 + <VbenVxeTableToolbar
294 296 ref="tableToolbarRef"
295 297 v-model:hidden-search="hiddenSearchBar"
296 298 >
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/api/api.ts.vm
  1 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
  2 +#if ( $table.templateType != 2 )
1 3 import type { PageParam, PageResult } from '@vben/request';
  4 +#end
2 5 import type { Dayjs } from 'dayjs';
3 6  
4 7 import { requestClient } from '#/api/request';
5 8 #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
6 9  
7   -export namespace ${simpleClassName}Api {
  10 +export namespace ${apiName} {
8 11 ## 特殊:主子表专属逻辑
9 12 #foreach ($subTable in $subTables)
10 13 #set ($index = $foreach.count - 1)
... ... @@ -60,27 +63,35 @@ export namespace ${simpleClassName}Api {
60 63 #if ( $table.templateType != 2 )
61 64 /** 查询${table.classComment}分页 */
62 65 export function get${simpleClassName}Page(params: PageParam) {
63   - return requestClient.get<PageResult<${simpleClassName}Api.${simpleClassName}>>('${baseURL}/page', { params });
  66 + return requestClient.get<PageResult<${apiName}.${simpleClassName}>>(
  67 + '${baseURL}/page',
  68 + { params },
  69 + );
64 70 }
65 71 #else
66 72 /** 查询${table.classComment}列表 */
67 73 export function get${simpleClassName}List(params: any) {
68   - return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>('${baseURL}/list', { params });
  74 + return requestClient.get<${apiName}.${simpleClassName}[]>(
  75 + '${baseURL}/list',
  76 + { params },
  77 + );
69 78 }
70 79 #end
71 80  
72 81 /** 查询${table.classComment}详情 */
73 82 export function get${simpleClassName}(id: number) {
74   - return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/get?id=${id}`);
  83 + return requestClient.get<${apiName}.${simpleClassName}>(
  84 + `${baseURL}/get?id=${id}`,
  85 + );
75 86 }
76 87  
77 88 /** 新增${table.classComment} */
78   -export function create${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  89 +export function create${simpleClassName}(data: ${apiName}.${simpleClassName}) {
79 90 return requestClient.post('${baseURL}/create', data);
80 91 }
81 92  
82 93 /** 修改${table.classComment} */
83   -export function update${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  94 +export function update${simpleClassName}(data: ${apiName}.${simpleClassName}) {
84 95 return requestClient.put('${baseURL}/update', data);
85 96 }
86 97  
... ... @@ -88,17 +99,19 @@ export function update${simpleClassName}(data: ${simpleClassName}Api.${simpleCla
88 99 export function delete${simpleClassName}(id: number) {
89 100 return requestClient.delete(`${baseURL}/delete?id=${id}`);
90 101 }
91   -
92 102 #if ( $table.templateType != 2 && $deleteBatchEnable)
  103 +
93 104 /** 批量删除${table.classComment} */
94 105 export function delete${simpleClassName}List(ids: number[]) {
95   - return requestClient.delete(`${baseURL}/delete-list?ids=${ids.join(',')}`)
  106 + return requestClient.delete(
  107 + `${baseURL}/delete-list?ids=${ids.join(',')}`,
  108 + );
96 109 }
97 110 #end
98 111  
99 112 /** 导出${table.classComment} */
100 113 export function export${simpleClassName}(params: any) {
101   - return requestClient.download('${baseURL}/export-excel', params);
  114 + return requestClient.download('${baseURL}/export-excel', { params });
102 115 }
103 116  
104 117 ## 特殊:主子表专属逻辑
... ... @@ -118,31 +131,38 @@ export function export${simpleClassName}(params: any) {
118 131 #if ( $table.templateType == 11 )
119 132 /** 获得${subTable.classComment}分页 */
120 133 export function get${subSimpleClassName}Page(params: PageParam) {
121   - return requestClient.get<PageResult<${simpleClassName}Api.${subSimpleClassName}>>(`${baseURL}/${subSimpleClassName_strikeCase}/page`, { params });
  134 + return requestClient.get<PageResult<${apiName}.${subSimpleClassName}>>(
  135 + `${baseURL}/${subSimpleClassName_strikeCase}/page`,
  136 + { params },
  137 + );
122 138 }
123 139 ## 情况二:非 MASTER_ERP 时,需要列表查询子表
124 140 #else
125 141 #if ( $subTable.subJoinMany )
126 142 /** 获得${subTable.classComment}列表 */
127 143 export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
128   - return requestClient.get<${simpleClassName}Api.${subSimpleClassName}[]>(`${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  144 + return requestClient.get<${apiName}.${subSimpleClassName}[]>(
  145 + `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`,
  146 + );
129 147 }
130 148 #else
131 149 /** 获得${subTable.classComment} */
132 150 export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
133   - return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  151 + return requestClient.get<${apiName}.${subSimpleClassName}>(
  152 + `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`,
  153 + );
134 154 }
135 155 #end
136 156 #end
137 157 ## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作
138 158 #if ( $table.templateType == 11 )
139 159 /** 新增${subTable.classComment} */
140   -export function create${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
  160 +export function create${subSimpleClassName}(data: ${apiName}.${subSimpleClassName}) {
141 161 return requestClient.post(`${baseURL}/${subSimpleClassName_strikeCase}/create`, data);
142 162 }
143 163  
144 164 /** 修改${subTable.classComment} */
145   -export function update${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
  165 +export function update${subSimpleClassName}(data: ${apiName}.${subSimpleClassName}) {
146 166 return requestClient.put(`${baseURL}/${subSimpleClassName_strikeCase}/update`, data);
147 167 }
148 168  
... ... @@ -154,13 +174,17 @@ export function delete${subSimpleClassName}(id: number) {
154 174 #if ($deleteBatchEnable)
155 175 /** 批量删除${subTable.classComment} */
156 176 export function delete${subSimpleClassName}List(ids: number[]) {
157   - return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete-list?ids=${ids.join(',')}`)
  177 + return requestClient.delete(
  178 + `${baseURL}/${subSimpleClassName_strikeCase}/delete-list?ids=${ids.join(',')}`,
  179 + );
158 180 }
159 181 #end
160 182  
161 183 /** 获得${subTable.classComment} */
162 184 export function get${subSimpleClassName}(id: number) {
163   - return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`);
  185 + return requestClient.get<${apiName}.${subSimpleClassName}>(
  186 + `${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`,
  187 + );
164 188 }
165 189 #end
166 190 #end
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm
  1 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
1 2 import type { VbenFormSchema } from '#/adapter/form';
2 3 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
3   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  4 +import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
4 5  
5   -import { z } from '#/adapter/form';
6   -import {
7   - DICT_TYPE,
8   - getDictOptions,
9   - getRangePickerDefaultProps,
10   -} from '#/utils';
  6 +import { DICT_TYPE } from '@vben/constants';
  7 +import { getDictOptions } from '@vben/hooks';
11 8 #if(${table.templateType} == 2)## 树表需要导入这些
12 9 import { get${simpleClassName}List } from '#/api/${table.moduleName}/${table.businessName}';
13 10 import { handleTree } from '@vben/utils';
14 11 #end
15 12  
  13 +import { getRangePickerDefaultProps } from '#/utils';
  14 +
16 15 /** 新增/修改的表单 */
17 16 export function useFormSchema(): VbenFormSchema[] {
18 17 return [
... ... @@ -30,7 +29,7 @@ export function useFormSchema(): VbenFormSchema[] {
30 29 label: '上级${table.classComment}',
31 30 component: 'ApiTreeSelect',
32 31 componentProps: {
33   - allowClear: true,
  32 + clearable: true,
34 33 api: async () => {
35 34 const data = await get${simpleClassName}List({});
36 35 data.unshift({
... ... @@ -158,13 +157,13 @@ export function useGridFormSchema(): VbenFormSchema[] {
158 157 #if ($column.htmlType == "input" || $column.htmlType == "textarea" || $column.htmlType == "editor")
159 158 component: 'Input',
160 159 componentProps: {
161   - allowClear: true,
  160 + clearable: true,
162 161 placeholder: '请输入${comment}',
163 162 },
164 163 #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
165 164 component: 'Select',
166 165 componentProps: {
167   - allowClear: true,
  166 + clearable: true,
168 167 #if ("" != $dictType)## 设置了 dictType 数据字典的情况
169 168 options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
170 169 #else## 未设置 dictType 数据字典的情况
... ... @@ -176,7 +175,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
176 175 component: 'RangePicker',
177 176 componentProps: {
178 177 ...getRangePickerDefaultProps(),
179   - allowClear: true,
  178 + clearable: true,
180 179 },
181 180 #end
182 181 },
... ... @@ -186,7 +185,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
186 185 }
187 186  
188 187 /** 列表的字段 */
189   -export function useGridColumns(): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] {
  188 +export function useGridColumns(): VxeTableGridOptions<${apiName}.${simpleClassName}>['columns'] {
190 189 return [
191 190 #if ($table.templateType != 2 && $deleteBatchEnable)
192 191 { type: 'checkbox', width: 40 },
... ... @@ -361,13 +360,13 @@ export function use${subSimpleClassName}GridFormSchema(): VbenFormSchema[] {
361 360 #if ($column.htmlType == "input" || $column.htmlType == "textarea" || $column.htmlType == "editor")
362 361 component: 'Input',
363 362 componentProps: {
364   - allowClear: true,
  363 + clearable: true,
365 364 placeholder: '请输入${comment}',
366 365 },
367 366 #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
368 367 component: 'Select',
369 368 componentProps: {
370   - allowClear: true,
  369 + clearable: true,
371 370 #if ("" != $dictType)## 设置了 dictType 数据字典的情况
372 371 options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
373 372 #else## 未设置 dictType 数据字典的情况
... ... @@ -379,7 +378,7 @@ export function use${subSimpleClassName}GridFormSchema(): VbenFormSchema[] {
379 378 component: 'RangePicker',
380 379 componentProps: {
381 380 ...getRangePickerDefaultProps(),
382   - allowClear: true,
  381 + clearable: true,
383 382 },
384 383 #end
385 384 },
... ... @@ -389,7 +388,7 @@ export function use${subSimpleClassName}GridFormSchema(): VbenFormSchema[] {
389 388 }
390 389  
391 390 /** 列表的字段 */
392   -export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  391 +export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${apiName}.${subSimpleClassName}>['columns'] {
393 392 return [
394 393 #if ($table.templateType != 2 && $deleteBatchEnable)
395 394 { type: 'checkbox', width: 40 },
... ... @@ -426,7 +425,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions&lt;${sim
426 425 #else
427 426 #if ($subTable.subJoinMany) ## 一对多
428 427 /** 新增/修改列表的字段 */
429   - export function use${subSimpleClassName}GridEditColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  428 + export function use${subSimpleClassName}GridEditColumns(): VxeTableGridOptions<${apiName}.${subSimpleClassName}>['columns'] {
430 429 return [
431 430 #foreach($column in $subColumns)
432 431 #if ($column.createOperation || $column.updateOperation)
... ... @@ -602,4 +601,4 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions&lt;${sim
602 601 }
603 602 #end
604 603 #end
605 604 -#end
  605 +#end
606 606 \ No newline at end of file
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/form.vue.vm
  1 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
1 2 <script lang="ts" setup>
2   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  3 +import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
  4 +
  5 +import { computed, ref } from 'vue';
3 6  
4 7 import { useVbenModal } from '@vben/common-ui';
5   -import { ElMessage, ElTabs, ElTabPane, ElCheckbox, ElInput, ElSelect, ElRadioGroup, ElCheckboxGroup, ElDatePicker } from 'element-plus';
  8 +
  9 +import { ElMessage#if ($table.templateType == 11), ElTabs, ElTabPane#end } from 'element-plus';
  10 +
  11 +import { useVbenForm } from '#/adapter/form';
  12 +import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  13 +import { $t } from '#/locales';
6 14 ## 特殊:主子表专属逻辑
7 15 #if ( $table.templateType == 10 || $table.templateType == 12 )
8 16 #foreach ($subSimpleClassName in $subSimpleClassNames)
... ... @@ -12,21 +20,15 @@ import { ElMessage, ElTabs, ElTabPane, ElCheckbox, ElInput, ElSelect, ElRadioGro
12 20 #end
13 21 #end
14 22  
15   -import { computed, ref } from 'vue';
16   -import { $t } from '#/locales';
17   -import { useVbenForm } from '#/adapter/form';
18   -import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
19   -
20 23 import { useFormSchema } from '../data';
21 24  
22 25 const emit = defineEmits(['success']);
23   -const formData = ref<${simpleClassName}Api.${simpleClassName}>();
  26 +const formData = ref<${apiName}.${simpleClassName}>();
24 27 const getTitle = computed(() => {
25 28 return formData.value?.id
26 29 ? $t('ui.actionTitle.edit', ['${table.classComment}'])
27 30 : $t('ui.actionTitle.create', ['${table.classComment}']);
28 31 });
29   -
30 32 ## 特殊:主子表专属逻辑
31 33 #if ( $table.templateType == 10 || $table.templateType == 12 )
32 34 #if ( $subTables && $subTables.size() > 0 )
... ... @@ -51,7 +53,7 @@ const [Form, formApi] = useVbenForm({
51 53 },
52 54 layout: 'horizontal',
53 55 schema: useFormSchema(),
54   - showDefaultActions: false
  56 + showDefaultActions: false,
55 57 });
56 58  
57 59 const [Modal, modalApi] = useVbenModal({
... ... @@ -60,8 +62,8 @@ const [Modal, modalApi] = useVbenModal({
60 62 if (!valid) {
61 63 return;
62 64 }
63   - ## 特殊:主子表专属逻辑
64   - #if ( $table.templateType == 10 || $table.templateType == 12 )
  65 +## 特殊:主子表专属逻辑
  66 +#if ( $table.templateType == 10 || $table.templateType == 12 )
65 67 #if ( $subTables && $subTables.size() > 0 )
66 68 // 校验子表单
67 69 #foreach ($subTable in $subTables)
... ... @@ -78,12 +80,12 @@ const [Modal, modalApi] = useVbenModal({
78 80 #end
79 81 #end
80 82 #end
81   - #end
  83 +#end
82 84 modalApi.lock();
83 85 // 提交表单
84   - const data = (await formApi.getValues()) as ${simpleClassName}Api.${simpleClassName};
85   - ## 特殊:主子表专属逻辑
86   - #if ( $table.templateType == 10 || $table.templateType == 12 )
  86 + const data = (await formApi.getValues()) as ${apiName}.${simpleClassName};
  87 +## 特殊:主子表专属逻辑
  88 +#if ( $table.templateType == 10 || $table.templateType == 12 )
87 89 #if ( $subTables && $subTables.size() > 0 )
88 90 // 拼接子表的数据
89 91 #foreach ($subTable in $subTables)
... ... @@ -96,7 +98,7 @@ const [Modal, modalApi] = useVbenModal({
96 98 #end
97 99 #end
98 100 #end
99   - #end
  101 +#end
100 102 try {
101 103 await (formData.value?.id ? update${simpleClassName}(data) : create${simpleClassName}(data));
102 104 // 关闭并提示
... ... @@ -113,21 +115,24 @@ const [Modal, modalApi] = useVbenModal({
113 115 return;
114 116 }
115 117 // 加载数据
116   - let data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>();
117   - if (!data) {
  118 + const data = modalApi.getData<${apiName}.${simpleClassName}>();
  119 + if (!data || !data.id) {
  120 +#if (${table.templateType} == 2)## 树表特有
  121 + // 设置上级
  122 + await formApi.setValues(data);
  123 +#end
118 124 return;
119 125 }
120   - if (data.id) {
121   - modalApi.lock();
122   - try {
123   - data = await get${simpleClassName}(data.id);
124   - } finally {
125   - modalApi.unlock();
  126 + modalApi.lock();
  127 + try {
  128 + formData.value = await get${simpleClassName}(data.id);
  129 + // 设置到 values
  130 + if (formData.value) {
  131 + await formApi.setValues(formData.value);
126 132 }
  133 + } finally {
  134 + modalApi.unlock();
127 135 }
128   - // 设置到 values
129   - formData.value = data;
130   - await formApi.setValues(formData.value);
131 136 },
132 137 });
133 138 </script>
... ... @@ -135,20 +140,20 @@ const [Modal, modalApi] = useVbenModal({
135 140 <template>
136 141 <Modal :title="getTitle">
137 142 <Form class="mx-4" />
138   - ## 特殊:主子表专属逻辑
139   - #if ( $table.templateType == 10 || $table.templateType == 12 )
  143 +## 特殊:主子表专属逻辑
  144 +#if ( $table.templateType == 10 || $table.templateType == 12 )
140 145 <!-- 子表的表单 -->
141   - <el-tabs v-model="subTabsName">
  146 + <ElTabs v-model="subTabsName">
142 147 #foreach ($subTable in $subTables)
143 148 #set ($index = $foreach.count - 1)
144 149 #set ($subClassNameVar = $subClassNameVars.get($index))
145 150 #set ($subSimpleClassName = $subSimpleClassNames.get($index))
146 151 #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
147   - <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}">
  152 + <ElTabPane name="$subClassNameVar" label="${subTable.classComment}">
148 153 <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData?.id" />
149   - </el-tab-pane>
  154 + </ElTabPane>
150 155 #end
151   - </el-tabs>
152   - #end
  156 + </ElTabs>
  157 +#end
153 158 </Modal>
154 159 </template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm
  1 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
1 2 <script lang="ts" setup>
2 3 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
3   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  4 +import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
4 5  
5   -import { Page, useVbenModal } from '@vben/common-ui';
6   -import { ElMessage, ElTabs, ElTabPane, ElLoading } from 'element-plus';
7   -import Form from './modules/form.vue';
  6 +import { ref } from 'vue';
8 7  
9   -## 特殊:主子表专属逻辑
10   -#if ( $table.templateType == 11 || $table.templateType == 12 )
11   - #foreach ($subSimpleClassName in $subSimpleClassNames)
12   - #set ($index = $foreach.count - 1)
13   - #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
14   -import ${subSimpleClassName}List from './modules/${subSimpleClassName_strikeCase}-list.vue'
15   - #end
16   -#end
  8 +import {#if ($table.templateType != 2 && $deleteBatchEnable) confirm,#end Page, useVbenModal } from '@vben/common-ui';
  9 +import { downloadFileFromBlobPart#if ($table.templateType != 2 && $deleteBatchEnable), isEmpty#end } from '@vben/utils';
  10 +
  11 +import { ElLoading, ElMessage#if ($table.templateType == 11), ElTabs, ElTabPane#end } from 'element-plus';
17 12  
18   -import { ref, computed } from 'vue';
19   -import { $t } from '#/locales';
20 13 import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
21 14 #if (${table.templateType} == 2)## 树表接口
22   -import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  15 +import {
  16 + delete${simpleClassName},
  17 + export${simpleClassName},
  18 + get${simpleClassName}List,
  19 +} from '#/api/${table.moduleName}/${table.businessName}';
23 20 #else## 标准表接口
24   -import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  21 +import {
  22 + delete${simpleClassName},#if ($deleteBatchEnable)
  23 +
  24 + delete${simpleClassName}List,#end
  25 + export${simpleClassName},
  26 + get${simpleClassName}Page,
  27 +} from '#/api/${table.moduleName}/${table.businessName}';
25 28 #end
26   -import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
  29 +import { $t } from '#/locales';
27 30  
28 31 import { useGridColumns, useGridFormSchema } from './data';
  32 +import Form from './modules/form.vue';
  33 +## 特殊:主子表专属逻辑
  34 +#if ( $table.templateType == 11 || $table.templateType == 12 )
  35 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  36 + #set ($index = $foreach.count - 1)
  37 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  38 +import ${subSimpleClassName}List from './modules/${subSimpleClassName_strikeCase}-list.vue';
  39 + #end
  40 +#end
29 41  
30 42 #if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况
31 43 /** 子表的列表 */
32 44 const subTabsName = ref('$subClassNameVars.get(0)')
33 45 #if ($table.templateType == 11)
34   -const select${simpleClassName} = ref<${simpleClassName}Api.${simpleClassName}>();
  46 +const select${simpleClassName} = ref<${apiName}.${simpleClassName}>();
35 47 #end
36 48 #end
37   -
38 49 const [FormModal, formModalApi] = useVbenModal({
39 50 connectedComponent: Form,
40 51 destroyOnClose: true,
41 52 });
42   -
43 53 #if (${table.templateType} == 2)## 树表特有:控制表格展开收缩
  54 +
44 55 /** 切换树形展开/收缩状态 */
45 56 const isExpanded = ref(true);
46   -function toggleExpand() {
  57 +function handleExpand() {
47 58 isExpanded.value = !isExpanded.value;
48 59 gridApi.grid.setAllTreeExpand(isExpanded.value);
49 60 }
50 61 #end
51 62  
52 63 /** 刷新表格 */
53   -function onRefresh() {
  64 +function handleRefresh() {
54 65 #if ($table.templateType == 12) ## 内嵌情况
55 66 gridApi.reload();
56 67 #else
... ... @@ -60,31 +71,30 @@ function onRefresh() {
60 71  
61 72 /** 创建${table.classComment} */
62 73 function handleCreate() {
63   - formModalApi.setData({}).open();
  74 + formModalApi.setData(null).open();
64 75 }
65   -
66   -/** 编辑${table.classComment} */
67   -function handleEdit(row: ${simpleClassName}Api.${simpleClassName}) {
68   - formModalApi.setData(row).open();
69   -}
70   -
71 76 #if (${table.templateType} == 2)## 树表特有:新增下级
72   -/** 新增下级${table.classComment} */
73   -function handleAppend(row: ${simpleClassName}Api.${simpleClassName}) {
  77 +
  78 +/** 添加下级${table.classComment} */
  79 +function handleAppend(row: ${apiName}.${simpleClassName}) {
74 80 formModalApi.setData({ ${treeParentColumn.javaField}: row.id }).open();
75 81 }
76 82 #end
77 83  
  84 +/** 编辑${table.classComment} */
  85 +function handleEdit(row: ${apiName}.${simpleClassName}) {
  86 + formModalApi.setData(row).open();
  87 +}
  88 +
78 89 /** 删除${table.classComment} */
79   -async function handleDelete(row: ${simpleClassName}Api.${simpleClassName}) {
  90 +async function handleDelete(row: ${apiName}.${simpleClassName}) {
80 91 const loadingInstance = ElLoading.service({
81 92 text: $t('ui.actionMessage.deleting', [row.id]),
82   - background: 'rgba(0, 0, 0, 0.7)',
83 93 });
84 94 try {
85   - await delete${simpleClassName}(row.id as number);
  95 + await delete${simpleClassName}(row.id!);
86 96 ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.id]));
87   - onRefresh();
  97 + handleRefresh();
88 98 } finally {
89 99 loadingInstance.close();
90 100 }
... ... @@ -93,27 +103,27 @@ async function handleDelete(row: ${simpleClassName}Api.${simpleClassName}) {
93 103 #if ($table.templateType != 2 && $deleteBatchEnable)
94 104 /** 批量删除${table.classComment} */
95 105 async function handleDeleteBatch() {
  106 + await confirm($t('ui.actionMessage.deleteBatchConfirm'));
96 107 const loadingInstance = ElLoading.service({
97   - text: $t('ui.actionMessage.deleting'),
98   - background: 'rgba(0, 0, 0, 0.7)',
  108 + text: $t('ui.actionMessage.deletingBatch'),
99 109 });
100 110 try {
101 111 await delete${simpleClassName}List(checkedIds.value);
102 112 checkedIds.value = [];
103 113 ElMessage.success($t('ui.actionMessage.deleteSuccess'));
104   - onRefresh();
  114 + handleRefresh();
105 115 } finally {
106 116 loadingInstance.close();
107 117 }
108 118 }
109 119  
110   -const checkedIds = ref<number[]>([])
  120 +const checkedIds = ref<number[]>([]);
111 121 function handleRowCheckboxChange({
112 122 records,
113 123 }: {
114   - records: ${simpleClassName}Api.${simpleClassName}[];
  124 + records: ${apiName}.${simpleClassName}[];
115 125 }) {
116   - checkedIds.value = records.map((item) => item.id);
  126 + checkedIds.value = records.map((item) => item.id!);
117 127 }
118 128 #end
119 129  
... ... @@ -135,20 +145,11 @@ const [Grid, gridApi] = useVbenVxeGrid({
135 145 height: 'auto',
136 146 #end
137 147 #if (${table.templateType} == 2)## 树表设置
138   - treeConfig: {
139   - parentField: '${treeParentColumn.javaField}',
140   - rowField: 'id',
141   - transform: true,
142   - expandAll: true,
143   - reserve: true,
144   - },
145   - pagerConfig: {
146   - enabled: false,
147   - },
148   -#else## 标准表设置
149 148 pagerConfig: {
150   - enabled: true,
  149 + enabled: false,
151 150 },
  151 +#else## 标准表设置
  152 + keepSource: true,
152 153 #end
153 154 proxyConfig: {
154 155 ajax: {
... ... @@ -178,27 +179,35 @@ const [Grid, gridApi] = useVbenVxeGrid({
178 179 refresh: true,
179 180 search: true,
180 181 },
181   - } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
182   -#if (${table.templateType} == 11 || $deleteBatchEnable)
183   - gridEvents:{
184   - #if(${table.templateType} == 11)
185   - cellClick: ({ row }: { row: ${simpleClassName}Api.${simpleClassName}}) => {
  182 +#if (${table.templateType} == 2)## 树表设置
  183 + treeConfig: {
  184 + parentField: '${treeParentColumn.javaField}',
  185 + rowField: 'id',
  186 + transform: true,
  187 + expandAll: true,
  188 + reserve: true,
  189 + },
  190 +#end
  191 + } as VxeTableGridOptions<${apiName}.${simpleClassName}>,
  192 +#if (${table.templateType} == 11 || (${table.templateType} != 2 && $deleteBatchEnable))
  193 + gridEvents: {
  194 + #if(${table.templateType} == 11)
  195 + cellClick: ({ row }: { row: ${apiName}.${simpleClassName}}) => {
186 196 select${simpleClassName}.value = row;
187 197 },
188   - #end
189   - #if(${table.templateType} != 2 && $deleteBatchEnable)
190   - checkboxAll: handleRowCheckboxChange,
191   - checkboxChange: handleRowCheckboxChange,
192   - #end
193   - }
  198 + #end
  199 + #if (${table.templateType} != 2 && $deleteBatchEnable)
  200 + checkboxAll: handleRowCheckboxChange,
  201 + checkboxChange: handleRowCheckboxChange,
  202 + #end
  203 + },
194 204 #end
195 205 });
196 206 </script>
197 207  
198 208 <template>
199 209 <Page auto-content-height>
200   - <FormModal @success="onRefresh" />
201   -
  210 + <FormModal @success="handleRefresh" />
202 211 #if ($table.templateType == 11) ## erp情况
203 212 <div>
204 213 #end
... ... @@ -206,29 +215,22 @@ const [Grid, gridApi] = useVbenVxeGrid({
206 215 #if ($table.templateType == 12) ## 内嵌情况
207 216 <template #expand_content="{ row }">
208 217 <!-- 子表的表单 -->
209   - <el-tabs v-model="subTabsName" class="mx-8">
  218 + <ElTabs v-model="subTabsName" class="mx-8">
210 219 #foreach ($subTable in $subTables)
211 220 #set ($index = $foreach.count - 1)
212 221 #set ($subClassNameVar = $subClassNameVars.get($index))
213 222 #set ($subSimpleClassName = $subSimpleClassNames.get($index))
214 223 #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
215   - <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}">
  224 + <ElTabPane name="$subClassNameVar" label="${subTable.classComment}">
216 225 <${subSimpleClassName}List :${subJoinColumn_strikeCase}="row?.id" />
217   - </el-tab-pane>
  226 + </ElTabPane>
218 227 #end
219   - </el-tabs>
  228 + </ElTabs>
220 229 </template>
221 230 #end
222 231 <template #toolbar-tools>
223 232 <TableAction
224 233 :actions="[
225   - #if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
226   - {
227   - label: isExpanded ? '收缩' : '展开',
228   - type: 'primary',
229   - onClick: toggleExpand,
230   - },
231   - #end
232 234 {
233 235 label: $t('ui.actionTitle.create', ['${table.classComment}']),
234 236 type: 'primary',
... ... @@ -236,6 +238,13 @@ const [Grid, gridApi] = useVbenVxeGrid({
236 238 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:create'],
237 239 onClick: handleCreate,
238 240 },
  241 + #if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
  242 + {
  243 + label: isExpanded ? '收缩' : '展开',
  244 + type: 'primary',
  245 + onClick: handleExpand,
  246 + },
  247 + #end
239 248 {
240 249 label: $t('ui.actionTitle.export'),
241 250 type: 'primary',
... ... @@ -248,8 +257,8 @@ const [Grid, gridApi] = useVbenVxeGrid({
248 257 label: $t('ui.actionTitle.deleteBatch'),
249 258 type: 'danger',
250 259 icon: ACTION_ICON.DELETE,
251   - disabled: isEmpty(checkedIds),
252 260 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:delete'],
  261 + disabled: isEmpty(checkedIds),
253 262 onClick: handleDeleteBatch,
254 263 },
255 264 #end
... ... @@ -262,7 +271,8 @@ const [Grid, gridApi] = useVbenVxeGrid({
262 271 #if (${table.templateType} == 2)## 树表特有:新增下级
263 272 {
264 273 label: '新增下级',
265   - type: 'text',
  274 + type: 'primary',
  275 + link: true,
266 276 icon: ACTION_ICON.ADD,
267 277 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:create'],
268 278 onClick: handleAppend.bind(null, row),
... ... @@ -270,7 +280,8 @@ const [Grid, gridApi] = useVbenVxeGrid({
270 280 #end
271 281 {
272 282 label: $t('common.edit'),
273   - type: 'text',
  283 + type: 'primary',
  284 + link: true,
274 285 icon: ACTION_ICON.EDIT,
275 286 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:update'],
276 287 onClick: handleEdit.bind(null, row),
... ... @@ -278,7 +289,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
278 289 {
279 290 label: $t('common.delete'),
280 291 type: 'danger',
281   - text: true,
  292 + link: true,
282 293 icon: ACTION_ICON.DELETE,
283 294 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:delete'],
284 295 popConfirm: {
... ... @@ -290,21 +301,20 @@ const [Grid, gridApi] = useVbenVxeGrid({
290 301 />
291 302 </template>
292 303 </Grid>
293   -
294 304 #if ($table.templateType == 11) ## erp情况
295 305 <!-- 子表的表单 -->
296   - <el-tabs v-model="subTabsName" class="mt-2">
  306 + <ElTabs v-model="subTabsName" class="mt-2">
297 307 #foreach ($subTable in $subTables)
298 308 #set ($index = $foreach.count - 1)
299 309 #set ($subClassNameVar = $subClassNameVars.get($index))
300 310 #set ($subSimpleClassName = $subSimpleClassNames.get($index))
301 311 #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
302   - <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}">
  312 + <ElTabPane name="$subClassNameVar" label="${subTable.classComment}">
303 313 <${subSimpleClassName}List :${subJoinColumn_strikeCase}="select${simpleClassName}?.id" />
304   - </el-tab-pane>
  314 + </ElTabPane>
305 315 #end
306   - </el-tabs>
  316 + </ElTabs>
307 317 </div>
308 318 #end
309 319 </Page>
310 320 -</template>
  321 +</template>
311 322 \ No newline at end of file
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/form_sub_erp.vue.vm
... ... @@ -2,21 +2,24 @@
2 2 #set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
3 3 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
4 4 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
5 6 <script lang="ts" setup>
6   - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  7 + import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
  8 +
  9 + import { computed, ref } from 'vue';
7 10  
8 11 import { useVbenModal } from '@vben/common-ui';
  12 +
9 13 import { ElMessage } from 'element-plus';
10 14  
11   - import { computed, ref } from 'vue';
12   - import { $t } from '#/locales';
13 15 import { useVbenForm } from '#/adapter/form';
14 16 import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  17 + import { $t } from '#/locales';
15 18  
16 19 import { use${subSimpleClassName}FormSchema } from '../data';
17 20  
18 21 const emit = defineEmits(['success']);
19   - const formData = ref<${simpleClassName}Api.${subSimpleClassName}>();
  22 + const formData = ref<${apiName}.${subSimpleClassName}>();
20 23 const getTitle = computed(() => {
21 24 return formData.value?.id
22 25 ? $t('ui.actionTitle.edit', ['${subTable.classComment}'])
... ... @@ -45,7 +48,7 @@
45 48  
46 49 modalApi.lock();
47 50 // 提交表单
48   - const data = (await formApi.getValues()) as ${simpleClassName}Api.${subSimpleClassName};
  51 + const data = (await formApi.getValues()) as ${apiName}.${subSimpleClassName};
49 52 data.${subJoinColumn.javaField} = formData.value?.${subJoinColumn.javaField};
50 53 try {
51 54 await (formData.value?.id ? update${subSimpleClassName}(data) : create${subSimpleClassName}(data));
... ... @@ -64,7 +67,7 @@
64 67 }
65 68  
66 69 // 加载数据
67   - let data = modalApi.getData<${simpleClassName}Api.${subSimpleClassName}>();
  70 + let data = modalApi.getData<${apiName}.${subSimpleClassName}>();
68 71 if (!data) {
69 72 return;
70 73 }
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/form_sub_normal.vue.vm
... ... @@ -4,10 +4,12 @@
4 4 #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
5 5 #set ($subClassNameVar = $subClassNameVars.get($subIndex))
6 6 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  7 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
7 8 <script lang="ts" setup>
8   - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  9 + import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
9 10  
10 11 import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
  12 +
11 13 import { $t } from '#/locales';
12 14  
13 15 #if ($subTable.subJoinMany) ## 一对多
... ... @@ -33,7 +35,7 @@ const props = defineProps&lt;{
33 35 function onActionClick({
34 36 code,
35 37 row,
36   -}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
  38 +}: OnActionClickParams<${apiName}.${subSimpleClassName}>) {
37 39 switch (code) {
38 40 case 'delete': {
39 41 onDelete(row);
... ... @@ -67,16 +69,16 @@ const onAdd = async () =&gt; {
67 69 }
68 70  
69 71 /** 删除${subTable.classComment} */
70   -const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  72 +const onDelete = async (row: ${apiName}.${subSimpleClassName}) => {
71 73 await gridApi.grid.remove(row);
72 74 }
73 75  
74 76 /** 提供获取表格数据的方法供父组件调用 */
75 77 defineExpose({
76   - getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
77   - const data = gridApi.grid.getData() as ${simpleClassName}Api.${subSimpleClassName}[];
78   - const removeRecords = gridApi.grid.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
79   - const insertRecords = gridApi.grid.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  78 + getData: (): ${apiName}.${subSimpleClassName}[] => {
  79 + const data = gridApi.grid.getData() as ${apiName}.${subSimpleClassName}[];
  80 + const removeRecords = gridApi.grid.getRemoveRecords() as ${apiName}.${subSimpleClassName}[];
  81 + const insertRecords = gridApi.grid.getInsertRecords() as ${apiName}.${subSimpleClassName}[];
80 82 return data
81 83 .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
82 84 .concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm
... ... @@ -5,9 +5,10 @@
5 5 #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
6 6 #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex))
7 7 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  8 +#set ($apiName = "${table.moduleName.substring(0,1).toUpperCase()}${table.moduleName.substring(1)}${simpleClassName}Api")
8 9 <script lang="ts" setup>
9 10 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
10   -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  11 +import type { ${apiName} } from '#/api/${table.moduleName}/${table.businessName}';
11 12  
12 13 #if ($table.templateType == 11) ## erp
13 14 import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
... ... @@ -41,6 +42,19 @@ const [FormModal, formModalApi] = useVbenModal({
41 42 destroyOnClose: true,
42 43 });
43 44  
  45 +/** 刷新表格 */
  46 +async function handleRefresh() {
  47 +#if ($table.templateType == 11) ## erp
  48 + await gridApi.query();
  49 +#else
  50 + #if ($subTable.subJoinMany) ## 一对多
  51 + await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  52 + #else
  53 + await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
  54 + #end
  55 +#end
  56 +}
  57 +
44 58 /** 创建${subTable.classComment} */
45 59 function handleCreate() {
46 60 if (!props.${subJoinColumn.javaField}){
... ... @@ -51,20 +65,19 @@ function handleCreate() {
51 65 }
52 66  
53 67 /** 编辑${subTable.classComment} */
54   -function handleEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
  68 +function handleEdit(row: ${apiName}.${subSimpleClassName}) {
55 69 formModalApi.setData(row).open();
56 70 }
57 71  
58 72 /** 删除${subTable.classComment} */
59   -async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
  73 +async function handleDelete(row: ${apiName}.${subSimpleClassName}) {
60 74 const loadingInstance = ElLoading.service({
61 75 text: $t('ui.actionMessage.deleting', [row.id]),
62   - background: 'rgba(0, 0, 0, 0.7)',
63 76 });
64 77 try {
65   - await delete${subSimpleClassName}(row.id as number);
  78 + await delete${subSimpleClassName}(row.id!);
66 79 ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.id]));
67   - onRefresh();
  80 + handleRefresh();
68 81 } finally {
69 82 loadingInstance.close();
70 83 }
... ... @@ -75,13 +88,12 @@ async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
75 88 async function handleDeleteBatch() {
76 89 const loadingInstance = ElLoading.service({
77 90 text: $t('ui.actionMessage.deleting'),
78   - background: 'rgba(0, 0, 0, 0.7)',
79 91 });
80 92 try {
81 93 await delete${subSimpleClassName}List(checkedIds.value);
82 94 checkedIds.value = [];
83 95 ElMessage.success($t('ui.actionMessage.deleteSuccess'));
84   - onRefresh();
  96 + handleRefresh();
85 97 } finally {
86 98 loadingInstance.close();
87 99 }
... ... @@ -91,7 +103,7 @@ const checkedIds = ref&lt;number[]&gt;([])
91 103 function handleRowCheckboxChange({
92 104 records,
93 105 }: {
94   - records: ${simpleClassName}Api.${subSimpleClassName}[];
  106 + records: ${apiName}.${subSimpleClassName}[];
95 107 }) {
96 108 checkedIds.value = records.map((item) => item.id);
97 109 }
... ... @@ -143,7 +155,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
143 155 keyField: 'id',
144 156 isHover: true,
145 157 },
146   - } as VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>,
  158 + } as VxeTableGridOptions<${apiName}.${subSimpleClassName}>,
147 159 #if (${table.templateType} == 11 && $deleteBatchEnable)
148 160 gridEvents:{
149 161 checkboxAll: handleRowCheckboxChange,
... ... @@ -152,19 +164,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
152 164 #end
153 165 });
154 166  
155   -/** 刷新表格 */
156   -async function onRefresh() {
157   -#if ($table.templateType == 11) ## erp
158   - await gridApi.query();
159   -#else
160   - #if ($subTable.subJoinMany) ## 一对多
161   - await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
162   - #else
163   - await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
164   - #end
165   -#end
166   -}
167   -
168 167 /** 监听主表的关联字段的变化,加载对应的子表数据 */
169 168 watch(
170 169 () => props.${subJoinColumn.javaField},
... ... @@ -173,7 +172,7 @@ watch(
173 172 return;
174 173 }
175 174 await nextTick();
176   - await onRefresh()
  175 + await handleRefresh()
177 176 },
178 177 { immediate: true },
179 178 );
... ... @@ -181,7 +180,7 @@ watch(
181 180  
182 181 <template>
183 182 #if ($table.templateType == 11) ## erp
184   - <FormModal @success="onRefresh" />
  183 + <FormModal @success="handleRefresh" />
185 184 <Grid table-title="${subTable.classComment}列表">
186 185 <template #toolbar-tools>
187 186 <TableAction
... ... @@ -211,7 +210,8 @@ watch(
211 210 :actions="[
212 211 {
213 212 label: $t('common.edit'),
214   - type: 'text',
  213 + type: 'primary',
  214 + link: true,
215 215 icon: ACTION_ICON.EDIT,
216 216 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:update'],
217 217 onClick: handleEdit.bind(null, row),
... ... @@ -219,7 +219,7 @@ watch(
219 219 {
220 220 label: $t('common.delete'),
221 221 type: 'danger',
222   - text: true,
  222 + link: true,
223 223 icon: ACTION_ICON.DELETE,
224 224 auth: ['${table.moduleName}:${simpleClassName_strikeCase}:delete'],
225 225 popConfirm: {
... ...