mirror of
https://gitee.com/yudaocode/yudao-boot-mini.git
synced 2026-03-22 05:27:15 +08:00
Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts: # yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java
This commit is contained in:
@@ -1,39 +1,58 @@
|
|||||||
package cn.iocoder.yudao.framework.common.util.json.databind;
|
package cn.iocoder.yudao.framework.common.util.json.databind;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于时间戳的 LocalDateTime 序列化器
|
* 基于时间戳的 LocalDateTime 序列化器
|
||||||
*
|
*
|
||||||
* @author 老五
|
* @author 老五
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class TimestampLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
|
public class TimestampLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
|
||||||
|
|
||||||
public static final TimestampLocalDateTimeSerializer INSTANCE = new TimestampLocalDateTimeSerializer();
|
public static final TimestampLocalDateTimeSerializer INSTANCE = new TimestampLocalDateTimeSerializer();
|
||||||
|
|
||||||
|
private static final Map<Class<?>, Map<String, Field>> FIELD_CACHE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||||
// 情况一:有 JsonFormat 自定义注解,则使用它。https://github.com/YunaiV/ruoyi-vue-pro/pull/1019
|
// 情况一:有 JsonFormat 自定义注解,则使用它。https://github.com/YunaiV/ruoyi-vue-pro/pull/1019
|
||||||
String fieldName = gen.getOutputContext().getCurrentName();
|
String fieldName = gen.getOutputContext().getCurrentName();
|
||||||
if (fieldName != null) {
|
if (fieldName != null) {
|
||||||
Class<?> clazz = gen.getOutputContext().getCurrentValue().getClass();
|
Object currentValue = gen.getOutputContext().getCurrentValue();
|
||||||
Field field = ReflectUtil.getField(clazz, fieldName);
|
if (currentValue != null) {
|
||||||
JsonFormat[] jsonFormats = field.getAnnotationsByType(JsonFormat.class);
|
Class<?> clazz = currentValue.getClass();
|
||||||
if (jsonFormats.length > 0) {
|
Map<String, Field> fieldMap = FIELD_CACHE.computeIfAbsent(clazz, this::buildFieldMap);
|
||||||
String pattern = jsonFormats[0].pattern();
|
Field field = fieldMap.get(fieldName);
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
// 进一步修复:https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1480
|
||||||
gen.writeString(formatter.format(value));
|
if (field != null && field.isAnnotationPresent(JsonFormat.class)) {
|
||||||
return;
|
JsonFormat jsonFormat = field.getAnnotation(JsonFormat.class);
|
||||||
|
try {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jsonFormat.pattern());
|
||||||
|
gen.writeString(formatter.format(value));
|
||||||
|
return;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("[serialize][({}#{}) 使用 JsonFormat pattern 失败,尝试使用默认的 Long 时间戳]",
|
||||||
|
clazz.getName(), fieldName, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,4 +60,26 @@ public class TimestampLocalDateTimeSerializer extends JsonSerializer<LocalDateTi
|
|||||||
gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
|
gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建字段映射(缓存)
|
||||||
|
*
|
||||||
|
* @param clazz 类
|
||||||
|
* @return 字段映射
|
||||||
|
*/
|
||||||
|
private Map<String, Field> buildFieldMap(Class<?> clazz) {
|
||||||
|
Map<String, Field> fieldMap = new HashMap<>();
|
||||||
|
for (Field field : ReflectUtil.getFields(clazz)) {
|
||||||
|
String fieldName = field.getName();
|
||||||
|
JsonProperty jsonProperty = field.getAnnotation(JsonProperty.class);
|
||||||
|
if (jsonProperty != null) {
|
||||||
|
String value = jsonProperty.value();
|
||||||
|
if (StrUtil.isNotEmpty(value) && ObjUtil.notEqual("\u0000", value)) {
|
||||||
|
fieldName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldMap.put(fieldName, field);
|
||||||
|
}
|
||||||
|
return fieldMap;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno
|
||||||
</description>
|
</description>
|
||||||
<properties>
|
<properties>
|
||||||
<spring-ai.version>1.1.0</spring-ai.version>
|
<spring-ai.version>1.1.2</spring-ai.version>
|
||||||
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud.ai/spring-ai-alibaba -->
|
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud.ai/spring-ai-alibaba -->
|
||||||
<alibaba-ai.version>1.1.0.0-RC1</alibaba-ai.version>
|
<alibaba-ai.version>1.1.0.0-RC2</alibaba-ai.version>
|
||||||
<tinyflow.version>1.2.6</tinyflow.version>
|
<tinyflow.version>1.2.6</tinyflow.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class BpmTaskController {
|
|||||||
|
|
||||||
@GetMapping("manager-page")
|
@GetMapping("manager-page")
|
||||||
@Operation(summary = "获取全部任务的分页", description = "用于【流程任务】菜单")
|
@Operation(summary = "获取全部任务的分页", description = "用于【流程任务】菜单")
|
||||||
@PreAuthorize("@ss.hasPermission('bpm:task:mananger-query')")
|
@PreAuthorize("@ss.hasPermission('bpm:task:manager-query')")
|
||||||
public CommonResult<PageResult<BpmTaskRespVO>> getTaskManagerPage(@Valid BpmTaskPageReqVO pageVO) {
|
public CommonResult<PageResult<BpmTaskRespVO>> getTaskManagerPage(@Valid BpmTaskPageReqVO pageVO) {
|
||||||
PageResult<HistoricTaskInstance> pageResult = taskService.getTaskPage(getLoginUserId(), pageVO);
|
PageResult<HistoricTaskInstance> pageResult = taskService.getTaskPage(getLoginUserId(), pageVO);
|
||||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav
|
|||||||
public BpmParallelMultiInstanceBehavior(Activity activity,
|
public BpmParallelMultiInstanceBehavior(Activity activity,
|
||||||
AbstractBpmnActivityBehavior innerActivityBehavior) {
|
AbstractBpmnActivityBehavior innerActivityBehavior) {
|
||||||
super(activity, innerActivityBehavior);
|
super(activity, innerActivityBehavior);
|
||||||
|
// 关联 Pull Request:https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1483
|
||||||
|
// 在解析/构造阶段基于 activityId 初始化与 activity 绑定且不变的字段,避免在运行期修改 Behavior 实例状态
|
||||||
|
super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的
|
||||||
|
super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(activity.getId());
|
||||||
|
// 从 execution.getVariable() 读取当前所有任务处理的人的 key
|
||||||
|
super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(activity.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,14 +56,7 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav
|
|||||||
protected int resolveNrOfInstances(DelegateExecution execution) {
|
protected int resolveNrOfInstances(DelegateExecution execution) {
|
||||||
// 情况一:UserTask 节点
|
// 情况一:UserTask 节点
|
||||||
if (execution.getCurrentFlowElement() instanceof UserTask) {
|
if (execution.getCurrentFlowElement() instanceof UserTask) {
|
||||||
// 第一步,设置 collectionVariable 和 CollectionVariable
|
// 获取任务的所有处理人
|
||||||
// 从 execution.getVariable() 读取所有任务处理人的 key
|
|
||||||
super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的
|
|
||||||
super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId());
|
|
||||||
// 从 execution.getVariable() 读取当前所有任务处理的人的 key
|
|
||||||
super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId());
|
|
||||||
|
|
||||||
// 第二步,获取任务的所有处理人
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariable(super.collectionVariable, Set.class);
|
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariable(super.collectionVariable, Set.class);
|
||||||
if (assigneeUserIds == null) {
|
if (assigneeUserIds == null) {
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB
|
|||||||
|
|
||||||
public BpmSequentialMultiInstanceBehavior(Activity activity, AbstractBpmnActivityBehavior innerActivityBehavior) {
|
public BpmSequentialMultiInstanceBehavior(Activity activity, AbstractBpmnActivityBehavior innerActivityBehavior) {
|
||||||
super(activity, innerActivityBehavior);
|
super(activity, innerActivityBehavior);
|
||||||
|
// 关联 Pull Request:https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1483
|
||||||
|
// 在解析/构造阶段基于 activityId 初始化与 activity 绑定且不变的字段,避免在运行期修改 Behavior 实例状态
|
||||||
|
super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的
|
||||||
|
super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(activity.getId());
|
||||||
|
// 从 execution.getVariable() 读取当前所有任务处理的人的 key
|
||||||
|
super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(activity.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,14 +47,7 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB
|
|||||||
protected int resolveNrOfInstances(DelegateExecution execution) {
|
protected int resolveNrOfInstances(DelegateExecution execution) {
|
||||||
// 情况一:UserTask 节点
|
// 情况一:UserTask 节点
|
||||||
if (execution.getCurrentFlowElement() instanceof UserTask) {
|
if (execution.getCurrentFlowElement() instanceof UserTask) {
|
||||||
// 第一步,设置 collectionVariable 和 CollectionVariable
|
// 获取任务的所有处理人
|
||||||
// 从 execution.getVariable() 读取所有任务处理人的 key
|
|
||||||
super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的
|
|
||||||
super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId());
|
|
||||||
// 从 execution.getVariable() 读取当前所有任务处理的人的 key
|
|
||||||
super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId());
|
|
||||||
|
|
||||||
// 第二步,获取任务的所有处理人
|
|
||||||
// 不使用 execution.getVariable 原因:目前依次审批任务回退后 collectionVariable 变量没有清理, 如果重新进入该任务不会重新分配审批人
|
// 不使用 execution.getVariable 原因:目前依次审批任务回退后 collectionVariable 变量没有清理, 如果重新进入该任务不会重新分配审批人
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariableLocal(super.collectionVariable, Set.class);
|
Set<Long> assigneeUserIds = (Set<Long>) execution.getVariableLocal(super.collectionVariable, Set.class);
|
||||||
@@ -88,10 +87,6 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB
|
|||||||
super.executeOriginalBehavior(execution, multiInstanceRootExecution, loopCounter);
|
super.executeOriginalBehavior(execution, multiInstanceRootExecution, loopCounter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 参见 https://gitee.com/zhijiantianya/yudao-cloud/issues/IC239F
|
|
||||||
super.collectionExpression = null;
|
|
||||||
super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId());
|
|
||||||
super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId());
|
|
||||||
super.executeOriginalBehavior(execution, multiInstanceRootExecution, loopCounter);
|
super.executeOriginalBehavior(execution, multiInstanceRootExecution, loopCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ public class BpmTaskCandidateInvoker {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DataPermission(enable = false) // 忽略数据权限,避免因为过滤,导致找不到候选人
|
||||||
public Set<Long> calculateUsersByActivity(BpmnModel bpmnModel, String activityId,
|
public Set<Long> calculateUsersByActivity(BpmnModel bpmnModel, String activityId,
|
||||||
Long startUserId, String processDefinitionId, Map<String, Object> processVariables) {
|
Long startUserId, String processDefinitionId, Map<String, Object> processVariables) {
|
||||||
// 如果是 CallActivity 子流程,不进行计算候选人
|
// 如果是 CallActivity 子流程,不进行计算候选人
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
|
|||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceCopyService;
|
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceCopyService;
|
||||||
import org.flowable.bpmn.model.FlowElement;
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
import org.flowable.engine.delegate.DelegateExecution;
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
@@ -40,8 +41,9 @@ public class BpmCopyTaskDelegate implements JavaDelegate {
|
|||||||
}
|
}
|
||||||
// 2. 执行抄送
|
// 2. 执行抄送
|
||||||
FlowElement currentFlowElement = execution.getCurrentFlowElement();
|
FlowElement currentFlowElement = execution.getCurrentFlowElement();
|
||||||
processInstanceCopyService.createProcessInstanceCopy(userIds, null, execution.getProcessInstanceId(),
|
FlowableUtils.execute(execution.getTenantId(), () ->
|
||||||
currentFlowElement.getId(), currentFlowElement.getName(), null);
|
processInstanceCopyService.createProcessInstanceCopy(userIds, null, execution.getProcessInstanceId(),
|
||||||
|
currentFlowElement.getId(), currentFlowElement.getName(), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ public class FileController {
|
|||||||
return success(fileService.createFile(createReqVO));
|
return success(fileService.createFile(createReqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获得文件")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true)
|
||||||
|
@PreAuthorize("@ss.hasPermission('infra:file:query')")
|
||||||
|
public CommonResult<FileRespVO> getFile(@RequestParam("id") Long id) {
|
||||||
|
return success(BeanUtils.toBean(fileService.getFile(id), FileRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@Operation(summary = "删除文件")
|
@Operation(summary = "删除文件")
|
||||||
@Parameter(name = "id", description = "编号", required = true)
|
@Parameter(name = "id", description = "编号", required = true)
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ public enum CodegenFrontTypeEnum {
|
|||||||
|
|
||||||
VUE3_VBEN5_EP_SCHEMA(50), // Vue3 VBEN5 + EP + schema 模版
|
VUE3_VBEN5_EP_SCHEMA(50), // Vue3 VBEN5 + EP + schema 模版
|
||||||
VUE3_VBEN5_EP_GENERAL(51), // Vue3 VBEN5 + EP 标准模版
|
VUE3_VBEN5_EP_GENERAL(51), // Vue3 VBEN5 + EP 标准模版
|
||||||
|
|
||||||
|
VUE3_ADMIN_UNIAPP_WOT(60), // Vue3 Admin + Uniapp + WOT 标准模版
|
||||||
;
|
;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class CodegenEngine {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后端的配置模版
|
* 前端的配置模版
|
||||||
*
|
*
|
||||||
* key1:UI 模版的类型 {@link CodegenFrontTypeEnum#getType()}
|
* key1:UI 模版的类型 {@link CodegenFrontTypeEnum#getType()}
|
||||||
* key2:模板在 resources 的地址
|
* key2:模板在 resources 的地址
|
||||||
@@ -137,6 +137,16 @@ public class CodegenEngine {
|
|||||||
vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue"))
|
vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue"))
|
||||||
.put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("api/api.ts"),
|
.put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("api/api.ts"),
|
||||||
vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
|
vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
|
||||||
|
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("api/api.ts"),
|
||||||
|
vue3UniappFilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
|
||||||
|
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/index.vue"),
|
||||||
|
vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/index.vue"))
|
||||||
|
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("components/search-form.vue"),
|
||||||
|
vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/components/search-form.vue"))
|
||||||
|
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/form/index.vue"),
|
||||||
|
vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/form/index.vue"))
|
||||||
|
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/detail/index.vue"),
|
||||||
|
vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/detail/index.vue"))
|
||||||
// VUE3_VBEN2_ANTD_SCHEMA
|
// VUE3_VBEN2_ANTD_SCHEMA
|
||||||
.put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("views/data.ts"),
|
.put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("views/data.ts"),
|
||||||
vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts"))
|
vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts"))
|
||||||
@@ -387,8 +397,8 @@ public class CodegenEngine {
|
|||||||
* @return 格式化后的代码
|
* @return 格式化后的代码
|
||||||
*/
|
*/
|
||||||
private String prettyCode(String content, String vmPath) {
|
private String prettyCode(String content, String vmPath) {
|
||||||
// Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错(需要排除 vben5)
|
// Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错(需要排除 vben5、vue3_admin_uniapp)
|
||||||
if (!StrUtil.contains(vmPath, "vben5")) {
|
if (!StrUtil.containsAny(vmPath, "vben5", "vue3_admin_uniapp")) {
|
||||||
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
|
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
|
||||||
}
|
}
|
||||||
// Vue 界面:去除多的 dateFormatter,只有一个的情况下,说明没使用到
|
// Vue 界面:去除多的 dateFormatter,只有一个的情况下,说明没使用到
|
||||||
@@ -617,6 +627,15 @@ public class CodegenEngine {
|
|||||||
"src/" + path;
|
"src/" + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String vue3AdminUniappTemplatePath(String path) {
|
||||||
|
return "codegen/vue3_admin_uniapp/" + path + ".vm";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String vue3UniappFilePath(String path) {
|
||||||
|
return "yudao-ui-${sceneEnum.basePackage}-uniapp/" + // 顶级目录
|
||||||
|
"src/" + path;
|
||||||
|
}
|
||||||
|
|
||||||
private static String vue3VbenFilePath(String path) {
|
private static String vue3VbenFilePath(String path) {
|
||||||
return "yudao-ui-${sceneEnum.basePackage}-vben/" + // 顶级目录
|
return "yudao-ui-${sceneEnum.basePackage}-vben/" + // 顶级目录
|
||||||
"src/" + path;
|
"src/" + path;
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public interface FileService {
|
|||||||
* @return 编号
|
* @return 编号
|
||||||
*/
|
*/
|
||||||
Long createFile(FileCreateReqVO createReqVO);
|
Long createFile(FileCreateReqVO createReqVO);
|
||||||
|
FileDO getFile(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除文件
|
* 删除文件
|
||||||
|
|||||||
@@ -152,6 +152,11 @@ public class FileServiceImpl implements FileService {
|
|||||||
return file.getId();
|
return file.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileDO getFile(Long id) {
|
||||||
|
return validateFileExists(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteFile(Long id) throws Exception {
|
public void deleteFile(Long id) throws Exception {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import type { PageParam, PageResult } from '@/http/types'
|
||||||
|
import { http } from '@/http/http'
|
||||||
|
|
||||||
|
#set ($primaryJavaType = $primaryColumn.javaType.toLowerCase())
|
||||||
|
#if(${primaryJavaType} == "long" || ${primaryJavaType} == "integer" || ${primaryJavaType} == "short" || ${primaryJavaType} == "double" || ${primaryJavaType} == "bigdecimal" || ${primaryJavaType} == "byte")
|
||||||
|
#set ($primaryTsType = "number")
|
||||||
|
#else
|
||||||
|
#set ($primaryTsType = "string")
|
||||||
|
#end
|
||||||
|
|
||||||
|
/** ${table.classComment}信息 */
|
||||||
|
export interface ${simpleClassName} {
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if ($column.primaryKey || $column.createOperation || $column.updateOperation || $column.listOperationResult)
|
||||||
|
#set ($javaType = $column.javaType.toLowerCase())
|
||||||
|
#set ($javaFieldLower = $column.javaField.toLowerCase())
|
||||||
|
#set ($optional = $column.nullable || $column.primaryKey || $javaFieldLower == "createtime" || $javaFieldLower == "updatetime")
|
||||||
|
#if(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte")
|
||||||
|
${column.javaField}#if($optional)?#end: number
|
||||||
|
#elseif(${javaType} == "date" || ${javaType} == "localdate" || ${javaType} == "localdatetime")
|
||||||
|
${column.javaField}#if($optional)?#end: Date
|
||||||
|
#elseif(${javaType} == "boolean")
|
||||||
|
${column.javaField}#if($optional)?#end: boolean
|
||||||
|
#else
|
||||||
|
${column.javaField}#if($optional)?#end: string
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO @AI:`/system/operate-log/get?id=${id}` 类似这种
|
||||||
|
/** 获取${table.classComment}分页列表 */
|
||||||
|
export function get${simpleClassName}Page(params: PageParam) {
|
||||||
|
return http.get<PageResult<${simpleClassName}>>('/${table.moduleName}/${simpleClassName_strikeCase}/page', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取${table.classComment}详情 */
|
||||||
|
export function get${simpleClassName}(id: ${primaryTsType}) {
|
||||||
|
return http.get<${simpleClassName}>('/${table.moduleName}/${simpleClassName_strikeCase}/get?id=' + id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建${table.classComment} */
|
||||||
|
export function create${simpleClassName}(data: ${simpleClassName}) {
|
||||||
|
return http.post<number>('/${table.moduleName}/${simpleClassName_strikeCase}/create', data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新${table.classComment} */
|
||||||
|
export function update${simpleClassName}(data: ${simpleClassName}) {
|
||||||
|
return http.put<boolean>('/${table.moduleName}/${simpleClassName_strikeCase}/update', data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO @AI:`/system/operate-log/get?id=${id}` 类似这种
|
||||||
|
/** 删除${table.classComment} */
|
||||||
|
export function delete${simpleClassName}(id: ${primaryTsType}) {
|
||||||
|
return http.delete<boolean>('/${table.moduleName}/${simpleClassName_strikeCase}/delete?id=' + id)
|
||||||
|
}
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 搜索框入口 -->
|
||||||
|
<view @click="visible = true">
|
||||||
|
<wd-search :placeholder="placeholder" hide-cancel disabled />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 搜索弹窗 -->
|
||||||
|
<wd-popup v-model="visible" position="top" @close="visible = false">
|
||||||
|
<view class="yd-search-form-container" :style="{ paddingTop: `#[[${]]#getNavbarHeight()#[[}]]#px` }">
|
||||||
|
#set ($hasDict = 0)
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if ($hasDict == 0 && $column.listOperation && $column.dictType && "" != $column.dictType)
|
||||||
|
#set ($hasDict = 1)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperation)
|
||||||
|
#set ($dictType = $column.dictType)
|
||||||
|
#set ($javaField = $column.javaField)
|
||||||
|
#set ($javaType = $column.javaType)
|
||||||
|
#set ($listOperationCondition = $column.listOperationCondition)
|
||||||
|
#set ($comment = $column.columnComment)
|
||||||
|
#set ($dictMethod = "getDictOptions")
|
||||||
|
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
|
||||||
|
#set ($dictMethod = "getIntDictOptions")
|
||||||
|
#elseif ($javaType == "String")
|
||||||
|
#set ($dictMethod = "getStrDictOptions")
|
||||||
|
#elseif ($javaType == "Boolean")
|
||||||
|
#set ($dictMethod = "getBoolDictOptions")
|
||||||
|
#end
|
||||||
|
#if ($column.htmlType == "input")
|
||||||
|
<view class="yd-search-form-item">
|
||||||
|
<view class="yd-search-form-label">
|
||||||
|
${comment}
|
||||||
|
</view>
|
||||||
|
<wd-input
|
||||||
|
v-model="formData.${javaField}"
|
||||||
|
placeholder="请输入${comment}"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
#elseif ($column.htmlType == "datetime" && $listOperationCondition == "BETWEEN")
|
||||||
|
#set ($AttrName = $javaField.substring(0,1).toUpperCase() + ${javaField.substring(1)})
|
||||||
|
<view class="yd-search-form-item">
|
||||||
|
<view class="yd-search-form-label">
|
||||||
|
${comment}
|
||||||
|
</view>
|
||||||
|
<view class="yd-search-form-date-range-container">
|
||||||
|
<view @click="visible${AttrName}[0] = true">
|
||||||
|
<view class="yd-search-form-date-range-picker">
|
||||||
|
{{ formatDate(formData.${javaField}?.[0]) || '开始日期' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
-
|
||||||
|
<view @click="visible${AttrName}[1] = true">
|
||||||
|
<view class="yd-search-form-date-range-picker">
|
||||||
|
{{ formatDate(formData.${javaField}?.[1]) || '结束日期' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<wd-datetime-picker-view v-if="visible${AttrName}[0]" v-model="temp${AttrName}[0]" type="date" />
|
||||||
|
<view v-if="visible${AttrName}[0]" class="yd-search-form-date-range-actions">
|
||||||
|
<wd-button size="small" plain @click="visible${AttrName}[0] = false">
|
||||||
|
取消
|
||||||
|
</wd-button>
|
||||||
|
<wd-button size="small" type="primary" @click="handle${AttrName}0Confirm">
|
||||||
|
确定
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
<wd-datetime-picker-view v-if="visible${AttrName}[1]" v-model="temp${AttrName}[1]" type="date" />
|
||||||
|
<view v-if="visible${AttrName}[1]" class="yd-search-form-date-range-actions">
|
||||||
|
<wd-button size="small" plain @click="visible${AttrName}[1] = false">
|
||||||
|
取消
|
||||||
|
</wd-button>
|
||||||
|
<wd-button size="small" type="primary" @click="handle${AttrName}1Confirm">
|
||||||
|
确定
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
#elseif (($column.htmlType == "select" || $column.htmlType == "radio") && $dictType && "" != $dictType)
|
||||||
|
<view class="yd-search-form-item">
|
||||||
|
<view class="yd-search-form-label">
|
||||||
|
${comment}
|
||||||
|
</view>
|
||||||
|
<wd-radio-group v-model="formData.${javaField}" shape="button">
|
||||||
|
<wd-radio :value="-1">
|
||||||
|
全部
|
||||||
|
</wd-radio>
|
||||||
|
<wd-radio
|
||||||
|
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
|
||||||
|
:key="dict.value"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</wd-radio>
|
||||||
|
</wd-radio-group>
|
||||||
|
</view>
|
||||||
|
#else
|
||||||
|
<view class="yd-search-form-item">
|
||||||
|
<view class="yd-search-form-label">
|
||||||
|
${comment}
|
||||||
|
</view>
|
||||||
|
<wd-input
|
||||||
|
v-model="formData.${javaField}"
|
||||||
|
placeholder="请输入${comment}"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
<view class="yd-search-form-actions">
|
||||||
|
<wd-button class="flex-1" plain @click="handleReset">
|
||||||
|
重置
|
||||||
|
</wd-button>
|
||||||
|
<wd-button class="flex-1" type="primary" @click="handleSearch">
|
||||||
|
搜索
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
#set ($hasDict = 0)
|
||||||
|
#set ($hasGetDictOptions = 0)
|
||||||
|
#set ($hasGetIntDictOptions = 0)
|
||||||
|
#set ($hasGetStrDictOptions = 0)
|
||||||
|
#set ($hasGetBoolDictOptions = 0)
|
||||||
|
#set ($hasDateTimeBetween = 0)
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperation && $column.dictType && "" != $column.dictType)
|
||||||
|
#set ($hasDict = 1)
|
||||||
|
#if ($column.htmlType == "select" || $column.htmlType == "radio")
|
||||||
|
#if ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short")
|
||||||
|
#set ($hasGetIntDictOptions = 1)
|
||||||
|
#elseif ($column.javaType == "String")
|
||||||
|
#set ($hasGetStrDictOptions = 1)
|
||||||
|
#elseif ($column.javaType == "Boolean")
|
||||||
|
#set ($hasGetBoolDictOptions = 1)
|
||||||
|
#else
|
||||||
|
#set ($hasGetDictOptions = 1)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#if ($hasDateTimeBetween == 0 && $column.listOperation && $column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
|
||||||
|
#set ($hasDateTimeBetween = 1)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
import { computed, reactive, ref } from 'vue'
|
||||||
|
import { getNavbarHeight } from '@/utils'
|
||||||
|
#if ($hasDateTimeBetween == 1)
|
||||||
|
import { formatDate, formatDateRange } from '@/utils/date'
|
||||||
|
#end
|
||||||
|
#if ($hasDict == 1)
|
||||||
|
#set ($dictImportNames = "getDictLabel, ")
|
||||||
|
#if ($hasGetDictOptions == 1)
|
||||||
|
#set ($dictImportNames = "${dictImportNames}getDictOptions, ")
|
||||||
|
#end
|
||||||
|
#if ($hasGetIntDictOptions == 1)
|
||||||
|
#set ($dictImportNames = "${dictImportNames}getIntDictOptions, ")
|
||||||
|
#end
|
||||||
|
#if ($hasGetStrDictOptions == 1)
|
||||||
|
#set ($dictImportNames = "${dictImportNames}getStrDictOptions, ")
|
||||||
|
#end
|
||||||
|
#if ($hasGetBoolDictOptions == 1)
|
||||||
|
#set ($dictImportNames = "${dictImportNames}getBoolDictOptions, ")
|
||||||
|
#end
|
||||||
|
#set ($dictImportNames = $dictImportNames.trim())
|
||||||
|
#set ($dictImportNames = $dictImportNames.substring(0, $dictImportNames.length() - 1))
|
||||||
|
import { $dictImportNames } from '@/hooks/useDict'
|
||||||
|
import { DICT_TYPE } from '@/utils/constants'
|
||||||
|
#end
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
search: [data: Record<string, any>]
|
||||||
|
reset: []
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
const formData = reactive({
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperation)
|
||||||
|
#set ($javaType = $column.javaType.toLowerCase())
|
||||||
|
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
|
||||||
|
${column.javaField}: [undefined, undefined] as [number | undefined, number | undefined],
|
||||||
|
#elseif ($column.dictType && "" != $column.dictType)
|
||||||
|
#if(${javaType} == "string")
|
||||||
|
${column.javaField}: -1 as -1 | string, // -1 表示全部
|
||||||
|
#elseif(${javaType} == "boolean")
|
||||||
|
${column.javaField}: -1 as -1 | boolean, // -1 表示全部
|
||||||
|
#else
|
||||||
|
${column.javaField}: -1, // -1 表示全部
|
||||||
|
#end
|
||||||
|
#elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte")
|
||||||
|
${column.javaField}: undefined as number | undefined,
|
||||||
|
#elseif(${javaType} == "boolean")
|
||||||
|
${column.javaField}: undefined as boolean | undefined,
|
||||||
|
#else
|
||||||
|
${column.javaField}: undefined as string | undefined,
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 搜索条件 placeholder 拼接 */
|
||||||
|
const placeholder = computed(() => {
|
||||||
|
const conditions: string[] = []
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperation)
|
||||||
|
#set ($dictType = $column.dictType)
|
||||||
|
#set ($javaField = $column.javaField)
|
||||||
|
#set ($javaType = $column.javaType.toLowerCase())
|
||||||
|
#set ($comment = $column.columnComment)
|
||||||
|
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
|
||||||
|
if (formData.${javaField}?.[0] && formData.${javaField}?.[1]) {
|
||||||
|
conditions.push(`${comment}:#[[${]]#formatDate(formData.${javaField}[0])#[[}]]#~#[[${]]#formatDate(formData.${javaField}[1])#[[}]]#`)
|
||||||
|
}
|
||||||
|
#elseif ($dictType && "" != $dictType)
|
||||||
|
if (formData.${javaField} !== -1) {
|
||||||
|
conditions.push(`${comment}:#[[${]]#getDictLabel(DICT_TYPE.${dictType.toUpperCase()}, formData.${javaField})#[[}]]#`)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#if(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte" || ${javaType} == "boolean")
|
||||||
|
if (formData.${javaField} !== undefined) {
|
||||||
|
conditions.push(`${comment}:#[[${]]#formData.${javaField}#[[}]]#`)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (formData.${javaField}) {
|
||||||
|
conditions.push(`${comment}:#[[${]]#formData.${javaField}#[[}]]#`)
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
return conditions.length > 0 ? conditions.join(' | ') : '搜索${table.classComment}'
|
||||||
|
})
|
||||||
|
|
||||||
|
#if ($hasDateTimeBetween == 1)
|
||||||
|
// 时间范围选择器状态
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperation && $column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
|
||||||
|
#set ($javaField = $column.javaField)
|
||||||
|
#set ($AttrName = $javaField.substring(0,1).toUpperCase() + ${javaField.substring(1)})
|
||||||
|
const visible${AttrName} = ref<[boolean, boolean]>([false, false])
|
||||||
|
const temp${AttrName} = ref<[number, number]>([Date.now(), Date.now()])
|
||||||
|
|
||||||
|
/** ${column.columnComment}[0]确认 */
|
||||||
|
function handle${AttrName}0Confirm() {
|
||||||
|
formData.${javaField} = [temp${AttrName}.value[0], formData.${javaField}?.[1]]
|
||||||
|
visible${AttrName}.value[0] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ${column.columnComment}[1]确认 */
|
||||||
|
function handle${AttrName}1Confirm() {
|
||||||
|
formData.${javaField} = [formData.${javaField}?.[0], temp${AttrName}.value[1]]
|
||||||
|
visible${AttrName}.value[1] = false
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
|
||||||
|
/** 搜索 */
|
||||||
|
function handleSearch() {
|
||||||
|
visible.value = false
|
||||||
|
emit('search', {
|
||||||
|
...formData,
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperation)
|
||||||
|
#if ($column.dictType && "" != $column.dictType)
|
||||||
|
${column.javaField}: formData.${column.javaField} === -1 ? undefined : formData.${column.javaField},
|
||||||
|
#elseif ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
|
||||||
|
${column.javaField}: formatDateRange(formData.${column.javaField}),
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置 */
|
||||||
|
function handleReset() {
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperation)
|
||||||
|
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
|
||||||
|
formData.${column.javaField} = [undefined, undefined]
|
||||||
|
#elseif ($column.dictType && "" != $column.dictType)
|
||||||
|
formData.${column.javaField} = -1
|
||||||
|
#else
|
||||||
|
formData.${column.javaField} = undefined
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
visible.value = false
|
||||||
|
emit('reset')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
<template>
|
||||||
|
<view class="yd-page-container">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<wd-navbar
|
||||||
|
title="${table.classComment}详情"
|
||||||
|
left-arrow placeholder safe-area-inset-top fixed
|
||||||
|
@click-left="handleBack"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 详情内容 -->
|
||||||
|
<view>
|
||||||
|
<wd-cell-group border>
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.primaryKey || $column.listOperationResult || $column.createOperation || $column.updateOperation)
|
||||||
|
#set ($javaField = $column.javaField)
|
||||||
|
#set ($comment = $column.columnComment)
|
||||||
|
#if ($column.dictType && "" != $column.dictType)
|
||||||
|
<wd-cell title="${comment}">
|
||||||
|
<dict-tag :type="DICT_TYPE.${column.dictType.toUpperCase()}" :value="formData?.${javaField}" />
|
||||||
|
</wd-cell>
|
||||||
|
#elseif ($column.javaType == "LocalDateTime")
|
||||||
|
<wd-cell title="${comment}" :value="formatDateTime(formData?.${javaField}) || '-'" />
|
||||||
|
#else
|
||||||
|
<wd-cell title="${comment}" :value="formData?.${javaField} ?? '-'" />
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
</wd-cell-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部操作按钮 -->
|
||||||
|
<view class="yd-detail-footer">
|
||||||
|
<view class="yd-detail-footer-actions">
|
||||||
|
<wd-button
|
||||||
|
v-if="hasAccessByCodes(['${permissionPrefix}:update'])"
|
||||||
|
class="flex-1" type="warning" @click="handleEdit"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</wd-button>
|
||||||
|
<wd-button
|
||||||
|
v-if="hasAccessByCodes(['${permissionPrefix}:delete'])"
|
||||||
|
class="flex-1" type="error" :loading="deleting" @click="handleDelete"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
#set ($hasDict = 0)
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($hasDict == 0 && $column.dictType && "" != $column.dictType)
|
||||||
|
#set ($hasDict = 1)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#set ($hasDateTime = 0)
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($hasDateTime == 0 && $column.javaType == "LocalDateTime")
|
||||||
|
#set ($hasDateTime = 1)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { useToast } from 'wot-design-uni'
|
||||||
|
import { delete${simpleClassName}, get${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
|
||||||
|
import { useAccess } from '@/hooks/useAccess'
|
||||||
|
import { navigateBackPlus } from '@/utils'
|
||||||
|
#if ($hasDict == 1)
|
||||||
|
import { DICT_TYPE } from '@/utils/constants'
|
||||||
|
#end
|
||||||
|
#if ($hasDateTime == 1)
|
||||||
|
import { formatDateTime } from '@/utils/date'
|
||||||
|
#end
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id?: number | any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
definePage({
|
||||||
|
style: {
|
||||||
|
navigationBarTitleText: '',
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { hasAccessByCodes } = useAccess()
|
||||||
|
const toast = useToast()
|
||||||
|
const formData = ref<${simpleClassName}>()
|
||||||
|
const deleting = ref(false)
|
||||||
|
|
||||||
|
/** 返回上一页 */
|
||||||
|
function handleBack() {
|
||||||
|
navigateBackPlus('/pages-${table.moduleName}/${table.businessName}/index')
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加载${table.classComment}详情 */
|
||||||
|
async function getDetail() {
|
||||||
|
if (!props.id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
toast.loading('加载中...')
|
||||||
|
formData.value = await get${simpleClassName}(props.id)
|
||||||
|
} finally {
|
||||||
|
toast.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 编辑${table.classComment} */
|
||||||
|
function handleEdit() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages-${table.moduleName}/${table.businessName}/form/index?id=#[[${]]#props.id#[[}]]#`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除${table.classComment} */
|
||||||
|
function handleDelete() {
|
||||||
|
if (!props.id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该${table.classComment}吗?',
|
||||||
|
success: async (res) => {
|
||||||
|
if (!res.confirm) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
deleting.value = true
|
||||||
|
try {
|
||||||
|
await delete${simpleClassName}(props.id)
|
||||||
|
toast.success('删除成功')
|
||||||
|
setTimeout(() => {
|
||||||
|
handleBack()
|
||||||
|
}, 500)
|
||||||
|
} finally {
|
||||||
|
deleting.value = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(() => {
|
||||||
|
getDetail()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,253 @@
|
|||||||
|
<template>
|
||||||
|
<view class="yd-page-container">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<wd-navbar
|
||||||
|
:title="getTitle"
|
||||||
|
left-arrow placeholder safe-area-inset-top fixed
|
||||||
|
@click-left="handleBack"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 表单区域 -->
|
||||||
|
<view>
|
||||||
|
<wd-form ref="formRef" :model="formData" :rules="formRules">
|
||||||
|
<wd-cell-group border>
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey)
|
||||||
|
#set ($dictType = $column.dictType)
|
||||||
|
#set ($javaField = $column.javaField)
|
||||||
|
#set ($javaType = $column.javaType)
|
||||||
|
#set ($comment = $column.columnComment)
|
||||||
|
#set ($dictMethod = "getDictOptions")
|
||||||
|
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
|
||||||
|
#set ($dictMethod = "getIntDictOptions")
|
||||||
|
#elseif ($javaType == "String")
|
||||||
|
#set ($dictMethod = "getStrDictOptions")
|
||||||
|
#elseif ($javaType == "Boolean")
|
||||||
|
#set ($dictMethod = "getBoolDictOptions")
|
||||||
|
#end
|
||||||
|
## 优先判断是否有字典,有字典则使用 radio-group
|
||||||
|
#if (($column.htmlType == "select" || $column.htmlType == "radio") && $dictType && "" != $dictType)
|
||||||
|
<wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center>
|
||||||
|
<wd-radio-group v-model="formData.${javaField}" shape="button">
|
||||||
|
<wd-radio
|
||||||
|
v-for="dict in $dictMethod(DICT_TYPE.${dictType.toUpperCase()})"
|
||||||
|
:key="dict.value"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</wd-radio>
|
||||||
|
</wd-radio-group>
|
||||||
|
</wd-cell>
|
||||||
|
## 数字类型(无字典)
|
||||||
|
#elseif (${javaType.toLowerCase()} == "long" || ${javaType.toLowerCase()} == "integer" || ${javaType.toLowerCase()} == "short" || ${javaType.toLowerCase()} == "double" || ${javaType.toLowerCase()} == "bigdecimal" || ${javaType.toLowerCase()} == "byte")
|
||||||
|
<wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center>
|
||||||
|
<wd-input-number
|
||||||
|
v-model="formData.${javaField}"
|
||||||
|
:min="0"
|
||||||
|
/>
|
||||||
|
</wd-cell>
|
||||||
|
## 布尔类型
|
||||||
|
#elseif (${javaType.toLowerCase()} == "boolean")
|
||||||
|
<wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center>
|
||||||
|
<wd-switch v-model="formData.${javaField}" />
|
||||||
|
</wd-cell>
|
||||||
|
## 日期时间类型
|
||||||
|
#elseif (${javaType.toLowerCase()} == "date" || ${javaType.toLowerCase()} == "localdate" || ${javaType.toLowerCase()} == "localdatetime")
|
||||||
|
#set ($pickerType = "date")
|
||||||
|
#if (${javaType.toLowerCase()} == "localdatetime")
|
||||||
|
#set ($pickerType = "datetime")
|
||||||
|
#end
|
||||||
|
<wd-datetime-picker
|
||||||
|
v-model="formData.${javaField}"
|
||||||
|
type="${pickerType}"
|
||||||
|
label="${comment}"
|
||||||
|
label-width="180rpx"
|
||||||
|
prop="${javaField}"
|
||||||
|
/>
|
||||||
|
## 文本域
|
||||||
|
#elseif ($column.htmlType == "textarea")
|
||||||
|
<wd-textarea
|
||||||
|
v-model="formData.${javaField}"
|
||||||
|
label="${comment}"
|
||||||
|
label-width="180rpx"
|
||||||
|
placeholder="请输入${comment}"
|
||||||
|
:maxlength="200"
|
||||||
|
show-word-limit
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
## 默认:文本输入
|
||||||
|
#else
|
||||||
|
<wd-input
|
||||||
|
v-model="formData.${javaField}"
|
||||||
|
label="${comment}"
|
||||||
|
label-width="180rpx"
|
||||||
|
prop="${javaField}"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入${comment}"
|
||||||
|
/>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
</wd-cell-group>
|
||||||
|
</wd-form>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部保存按钮 -->
|
||||||
|
<view class="yd-detail-footer">
|
||||||
|
<wd-button
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
:loading="formLoading"
|
||||||
|
@click="handleSubmit"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
#set ($primaryJavaType = $primaryColumn.javaType.toLowerCase())
|
||||||
|
#if(${primaryJavaType} == "long" || ${primaryJavaType} == "integer" || ${primaryJavaType} == "short" || ${primaryJavaType} == "double" || ${primaryJavaType} == "bigdecimal" || ${primaryJavaType} == "byte")
|
||||||
|
#set ($primaryTsType = "number")
|
||||||
|
#else
|
||||||
|
#set ($primaryTsType = "string")
|
||||||
|
#end
|
||||||
|
#set ($hasDict = 0)
|
||||||
|
#set ($hasGetDictOptions = 0)
|
||||||
|
#set ($hasGetIntDictOptions = 0)
|
||||||
|
#set ($hasGetStrDictOptions = 0)
|
||||||
|
#set ($hasGetBoolDictOptions = 0)
|
||||||
|
#foreach ($column in $columns)
|
||||||
|
#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey
|
||||||
|
&& ($column.htmlType == "select" || $column.htmlType == "radio")
|
||||||
|
&& $column.dictType && "" != $column.dictType)
|
||||||
|
#set ($hasDict = 1)
|
||||||
|
#if ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short")
|
||||||
|
#set ($hasGetIntDictOptions = 1)
|
||||||
|
#elseif ($column.javaType == "String")
|
||||||
|
#set ($hasGetStrDictOptions = 1)
|
||||||
|
#elseif ($column.javaType == "Boolean")
|
||||||
|
#set ($hasGetBoolDictOptions = 1)
|
||||||
|
#else
|
||||||
|
#set ($hasGetDictOptions = 1)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
|
||||||
|
import { computed, onMounted, ref } from 'vue'
|
||||||
|
import { useToast } from 'wot-design-uni'
|
||||||
|
import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
|
||||||
|
#if ($hasDict == 1)
|
||||||
|
#set ($dictImportNames = "")
|
||||||
|
#if ($hasGetDictOptions == 1)
|
||||||
|
#set ($dictImportNames = "${dictImportNames}getDictOptions, ")
|
||||||
|
#end
|
||||||
|
#if ($hasGetIntDictOptions == 1)
|
||||||
|
#set ($dictImportNames = "${dictImportNames}getIntDictOptions, ")
|
||||||
|
#end
|
||||||
|
#if ($hasGetStrDictOptions == 1)
|
||||||
|
#set ($dictImportNames = "${dictImportNames}getStrDictOptions, ")
|
||||||
|
#end
|
||||||
|
#if ($hasGetBoolDictOptions == 1)
|
||||||
|
#set ($dictImportNames = "${dictImportNames}getBoolDictOptions, ")
|
||||||
|
#end
|
||||||
|
#set ($dictImportNames = $dictImportNames.trim())
|
||||||
|
#set ($dictImportNames = $dictImportNames.substring(0, $dictImportNames.length() - 1))
|
||||||
|
import { $dictImportNames } from '@/hooks/useDict'
|
||||||
|
#end
|
||||||
|
import { navigateBackPlus } from '@/utils'
|
||||||
|
#if ($hasDict == 1)
|
||||||
|
import { DICT_TYPE } from '@/utils/constants'
|
||||||
|
#end
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id?: ${primaryTsType} | any
|
||||||
|
}>()
|
||||||
|
|
||||||
|
definePage({
|
||||||
|
style: {
|
||||||
|
navigationBarTitleText: '',
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const toast = useToast()
|
||||||
|
const getTitle = computed(() => props.id ? '编辑${table.classComment}' : '新增${table.classComment}')
|
||||||
|
const formLoading = ref(false)
|
||||||
|
const formData = ref<${simpleClassName}>({
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if (($column.createOperation || $column.updateOperation) || $column.primaryKey)
|
||||||
|
#set ($javaType = $column.javaType.toLowerCase())
|
||||||
|
#set ($javaFieldLower = $column.javaField.toLowerCase())
|
||||||
|
#set ($optional = $column.nullable || $column.primaryKey || $javaFieldLower == "createtime" || $javaFieldLower == "updatetime")
|
||||||
|
#if ($column.primaryKey)
|
||||||
|
${column.javaField}: undefined,
|
||||||
|
#elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte")
|
||||||
|
${column.javaField}: 0,
|
||||||
|
#elseif(${javaType} == "boolean")
|
||||||
|
${column.javaField}: false,
|
||||||
|
#elseif(${javaType} == "date" || ${javaType} == "localdate" || ${javaType} == "localdatetime")
|
||||||
|
${column.javaField}: undefined,
|
||||||
|
#else
|
||||||
|
${column.javaField}: '',
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
})
|
||||||
|
const formRules = {
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#set ($javaFieldLower = $column.javaField.toLowerCase())
|
||||||
|
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey
|
||||||
|
&& $javaFieldLower != "createtime" && $javaFieldLower != "updatetime")
|
||||||
|
${column.javaField}: [{ required: true, message: '${column.columnComment}不能为空' }],
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
const formRef = ref()
|
||||||
|
|
||||||
|
/** 返回上一页 */
|
||||||
|
function handleBack() {
|
||||||
|
navigateBackPlus('/pages-${table.moduleName}/${table.businessName}/index')
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加载${table.classComment}详情 */
|
||||||
|
async function getDetail() {
|
||||||
|
if (!props.id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formData.value = await get${simpleClassName}(props.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交表单 */
|
||||||
|
async function handleSubmit() {
|
||||||
|
const { valid } = await formRef.value.validate()
|
||||||
|
if (!valid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
formLoading.value = true
|
||||||
|
try {
|
||||||
|
if (props.id) {
|
||||||
|
await update${simpleClassName}(formData.value)
|
||||||
|
toast.success('修改成功')
|
||||||
|
} else {
|
||||||
|
await create${simpleClassName}(formData.value)
|
||||||
|
toast.success('新增成功')
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
handleBack()
|
||||||
|
}, 500)
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(() => {
|
||||||
|
getDetail()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
<template>
|
||||||
|
<view class="yd-page-container">
|
||||||
|
<!-- 顶部导航栏 -->
|
||||||
|
<wd-navbar
|
||||||
|
title="${table.classComment}管理"
|
||||||
|
left-arrow placeholder safe-area-inset-top fixed
|
||||||
|
@click-left="handleBack"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 搜索组件 -->
|
||||||
|
<SearchForm @search="handleQuery" @reset="handleReset" />
|
||||||
|
|
||||||
|
<!-- ${table.classComment}列表 -->
|
||||||
|
<view class="p-24rpx">
|
||||||
|
<view
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.${primaryColumn.javaField}"
|
||||||
|
class="mb-24rpx overflow-hidden rounded-12rpx bg-white shadow-sm"
|
||||||
|
@click="handleDetail(item)"
|
||||||
|
>
|
||||||
|
<view class="p-24rpx">
|
||||||
|
#set ($titleField = "")
|
||||||
|
#set ($statusField = "")
|
||||||
|
#set ($statusDictType = "")
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($titleField == "" && !$column.primaryKey && $column.listOperationResult)
|
||||||
|
#set ($titleField = $column.javaField)
|
||||||
|
#set ($titleComment = $column.columnComment)
|
||||||
|
#end
|
||||||
|
#if ($statusField == "" && $column.listOperationResult && $column.dictType && "" != $column.dictType)
|
||||||
|
#set ($statusField = $column.javaField)
|
||||||
|
#set ($statusDictType = $column.dictType)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#if ($titleField == "")
|
||||||
|
#set ($titleField = $primaryColumn.javaField)
|
||||||
|
#end
|
||||||
|
<view class="mb-16rpx flex items-center justify-between">
|
||||||
|
<view class="text-32rpx text-[#333] font-semibold">
|
||||||
|
{{ item.${titleField} }}
|
||||||
|
</view>
|
||||||
|
#if($statusField != "")
|
||||||
|
<dict-tag :type="DICT_TYPE.${statusDictType.toUpperCase()}" :value="item.${statusField}" />
|
||||||
|
#end
|
||||||
|
</view>
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperationResult && !$column.primaryKey && $column.javaField != $titleField && $column.javaField != $statusField)
|
||||||
|
#set ($javaField = $column.javaField)
|
||||||
|
#set ($comment = $column.columnComment)
|
||||||
|
#set ($dictType = $column.dictType)
|
||||||
|
#set ($javaType = $column.javaType)
|
||||||
|
#if ($dictType && "" != $dictType)
|
||||||
|
<view class="mb-12rpx flex items-center text-28rpx text-[#666]">
|
||||||
|
<text class="mr-8rpx text-[#999]">${comment}:</text>
|
||||||
|
<dict-tag :type="DICT_TYPE.${dictType.toUpperCase()}" :value="item.${javaField}" />
|
||||||
|
</view>
|
||||||
|
#elseif ($javaType == "LocalDateTime")
|
||||||
|
<view class="mb-12rpx flex items-center text-28rpx text-[#666]">
|
||||||
|
<text class="mr-8rpx text-[#999]">${comment}:</text>
|
||||||
|
<text class="line-clamp-1">{{ formatDateTime(item.${javaField}) || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
#else
|
||||||
|
<view class="mb-12rpx flex items-center text-28rpx text-[#666]">
|
||||||
|
<text class="mr-8rpx text-[#999]">${comment}:</text>
|
||||||
|
<text class="line-clamp-1">{{ item.${javaField} }}</text>
|
||||||
|
</view>
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载更多 -->
|
||||||
|
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="py-100rpx text-center">
|
||||||
|
<wd-status-tip image="content" tip="暂无${table.classComment}数据" />
|
||||||
|
</view>
|
||||||
|
<wd-loadmore
|
||||||
|
v-if="list.length > 0"
|
||||||
|
:state="loadMoreState"
|
||||||
|
@reload="loadMore"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 新增按钮 -->
|
||||||
|
<wd-fab
|
||||||
|
v-if="hasAccessByCodes(['${permissionPrefix}:create'])"
|
||||||
|
position="right-bottom"
|
||||||
|
type="primary"
|
||||||
|
:expandable="false"
|
||||||
|
@click="handleAdd"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
#set ($hasDict = 0)
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($hasDict == 0 && $column.listOperationResult && $column.dictType && "" != $column.dictType)
|
||||||
|
#set ($hasDict = 1)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#set ($hasDateTime = 0)
|
||||||
|
#foreach($column in $columns)
|
||||||
|
#if ($column.listOperationResult)
|
||||||
|
#if ($hasDateTime == 0 && $column.javaType == "LocalDateTime")
|
||||||
|
#set ($hasDateTime = 1)
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
|
||||||
|
import type { LoadMoreState } from '@/http/types'
|
||||||
|
import { onReachBottom } from '@dcloudio/uni-app'
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { get${simpleClassName}Page } from '@/api/${table.moduleName}/${table.businessName}'
|
||||||
|
import { useAccess } from '@/hooks/useAccess'
|
||||||
|
import { navigateBackPlus } from '@/utils'
|
||||||
|
#if ($hasDict == 1)
|
||||||
|
import { DICT_TYPE } from '@/utils/constants'
|
||||||
|
#end
|
||||||
|
#if ($hasDateTime == 1)
|
||||||
|
import { formatDateTime } from '@/utils/date'
|
||||||
|
#end
|
||||||
|
import SearchForm from './components/search-form.vue'
|
||||||
|
|
||||||
|
definePage({
|
||||||
|
style: {
|
||||||
|
navigationBarTitleText: '',
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { hasAccessByCodes } = useAccess()
|
||||||
|
const total = ref(0)
|
||||||
|
const list = ref<${simpleClassName}[]>([])
|
||||||
|
const loadMoreState = ref<LoadMoreState>('loading')
|
||||||
|
const queryParams = ref({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 返回上一页 */
|
||||||
|
function handleBack() {
|
||||||
|
navigateBackPlus()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询${table.classComment}列表 */
|
||||||
|
async function getList() {
|
||||||
|
loadMoreState.value = 'loading'
|
||||||
|
try {
|
||||||
|
const data = await get${simpleClassName}Page(queryParams.value)
|
||||||
|
list.value = [...list.value, ...data.list]
|
||||||
|
total.value = data.total
|
||||||
|
loadMoreState.value = list.value.length >= total.value ? 'finished' : 'loading'
|
||||||
|
} catch {
|
||||||
|
queryParams.value.pageNo = queryParams.value.pageNo > 1 ? queryParams.value.pageNo - 1 : 1
|
||||||
|
loadMoreState.value = 'error'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
function handleQuery(data?: Record<string, any>) {
|
||||||
|
queryParams.value = {
|
||||||
|
...data,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: queryParams.value.pageSize,
|
||||||
|
}
|
||||||
|
list.value = []
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
function handleReset() {
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加载更多 */
|
||||||
|
function loadMore() {
|
||||||
|
if (loadMoreState.value === 'finished') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
queryParams.value.pageNo++
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增${table.classComment} */
|
||||||
|
function handleAdd() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages-${table.moduleName}/${table.businessName}/form/index',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查看详情 */
|
||||||
|
function handleDetail(item: ${simpleClassName}) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages-${table.moduleName}/${table.businessName}/detail/index?id=#[[${]]#item.${primaryColumn.javaField}#[[}]]#`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 触底加载更多 */
|
||||||
|
onReachBottom(() => {
|
||||||
|
loadMore()
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@@ -82,7 +82,17 @@ public class MemberUserController {
|
|||||||
@PreAuthorize("@ss.hasPermission('member:user:query')")
|
@PreAuthorize("@ss.hasPermission('member:user:query')")
|
||||||
public CommonResult<MemberUserRespVO> getUser(@RequestParam("id") Long id) {
|
public CommonResult<MemberUserRespVO> getUser(@RequestParam("id") Long id) {
|
||||||
MemberUserDO user = memberUserService.getUser(id);
|
MemberUserDO user = memberUserService.getUser(id);
|
||||||
return success(MemberUserConvert.INSTANCE.convert03(user));
|
if (user == null) {
|
||||||
|
return success(null);
|
||||||
|
}
|
||||||
|
MemberUserRespVO userVO = MemberUserConvert.INSTANCE.convert03(user);
|
||||||
|
if (user.getLevelId() != null) {
|
||||||
|
MemberLevelDO level = memberLevelService.getLevel(userVO.getId());
|
||||||
|
if (level != null) {
|
||||||
|
userVO.setLevelName(level.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success(userVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class SocialClientApiImpl implements SocialClientApi {
|
|||||||
// 2. 获得社交用户
|
// 2. 获得社交用户
|
||||||
SocialUserRespDTO socialUser = socialUserService.getSocialUserByUserId(reqDTO.getUserType(), reqDTO.getUserId(),
|
SocialUserRespDTO socialUser = socialUserService.getSocialUserByUserId(reqDTO.getUserType(), reqDTO.getUserId(),
|
||||||
SocialTypeEnum.WECHAT_MINI_PROGRAM.getType());
|
SocialTypeEnum.WECHAT_MINI_PROGRAM.getType());
|
||||||
if (StrUtil.isBlankIfStr(socialUser.getOpenid())) {
|
if (ObjUtil.isNull(socialUser) || StrUtil.isBlankIfStr(socialUser.getOpenid())) {
|
||||||
log.warn("[sendWxaSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:会员 openid 缺失]", reqDTO);
|
log.warn("[sendWxaSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:会员 openid 缺失]", reqDTO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ public class LoginLogController {
|
|||||||
@Resource
|
@Resource
|
||||||
private LoginLogService loginLogService;
|
private LoginLogService loginLogService;
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获得登录日志")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:login-log:query')")
|
||||||
|
public CommonResult<LoginLogRespVO> getLoginLog(Long id) {
|
||||||
|
LoginLogDO loginLog = loginLogService.getLoginLog(id);
|
||||||
|
return success(BeanUtils.toBean(loginLog, LoginLogRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
@Operation(summary = "获得登录日志分页列表")
|
@Operation(summary = "获得登录日志分页列表")
|
||||||
@PreAuthorize("@ss.hasPermission('system:login-log:query')")
|
@PreAuthorize("@ss.hasPermission('system:login-log:query')")
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog;
|
package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
import cn.idev.excel.annotation.ExcelProperty;
|
import cn.idev.excel.annotation.ExcelProperty;
|
||||||
|
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
|
||||||
import com.fhs.core.trans.anno.Trans;
|
import com.fhs.core.trans.anno.Trans;
|
||||||
import com.fhs.core.trans.constant.TransType;
|
import com.fhs.core.trans.constant.TransType;
|
||||||
import com.fhs.core.trans.vo.VO;
|
import com.fhs.core.trans.vo.VO;
|
||||||
@@ -31,6 +33,11 @@ public class OperateLogRespVO implements VO {
|
|||||||
@ExcelProperty("操作人")
|
@ExcelProperty("操作人")
|
||||||
private String userName;
|
private String userName;
|
||||||
|
|
||||||
|
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1", implementation = Integer.class)
|
||||||
|
@ExcelProperty("用户类型")
|
||||||
|
@DictFormat(DictTypeConstants.USER_TYPE)
|
||||||
|
private Integer userType;
|
||||||
|
|
||||||
@Schema(description = "操作模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单")
|
@Schema(description = "操作模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单")
|
||||||
@ExcelProperty("操作模块类型")
|
@ExcelProperty("操作模块类型")
|
||||||
private String type;
|
private String type;
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogRespVO;
|
|||||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO;
|
||||||
import cn.iocoder.yudao.module.system.service.sms.SmsLogService;
|
import cn.iocoder.yudao.module.system.service.sms.SmsLogService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@@ -44,6 +46,15 @@ public class SmsLogController {
|
|||||||
return success(BeanUtils.toBean(pageResult, SmsLogRespVO.class));
|
return success(BeanUtils.toBean(pageResult, SmsLogRespVO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获得短信日志")
|
||||||
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:sms-log:query')")
|
||||||
|
public CommonResult<SmsLogRespVO> getSmsLog(@RequestParam("id") Long id) {
|
||||||
|
SmsLogDO smsLog = smsLogService.getSmsLog(id);
|
||||||
|
return success(BeanUtils.toBean(smsLog, SmsLogRespVO.class));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/export-excel")
|
@GetMapping("/export-excel")
|
||||||
@Operation(summary = "导出短信日志 Excel")
|
@Operation(summary = "导出短信日志 Excel")
|
||||||
@PreAuthorize("@ss.hasPermission('system:sms-log:export')")
|
@PreAuthorize("@ss.hasPermission('system:sms-log:export')")
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ import javax.validation.Valid;
|
|||||||
*/
|
*/
|
||||||
public interface LoginLogService {
|
public interface LoginLogService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得登录日志
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return 登录日志
|
||||||
|
*/
|
||||||
|
LoginLogDO getLoginLog(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得登录日志分页
|
* 获得登录日志分页
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ public class LoginLogServiceImpl implements LoginLogService {
|
|||||||
@Resource
|
@Resource
|
||||||
private LoginLogMapper loginLogMapper;
|
private LoginLogMapper loginLogMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginLogDO getLoginLog(Long id) {
|
||||||
|
return loginLogMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<LoginLogDO> getLoginLogPage(LoginLogPageReqVO pageReqVO) {
|
public PageResult<LoginLogDO> getLoginLogPage(LoginLogPageReqVO pageReqVO) {
|
||||||
return loginLogMapper.selectPage(pageReqVO);
|
return loginLogMapper.selectPage(pageReqVO);
|
||||||
|
|||||||
@@ -11,16 +11,18 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
|
|||||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper;
|
||||||
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
|
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import java.util.ArrayList;
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
@@ -53,7 +55,7 @@ public class MailTemplateServiceImpl implements MailTemplateService {
|
|||||||
|
|
||||||
// 插入
|
// 插入
|
||||||
MailTemplateDO template = BeanUtils.toBean(createReqVO, MailTemplateDO.class)
|
MailTemplateDO template = BeanUtils.toBean(createReqVO, MailTemplateDO.class)
|
||||||
.setParams(parseTemplateContentParams(createReqVO.getContent()));
|
.setParams(parseTemplateTitleAndContentParams(createReqVO.getTitle(), createReqVO.getContent()));
|
||||||
mailTemplateMapper.insert(template);
|
mailTemplateMapper.insert(template);
|
||||||
return template.getId();
|
return template.getId();
|
||||||
}
|
}
|
||||||
@@ -69,7 +71,7 @@ public class MailTemplateServiceImpl implements MailTemplateService {
|
|||||||
|
|
||||||
// 更新
|
// 更新
|
||||||
MailTemplateDO updateObj = BeanUtils.toBean(updateReqVO, MailTemplateDO.class)
|
MailTemplateDO updateObj = BeanUtils.toBean(updateReqVO, MailTemplateDO.class)
|
||||||
.setParams(parseTemplateContentParams(updateReqVO.getContent()));
|
.setParams(parseTemplateTitleAndContentParams(updateReqVO.getTitle(), updateReqVO.getContent()));
|
||||||
mailTemplateMapper.updateById(updateObj);
|
mailTemplateMapper.updateById(updateObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +131,77 @@ public class MailTemplateServiceImpl implements MailTemplateService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String formatMailTemplateContent(String content, Map<String, Object> params) {
|
public String formatMailTemplateContent(String content, Map<String, Object> params) {
|
||||||
return StrUtil.format(content, params);
|
// 1. 先替换模板变量
|
||||||
|
String formattedContent = StrUtil.format(content, params);
|
||||||
|
|
||||||
|
// 关联 Pull Request:https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1461 讨论
|
||||||
|
// 2.1 反转义HTML特殊字符
|
||||||
|
formattedContent = unescapeHtml(formattedContent);
|
||||||
|
// 2.2 处理代码块(确保<pre><code>标签格式正确)
|
||||||
|
formattedContent = formatHtmlCodeBlocks(formattedContent);
|
||||||
|
// 2.3 将最外层的 pre 标签替换为 div 标签
|
||||||
|
formattedContent = replaceOuterPreWithDiv(formattedContent);
|
||||||
|
return formattedContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String replaceOuterPreWithDiv(String content) {
|
||||||
|
if (StrUtil.isEmpty(content)) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
// 使用正则表达式匹配所有的 <pre> 标签,包括嵌套的 <code> 标签
|
||||||
|
String regex = "(?s)<pre[^>]*>(.*?)</pre>";
|
||||||
|
Pattern pattern = Pattern.compile(regex);
|
||||||
|
Matcher matcher = pattern.matcher(content);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (matcher.find()) {
|
||||||
|
// 提取 <pre> 标签内的内容
|
||||||
|
String innerContent = matcher.group(1);
|
||||||
|
// 返回 div 标签包裹的内容
|
||||||
|
matcher.appendReplacement(sb, "<div>" + innerContent + "</div>");
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反转义 HTML 特殊字符
|
||||||
|
*
|
||||||
|
* @param input 输入字符串
|
||||||
|
* @return 反转义后的字符串
|
||||||
|
*/
|
||||||
|
private String unescapeHtml(String input) {
|
||||||
|
if (StrUtil.isEmpty(input)) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
return input
|
||||||
|
.replace("&", "&")
|
||||||
|
.replace("<", "<")
|
||||||
|
.replace(">", ">")
|
||||||
|
.replace(""", "\"")
|
||||||
|
.replace("'", "'")
|
||||||
|
.replace(" ", " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化 HTML 中的代码块
|
||||||
|
*
|
||||||
|
* @param content 邮件内容
|
||||||
|
* @return 格式化后的邮件内容
|
||||||
|
*/
|
||||||
|
private String formatHtmlCodeBlocks(String content) {
|
||||||
|
// 匹配 <pre><code> 标签的代码块
|
||||||
|
Pattern codeBlockPattern = Pattern.compile("<pre\\s*.*?><code\\s*.*?>(.*?)</code></pre>", Pattern.DOTALL);
|
||||||
|
Matcher matcher = codeBlockPattern.matcher(content);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (matcher.find()) {
|
||||||
|
// 获取代码块内容
|
||||||
|
String codeBlock = matcher.group(1);
|
||||||
|
// 为代码块添加样式
|
||||||
|
String replacement = "<pre style=\"background-color: #f5f5f5; padding: 10px; border-radius: 5px; overflow-x: auto;\"><code>" + codeBlock + "</code></pre>";
|
||||||
|
matcher.appendReplacement(sb, replacement);
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -137,14 +209,31 @@ public class MailTemplateServiceImpl implements MailTemplateService {
|
|||||||
return mailTemplateMapper.selectCountByAccountId(accountId);
|
return mailTemplateMapper.selectCountByAccountId(accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析标题和内容中的参数
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public List<String> parseTemplateTitleAndContentParams(String title, String content) {
|
||||||
|
List<String> titleParams = ReUtil.findAllGroup1(PATTERN_PARAMS, title);
|
||||||
|
List<String> contentParams = ReUtil.findAllGroup1(PATTERN_PARAMS, content);
|
||||||
|
// 合并参数并去重
|
||||||
|
List<String> allParams = new ArrayList<>(titleParams);
|
||||||
|
for (String param : contentParams) {
|
||||||
|
if (!allParams.contains(param)) {
|
||||||
|
allParams.add(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allParams;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得邮件模板中的参数,形如 {key}
|
* 获得邮件模板中的参数,形如 {key}
|
||||||
*
|
*
|
||||||
* @param content 内容
|
* @param content 内容
|
||||||
* @return 参数列表
|
* @return 参数列表
|
||||||
*/
|
*/
|
||||||
private List<String> parseTemplateContentParams(String content) {
|
List<String> parseTemplateContentParams(String content) {
|
||||||
return ReUtil.findAllGroup1(PATTERN_PARAMS, content);
|
return ReUtil.findAllGroup1(PATTERN_PARAMS, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -255,6 +255,9 @@ public class MenuServiceImpl implements MenuService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 如果 id 为空,说明不用比较是否为相同 id 的菜单
|
// 如果 id 为空,说明不用比较是否为相同 id 的菜单
|
||||||
|
if (id == null) {
|
||||||
|
throw exception(MENU_NAME_DUPLICATE);
|
||||||
|
}
|
||||||
if (!menu.getId().equals(id)) {
|
if (!menu.getId().equals(id)) {
|
||||||
throw exception(MENU_NAME_DUPLICATE);
|
throw exception(MENU_NAME_DUPLICATE);
|
||||||
}
|
}
|
||||||
@@ -277,7 +280,7 @@ public class MenuServiceImpl implements MenuService {
|
|||||||
}
|
}
|
||||||
// 如果 id 为空,说明不用比较是否为相同 id 的菜单
|
// 如果 id 为空,说明不用比较是否为相同 id 的菜单
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
return;
|
throw exception(MENU_COMPONENT_NAME_DUPLICATE);
|
||||||
}
|
}
|
||||||
if (!menu.getId().equals(id)) {
|
if (!menu.getId().equals(id)) {
|
||||||
throw exception(MENU_COMPONENT_NAME_DUPLICATE);
|
throw exception(MENU_COMPONENT_NAME_DUPLICATE);
|
||||||
|
|||||||
@@ -58,6 +58,14 @@ public interface SmsLogService {
|
|||||||
void updateSmsReceiveResult(Long id, String apiSerialNo, Boolean success,
|
void updateSmsReceiveResult(Long id, String apiSerialNo, Boolean success,
|
||||||
LocalDateTime receiveTime, String apiReceiveCode, String apiReceiveMsg);
|
LocalDateTime receiveTime, String apiReceiveCode, String apiReceiveMsg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得短信日志
|
||||||
|
*
|
||||||
|
* @param id 日志编号
|
||||||
|
* @return 短信日志
|
||||||
|
*/
|
||||||
|
SmsLogDO getSmsLog(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得短信日志分页
|
* 获得短信日志分页
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -78,6 +78,11 @@ public class SmsLogServiceImpl implements SmsLogService {
|
|||||||
.receiveTime(receiveTime).apiReceiveCode(apiReceiveCode).apiReceiveMsg(apiReceiveMsg).build());
|
.receiveTime(receiveTime).apiReceiveCode(apiReceiveCode).apiReceiveMsg(apiReceiveMsg).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SmsLogDO getSmsLog(Long id) {
|
||||||
|
return smsLogMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageResult<SmsLogDO> getSmsLogPage(SmsLogPageReqVO pageReqVO) {
|
public PageResult<SmsLogDO> getSmsLogPage(SmsLogPageReqVO pageReqVO) {
|
||||||
return smsLogMapper.selectPage(pageReqVO);
|
return smsLogMapper.selectPage(pageReqVO);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user