From e9616a69c5a6013a4051fc5ae7eb8e884002dfe0 Mon Sep 17 00:00:00 2001 From: Wang Date: Tue, 13 Jan 2026 10:22:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B4=BB=E5=8A=A8=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=E8=AE=BE=E8=AE=A1=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seer/teach/common/utils/CommonUtils.java | 2 +- .../common/utils/PageConverterUtils.java | 14 + seer-dependencies/pom.xml | 5 +- .../mp/api/dto/ActivityFormExecutionDTO.java | 46 ++++ .../mp/api/dto/ActivityFormFieldDTO.java | 50 ++++ .../mp/api/dto/ActivityFormTemplateDTO.java | 29 ++ .../mp/api/dto/ActivityFormVariableDTO.java | 35 +++ .../teach/mp/entity/MpActivityFormEntity.java | 50 ++++ .../entity/MpActivityFormExecutionEntity.java | 74 +++++ .../mp/entity/MpActivityFormFieldEntity.java | 84 ++++++ .../entity/MpActivityFormRelationEntity.java | 47 ++++ .../entity/MpActivityFormVariableEntity.java | 54 ++++ .../mapper/MpActivityFormExecutionMapper.java | 18 ++ .../mp/mapper/MpActivityFormFieldMapper.java | 18 ++ .../teach/mp/mapper/MpActivityFormMapper.java | 18 ++ .../mapper/MpActivityFormRelationMapper.java | 18 ++ .../mapper/MpActivityFormVariableMapper.java | 18 ++ .../AdminActivityFormController.java | 81 ++++++ .../AdminActivityFormExecutionController.java | 77 ++++++ .../AdminActivityFormFieldController.java | 78 ++++++ .../AdminActivityFormRelationController.java | 63 +++++ .../AdminActivityFormVariableController.java | 78 ++++++ .../req/ActivityFormExecutionQueryReq.java | 50 ++++ .../req/ActivityFormFieldQueryReq.java | 58 ++++ .../req/ActivityFormPublishVersionReq.java | 15 ++ .../controller/req/ActivityFormQueryReq.java | 30 +++ .../admin/controller/req/ActivityFormReq.java | 40 +++ .../req/ActivityFormVariableQueryReq.java | 38 +++ .../resp/AdminActivityFormExecutionResp.java | 46 ++++ .../resp/AdminActivityFormFieldResp.java | 52 ++++ .../resp/AdminActivityFormRelationResp.java | 55 ++++ .../resp/AdminActivityFormResp.java | 42 +++ .../resp/AdminActivityFormVariableResp.java | 37 +++ .../convert/AdminActivityFormConvert.java | 20 ++ .../AdminActivityFormExecutionConvert.java | 15 ++ .../AdminActivityFormFieldConvert.java | 14 + .../AdminActivityFormVariableConvert.java | 20 ++ .../AdminMpActivityFormRelationConvert.java | 25 ++ .../IAdminActivityFormExecutionService.java | 56 ++++ .../IAdminActivityFormFieldService.java | 58 ++++ .../IAdminActivityFormRelationService.java | 43 +++ .../service/IAdminActivityFormService.java | 58 ++++ .../IAdminActivityFormVariableService.java | 58 ++++ ...AdminActivityFormExecutionServiceImpl.java | 90 +++++++ .../AdminActivityFormFieldServiceImpl.java | 99 +++++++ .../AdminActivityFormRelationServiceImpl.java | 90 +++++++ .../impl/AdminActivityFormServiceImpl.java | 109 ++++++++ .../AdminActivityFormVariableServiceImpl.java | 96 +++++++ .../V1.0.2__add_agent_activity_tables.sql | 1 + .../V1.0.5__add_activity_form_tables.sql | 105 ++++++++ .../controller/AppActivityFormController.java | 90 +++++++ .../controller/req/ActivityFormSubmitReq.java | 28 ++ .../req/AppActivityFormExecutionQueryReq.java | 19 ++ .../resp/AppActivityFormExecutionResp.java | 47 ++++ .../resp/AppActivityFormFieldResp.java | 39 +++ .../resp/AppActivityFormTemplateResp.java | 23 ++ .../app/convert/AppActivityFormConvert.java | 22 ++ .../app/service/IAppActivityFormService.java | 63 +++++ .../impl/AppActivityFormServiceImpl.java | 254 ++++++++++++++++++ .../AppAgentEmployeeRelationServiceImpl.java | 2 - .../IMpActivityFormExecutionService.java | 16 ++ .../service/IMpActivityFormFieldService.java | 16 ++ .../IMpActivityFormRelationService.java | 50 ++++ .../mp/service/IMpActivityFormService.java | 16 ++ .../IMpActivityFormVariableService.java | 16 ++ .../MpActivityFormExecutionServiceImpl.java | 24 ++ .../impl/MpActivityFormFieldServiceImpl.java | 24 ++ .../MpActivityFormRelationServiceImpl.java | 73 +++++ .../impl/MpActivityFormServiceImpl.java | 24 ++ .../MpActivityFormVariableServiceImpl.java | 24 ++ 70 files changed, 3243 insertions(+), 4 deletions(-) create mode 100644 seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormExecutionDTO.java create mode 100644 seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormFieldDTO.java create mode 100644 seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormTemplateDTO.java create mode 100644 seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormVariableDTO.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormEntity.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormExecutionEntity.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormFieldEntity.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormRelationEntity.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormVariableEntity.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormExecutionMapper.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormFieldMapper.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormMapper.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormRelationMapper.java create mode 100644 seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormVariableMapper.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormController.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormExecutionController.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormFieldController.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormRelationController.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormVariableController.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormExecutionQueryReq.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormFieldQueryReq.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormPublishVersionReq.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormQueryReq.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormReq.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormVariableQueryReq.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormExecutionResp.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormFieldResp.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormRelationResp.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormResp.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormVariableResp.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormConvert.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormExecutionConvert.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormFieldConvert.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormVariableConvert.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminMpActivityFormRelationConvert.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormExecutionService.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormFieldService.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormRelationService.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormService.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormVariableService.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormExecutionServiceImpl.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormFieldServiceImpl.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormRelationServiceImpl.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormServiceImpl.java create mode 100644 seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormVariableServiceImpl.java create mode 100644 seer-mp/seer-mp-service-app-bootstrap/src/main/resources/db/mysql/V1.0.5__add_activity_form_tables.sql create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/AppActivityFormController.java create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/req/ActivityFormSubmitReq.java create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/req/AppActivityFormExecutionQueryReq.java create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormExecutionResp.java create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormFieldResp.java create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormTemplateResp.java create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/convert/AppActivityFormConvert.java create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/IAppActivityFormService.java create mode 100644 seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/impl/AppActivityFormServiceImpl.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormExecutionService.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormFieldService.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormRelationService.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormService.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormVariableService.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormExecutionServiceImpl.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormFieldServiceImpl.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormRelationServiceImpl.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormServiceImpl.java create mode 100644 seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormVariableServiceImpl.java diff --git a/seer-common/common-utils/src/main/java/com/seer/teach/common/utils/CommonUtils.java b/seer-common/common-utils/src/main/java/com/seer/teach/common/utils/CommonUtils.java index 041cf1f..79ecf49 100644 --- a/seer-common/common-utils/src/main/java/com/seer/teach/common/utils/CommonUtils.java +++ b/seer-common/common-utils/src/main/java/com/seer/teach/common/utils/CommonUtils.java @@ -1 +1 @@ -package com.seer.teach.common.utils; import cn.hutool.core.collection.CollUtil; import cn.hutool.crypto.SecureUtil; import com.alibaba.fastjson2.JSON; import com.seer.teach.common.enums.ResultCodeEnum; import com.seer.teach.common.enums.Salt; import com.seer.teach.common.exception.FileUploadException; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.BinaryOperator; import java.util.function.Function; /** * @Author: Captain * @Autograph: 安稳 * @Description: 通用工具类,提供各种常用方法 * @Date: 2023-07-03 20:32:08 */ @Slf4j @Component public class CommonUtils { /** * 格式化数字,单位为 K(千)或 W(万) * * @param number 原始整数 * @return 格式化后的字符串,带单位 */ public static String formatNumber(int number) { if (number >= 10000) { // 单位为 W(万) double wValue = number / 10000.0; return String.format("%.2fW", wValue); } else { // 单位为 K(千) double kValue = number / 1000.0; return String.format("%.2fK", kValue); } } /** * 将 Linux 秒级时间戳字符串转换为 "MM月dd日" 格式 * * @param timestampStr 秒级时间戳字符串,如 "1703558400" * @return 格式化后的日期字符串,如 "12月26日" */ public static String formatTimestampToMonthDay(String timestampStr) { long timestamp = Long.parseLong(timestampStr); LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault()); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M月d日"); return dateTime.format(formatter); } /** * 将比例小数(如 0.9500)转换为百分比字符串(如 "95%") * * @param ratio 比例小数,范围应在 0 ~ 1 之间 * @return 百分比字符串,例如 "95%", "87.5%" * @throws IllegalArgumentException 如果比例不在 0~1 之间 */ public static String formatToPercentage(BigDecimal ratio) { if (ratio == null || ratio.compareTo(BigDecimal.ZERO) < 0 || ratio.compareTo(BigDecimal.ONE) > 0) { throw new IllegalArgumentException("比例必须在 0 和 1 之间"); } // 比例 × 100,保留最多一位小数(如 87.5%),也可以改为 setScale(0) 表示整数百分比 BigDecimal percentage = ratio.multiply(BigDecimal.valueOf(100)).setScale(1, RoundingMode.HALF_UP); return percentage.stripTrailingZeros().toPlainString() + "%"; } /** * 将比例小数(如 0.9500)转换为百分比数值(如 95.0) * * @param ratio 比例小数,范围应在 0 ~ 1 之间 * @return 百分比数值,例如 95.0, 87.5 * @throws IllegalArgumentException 如果比例不在 0~1 之间 */ public static BigDecimal formatToPercentageAsDecimal(BigDecimal ratio) { if (ratio == null || ratio.compareTo(BigDecimal.ZERO) < 0 || ratio.compareTo(BigDecimal.ONE) > 0) { throw new IllegalArgumentException("比例必须在 0 和 1 之间"); } // 比例 × 100,保留最多一位小数 BigDecimal percentage = ratio.multiply(BigDecimal.valueOf(100)).setScale(1, RoundingMode.HALF_UP); return percentage; } /** * 计算百分比,返回整数形式(如:95% 返回 95) * * @param part 部分值(分子) * @param total 总值(分母) * @return 百分比整数,如果总值为 0 则返回 0 */ public static int calculatePercentage(int part, int total) { if (total == 0) { // 防止除以0 return 0; } return (int) Math.round((double) part * 100 / total); } /** * 获取当前时间的Linux时间戳 * * @return 当前时间的Linux时间戳字符串 */ public static String getCurrentLinuxTimeCode() { return Long.toString(Instant.now().getEpochSecond()); } /** * 生成基于 userId 和当前时间戳的唯一文件名,保留文件原始扩展名 * * @param fileName 文件名称 * @return 唯一文件名(包含扩展名) */ public static String generateUniqueFileName(String fileName) { long timestamp = System.currentTimeMillis(); String randomPart = UUID.randomUUID().toString().replace("-", "").substring(0, 8); // 获取原始文件名 String originalFilename = fileName; // 提取扩展名 String extension = ""; if (originalFilename != null && originalFilename.contains(".")) { extension = originalFilename.substring(originalFilename.lastIndexOf(".")); } // 返回组合后的唯一文件名 return timestamp + randomPart + extension; } public static String generateUniqueFileName() { return generateUniqueFileName(""); } public static String generateUniqueFileName(Integer userId,MultipartFile file) { long timestamp = System.currentTimeMillis(); String randomPart = UUID.randomUUID().toString().replace("-", "").substring(0, 8); if(Objects.nonNull(userId)){ randomPart = randomPart + "_" + userId; } // 获取原始文件名 String originalFilename = file.getOriginalFilename(); // 提取扩展名 String extension = ""; if (originalFilename != null && originalFilename.contains(".")) { extension = originalFilename.substring(originalFilename.lastIndexOf(".")); } // 返回组合后的唯一文件名 return timestamp + randomPart + extension; } /** * 生成基于 childrenId 和当前时间戳的唯一 .wav 文件名 * * @param childrenId 用户ID * @return 唯一的 .wav 文件名 */ public static String generateWavFileName(Integer childrenId) { long timestamp = System.currentTimeMillis(); String randomPart = UUID.randomUUID().toString().replace("-", "").substring(0, 8); return childrenId + "_" + timestamp + "_" + randomPart + ".flac"; } /** * 基于当前时间生成唯一UUID格式的消息ID * * @return UUID风格的消息ID */ public static String generateUUIDMessageId() { try { String timestamp = getCurrentLinuxTimeCode(); String randomPart = UUID.randomUUID().toString(); String base = timestamp + "_" + randomPart; // 使用 SHA-1 生成摘要 MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] hash = md.digest(base.getBytes(StandardCharsets.UTF_8)); // 构造 UUID long mostSigBits = 0; long leastSigBits = 0; for (int i = 0; i < 8; i++) { mostSigBits = (mostSigBits << 8) | (hash[i] & 0xff); } for (int i = 8; i < 16; i++) { leastSigBits = (leastSigBits << 8) | (hash[i] & 0xff); } return new UUID(mostSigBits, leastSigBits).toString(); } catch (Exception e) { throw new RuntimeException("生成UUID消息ID失败", e); } } /** * 验证上传的文件是否为合法的图片类型 * * @param file 上传的文件 */ public static void isIllegalImageType(MultipartFile file) { long size = file.getSize(); String originalFilename = file.getOriginalFilename(); String contentType = file.getContentType(); log.info("上传文件信息 -> 文件名: {}, 大小: {} bytes (≈{} KB), 类型: {}", originalFilename, size, size / 1024, contentType); String filename = file.getOriginalFilename(); if (filename == null || !filename.contains(".")) { throw new FileUploadException(ResultCodeEnum.FILE_FORMAT_ERROR); } String extension = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase(); List allowedTypes = Arrays.asList("jpg", "jpeg", "png", "mp3", "apk"); if (!allowedTypes.contains(extension)) { throw new FileUploadException(ResultCodeEnum.FILE_FORMAT_ERROR); } } /** * 将data对象转换成List * * @param data 要转换的数据对象 * @param clazz 目标列表元素类型 * @return 转换后的列表对象 */ public static List parseJsonToListObject(Object data, Class clazz) { return JSON.parseArray(JSON.toJSONString(data), clazz); } /** * 将data对象转换成clazz对象 * * @param data 要转换的数据对象 * @param clazz 目标对象类型 * @return 转换后的对象 */ public static T parseJsonToObject(Object data, Class clazz) { return JSON.parseObject(JSON.toJSONString(data), clazz); } /** * 加密密码 * * @param password 需要加密的原始密码 * @return 加密后的密码字符串 */ public static String encryptPassword(String password) { return SecureUtil.md5(Salt.PREFIX.getMsg() + password + Salt.SUFFIX.getMsg()); } /** * 将时间戳转换为LocalDateTime * * @param timestampStr 时间戳字符串 * @return 转换后的LocalDateTime对象 */ public static LocalDateTime parseTimestamp(String timestampStr) { if (timestampStr == null || timestampStr.trim().isEmpty()) { return null; } long seconds = Long.parseLong(timestampStr); return LocalDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneId.systemDefault()); } /** * 从列表中获取指定属性的最小值 * * @param from 数据源列表 * @param valueFunc 属性提取函数 * @param 数据源类型 * @param 属性类型 * @return 最小值 */ public static > V getMinValue(List from, Function valueFunc) { if (CollUtil.isEmpty(from)) { return null; } // 断言,避免告警 assert from.size() > 0; T t = from.stream().min(Comparator.comparing(valueFunc)).get(); return valueFunc.apply(t); } /** * 计算评价最终综合评分 * * @param descriptionScores 商品评星 * @param benefitScores 服务评星 * @return 综合评分结果 */ public static Integer calcScores(Integer descriptionScores, Integer benefitScores) { // 计算评价最终综合评分 最终星数 = (商品评星 + 服务评星) / 2 BigDecimal sumScore = new BigDecimal(descriptionScores + benefitScores); BigDecimal divide = sumScore.divide(BigDecimal.valueOf(2L), 0, RoundingMode.DOWN); return divide.intValue(); } /** * 对集合中的元素按指定属性进行求和 * * @param from 数据源集合 * @param valueFunc 属性提取函数 * @param accumulator 累加器函数 * @param 数据源类型 * @param 属性类型 * @return 求和结果 */ public static > V getSumValue(Collection from, Function valueFunc, BinaryOperator accumulator) { return getSumValue(from, valueFunc, accumulator, null); } /** * 对集合中的元素按指定属性进行求和 * * @param from 数据源集合 * @param valueFunc 属性提取函数 * @param accumulator 累加器函数 * @param defaultValue 默认值 * @param 数据源类型 * @param 属性类型 * @return 求和结果 */ public static > V getSumValue(Collection from, Function valueFunc, BinaryOperator accumulator, V defaultValue) { if (CollUtil.isEmpty(from)) { return defaultValue; } // 断言,避免告警 assert !from.isEmpty(); return from.stream().map(valueFunc).filter(Objects::nonNull).reduce(accumulator).orElse(defaultValue); } } \ No newline at end of file +package com.seer.teach.common.utils; import cn.hutool.core.collection.CollUtil; import cn.hutool.crypto.SecureUtil; import com.alibaba.fastjson2.JSON; import com.seer.teach.common.enums.ResultCodeEnum; import com.seer.teach.common.enums.Salt; import com.seer.teach.common.exception.FileUploadException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.BinaryOperator; import java.util.function.Function; /** * @Author: Captain * @Autograph: 安稳 * @Description: 通用工具类,提供各种常用方法 * @Date: 2023-07-03 20:32:08 */ @Slf4j @Component public class CommonUtils { /** * 格式化数字,单位为 K(千)或 W(万) * * @param number 原始整数 * @return 格式化后的字符串,带单位 */ public static String formatNumber(int number) { if (number >= 10000) { // 单位为 W(万) double wValue = number / 10000.0; return String.format("%.2fW", wValue); } else { // 单位为 K(千) double kValue = number / 1000.0; return String.format("%.2fK", kValue); } } /** * 将 Linux 秒级时间戳字符串转换为 "MM月dd日" 格式 * * @param timestampStr 秒级时间戳字符串,如 "1703558400" * @return 格式化后的日期字符串,如 "12月26日" */ public static String formatTimestampToMonthDay(String timestampStr) { long timestamp = Long.parseLong(timestampStr); LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault()); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M月d日"); return dateTime.format(formatter); } /** * 将比例小数(如 0.9500)转换为百分比字符串(如 "95%") * * @param ratio 比例小数,范围应在 0 ~ 1 之间 * @return 百分比字符串,例如 "95%", "87.5%" * @throws IllegalArgumentException 如果比例不在 0~1 之间 */ public static String formatToPercentage(BigDecimal ratio) { if (ratio == null || ratio.compareTo(BigDecimal.ZERO) < 0 || ratio.compareTo(BigDecimal.ONE) > 0) { throw new IllegalArgumentException("比例必须在 0 和 1 之间"); } // 比例 × 100,保留最多一位小数(如 87.5%),也可以改为 setScale(0) 表示整数百分比 BigDecimal percentage = ratio.multiply(BigDecimal.valueOf(100)).setScale(1, RoundingMode.HALF_UP); return percentage.stripTrailingZeros().toPlainString() + "%"; } /** * 将比例小数(如 0.9500)转换为百分比数值(如 95.0) * * @param ratio 比例小数,范围应在 0 ~ 1 之间 * @return 百分比数值,例如 95.0, 87.5 * @throws IllegalArgumentException 如果比例不在 0~1 之间 */ public static BigDecimal formatToPercentageAsDecimal(BigDecimal ratio) { if (ratio == null || ratio.compareTo(BigDecimal.ZERO) < 0 || ratio.compareTo(BigDecimal.ONE) > 0) { throw new IllegalArgumentException("比例必须在 0 和 1 之间"); } // 比例 × 100,保留最多一位小数 BigDecimal percentage = ratio.multiply(BigDecimal.valueOf(100)).setScale(1, RoundingMode.HALF_UP); return percentage; } /** * 计算百分比,返回整数形式(如:95% 返回 95) * * @param part 部分值(分子) * @param total 总值(分母) * @return 百分比整数,如果总值为 0 则返回 0 */ public static int calculatePercentage(int part, int total) { if (total == 0) { // 防止除以0 return 0; } return (int) Math.round((double) part * 100 / total); } /** * 获取当前时间的Linux时间戳 * * @return 当前时间的Linux时间戳字符串 */ public static String getCurrentLinuxTimeCode() { return Long.toString(Instant.now().getEpochSecond()); } /** * 生成基于 userId 和当前时间戳的唯一文件名,保留文件原始扩展名 * * @param fileName 文件名称 * @return 唯一文件名(包含扩展名) */ public static String generateUniqueFileName(String fileName) { long timestamp = System.currentTimeMillis(); String randomPart = UUID.randomUUID().toString().replace("-", "").substring(0, 8); // 获取原始文件名 String originalFilename = fileName; // 提取扩展名 String extension = ""; if (originalFilename != null && originalFilename.contains(".")) { extension = originalFilename.substring(originalFilename.lastIndexOf(".")); } // 返回组合后的唯一文件名 return timestamp + randomPart + extension; } public static String generateUniqueFileName() { return generateUniqueFileName(""); } public static String generateUniqueFileName(Integer userId,MultipartFile file) { long timestamp = System.currentTimeMillis(); String randomPart = UUID.randomUUID().toString().replace("-", "").substring(0, 8); if(Objects.nonNull(userId)){ randomPart = randomPart + "_" + userId; } // 获取原始文件名 String originalFilename = file.getOriginalFilename(); // 提取扩展名 String extension = ""; if (originalFilename != null && originalFilename.contains(".")) { extension = originalFilename.substring(originalFilename.lastIndexOf(".")); } // 返回组合后的唯一文件名 return timestamp + randomPart + extension; } /** * 生成基于 childrenId 和当前时间戳的唯一 .wav 文件名 * * @param childrenId 用户ID * @return 唯一的 .wav 文件名 */ public static String generateWavFileName(Integer childrenId) { long timestamp = System.currentTimeMillis(); String randomPart = UUID.randomUUID().toString().replace("-", "").substring(0, 8); return childrenId + "_" + timestamp + "_" + randomPart + ".flac"; } /** * 基于当前时间生成唯一UUID格式的消息ID * * @return UUID风格的消息ID */ public static String generateUUIDMessageId() { try { String timestamp = getCurrentLinuxTimeCode(); String randomPart = UUID.randomUUID().toString(); String base = timestamp + "_" + randomPart; // 使用 SHA-1 生成摘要 MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] hash = md.digest(base.getBytes(StandardCharsets.UTF_8)); // 构造 UUID long mostSigBits = 0; long leastSigBits = 0; for (int i = 0; i < 8; i++) { mostSigBits = (mostSigBits << 8) | (hash[i] & 0xff); } for (int i = 8; i < 16; i++) { leastSigBits = (leastSigBits << 8) | (hash[i] & 0xff); } return new UUID(mostSigBits, leastSigBits).toString(); } catch (Exception e) { throw new RuntimeException("生成UUID消息ID失败", e); } } /** * 验证上传的文件是否为合法的图片类型 * * @param file 上传的文件 */ public static void isIllegalImageType(MultipartFile file) { long size = file.getSize(); String originalFilename = file.getOriginalFilename(); String contentType = file.getContentType(); log.info("上传文件信息 -> 文件名: {}, 大小: {} bytes (≈{} KB), 类型: {}", originalFilename, size, size / 1024, contentType); String filename = file.getOriginalFilename(); if (filename == null || !filename.contains(".")) { throw new FileUploadException(ResultCodeEnum.FILE_FORMAT_ERROR); } String extension = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase(); List allowedTypes = Arrays.asList("jpg", "jpeg", "png", "mp3", "apk"); if (!allowedTypes.contains(extension)) { throw new FileUploadException(ResultCodeEnum.FILE_FORMAT_ERROR); } } /** * 将data对象转换成List * * @param data 要转换的数据对象 * @param clazz 目标列表元素类型 * @return 转换后的列表对象 */ public static List parseJsonToListObject(Object data, Class clazz) { return JSON.parseArray(JSON.toJSONString(data), clazz); } /** * 将data对象转换成clazz对象 * * @param data 要转换的数据对象 * @param clazz 目标对象类型 * @return 转换后的对象 */ public static T parseJsonToObject(Object data, Class clazz) { return JSON.parseObject(JSON.toJSONString(data), clazz); } /** * 加密密码 * * @param password 需要加密的原始密码 * @return 加密后的密码字符串 */ public static String encryptPassword(String password) { return SecureUtil.md5(Salt.PREFIX.getMsg() + password + Salt.SUFFIX.getMsg()); } /** * 将时间戳转换为LocalDateTime * * @param timestampStr 时间戳字符串 * @return 转换后的LocalDateTime对象 */ public static LocalDateTime parseTimestamp(String timestampStr) { if (timestampStr == null || timestampStr.trim().isEmpty()) { return null; } long seconds = Long.parseLong(timestampStr); return LocalDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneId.systemDefault()); } /** * 从列表中获取指定属性的最小值 * * @param from 数据源列表 * @param valueFunc 属性提取函数 * @param 数据源类型 * @param 属性类型 * @return 最小值 */ public static > V getMinValue(List from, Function valueFunc) { if (CollUtil.isEmpty(from)) { return null; } // 断言,避免告警 assert from.size() > 0; T t = from.stream().min(Comparator.comparing(valueFunc)).get(); return valueFunc.apply(t); } /** * 计算评价最终综合评分 * * @param descriptionScores 商品评星 * @param benefitScores 服务评星 * @return 综合评分结果 */ public static Integer calcScores(Integer descriptionScores, Integer benefitScores) { // 计算评价最终综合评分 最终星数 = (商品评星 + 服务评星) / 2 BigDecimal sumScore = new BigDecimal(descriptionScores + benefitScores); BigDecimal divide = sumScore.divide(BigDecimal.valueOf(2L), 0, RoundingMode.DOWN); return divide.intValue(); } /** * 对集合中的元素按指定属性进行求和 * * @param from 数据源集合 * @param valueFunc 属性提取函数 * @param accumulator 累加器函数 * @param 数据源类型 * @param 属性类型 * @return 求和结果 */ public static > V getSumValue(Collection from, Function valueFunc, BinaryOperator accumulator) { return getSumValue(from, valueFunc, accumulator, null); } /** * 对集合中的元素按指定属性进行求和 * * @param from 数据源集合 * @param valueFunc 属性提取函数 * @param accumulator 累加器函数 * @param defaultValue 默认值 * @param 数据源类型 * @param 属性类型 * @return 求和结果 */ public static > V getSumValue(Collection from, Function valueFunc, BinaryOperator accumulator, V defaultValue) { if (CollUtil.isEmpty(from)) { return defaultValue; } // 断言,避免告警 assert !from.isEmpty(); return from.stream().map(valueFunc).filter(Objects::nonNull).reduce(accumulator).orElse(defaultValue); } /** * 生成新版本号 * * @param currentVersion 当前版本号 * @return 新版本号 */ public static String generateVersionNumber(String currentVersion) { if (StringUtils.isBlank(currentVersion)){ return "1.0.0"; } try { String[] parts = currentVersion.split("\\."); if (parts.length >= 3) { int major = Integer.parseInt(parts[0]); int minor = Integer.parseInt(parts[1]); int patch = Integer.parseInt(parts[2]); return major + "." + minor + "." + (patch + 1); } else { int major = Integer.parseInt(parts[0]); int minor = parts.length > 1 ? Integer.parseInt(parts[1]) : 0; return major + "." + (minor + 1) + ".0"; } } catch (NumberFormatException e) { log.warn("Failed to parse version number: {}, using fallback", currentVersion, e); return currentVersion + "." + System.currentTimeMillis(); } } } \ No newline at end of file diff --git a/seer-common/common-utils/src/main/java/com/seer/teach/common/utils/PageConverterUtils.java b/seer-common/common-utils/src/main/java/com/seer/teach/common/utils/PageConverterUtils.java index c44a08b..e1c5aee 100644 --- a/seer-common/common-utils/src/main/java/com/seer/teach/common/utils/PageConverterUtils.java +++ b/seer-common/common-utils/src/main/java/com/seer/teach/common/utils/PageConverterUtils.java @@ -43,6 +43,20 @@ public class PageConverterUtils { return result; } + public static PageListBean convertPageListBean( + IPage sourcePage, + List records) { + PageListBean result = new PageListBean<>(); + if (null == sourcePage || sourcePage.getRecords() == null || sourcePage.getRecords().isEmpty()) { + return result; + } + result.setList(records); + result.setPageSize(sourcePage.getSize()); + result.setTotalPage(sourcePage.getPages()); + result.setTotal(sourcePage.getTotal()); + return result; + } + /** * 分页数据转换方法 * 将MyBatis-Plus的IPage分页结果转换为目标分页Bean diff --git a/seer-dependencies/pom.xml b/seer-dependencies/pom.xml index f3db6b4..95b9bf4 100644 --- a/seer-dependencies/pom.xml +++ b/seer-dependencies/pom.xml @@ -757,7 +757,10 @@ UTF-8 true lines,vars,source - -parameters + + -parameters + -Xlint:-options + diff --git a/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormExecutionDTO.java b/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormExecutionDTO.java new file mode 100644 index 0000000..9885df0 --- /dev/null +++ b/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormExecutionDTO.java @@ -0,0 +1,46 @@ +package com.seer.teach.mp.api.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 活动表单执行实例DTO + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Schema(name = "ActivityFormExecutionDTO", description = "活动表单执行实例DTO") +@Data +public class ActivityFormExecutionDTO { + + private Integer id; + + @Schema(description = "执行编号") + private String executionNo; + + @Schema(description = "活动ID") + private Integer activityId; + + @Schema(description = "代理商ID") + private Integer agentId; + + @Schema(description = "使用的表单模板ID") + private Integer templateId; + + @Schema(description = "提交人ID(家长ID)") + private Integer submitterId; + + @Schema(description = "提交人姓名") + private String submitterName; + + @Schema(description = "提交时间") + private LocalDateTime submitTime; + + @Schema(description = "状态:draft-草稿,submitted-已提交,approved-已批准,rejected-已拒绝") + private String status; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormFieldDTO.java b/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormFieldDTO.java new file mode 100644 index 0000000..a4caeb7 --- /dev/null +++ b/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormFieldDTO.java @@ -0,0 +1,50 @@ +package com.seer.teach.mp.api.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 活动表单字段DTO + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Schema(name = "ActivityFormFieldDTO", description = "活动表单字段DTO") +@Data +public class ActivityFormFieldDTO { + + private Integer id; + + @Schema(description = "所属模板ID") + private Integer templateId; + + @Schema(description = "字段名称") + private String fieldName; + + @Schema(description = "字段代码(英文标识)") + private String fieldCode; + + @Schema(description = "字段类型:text, textarea, select, radio, checkbox, date, number等") + private String fieldType; + + @Schema(description = "字段选项(JSON格式,适用于select, radio, checkbox等)") + private String fieldOptions; + + @Schema(description = "占位符提示") + private String placeholder; + + @Schema(description = "是否必填:0-否,1-是") + private Integer isRequired; + + @Schema(description = "排序") + private Integer sortOrder; + + @Schema(description = "验证规则(JSON格式)") + private String validationRules; + + @Schema(description = "字段描述") + private String description; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormTemplateDTO.java b/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormTemplateDTO.java new file mode 100644 index 0000000..76db1ad --- /dev/null +++ b/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormTemplateDTO.java @@ -0,0 +1,29 @@ +package com.seer.teach.mp.api.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 活动表单模板DTO + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Schema(name = "ActivityFormTemplateDTO", description = "活动表单模板DTO") +@Data +public class ActivityFormTemplateDTO { + + private Integer id; + + @Schema(description = "表单模板名称") + private String templateName; + + @Schema(description = "表单模板描述") + private String templateDescription; + + @Schema(description = "状态:0-禁用,1-启用") + private Integer status; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormVariableDTO.java b/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormVariableDTO.java new file mode 100644 index 0000000..2639b99 --- /dev/null +++ b/seer-mp/seer-mp-api/src/main/java/com/seer/teach/mp/api/dto/ActivityFormVariableDTO.java @@ -0,0 +1,35 @@ +package com.seer.teach.mp.api.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + *

+ * 活动表单变量DTO + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Schema(name = "ActivityFormVariableDTO", description = "活动表单变量DTO") +@Data +public class ActivityFormVariableDTO { + + private Integer id; + + @Schema(description = "表单执行实例ID") + private Integer executionId; + + @Schema(description = "变量名称") + private String variableName; + + @Schema(description = "变量代码") + private String variableCode; + + @Schema(description = "变量值") + private String variableValue; + + @Schema(description = "数据类型:string, number, boolean, json等") + private String dataType; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormEntity.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormEntity.java new file mode 100644 index 0000000..b76cfa5 --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormEntity.java @@ -0,0 +1,50 @@ +package com.seer.teach.mp.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.seer.teach.common.entity.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + *

+ * 活动表单模板表 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Getter +@Setter +@TableName(value = "mp_activity_form",autoResultMap = true) +@Schema(name = "MpActivityFormEntity对象", description = "活动表单表") +public class MpActivityFormEntity extends BaseEntity { + + /** + * 表单名称 + */ + @TableField("form_name") + private String formName; + + /** + * 表单描述 + */ + @TableField("form_description") + private String formDescription; + + /** + * 配置 + */ + @TableField("config") + private String config; + + /** + * 字段列表 + */ + @TableField(value = "fields",typeHandler = JacksonTypeHandler.class) + private List fields; +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormExecutionEntity.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormExecutionEntity.java new file mode 100644 index 0000000..a9b3e8c --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormExecutionEntity.java @@ -0,0 +1,74 @@ +package com.seer.teach.mp.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.seer.teach.common.entity.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +/** + *

+ * 活动表单执行实例表 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Getter +@Setter +@TableName("mp_activity_form_execution") +@Schema(name = "MpActivityFormExecutionEntity对象", description = "活动表单执行实例表") +public class MpActivityFormExecutionEntity extends BaseEntity { + + /** + * 执行编号 + */ + @TableField("execution_no") + private String executionNo; + + /** + * 活动ID + */ + @TableField("activity_id") + private Integer activityId; + + /** + * 代理商ID + */ + @TableField("agent_id") + private Integer agentId; + + /** + * 使用的表单模板ID + */ + @TableField("form_id") + private Integer formId; + + /** + * 提交人ID(家长ID) + */ + @TableField("submitter_id") + private Integer submitterId; + + /** + * 提交人姓名 + */ + @TableField("submitter_name") + private String submitterName; + + /** + * 提交时间 + */ + @TableField("submit_time") + private LocalDateTime submitTime; + + /** + * 状态:draft-草稿,submitted-已提交,approved-已批准,rejected-已拒绝 + */ + @TableField("status") + private String status; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormFieldEntity.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormFieldEntity.java new file mode 100644 index 0000000..c989f31 --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormFieldEntity.java @@ -0,0 +1,84 @@ +package com.seer.teach.mp.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.seer.teach.common.entity.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 活动表单字段定义表 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Getter +@Setter +@TableName("mp_activity_form_field") +@Schema(name = "MpActivityFormFieldEntity对象", description = "活动表单字段定义表") +public class MpActivityFormFieldEntity extends BaseEntity { + + /** + * 所属模板ID + */ + @TableField("form_id") + private Integer formId; + + /** + * 字段名称 + */ + @TableField("field_name") + private String fieldName; + + /** + * 字段代码(英文标识) + */ + @TableField("field_code") + private String fieldCode; + + /** + * 字段类型:text, textarea, select, radio, checkbox, date, number等 + */ + @TableField("field_type") + private String fieldType; + + /** + * 字段选项(JSON格式,适用于select, radio, checkbox等) + */ + @TableField("field_options") + private String fieldOptions; + + /** + * 占位符提示 + */ + @TableField("placeholder") + private String placeholder; + + /** + * 是否必填:0-否,1-是 + */ + @TableField("is_required") + private Integer isRequired; + + /** + * 排序 + */ + @TableField("sort_order") + private Integer sortOrder; + + /** + * 验证规则(JSON格式) + */ + @TableField("validation_rules") + private String validationRules; + + /** + * 字段描述 + */ + @TableField("description") + private String description; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormRelationEntity.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormRelationEntity.java new file mode 100644 index 0000000..12bd3d5 --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormRelationEntity.java @@ -0,0 +1,47 @@ +package com.seer.teach.mp.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.seer.teach.common.entity.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 活动与表单模板关联表 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Getter +@Setter +@TableName("mp_activity_form_relation") +@Schema(name = "MpActivityFormRelationEntity对象", description = "活动与表单模板关联表") +public class MpActivityFormRelationEntity extends BaseEntity { + + /** + * 活动ID + */ + @TableField("activity_id") + private Integer activityId; + + /** + * 表单模板ID + */ + @TableField("form_id") + private Integer formId; + + /** + * 是否主要:0-否,1-是 + */ + @TableField("is_primary") + private Integer isPrimary; + + /** + * 版本,如1.0.0 + */ + @TableField("version") + private String version; +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormVariableEntity.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormVariableEntity.java new file mode 100644 index 0000000..ac48379 --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/entity/MpActivityFormVariableEntity.java @@ -0,0 +1,54 @@ +package com.seer.teach.mp.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.seer.teach.common.entity.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 活动表单变量表 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Getter +@Setter +@TableName("mp_activity_form_variable") +@Schema(name = "MpActivityFormVariableEntity对象", description = "活动表单变量表") +public class MpActivityFormVariableEntity extends BaseEntity { + + /** + * 表单执行实例ID + */ + @TableField("execution_id") + private Integer executionId; + + /** + * 变量名称 + */ + @TableField("variable_name") + private String variableName; + + /** + * 变量代码 + */ + @TableField("variable_code") + private String variableCode; + + /** + * 变量值 + */ + @TableField("variable_value") + private String variableValue; + + /** + * 数据类型:string, number, boolean, json等 + */ + @TableField("data_type") + private String dataType; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormExecutionMapper.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormExecutionMapper.java new file mode 100644 index 0000000..3e9fd63 --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormExecutionMapper.java @@ -0,0 +1,18 @@ +package com.seer.teach.mp.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.seer.teach.mp.entity.MpActivityFormExecutionEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 活动表单执行实例表 Mapper 接口 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Mapper +public interface MpActivityFormExecutionMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormFieldMapper.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormFieldMapper.java new file mode 100644 index 0000000..2b40d69 --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormFieldMapper.java @@ -0,0 +1,18 @@ +package com.seer.teach.mp.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.seer.teach.mp.entity.MpActivityFormFieldEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 活动表单字段定义表 Mapper 接口 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Mapper +public interface MpActivityFormFieldMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormMapper.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormMapper.java new file mode 100644 index 0000000..3de0848 --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormMapper.java @@ -0,0 +1,18 @@ +package com.seer.teach.mp.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.seer.teach.mp.entity.MpActivityFormEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 活动表单模板表 Mapper 接口 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Mapper +public interface MpActivityFormMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormRelationMapper.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormRelationMapper.java new file mode 100644 index 0000000..42844d8 --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormRelationMapper.java @@ -0,0 +1,18 @@ +package com.seer.teach.mp.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.seer.teach.mp.entity.MpActivityFormRelationEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 活动与表单模板关联表 Mapper 接口 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Mapper +public interface MpActivityFormRelationMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormVariableMapper.java b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormVariableMapper.java new file mode 100644 index 0000000..7f691bd --- /dev/null +++ b/seer-mp/seer-mp-data-module/src/main/java/com/seer/teach/mp/mapper/MpActivityFormVariableMapper.java @@ -0,0 +1,18 @@ +package com.seer.teach.mp.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.seer.teach.mp.entity.MpActivityFormVariableEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 活动表单变量表 Mapper 接口 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Mapper +public interface MpActivityFormVariableMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormController.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormController.java new file mode 100644 index 0000000..f255e82 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormController.java @@ -0,0 +1,81 @@ +package com.seer.teach.mp.admin.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.seer.teach.common.ResultBean; +import com.seer.teach.common.annotation.DecryptionAnnotation; +import com.seer.teach.common.annotation.EncryptionAnnotation; +import com.seer.teach.common.annotation.LogPrint; +import com.seer.teach.mp.admin.controller.req.ActivityFormReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormResp; +import com.seer.teach.mp.admin.service.IAdminActivityFormService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 活动表单管理端控制器 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Tag(name = "ADMIN - 活动表单") +@RestController +@RequestMapping("/activity/form") +@LogPrint +@EncryptionAnnotation +@DecryptionAnnotation +@RequiredArgsConstructor +public class AdminActivityFormController { + + private final IAdminActivityFormService adminActivityFormService; + + @Operation(summary = "创建表单") + @PostMapping("/save") + @SaCheckPermission("mp:admin:activity:form:save") + public ResultBean save(@Valid @RequestBody ActivityFormReq request) { + Boolean result = adminActivityFormService.save(request); + return ResultBean.success(result); + } + + @Operation(summary = "更新表单") + @PostMapping("/update") + @SaCheckPermission("mp:admin:activity:form:update") + public ResultBean update(@Valid @RequestBody ActivityFormReq request) { + Boolean result = adminActivityFormService.update(request); + return ResultBean.success(result); + } + + @Operation(summary = "删除表单") + @DeleteMapping("/{id}") + @SaCheckPermission("mp:admin:activity:form:delete") + public ResultBean delete(@PathVariable Integer id) { + Boolean result = adminActivityFormService.deleteById(id); + return ResultBean.success(result); + } + + @Operation(summary = "详情") + @GetMapping("/{id}") + @SaCheckPermission("mp:admin:activity:form:get") + public ResultBean get(@PathVariable Integer id) { + AdminActivityFormResp result = adminActivityFormService.getById(id); + return ResultBean.success(result); + } + + @Operation(summary = "发布新版本") + @PostMapping("/publish-new-version") + @SaCheckPermission("mp:admin:activity:form:publish") + public ResultBean publishNewVersion(@RequestBody @Valid ActivityFormReq req) { + Boolean result = adminActivityFormService.publishNewVersion(req); + return ResultBean.success(result); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormExecutionController.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormExecutionController.java new file mode 100644 index 0000000..bebda96 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormExecutionController.java @@ -0,0 +1,77 @@ +package com.seer.teach.mp.admin.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.seer.teach.common.PageListBean; +import com.seer.teach.common.ResultBean; +import com.seer.teach.common.annotation.DecryptionAnnotation; +import com.seer.teach.common.annotation.EncryptionAnnotation; +import com.seer.teach.common.annotation.LogPrint; +import com.seer.teach.mp.admin.controller.req.ActivityFormExecutionQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormExecutionResp; +import com.seer.teach.mp.admin.service.IAdminActivityFormExecutionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import jakarta.validation.Valid; + +/** + *

+ * 活动表单执行实例管理端控制器 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Tag(name = "ADMIN - 活动表单执行实例") +@RestController +@RequestMapping("/activity/form/execution") +@LogPrint +@EncryptionAnnotation +@DecryptionAnnotation +@RequiredArgsConstructor +public class AdminActivityFormExecutionController { + + private final IAdminActivityFormExecutionService adminActivityFormExecutionService; + + @Operation(summary = "表单执行实例列表") + @PostMapping("/page-list") + @SaCheckPermission("mp:admin:activity:form:execution:list") + public ResultBean> pageList(@RequestBody @Valid ActivityFormExecutionQueryReq query) { + PageListBean result = adminActivityFormExecutionService.pageList(query); + return ResultBean.success(result); + } + + @Operation(summary = "创建或更新表单执行实例") + @PostMapping("/save") + @SaCheckPermission("mp:admin:activity:form:execution:save") + public ResultBean save(@Valid @RequestBody ActivityFormExecutionQueryReq request) { + Boolean result = adminActivityFormExecutionService.saveOrUpdate(request); + return ResultBean.success(result); + } + + @Operation(summary = "删除表单执行实例") + @DeleteMapping("/{id}") + @SaCheckPermission("mp:admin:activity:form:execution:delete") + public ResultBean delete(@PathVariable Integer id) { + Boolean result = adminActivityFormExecutionService.deleteById(id); + return ResultBean.success(result); + } + + @Operation(summary = "详情") + @GetMapping("/{id}") + @SaCheckPermission("mp:admin:activity:form:execution:get") + public ResultBean get(@PathVariable Integer id) { + AdminActivityFormExecutionResp result = adminActivityFormExecutionService.getById(id); + return ResultBean.success(result); + } + + @Operation(summary = "提交表单") + @PostMapping("/submit/{id}") + @SaCheckPermission("mp:admin:activity:form:execution:submit") + public ResultBean submit(@PathVariable Integer id) { + Boolean result = adminActivityFormExecutionService.submitById(id); + return ResultBean.success(result); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormFieldController.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormFieldController.java new file mode 100644 index 0000000..d9a95b1 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormFieldController.java @@ -0,0 +1,78 @@ +package com.seer.teach.mp.admin.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.seer.teach.common.PageListBean; +import com.seer.teach.common.ResultBean; +import com.seer.teach.common.annotation.DecryptionAnnotation; +import com.seer.teach.common.annotation.EncryptionAnnotation; +import com.seer.teach.common.annotation.LogPrint; +import com.seer.teach.mp.admin.controller.req.ActivityFormFieldQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormFieldResp; +import com.seer.teach.mp.admin.service.IAdminActivityFormFieldService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import jakarta.validation.Valid; +import java.util.List; + +/** + *

+ * 活动表单字段管理端控制器 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Tag(name = "ADMIN - 活动表单字段") +@RestController +@RequestMapping("/activity/form/field") +@LogPrint +@EncryptionAnnotation +@DecryptionAnnotation +@RequiredArgsConstructor +public class AdminActivityFormFieldController { + + private final IAdminActivityFormFieldService adminActivityFormFieldService; + + @Operation(summary = "表单字段列表") + @PostMapping("/page-list") + @SaCheckPermission("mp:admin:activity:form:field:list") + public ResultBean> pageList(@RequestBody @Valid ActivityFormFieldQueryReq query) { + PageListBean result = adminActivityFormFieldService.pageList(query); + return ResultBean.success(result); + } + + @Operation(summary = "创建或更新表单字段") + @PostMapping("/save") + @SaCheckPermission("mp:admin:activity:form:field:save") + public ResultBean save(@Valid @RequestBody ActivityFormFieldQueryReq request) { + Boolean result = adminActivityFormFieldService.saveOrUpdate(request); + return ResultBean.success(result); + } + + @Operation(summary = "删除表单字段") + @DeleteMapping("/{id}") + @SaCheckPermission("mp:admin:activity:form:field:delete") + public ResultBean delete(@PathVariable Integer id) { + Boolean result = adminActivityFormFieldService.deleteById(id); + return ResultBean.success(result); + } + + @Operation(summary = "详情") + @GetMapping("/{id}") + @SaCheckPermission("mp:admin:activity:form:field:get") + public ResultBean get(@PathVariable Integer id) { + AdminActivityFormFieldResp result = adminActivityFormFieldService.getById(id); + return ResultBean.success(result); + } + + @Operation(summary = "根据模板ID获取字段列表") + @GetMapping("/list-by-template/{templateId}") + @SaCheckPermission("mp:admin:activity:form:field:list") + public ResultBean> listByTemplate(@PathVariable Integer templateId) { + List result = adminActivityFormFieldService.listByTemplateId(templateId); + return ResultBean.success(result); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormRelationController.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormRelationController.java new file mode 100644 index 0000000..f17f4ea --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormRelationController.java @@ -0,0 +1,63 @@ +package com.seer.teach.mp.admin.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.seer.teach.common.ResultBean; +import com.seer.teach.common.annotation.DecryptionAnnotation; +import com.seer.teach.common.annotation.EncryptionAnnotation; +import com.seer.teach.common.annotation.LogPrint; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormRelationResp; +import com.seer.teach.mp.admin.service.IAdminActivityFormRelationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + *

+ * 活动与表单关联管理端控制器 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Tag(name = "ADMIN - 活动与表单关联") +@RestController +@RequestMapping("/activity/form/relation") +@LogPrint +@EncryptionAnnotation +@DecryptionAnnotation +@RequiredArgsConstructor +public class AdminActivityFormRelationController { + + private final IAdminActivityFormRelationService adminActivityFormRelationService; + + @Operation(summary = "为活动关联表单") + @PostMapping("/associate") + @SaCheckPermission("mp:admin:activity:form:relation:associate") + public ResultBean associateFormWithActivity( + @RequestParam Integer activityId, + @RequestParam Integer templateId) { + Boolean result = adminActivityFormRelationService.associateFormWithActivity(activityId, templateId); + return ResultBean.success(result); + } + + @Operation(summary = "解除活动与表单的关联") + @DeleteMapping("/disassociate") + @SaCheckPermission("mp:admin:activity:form:relation:disassociate") + public ResultBean disassociateFormWithActivity( + @RequestParam Integer activityId, + @RequestParam Integer templateId) { + Boolean result = adminActivityFormRelationService.disassociateFormWithActivity(activityId, templateId); + return ResultBean.success(result); + } + + @Operation(summary = "获取活动关联的表单列表") + @GetMapping("/{activityId}") + @SaCheckPermission("mp:admin:activity:form:relation:list") + public ResultBean> getFormsByActivity(@PathVariable Integer activityId) { + List result = adminActivityFormRelationService.getFormsByActivity(activityId); + return ResultBean.success(result); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormVariableController.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormVariableController.java new file mode 100644 index 0000000..4d4286b --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/AdminActivityFormVariableController.java @@ -0,0 +1,78 @@ +package com.seer.teach.mp.admin.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.seer.teach.common.PageListBean; +import com.seer.teach.common.ResultBean; +import com.seer.teach.common.annotation.DecryptionAnnotation; +import com.seer.teach.common.annotation.EncryptionAnnotation; +import com.seer.teach.common.annotation.LogPrint; +import com.seer.teach.mp.admin.controller.req.ActivityFormVariableQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormVariableResp; +import com.seer.teach.mp.admin.service.IAdminActivityFormVariableService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import jakarta.validation.Valid; +import java.util.List; + +/** + *

+ * 活动表单变量管理端控制器 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Tag(name = "ADMIN - 活动表单变量") +@RestController +@RequestMapping("/activity/form/variable") +@LogPrint +@EncryptionAnnotation +@DecryptionAnnotation +@RequiredArgsConstructor +public class AdminActivityFormVariableController { + + private final IAdminActivityFormVariableService adminActivityFormVariableService; + + @Operation(summary = "表单变量列表") + @PostMapping("/page-list") + @SaCheckPermission("mp:admin:activity:form:variable:list") + public ResultBean> pageList(@RequestBody @Valid ActivityFormVariableQueryReq query) { + PageListBean result = adminActivityFormVariableService.pageList(query); + return ResultBean.success(result); + } + + @Operation(summary = "创建或更新表单变量") + @PostMapping("/save") + @SaCheckPermission("mp:admin:activity:form:variable:save") + public ResultBean save(@Valid @RequestBody ActivityFormVariableQueryReq request) { + Boolean result = adminActivityFormVariableService.saveOrUpdate(request); + return ResultBean.success(result); + } + + @Operation(summary = "删除表单变量") + @DeleteMapping("/{id}") + @SaCheckPermission("mp:admin:activity:form:variable:delete") + public ResultBean delete(@PathVariable Integer id) { + Boolean result = adminActivityFormVariableService.deleteById(id); + return ResultBean.success(result); + } + + @Operation(summary = "详情") + @GetMapping("/{id}") + @SaCheckPermission("mp:admin:activity:form:variable:get") + public ResultBean get(@PathVariable Integer id) { + AdminActivityFormVariableResp result = adminActivityFormVariableService.getById(id); + return ResultBean.success(result); + } + + @Operation(summary = "根据执行实例ID获取变量列表") + @GetMapping("/list-by-execution/{executionId}") + @SaCheckPermission("mp:admin:activity:form:variable:list") + public ResultBean> listByExecution(@PathVariable Integer executionId) { + List result = adminActivityFormVariableService.listByExecutionId(executionId); + return ResultBean.success(result); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormExecutionQueryReq.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormExecutionQueryReq.java new file mode 100644 index 0000000..4764160 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormExecutionQueryReq.java @@ -0,0 +1,50 @@ +package com.seer.teach.mp.admin.controller.req; + +import com.seer.teach.common.request.PageRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.time.LocalDateTime; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "活动表单执行实例查询请求") +public class ActivityFormExecutionQueryReq extends PageRequest { + + @Schema(description = "ID") + private Integer id; + + @Schema(description = "执行编号") + @Size(max = 100, message = "执行编号长度不能超过100个字符") + private String executionNo; + + @Schema(description = "活动ID") + @NotNull(message = "活动ID不能为空") + private Integer activityId; + + @Schema(description = "代理商ID") + @NotNull(message = "代理商ID不能为空") + private Integer agentId; + + @Schema(description = "使用的表单ID") + @NotNull(message = "表单ID不能为空") + private Integer formId; + + @Schema(description = "提交人ID(家长ID)") + private Integer submitterId; + + @Schema(description = "提交人姓名") + @Size(max = 255, message = "提交人姓名长度不能超过255个字符") + private String submitterName; + + @Schema(description = "提交时间") + private LocalDateTime submitTime; + + @Schema(description = "状态:draft-草稿,submitted-已提交,approved-已批准,rejected-已拒绝") + @Size(max = 50, message = "状态长度不能超过50个字符") + private String status; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormFieldQueryReq.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormFieldQueryReq.java new file mode 100644 index 0000000..d1cf7e0 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormFieldQueryReq.java @@ -0,0 +1,58 @@ +package com.seer.teach.mp.admin.controller.req; + +import com.seer.teach.common.request.PageRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "活动表单字段查询请求") +public class ActivityFormFieldQueryReq extends PageRequest { + + @Schema(description = "ID") + private Integer id; + + @Schema(description = "所属ID") + @NotNull(message = "所属ID不能为空") + private Integer formId; + + @Schema(description = "字段名称") + @NotBlank(message = "字段名称不能为空") + @Size(max = 255, message = "字段名称长度不能超过255个字符") + private String fieldName; + + @Schema(description = "字段代码(英文标识)") + @NotBlank(message = "字段代码不能为空") + @Size(max = 100, message = "字段代码长度不能超过100个字符") + private String fieldCode; + + @Schema(description = "字段类型:text, textarea, select, radio, checkbox, date, number等") + @NotBlank(message = "字段类型不能为空") + @Size(max = 50, message = "字段类型长度不能超过50个字符") + private String fieldType; + + @Schema(description = "字段选项(JSON格式,适用于select, radio, checkbox等)") + private String fieldOptions; + + @Schema(description = "占位符提示") + @Size(max = 500, message = "占位符提示长度不能超过500个字符") + private String placeholder; + + @Schema(description = "是否必填:0-否,1-是") + private Integer isRequired; + + @Schema(description = "排序") + private Integer sortOrder; + + @Schema(description = "验证规则(JSON格式)") + private String validationRules; + + @Schema(description = "字段描述") + private String description; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormPublishVersionReq.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormPublishVersionReq.java new file mode 100644 index 0000000..3f9a65a --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormPublishVersionReq.java @@ -0,0 +1,15 @@ +package com.seer.teach.mp.admin.controller.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +@Data +@Schema(description = "活动表单发布新版本请求") +public class ActivityFormPublishVersionReq { + + @NotNull(message = "活动ID不能为空") + @Schema(description = "活动ID") + private Integer activityId; +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormQueryReq.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormQueryReq.java new file mode 100644 index 0000000..496720d --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormQueryReq.java @@ -0,0 +1,30 @@ +package com.seer.teach.mp.admin.controller.req; + +import com.seer.teach.common.request.PageRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "活动表单模板查询请求") +public class ActivityFormQueryReq extends PageRequest { + + @Schema(description = "ID") + private Integer id; + + @Schema(description = "表单名称") + @NotBlank(message = "表单名称不能为空") + @Size(max = 255, message = "表单名称长度不能超过255个字符") + private String formName; + + @Schema(description = "表单模板描述") + private String formDescription; + + @Schema(description = "状态:0-禁用,1-启用") + private Integer status; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormReq.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormReq.java new file mode 100644 index 0000000..94f59ef --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormReq.java @@ -0,0 +1,40 @@ +package com.seer.teach.mp.admin.controller.req; + +import com.seer.teach.common.request.PageRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "活动表单模板查询请求") +public class ActivityFormReq extends PageRequest { + + @Schema(description = "ID") + private Integer id; + + @Schema(description = "活动ID") + private Integer activityId; + + @Schema(description = "表单名称") + @NotBlank(message = "表单名称不能为空") + @Size(max = 255, message = "表单名称长度不能超过255个字符") + private String formName; + + @Schema(description = "表单模板描述") + private String formDescription; + + @Schema(description = "状态:0-禁用,1-启用") + private Integer status; + + @Schema(description = "表单配置") + private String config; + + @Schema(description = "表单字段") + private List fields; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormVariableQueryReq.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormVariableQueryReq.java new file mode 100644 index 0000000..ba98388 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/req/ActivityFormVariableQueryReq.java @@ -0,0 +1,38 @@ +package com.seer.teach.mp.admin.controller.req; + +import com.seer.teach.common.request.PageRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "活动表单变量查询请求") +public class ActivityFormVariableQueryReq extends PageRequest { + + @Schema(description = "ID") + private Integer id; + + @Schema(description = "表单执行实例ID") + @NotNull(message = "表单执行实例ID不能为空") + private Integer executionId; + + @Schema(description = "变量名称") + @Size(max = 255, message = "变量名称长度不能超过255个字符") + private String variableName; + + @Schema(description = "变量代码") + @Size(max = 100, message = "变量代码长度不能超过100个字符") + private String variableCode; + + @Schema(description = "变量值") + private String variableValue; + + @Schema(description = "数据类型:string, number, boolean, json等") + @Size(max = 50, message = "数据类型长度不能超过50个字符") + private String dataType; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormExecutionResp.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormExecutionResp.java new file mode 100644 index 0000000..a79cd1c --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormExecutionResp.java @@ -0,0 +1,46 @@ +package com.seer.teach.mp.admin.controller.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(name = "AdminActivityFormExecutionResp", description = "活动表单执行实例响应参数") +@Data +public class AdminActivityFormExecutionResp { + + private Integer id; + + @Schema(description = "执行编号") + private String executionNo; + + @Schema(description = "活动ID") + private Integer activityId; + + @Schema(description = "代理商ID") + private Integer agentId; + + @Schema(description = "使用的表单ID") + private Integer formId; + + @Schema(description = "提交人ID(家长ID)") + private Integer submitterId; + + @Schema(description = "提交人姓名") + private String submitterName; + + @Schema(description = "提交时间") + private LocalDateTime submitTime; + + @Schema(description = "状态:draft-草稿,submitted-已提交,approved-已批准,rejected-已拒绝") + private String status; + + @Schema(description = "创建人ID") + private Integer creatorId; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormFieldResp.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormFieldResp.java new file mode 100644 index 0000000..74a7f18 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormFieldResp.java @@ -0,0 +1,52 @@ +package com.seer.teach.mp.admin.controller.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(name = "AdminActivityFormFieldResp", description = "活动表单字段响应参数") +@Data +public class AdminActivityFormFieldResp { + + private Integer id; + + @Schema(description = "所属表单ID") + private Integer formId; + + @Schema(description = "字段名称") + private String fieldName; + + @Schema(description = "字段代码(英文标识)") + private String fieldCode; + + @Schema(description = "字段类型:text, textarea, select, radio, checkbox, date, number等") + private String fieldType; + + @Schema(description = "字段选项(JSON格式,适用于select, radio, checkbox等)") + private String fieldOptions; + + @Schema(description = "占位符提示") + private String placeholder; + + @Schema(description = "是否必填:0-否,1-是") + private Integer isRequired; + + @Schema(description = "排序") + private Integer sortOrder; + + @Schema(description = "验证规则(JSON格式)") + private String validationRules; + + @Schema(description = "字段描述") + private String description; + + @Schema(description = "创建人ID") + private Integer creatorId; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormRelationResp.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormRelationResp.java new file mode 100644 index 0000000..eec17a2 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormRelationResp.java @@ -0,0 +1,55 @@ +package com.seer.teach.mp.admin.controller.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(name = "AdminActivityFormRelationResp", description = "活动表单模板响应参数") +@Data +public class AdminActivityFormRelationResp { + + + /** + * 活动ID + */ + @Schema(description = "活动ID") + private Integer activityId; + + /** + * 表单模板ID + */ + @Schema(description = "表单ID") + private Integer formId; + + /** + * 是否主要:0-否,1-是 + */ + @Schema(description = "是否主要:0-否,1-是") + private Integer isPrimary; + + /** + * 版本,如1.0.0 + */ + @Schema(description = "版本,如1.0.0") + private String version; + + /** + * 表单名称 + */ + @Schema(description = "表单名称") + private String formName; + + /** + * 表单描述 + */ + @Schema(description = "表单描述") + private String fromDescription; + + /** + * 状态:0-禁用,1-启用 + */ + @Schema(description = "状态:0-禁用,1-启用") + private Integer status; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormResp.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormResp.java new file mode 100644 index 0000000..20b61bb --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormResp.java @@ -0,0 +1,42 @@ +package com.seer.teach.mp.admin.controller.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(name = "AdminActivityFormResp", description = "活动表单响应参数") +@Data +public class AdminActivityFormResp { + + /** + * 表单ID + */ + @Schema(description = "表单ID") + private Integer id; + + /** + * 活动ID + */ + @Schema(description = "活动ID") + private Integer activityId; + + /** + * 表单名称 + */ + @Schema(description = "表单名称") + private String formName; + + /** + * 表单描述 + */ + @Schema(description = "表单描述") + private String fromDescription; + + /** + * 表单字段 + */ + @Schema(description = "表单字段") + private List fields; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormVariableResp.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormVariableResp.java new file mode 100644 index 0000000..d922c76 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/controller/resp/AdminActivityFormVariableResp.java @@ -0,0 +1,37 @@ +package com.seer.teach.mp.admin.controller.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(name = "AdminActivityFormVariableResp", description = "活动表单变量响应参数") +@Data +public class AdminActivityFormVariableResp { + + private Integer id; + + @Schema(description = "表单执行实例ID") + private Integer executionId; + + @Schema(description = "变量名称") + private String variableName; + + @Schema(description = "变量代码") + private String variableCode; + + @Schema(description = "变量值") + private String variableValue; + + @Schema(description = "数据类型:string, number, boolean, json等") + private String dataType; + + @Schema(description = "创建人ID") + private Integer creatorId; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormConvert.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormConvert.java new file mode 100644 index 0000000..33dfde8 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormConvert.java @@ -0,0 +1,20 @@ +package com.seer.teach.mp.admin.convert; + +import com.seer.teach.mp.admin.controller.req.ActivityFormReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormRelationResp; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormResp; +import com.seer.teach.mp.entity.MpActivityFormEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AdminActivityFormConvert { + AdminActivityFormConvert INSTANCE = Mappers.getMapper(AdminActivityFormConvert.class); + + AdminActivityFormResp convertToResp(MpActivityFormEntity entity); + + + AdminActivityFormRelationResp convertToRelationResp(MpActivityFormEntity entity); + + MpActivityFormEntity convertToEntity(ActivityFormReq request); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormExecutionConvert.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormExecutionConvert.java new file mode 100644 index 0000000..1de9e46 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormExecutionConvert.java @@ -0,0 +1,15 @@ +package com.seer.teach.mp.admin.convert; + +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormExecutionResp; +import com.seer.teach.mp.entity.MpActivityFormExecutionEntity; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AdminActivityFormExecutionConvert { + AdminActivityFormExecutionConvert INSTANCE = Mappers.getMapper(AdminActivityFormExecutionConvert.class); + + + AdminActivityFormExecutionResp convertToResp(MpActivityFormExecutionEntity entity); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormFieldConvert.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormFieldConvert.java new file mode 100644 index 0000000..65965eb --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormFieldConvert.java @@ -0,0 +1,14 @@ +package com.seer.teach.mp.admin.convert; + +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormFieldResp; +import com.seer.teach.mp.entity.MpActivityFormFieldEntity; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AdminActivityFormFieldConvert { + AdminActivityFormFieldConvert INSTANCE = Mappers.getMapper(AdminActivityFormFieldConvert.class); + + AdminActivityFormFieldResp convertToResp(MpActivityFormFieldEntity entity); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormVariableConvert.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormVariableConvert.java new file mode 100644 index 0000000..23fa7ae --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminActivityFormVariableConvert.java @@ -0,0 +1,20 @@ +package com.seer.teach.mp.admin.convert; + +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormVariableResp; +import com.seer.teach.mp.entity.MpActivityFormVariableEntity; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AdminActivityFormVariableConvert { + AdminActivityFormVariableConvert INSTANCE = Mappers.getMapper(AdminActivityFormVariableConvert.class); + + @Mapping(source = "id", target = "id") + @Mapping(source = "executionId", target = "executionId") + @Mapping(source = "variableName", target = "variableName") + @Mapping(source = "variableCode", target = "variableCode") + @Mapping(source = "variableValue", target = "variableValue") + @Mapping(source = "dataType", target = "dataType") + AdminActivityFormVariableResp convertToResp(MpActivityFormVariableEntity entity); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminMpActivityFormRelationConvert.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminMpActivityFormRelationConvert.java new file mode 100644 index 0000000..7fff32d --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/convert/AdminMpActivityFormRelationConvert.java @@ -0,0 +1,25 @@ +package com.seer.teach.mp.admin.convert; + +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormRelationResp; +import com.seer.teach.mp.entity.MpActivityFormRelationEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface AdminMpActivityFormRelationConvert { + + AdminMpActivityFormRelationConvert INSTANCE = Mappers.getMapper(AdminMpActivityFormRelationConvert.class); + + /** + * 转换 + * + * @param entity + * @return + */ + AdminActivityFormRelationResp toAdminActivityFormRelationResp(MpActivityFormRelationEntity entity); + + + List toAdminActivityFormRelationRespList(List entityList); +} diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormExecutionService.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormExecutionService.java new file mode 100644 index 0000000..eceea5e --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormExecutionService.java @@ -0,0 +1,56 @@ +package com.seer.teach.mp.admin.service; + +import com.seer.teach.common.PageListBean; +import com.seer.teach.mp.admin.controller.req.ActivityFormExecutionQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormExecutionResp; + +/** + *

+ * 管理端活动表单执行实例服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IAdminActivityFormExecutionService { + + /** + * 分页查询活动表单执行实例 + * + * @param query 查询参数 + * @return 分页结果 + */ + PageListBean pageList(ActivityFormExecutionQueryReq query); + + /** + * 保存或更新活动表单执行实例 + * + * @param request 请求参数 + * @return 操作结果 + */ + Boolean saveOrUpdate(ActivityFormExecutionQueryReq request); + + /** + * 删除活动表单执行实例 + * + * @param id 实例ID + * @return 操作结果 + */ + Boolean deleteById(Integer id); + + /** + * 根据ID获取活动表单执行实例 + * + * @param id 实例ID + * @return 实例信息 + */ + AdminActivityFormExecutionResp getById(Integer id); + + /** + * 提交表单 + * + * @param id 实例ID + * @return 操作结果 + */ + Boolean submitById(Integer id); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormFieldService.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormFieldService.java new file mode 100644 index 0000000..8fdb9f4 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormFieldService.java @@ -0,0 +1,58 @@ +package com.seer.teach.mp.admin.service; + +import com.seer.teach.common.PageListBean; +import com.seer.teach.mp.admin.controller.req.ActivityFormFieldQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormFieldResp; + +import java.util.List; + +/** + *

+ * 管理端活动表单字段服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IAdminActivityFormFieldService { + + /** + * 分页查询活动表单字段 + * + * @param query 查询参数 + * @return 分页结果 + */ + PageListBean pageList(ActivityFormFieldQueryReq query); + + /** + * 保存或更新活动表单字段 + * + * @param request 请求参数 + * @return 操作结果 + */ + Boolean saveOrUpdate(ActivityFormFieldQueryReq request); + + /** + * 删除活动表单字段 + * + * @param id 字段ID + * @return 操作结果 + */ + Boolean deleteById(Integer id); + + /** + * 根据ID获取活动表单字段 + * + * @param id 字段ID + * @return 字段信息 + */ + AdminActivityFormFieldResp getById(Integer id); + + /** + * 根据模板ID获取字段列表 + * + * @param templateId 模板ID + * @return 字段列表 + */ + List listByTemplateId(Integer templateId); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormRelationService.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormRelationService.java new file mode 100644 index 0000000..f2f639d --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormRelationService.java @@ -0,0 +1,43 @@ +package com.seer.teach.mp.admin.service; + +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormRelationResp; + +import java.util.List; + +/** + *

+ * 管理端活动与表单关联服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IAdminActivityFormRelationService { + + /** + * 为活动关联表单 + * + * @param activityId 活动ID + * @param formId 表单ID + * @return 操作结果 + */ + Boolean associateFormWithActivity(Integer activityId, Integer formId); + + /** + * 解除活动与表单的关联 + * + * @param activityId 表单ID + * @param formId ID + * @return 操作结果 + */ + Boolean disassociateFormWithActivity(Integer activityId, Integer formId); + + /** + * 获取活动关联的表单列表 + * + * @param activityId 活动ID + * @return 表单列表 + */ + List getFormsByActivity(Integer activityId); + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormService.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormService.java new file mode 100644 index 0000000..2ab255d --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormService.java @@ -0,0 +1,58 @@ +package com.seer.teach.mp.admin.service; + +import com.seer.teach.common.PageListBean; +import com.seer.teach.mp.admin.controller.req.ActivityFormQueryReq; +import com.seer.teach.mp.admin.controller.req.ActivityFormReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormRelationResp; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormResp; + +/** + *

+ * 管理端活动表单模板服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IAdminActivityFormService { + + /** + * 保存活动表单模板 + * + * @param request 请求参数 + * @return 操作结果 + */ + Boolean save(ActivityFormReq request); + + /** + * 删除活动表单模板 + * + * @param id 模板ID + * @return 操作结果 + */ + Boolean deleteById(Integer id); + + /** + * 根据ID获取活动表单模板 + * + * @param id 模板ID + * @return 模板信息 + */ + AdminActivityFormResp getById(Integer id); + + /** + * 更新活动表单模板 + * + * @param request 模板信息 + * @return 操作结果 + */ + Boolean update(ActivityFormReq request); + + /** + * 发布新版本 + * + * @param req 请求参数 + * @return 操作结果 + */ + Boolean publishNewVersion(ActivityFormReq req); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormVariableService.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormVariableService.java new file mode 100644 index 0000000..35ef6c7 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/IAdminActivityFormVariableService.java @@ -0,0 +1,58 @@ +package com.seer.teach.mp.admin.service; + +import com.seer.teach.common.PageListBean; +import com.seer.teach.mp.admin.controller.req.ActivityFormVariableQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormVariableResp; + +import java.util.List; + +/** + *

+ * 管理端活动表单变量服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IAdminActivityFormVariableService { + + /** + * 分页查询活动表单变量 + * + * @param query 查询参数 + * @return 分页结果 + */ + PageListBean pageList(ActivityFormVariableQueryReq query); + + /** + * 保存或更新活动表单变量 + * + * @param request 请求参数 + * @return 操作结果 + */ + Boolean saveOrUpdate(ActivityFormVariableQueryReq request); + + /** + * 删除活动表单变量 + * + * @param id 变量ID + * @return 操作结果 + */ + Boolean deleteById(Integer id); + + /** + * 根据ID获取活动表单变量 + * + * @param id 变量ID + * @return 变量信息 + */ + AdminActivityFormVariableResp getById(Integer id); + + /** + * 根据执行实例ID获取变量列表 + * + * @param executionId 执行实例ID + * @return 变量列表 + */ + List listByExecutionId(Integer executionId); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormExecutionServiceImpl.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormExecutionServiceImpl.java new file mode 100644 index 0000000..0365f61 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormExecutionServiceImpl.java @@ -0,0 +1,90 @@ +package com.seer.teach.mp.admin.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.seer.teach.common.PageListBean; +import com.seer.teach.common.utils.PageConverterUtils; +import com.seer.teach.mp.admin.controller.req.ActivityFormExecutionQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormExecutionResp; +import com.seer.teach.mp.admin.convert.AdminActivityFormExecutionConvert; +import com.seer.teach.mp.admin.service.IAdminActivityFormExecutionService; +import com.seer.teach.mp.entity.MpActivityFormExecutionEntity; +import com.seer.teach.mp.service.IMpActivityFormExecutionService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +/** + *

+ * 管理端活动表单执行实例服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AdminActivityFormExecutionServiceImpl implements IAdminActivityFormExecutionService { + + private final IMpActivityFormExecutionService activityFormExecutionService; + + @Override + public PageListBean pageList(ActivityFormExecutionQueryReq query) { + Page page = new Page<>(query.getPageNo(), query.getPageSize()); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(query.getActivityId() != null, MpActivityFormExecutionEntity::getActivityId, query.getActivityId()) + .eq(query.getAgentId() != null, MpActivityFormExecutionEntity::getAgentId, query.getAgentId()) + .eq(query.getFormId() != null, MpActivityFormExecutionEntity::getFormId, query.getFormId()) + .eq(StringUtils.isNotBlank(query.getStatus()), + MpActivityFormExecutionEntity::getStatus, query.getStatus()) + .like(StringUtils.isNotBlank(query.getSubmitterName()), + MpActivityFormExecutionEntity::getSubmitterName, query.getSubmitterName()) + .orderByDesc(MpActivityFormExecutionEntity::getId); + + Page pageResult = activityFormExecutionService.page(page, wrapper); + + + return PageConverterUtils.convertPageList(pageResult, AdminActivityFormExecutionConvert.INSTANCE::convertToResp); + } + + @Override + public Boolean saveOrUpdate(ActivityFormExecutionQueryReq request) { + MpActivityFormExecutionEntity entity = new MpActivityFormExecutionEntity(); + BeanUtil.copyProperties(request, entity); + + if (request.getId() == null) { + // 新增时设置默认值 + entity.setStatus(entity.getStatus() == null ? "draft" : entity.getStatus()); + } + + return activityFormExecutionService.saveOrUpdate(entity); + } + + @Override + public Boolean deleteById(Integer id) { + return activityFormExecutionService.removeById(id); + } + + @Override + public AdminActivityFormExecutionResp getById(Integer id) { + if (id == null) { + return null; + } + MpActivityFormExecutionEntity entity = activityFormExecutionService.getById(id); + return AdminActivityFormExecutionConvert.INSTANCE.convertToResp(entity); + } + + @Override + public Boolean submitById(Integer id) { + MpActivityFormExecutionEntity entity = activityFormExecutionService.getById(id); + if (entity == null) { + return false; + } + entity.setStatus("submitted"); + return activityFormExecutionService.updateById(entity); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormFieldServiceImpl.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormFieldServiceImpl.java new file mode 100644 index 0000000..b969dee --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormFieldServiceImpl.java @@ -0,0 +1,99 @@ +package com.seer.teach.mp.admin.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.seer.teach.common.PageListBean; +import com.seer.teach.common.utils.PageConverterUtils; +import com.seer.teach.mp.admin.controller.req.ActivityFormFieldQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormFieldResp; +import com.seer.teach.mp.admin.convert.AdminActivityFormFieldConvert; +import com.seer.teach.mp.admin.service.IAdminActivityFormFieldService; +import com.seer.teach.mp.entity.MpActivityFormFieldEntity; +import com.seer.teach.mp.service.IMpActivityFormFieldService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 管理端活动表单字段服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AdminActivityFormFieldServiceImpl implements IAdminActivityFormFieldService { + + private final IMpActivityFormFieldService activityFormFieldService; + + @Override + public PageListBean pageList(ActivityFormFieldQueryReq query) { + Page page = new Page<>(query.getPageNo(), query.getPageSize()); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(query.getFormId() != null, MpActivityFormFieldEntity::getFormId, query.getFormId()) + .like(StringUtils.isNotBlank(query.getFieldName()), + MpActivityFormFieldEntity::getFieldName, query.getFieldName()) + .eq(StringUtils.isNotBlank(query.getFieldType()), + MpActivityFormFieldEntity::getFieldType, query.getFieldType()) + .orderByAsc(MpActivityFormFieldEntity::getSortOrder) + .orderByDesc(MpActivityFormFieldEntity::getId); + + Page pageResult = activityFormFieldService.page(page, wrapper); + + return PageConverterUtils.convertPageList(pageResult, AdminActivityFormFieldConvert.INSTANCE::convertToResp); + } + + @Override + public Boolean saveOrUpdate(ActivityFormFieldQueryReq request) { + MpActivityFormFieldEntity entity = new MpActivityFormFieldEntity(); + BeanUtil.copyProperties(request, entity); + + if (request.getId() == null) { + // 新增时设置默认值 + entity.setIsRequired(entity.getIsRequired() == null ? 0 : entity.getIsRequired()); + entity.setSortOrder(entity.getSortOrder() == null ? 0 : entity.getSortOrder()); + } + + return activityFormFieldService.saveOrUpdate(entity); + } + + @Override + public Boolean deleteById(Integer id) { + return activityFormFieldService.removeById(id); + } + + @Override + public AdminActivityFormFieldResp getById(Integer id) { + if (id == null) { + return null; + } + MpActivityFormFieldEntity entity = activityFormFieldService.getById(id); + return AdminActivityFormFieldConvert.INSTANCE.convertToResp(entity); + } + + @Override + public List listByTemplateId(Integer templateId) { + if (templateId == null) { + return java.util.Collections.emptyList(); + } + List entities = activityFormFieldService.list( + new LambdaQueryWrapper() + .eq(MpActivityFormFieldEntity::getFormId, templateId) + .orderByAsc(MpActivityFormFieldEntity::getSortOrder) + .orderByDesc(MpActivityFormFieldEntity::getId) + ); + + return entities.stream() + .map(AdminActivityFormFieldConvert.INSTANCE::convertToResp) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormRelationServiceImpl.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormRelationServiceImpl.java new file mode 100644 index 0000000..aa0de3e --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormRelationServiceImpl.java @@ -0,0 +1,90 @@ +package com.seer.teach.mp.admin.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormRelationResp; +import com.seer.teach.mp.admin.convert.AdminMpActivityFormRelationConvert; +import com.seer.teach.mp.admin.service.IAdminActivityFormRelationService; +import com.seer.teach.mp.entity.MpActivityFormEntity; +import com.seer.teach.mp.entity.MpActivityFormRelationEntity; +import com.seer.teach.mp.service.IMpActivityFormRelationService; +import com.seer.teach.mp.service.IMpActivityFormService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + *

+ * 管理端活动与表单模板关联服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AdminActivityFormRelationServiceImpl implements IAdminActivityFormRelationService { + + private final IMpActivityFormRelationService activityFormTemplateRelationService; + private final IMpActivityFormService activityFormTemplateService; + + @Override + public Boolean associateFormWithActivity(Integer activityId, Integer formId) { + return activityFormTemplateRelationService.createRelation(activityId, formId); + } + + @Override + public Boolean disassociateFormWithActivity(Integer activityId, Integer formId) { + return activityFormTemplateRelationService.remove( + new LambdaQueryWrapper() + .eq(MpActivityFormRelationEntity::getActivityId, activityId) + .eq(MpActivityFormRelationEntity::getFormId, formId) + ); + } + + @Override + public List getFormsByActivity(Integer activityId) { + if (activityId == null) { + return java.util.Collections.emptyList(); + } + List relations = activityFormTemplateRelationService.list( + new LambdaQueryWrapper() + .eq(MpActivityFormRelationEntity::getActivityId, activityId) + ); + if(CollectionUtil.isEmpty(relations)){ + return Collections.emptyList(); + } + List formIds = relations.stream() + .map(MpActivityFormRelationEntity::getFormId) + .collect(java.util.stream.Collectors.toList()); + + List forms = activityFormTemplateService.list( + new LambdaQueryWrapper() + .in(MpActivityFormEntity::getId, formIds) + ); + log.info("getFormsByActivity: {}", forms); + if(CollectionUtil.isEmpty(forms)){ + return Collections.emptyList(); + } + Map mapping = forms.stream().collect(Collectors.toMap(MpActivityFormEntity::getId, Function.identity(), (old, newOne) -> newOne)); + + List adminActivityFormRelationRespList = AdminMpActivityFormRelationConvert.INSTANCE.toAdminActivityFormRelationRespList(relations); + for (AdminActivityFormRelationResp adminActivityFormRelationResp : adminActivityFormRelationRespList) { + MpActivityFormEntity activityForm = mapping.get(adminActivityFormRelationResp.getFormId()); + if(Objects.nonNull(activityForm)){ + adminActivityFormRelationResp.setFormName(activityForm.getFormName()); + adminActivityFormRelationResp.setFromDescription(activityForm.getFormDescription()); + } + } + log.debug("getFormsByActivity: {}", adminActivityFormRelationRespList); + return adminActivityFormRelationRespList; + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormServiceImpl.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormServiceImpl.java new file mode 100644 index 0000000..0c8e9b6 --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormServiceImpl.java @@ -0,0 +1,109 @@ +package com.seer.teach.mp.admin.service.impl; + +import com.seer.teach.common.constants.CommonConstant; +import com.seer.teach.common.utils.CommonUtils; +import com.seer.teach.mp.admin.controller.req.ActivityFormReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormResp; +import com.seer.teach.mp.admin.convert.AdminActivityFormConvert; +import com.seer.teach.mp.admin.service.IAdminActivityFormService; +import com.seer.teach.mp.entity.MpActivityFormEntity; +import com.seer.teach.mp.entity.MpActivityFormRelationEntity; +import com.seer.teach.mp.service.IMpActivityFormRelationService; +import com.seer.teach.mp.service.IMpActivityFormService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +/** + *

+ * 管理端活动表单模板服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AdminActivityFormServiceImpl implements IAdminActivityFormService { + + private final IMpActivityFormService activityFormService; + + private final IMpActivityFormRelationService activityFormRelationService; + + @Override + public Boolean save(ActivityFormReq request) { + MpActivityFormEntity form = AdminActivityFormConvert.INSTANCE.convertToEntity(request); + boolean saveResult = activityFormService.save(form); + + if (saveResult) { + MpActivityFormRelationEntity relation = new MpActivityFormRelationEntity(); + relation.setActivityId(request.getActivityId()); + relation.setFormId(form.getId()); + Optional optionalRelation = activityFormRelationService.getLatestVersionByActivityId(request.getActivityId()); + if (optionalRelation.isPresent()) { + relation.setIsPrimary(CommonConstant.IS_NOT_DEFAULT); + relation.setVersion(CommonUtils.generateVersionNumber(optionalRelation.get().getVersion())); + } else { + relation.setIsPrimary(CommonConstant.IS_DEFAULT); + relation.setVersion("1.0.0"); + } + boolean saved = activityFormRelationService.save(relation); + log.info("保存关联关系:{}", saved); + } + return saveResult; + } + + @Override + public Boolean deleteById(Integer id) { + return activityFormService.removeById(id); + } + + @Override + public AdminActivityFormResp getById(Integer id) { + if (id == null) { + return null; + } + MpActivityFormEntity entity = activityFormService.getById(id); + return AdminActivityFormConvert.INSTANCE.convertToResp(entity); + } + + @Override + public Boolean update(ActivityFormReq request) { + if (request.getId() == null) { + return false; + } + MpActivityFormEntity form = AdminActivityFormConvert.INSTANCE.convertToEntity(request); + return activityFormService.updateById(form); + } + + @Override + public Boolean publishNewVersion(ActivityFormReq req) { + Integer activityId = req.getActivityId(); + if (activityId == null) { + return false; + } + Optional optionalRelation = activityFormRelationService.getLatestVersionByActivityId(activityId); + if (optionalRelation.isEmpty()) { + return false; + } + MpActivityFormRelationEntity latestRelation = optionalRelation.get(); + + // 复制当前表单信息创建新版本 + MpActivityFormEntity newForm = AdminActivityFormConvert.INSTANCE.convertToEntity(req); + // 保存新的表单记录 + boolean saved = activityFormService.save(newForm); + if (!saved) { + log.error("publishNewVersion失败:{}", newForm); + return false; + } + MpActivityFormRelationEntity newRelation = new MpActivityFormRelationEntity(); + newRelation.setActivityId(req.getActivityId()); + newRelation.setFormId(req.getId()); + newRelation.setIsPrimary(CommonConstant.IS_NOT_DEFAULT); + newRelation.setVersion(CommonUtils.generateVersionNumber(latestRelation.getVersion())); + return activityFormRelationService.save(newRelation); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormVariableServiceImpl.java b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormVariableServiceImpl.java new file mode 100644 index 0000000..d1a270f --- /dev/null +++ b/seer-mp/seer-mp-service-admin/src/main/java/com/seer/teach/mp/admin/service/impl/AdminActivityFormVariableServiceImpl.java @@ -0,0 +1,96 @@ +package com.seer.teach.mp.admin.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.seer.teach.common.PageListBean; +import com.seer.teach.common.utils.PageConverterUtils; +import com.seer.teach.mp.admin.controller.req.ActivityFormVariableQueryReq; +import com.seer.teach.mp.admin.controller.resp.AdminActivityFormVariableResp; +import com.seer.teach.mp.admin.convert.AdminActivityFormVariableConvert; +import com.seer.teach.mp.admin.service.IAdminActivityFormVariableService; +import com.seer.teach.mp.entity.MpActivityFormVariableEntity; +import com.seer.teach.mp.service.IMpActivityFormVariableService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 管理端活动表单变量服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AdminActivityFormVariableServiceImpl implements IAdminActivityFormVariableService { + + private final IMpActivityFormVariableService activityFormVariableService; + + @Override + public PageListBean pageList(ActivityFormVariableQueryReq query) { + Page page = new Page<>(query.getPageNo(), query.getPageSize()); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(query.getExecutionId() != null, MpActivityFormVariableEntity::getExecutionId, query.getExecutionId()) + .eq(StringUtils.isNotBlank(query.getVariableCode()), + MpActivityFormVariableEntity::getVariableCode, query.getVariableCode()) + .like(StringUtils.isNotBlank(query.getVariableName()), + MpActivityFormVariableEntity::getVariableName, query.getVariableName()) + .orderByDesc(MpActivityFormVariableEntity::getId); + + Page pageResult = activityFormVariableService.page(page, wrapper); + List records = pageResult.getRecords().stream() + .map(AdminActivityFormVariableConvert.INSTANCE::convertToResp) + .collect(Collectors.toList()); + + return PageConverterUtils.convertPageListBean(pageResult, records); + } + + @Override + public Boolean saveOrUpdate(ActivityFormVariableQueryReq request) { + MpActivityFormVariableEntity entity = new MpActivityFormVariableEntity(); + BeanUtil.copyProperties(request, entity); + + if (request.getId() == null) { + // 新增时设置默认值 + entity.setDataType(entity.getDataType() == null ? "string" : entity.getDataType()); + } + + return activityFormVariableService.saveOrUpdate(entity); + } + + @Override + public Boolean deleteById(Integer id) { + return activityFormVariableService.removeById(id); + } + + @Override + public AdminActivityFormVariableResp getById(Integer id) { + MpActivityFormVariableEntity entity = activityFormVariableService.getById(id); + return AdminActivityFormVariableConvert.INSTANCE.convertToResp(entity); + } + + @Override + public List listByExecutionId(Integer executionId) { + if (executionId == null) { + return java.util.Collections.emptyList(); + } + List entities = activityFormVariableService.list( + new LambdaQueryWrapper() + .eq(MpActivityFormVariableEntity::getExecutionId, executionId) + .orderByDesc(MpActivityFormVariableEntity::getId) + ); + + return entities.stream() + .map(AdminActivityFormVariableConvert.INSTANCE::convertToResp) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app-bootstrap/src/main/resources/db/mysql/V1.0.2__add_agent_activity_tables.sql b/seer-mp/seer-mp-service-app-bootstrap/src/main/resources/db/mysql/V1.0.2__add_agent_activity_tables.sql index a99ac6c..1188a1d 100644 --- a/seer-mp/seer-mp-service-app-bootstrap/src/main/resources/db/mysql/V1.0.2__add_agent_activity_tables.sql +++ b/seer-mp/seer-mp-service-app-bootstrap/src/main/resources/db/mysql/V1.0.2__add_agent_activity_tables.sql @@ -138,6 +138,7 @@ CREATE TABLE `mp_activity_info_collection` ( `region` varchar(255) COMMENT '地区', `parent_identity` varchar(20) COMMENT '家长身份(爸爸,妈妈)', `learning_situation` varchar(20) COMMENT '学习情况(优、良、中、差)', + `contact_call_count` int NOT NULL DEFAULT 0 COMMENT '代理商拨打电话联系家长次数', `weak_subject_ids` varchar(50) COMMENT '薄弱科目', `strong_subject_ids` varchar(50) COMMENT '优势科目', `weak_subject` varchar(50) COMMENT '偏科(数学、英语等)', diff --git a/seer-mp/seer-mp-service-app-bootstrap/src/main/resources/db/mysql/V1.0.5__add_activity_form_tables.sql b/seer-mp/seer-mp-service-app-bootstrap/src/main/resources/db/mysql/V1.0.5__add_activity_form_tables.sql new file mode 100644 index 0000000..c63756e --- /dev/null +++ b/seer-mp/seer-mp-service-app-bootstrap/src/main/resources/db/mysql/V1.0.5__add_activity_form_tables.sql @@ -0,0 +1,105 @@ +-- 创建表单表 +DROP TABLE IF EXISTS `mp_activity_form`; +CREATE TABLE `mp_activity_form` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `form_name` varchar(255) NOT NULL COMMENT '表单名称', + `form_description` text COMMENT '表单描述', + `config` text COMMENT '表单的配置信息', + `fields` text COMMENT '表单项的数组', + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `create_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `update_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '修改人', + `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` varchar(20) DEFAULT 'Default' COMMENT '租户id', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动表单表'; + +-- 创建表单字段定义表 +DROP TABLE IF EXISTS `mp_activity_form_field`; +CREATE TABLE `mp_activity_form_field` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `form_id` int NOT NULL COMMENT '所属ID', + `field_name` varchar(255) NOT NULL COMMENT '字段名称', + `field_code` varchar(100) NOT NULL COMMENT '字段代码(英文标识)', + `field_type` varchar(50) NOT NULL COMMENT '字段类型:text, textarea, select, radio, checkbox, date, number等', + `field_options` text COMMENT '字段选项(JSON格式,适用于select, radio, checkbox等)', + `placeholder` varchar(500) DEFAULT NULL COMMENT '占位符提示', + `is_required` tinyint NOT NULL DEFAULT '0' COMMENT '是否必填:0-否,1-是', + `sort_order` int DEFAULT '0' COMMENT '排序', + `validation_rules` text COMMENT '验证规则(JSON格式)', + `description` text COMMENT '字段描述', + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `create_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `update_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '修改人', + `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` varchar(20) DEFAULT 'Default' COMMENT '租户id', + PRIMARY KEY (`id`), + KEY `idx_form_id` (`form_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动表单字段定义表'; + +-- 创建表单执行实例表 +DROP TABLE IF EXISTS `mp_activity_form_execution`; +CREATE TABLE `mp_activity_form_execution` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `execution_no` varchar(100) NOT NULL COMMENT '执行编号', + `activity_id` int NOT NULL COMMENT '活动ID', + `agent_id` int NOT NULL COMMENT '代理商ID', + `form_id` int NOT NULL COMMENT '使用的表单ID', + `submitter_id` int DEFAULT NULL COMMENT '提交人ID(家长ID)', + `submitter_name` varchar(255) DEFAULT NULL COMMENT '提交人姓名', + `submit_time` datetime DEFAULT NULL COMMENT '提交时间', + `status` varchar(50) NOT NULL DEFAULT 'draft' COMMENT '状态:draft-草稿,submitted-已提交,approved-已批准,rejected-已拒绝', + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `create_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `update_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '修改人', + `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` varchar(20) DEFAULT 'Default' COMMENT '租户id', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_execution_no` (`execution_no`), + KEY `idx_activity_id` (`activity_id`), + KEY `idx_agent_id` (`agent_id`), + KEY `idx_form_id` (`form_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动表单执行实例表'; + +-- 创建表单变量表 +DROP TABLE IF EXISTS `mp_activity_form_variable`; +CREATE TABLE `mp_activity_form_variable` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `execution_id` int NOT NULL COMMENT '表单执行实例ID', + `variable_name` varchar(255) NOT NULL COMMENT '变量名称', + `variable_code` varchar(100) NOT NULL COMMENT '变量代码', + `variable_value` text NOT NULL COMMENT '变量值', + `data_type` varchar(50) DEFAULT 'string' COMMENT '数据类型:string, number, boolean, json等', + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `create_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '创建人', + `update_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '修改人', + `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` varchar(20) DEFAULT 'Default' COMMENT '租户id', + PRIMARY KEY (`id`), + KEY `idx_execution_id` (`execution_id`), + KEY `idx_variable_code` (`variable_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动表单变量表'; + +-- 创建活动与表单关联表 +DROP TABLE IF EXISTS `mp_activity_form_relation`; +CREATE TABLE `mp_activity_form_relation` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `activity_id` int NOT NULL COMMENT '活动ID', + `form_id` int NOT NULL COMMENT '表单ID', + `is_primary` tinyint NOT NULL DEFAULT '0' COMMENT '是否主要:0-否,1-是', + `version` varchar(32) NOT NULL DEFAULT '1.0.0' COMMENT '版本号', + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `create_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '创建人', + `update_by` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL COMMENT '修改人', + `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` varchar(20) DEFAULT 'Default' COMMENT '租户id', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_activity_template` (`activity_id`, `form_id`), + KEY `idx_activity_id` (`activity_id`), + KEY `idx_form_id` (`form_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动与表单关联表'; \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/AppActivityFormController.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/AppActivityFormController.java new file mode 100644 index 0000000..754be12 --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/AppActivityFormController.java @@ -0,0 +1,90 @@ +package com.seer.teach.mp.app.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.stp.StpUtil; +import com.seer.teach.common.PageListBean; +import com.seer.teach.common.ResultBean; +import com.seer.teach.common.annotation.DecryptionAnnotation; +import com.seer.teach.common.annotation.EncryptionAnnotation; +import com.seer.teach.common.annotation.LogPrint; +import com.seer.teach.mp.app.controller.req.ActivityFormSubmitReq; +import com.seer.teach.mp.app.controller.req.AppActivityFormExecutionQueryReq; +import com.seer.teach.mp.app.controller.resp.AppActivityFormExecutionResp; +import com.seer.teach.mp.app.controller.resp.AppActivityFormFieldResp; +import com.seer.teach.mp.app.controller.resp.AppActivityFormTemplateResp; +import com.seer.teach.mp.app.service.IAppActivityFormService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * APP端活动表单控制器 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Tag(name = "APP - 活动表单") +@RestController +@RequestMapping("/app/activity/form") +@LogPrint +@EncryptionAnnotation +@DecryptionAnnotation +@RequiredArgsConstructor +@Slf4j +public class AppActivityFormController { + + private final IAppActivityFormService appActivityFormService; + + @Operation(summary = "获取活动可用的表单") + @GetMapping("/template/{activityId}") + @SaCheckLogin + public ResultBean getTemplateByActivity(@PathVariable Integer activityId) { + AppActivityFormTemplateResp result = appActivityFormService.getTemplateByActivity(activityId); + return ResultBean.success(result); + } + + @Operation(summary = "获取表单字段列表") + @GetMapping("/field/{templateId}") + @SaCheckLogin + public ResultBean> getFieldList(@PathVariable Integer templateId) { + List result = appActivityFormService.getFieldListByTemplate(templateId); + return ResultBean.success(result); + } + + @Operation(summary = "获取用户提交的表单列表") + @PostMapping("/execution/page-list") + @SaCheckLogin + public ResultBean> getExecutionList(@RequestBody @Valid AppActivityFormExecutionQueryReq query) { + Integer userId = StpUtil.getLoginIdAsInt(); + PageListBean result = appActivityFormService.getExecutionList(query, userId); + return ResultBean.success(result); + } + + @Operation(summary = "提交表单") + @PostMapping("/submit") + @SaCheckLogin + public ResultBean submitForm(@RequestBody @Valid ActivityFormSubmitReq req) { + Integer userId = StpUtil.getLoginIdAsInt(); + String executionNo = appActivityFormService.submitForm(req, userId); + return ResultBean.success(executionNo); + } + + @Operation(summary = "获取表单执行详情") + @GetMapping("/execution/{id}") + @SaCheckLogin + public ResultBean getExecutionDetail(@PathVariable Integer id) { + return ResultBean.success(appActivityFormService.getExecutionWithFormData(id)); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/req/ActivityFormSubmitReq.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/req/ActivityFormSubmitReq.java new file mode 100644 index 0000000..2e9c0b3 --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/req/ActivityFormSubmitReq.java @@ -0,0 +1,28 @@ +package com.seer.teach.mp.app.controller.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; +import java.util.Map; + +@Data +@Schema(description = "活动表单提交请求") +public class ActivityFormSubmitReq { + + @Schema(description = "活动ID") + @NotNull(message = "活动ID不能为空") + private Integer activityId; + + @Schema(description = "代理商ID") + @NotNull(message = "代理商ID不能为空") + private Integer agentId; + + @Schema(description = "表单ID") + @NotNull(message = "表单ID不能为空") + private Integer formId; + + @Schema(description = "表单数据") + private Map formData; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/req/AppActivityFormExecutionQueryReq.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/req/AppActivityFormExecutionQueryReq.java new file mode 100644 index 0000000..314e861 --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/req/AppActivityFormExecutionQueryReq.java @@ -0,0 +1,19 @@ +package com.seer.teach.mp.app.controller.req; + +import com.seer.teach.common.request.PageRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "APP端活动表单执行实例查询请求") +public class AppActivityFormExecutionQueryReq extends PageRequest { + + @Schema(description = "活动ID") + private Integer activityId; + + @Schema(description = "代理商ID") + private Integer agentId; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormExecutionResp.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormExecutionResp.java new file mode 100644 index 0000000..6e4e2c3 --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormExecutionResp.java @@ -0,0 +1,47 @@ +package com.seer.teach.mp.app.controller.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Map; + +@Schema(name = "AppActivityFormExecutionResp", description = "APP端活动表单执行实例响应参数") +@Data +public class AppActivityFormExecutionResp { + + private Integer id; + + @Schema(description = "执行编号") + private String executionNo; + + @Schema(description = "活动ID") + private Integer activityId; + + @Schema(description = "代理商ID") + private Integer agentId; + + @Schema(description = "使用的表单模板ID") + private Integer templateId; + + @Schema(description = "提交人ID") + private Integer submitterId; + + @Schema(description = "提交人姓名") + private String submitterName; + + @Schema(description = "提交时间") + private LocalDateTime submitTime; + + @Schema(description = "状态:draft-草稿,submitted-已提交,approved-已批准,rejected-已拒绝") + private String status; + + @Schema(description = "表单数据") + private Map formData; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormFieldResp.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormFieldResp.java new file mode 100644 index 0000000..6f8071c --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormFieldResp.java @@ -0,0 +1,39 @@ +package com.seer.teach.mp.app.controller.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(name = "AppActivityFormFieldResp", description = "APP端活动表单字段响应参数") +@Data +public class AppActivityFormFieldResp { + + private Integer id; + + @Schema(description = "字段名称") + private String fieldName; + + @Schema(description = "字段代码(英文标识)") + private String fieldCode; + + @Schema(description = "字段类型:text, textarea, select, radio, checkbox, date, number等") + private String fieldType; + + @Schema(description = "字段选项(JSON格式,适用于select, radio, checkbox等)") + private String fieldOptions; + + @Schema(description = "占位符提示") + private String placeholder; + + @Schema(description = "是否必填:0-否,1-是") + private Integer isRequired; + + @Schema(description = "排序") + private Integer sortOrder; + + @Schema(description = "验证规则(JSON格式)") + private String validationRules; + + @Schema(description = "字段描述") + private String description; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormTemplateResp.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormTemplateResp.java new file mode 100644 index 0000000..b8574d2 --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/controller/resp/AppActivityFormTemplateResp.java @@ -0,0 +1,23 @@ +package com.seer.teach.mp.app.controller.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(name = "AppActivityFormTemplateResp", description = "APP端活动表单模板响应参数") +@Data +public class AppActivityFormTemplateResp { + + private Integer id; + + @Schema(description = "表单模板名称") + private String templateName; + + @Schema(description = "表单模板描述") + private String templateDescription; + + @Schema(description = "表单字段列表") + private List fields; + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/convert/AppActivityFormConvert.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/convert/AppActivityFormConvert.java new file mode 100644 index 0000000..64f65a9 --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/convert/AppActivityFormConvert.java @@ -0,0 +1,22 @@ +package com.seer.teach.mp.app.convert; + +import com.seer.teach.mp.app.controller.resp.AppActivityFormExecutionResp; +import com.seer.teach.mp.app.controller.resp.AppActivityFormFieldResp; +import com.seer.teach.mp.app.controller.resp.AppActivityFormTemplateResp; +import com.seer.teach.mp.entity.MpActivityFormExecutionEntity; +import com.seer.teach.mp.entity.MpActivityFormFieldEntity; +import com.seer.teach.mp.entity.MpActivityFormEntity; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AppActivityFormConvert { + AppActivityFormConvert INSTANCE = Mappers.getMapper(AppActivityFormConvert.class); + + AppActivityFormTemplateResp convertToAppTemplateResp(MpActivityFormEntity entity); + + AppActivityFormFieldResp convertToAppFieldResp(MpActivityFormFieldEntity entity); + + AppActivityFormExecutionResp convertToAppExecutionResp(MpActivityFormExecutionEntity entity); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/IAppActivityFormService.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/IAppActivityFormService.java new file mode 100644 index 0000000..ea07550 --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/IAppActivityFormService.java @@ -0,0 +1,63 @@ +package com.seer.teach.mp.app.service; + +import com.seer.teach.common.PageListBean; +import com.seer.teach.mp.app.controller.req.ActivityFormSubmitReq; +import com.seer.teach.mp.app.controller.req.AppActivityFormExecutionQueryReq; +import com.seer.teach.mp.app.controller.resp.AppActivityFormExecutionResp; +import com.seer.teach.mp.app.controller.resp.AppActivityFormTemplateResp; +import com.seer.teach.mp.app.controller.resp.AppActivityFormFieldResp; + +import java.util.List; + +/** + *

+ * APP端活动表单服务接口 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IAppActivityFormService { + + /** + * 根据活动ID获取表单模板 + * + * @param activityId 活动ID + * @return 表单模板响应对象 + */ + AppActivityFormTemplateResp getTemplateByActivity(Integer activityId); + + /** + * 根据模板ID获取字段列表 + * + * @param templateId 模板ID + * @return 字段列表 + */ + List getFieldListByTemplate(Integer templateId); + + /** + * 提交表单 + * + * @param req 表单提交请求 + * @param userId 用户ID + * @return 执行编号 + */ + String submitForm(ActivityFormSubmitReq req, Integer userId); + + /** + * 根据执行ID获取完整表单数据 + * + * @param executionId 执行ID + * @return 完整表单数据 + */ + AppActivityFormExecutionResp getExecutionWithFormData(Integer executionId); + + /** + * 根据查询条件获取执行列表 + * + * @param query 查询条件 + * @param userId 用户ID + * @return 执行记录分页列表 + */ + PageListBean getExecutionList(AppActivityFormExecutionQueryReq query, Integer userId); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/impl/AppActivityFormServiceImpl.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/impl/AppActivityFormServiceImpl.java new file mode 100644 index 0000000..026dcdc --- /dev/null +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/impl/AppActivityFormServiceImpl.java @@ -0,0 +1,254 @@ +package com.seer.teach.mp.app.service.impl; + +import cn.hutool.core.util.IdUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.seer.teach.common.PageListBean; +import com.seer.teach.common.utils.PageConverterUtils; +import com.seer.teach.mp.app.controller.req.ActivityFormSubmitReq; +import com.seer.teach.mp.app.controller.req.AppActivityFormExecutionQueryReq; +import com.seer.teach.mp.app.controller.resp.AppActivityFormExecutionResp; +import com.seer.teach.mp.app.controller.resp.AppActivityFormTemplateResp; +import com.seer.teach.mp.app.controller.resp.AppActivityFormFieldResp; +import com.seer.teach.mp.app.convert.AppActivityFormConvert; +import com.seer.teach.mp.app.service.IAppActivityFormService; +import com.seer.teach.mp.entity.*; +import com.seer.teach.mp.service.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * APP端活动表单服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AppActivityFormServiceImpl implements IAppActivityFormService { + + private final IMpActivityFormService activityFormTemplateService; + private final IMpActivityFormFieldService activityFormFieldService; + private final IMpActivityFormExecutionService activityFormExecutionService; + private final IMpActivityFormVariableService activityFormVariableService; + private final IMpActivityService mpActivityService; + private final IMpActivityFormRelationService activityFormTemplateRelationService; + + @Override + public AppActivityFormTemplateResp getTemplateByActivity(Integer activityId) { + // 首先检查活动是否存在 + MpActivityEntity activity = mpActivityService.getById(activityId); + if (activity == null) { + log.warn("活动不存在,ID:{}", activityId); + return null; + } + + // 从关联表中获取与活动关联的表单ID + Integer templateId = activityFormTemplateRelationService.getPrimaryTemplateIdByActivityId(activityId); + + if (templateId != null) { + MpActivityFormEntity template = activityFormTemplateService.getById(templateId); + if (template != null) { + AppActivityFormTemplateResp resp = AppActivityFormConvert.INSTANCE.convertToAppTemplateResp(template); + + // 获取该表单的所有字段 + List fields = activityFormFieldService.list( + new LambdaQueryWrapper() + .eq(MpActivityFormFieldEntity::getFormId, templateId) + .orderByAsc(MpActivityFormFieldEntity::getSortOrder) + .orderByDesc(MpActivityFormFieldEntity::getId) + ); + + List fieldResps = fields.stream() + .map(AppActivityFormConvert.INSTANCE::convertToAppFieldResp) + .collect(Collectors.toList()); + + resp.setFields(fieldResps); + return resp; + } + } + List relations = activityFormTemplateRelationService.list( + new LambdaQueryWrapper() + .eq(MpActivityFormRelationEntity::getActivityId, activityId) + .last("LIMIT 1") + ); + + if (!relations.isEmpty()) { + templateId = relations.get(0).getFormId(); + MpActivityFormEntity template = activityFormTemplateService.getById(templateId); + if (template != null) { + AppActivityFormTemplateResp resp = AppActivityFormConvert.INSTANCE.convertToAppTemplateResp(template); + + // 获取该表单的所有字段 + List fields = activityFormFieldService.list( + new LambdaQueryWrapper() + .eq(MpActivityFormFieldEntity::getFormId, templateId) + .orderByAsc(MpActivityFormFieldEntity::getSortOrder) + .orderByDesc(MpActivityFormFieldEntity::getId) + ); + + List fieldResps = fields.stream() + .map(AppActivityFormConvert.INSTANCE::convertToAppFieldResp) + .collect(Collectors.toList()); + + resp.setFields(fieldResps); + return resp; + } + } + + log.warn("未找到活动 {} 关联的表单表单", activityId); + return null; + } + + @Override + public List getFieldListByTemplate(Integer templateId) { + List fields = activityFormFieldService.list( + new LambdaQueryWrapper() + .eq(MpActivityFormFieldEntity::getFormId, templateId) + .orderByAsc(MpActivityFormFieldEntity::getSortOrder) + .orderByDesc(MpActivityFormFieldEntity::getId) + ); + + return fields.stream() + .map(AppActivityFormConvert.INSTANCE::convertToAppFieldResp) + .collect(Collectors.toList()); + } + + @Override + @Transactional + public String submitForm(ActivityFormSubmitReq req, Integer userId) { + // 生成执行编号 + String executionNo = "AFE-" + System.currentTimeMillis() + "-" + IdUtil.getSnowflakeNextId(); + + // 创建表单执行实例 + MpActivityFormExecutionEntity execution = new MpActivityFormExecutionEntity(); + execution.setExecutionNo(executionNo); + execution.setActivityId(req.getActivityId()); + execution.setAgentId(req.getAgentId()); + execution.setFormId(req.getFormId()); + execution.setSubmitterId(userId); // 设置提交人ID为当前登录用户ID + execution.setSubmitTime(LocalDateTime.now()); + execution.setStatus("submitted"); // 设置状态为已提交 + + // 保存表单执行实例 + activityFormExecutionService.save(execution); + + // 处理表单数据,将其存储到变量表中 + if (req.getFormData() != null && !req.getFormData().isEmpty()) { + for (Map.Entry entry : req.getFormData().entrySet()) { + MpActivityFormVariableEntity variable = new MpActivityFormVariableEntity(); + variable.setExecutionId(execution.getId()); + variable.setVariableName(entry.getKey()); // 使用字段代码作为变量名 + variable.setVariableCode(entry.getKey()); // 使用字段代码作为变量代码 + variable.setVariableValue(String.valueOf(entry.getValue())); // 将值转换为字符串存储 + variable.setDataType(getDataType(entry.getValue())); // 根据值确定数据类型 + + activityFormVariableService.save(variable); + } + } + + log.info("表单提交成功,执行编号:{}", executionNo); + return executionNo; + } + + /** + * 根据执行ID获取完整表单数据 + */ + public AppActivityFormExecutionResp getExecutionWithFormData(Integer executionId) { + MpActivityFormExecutionEntity execution = activityFormExecutionService.getById(executionId); + if (execution == null) { + return null; + } + + AppActivityFormExecutionResp resp = AppActivityFormConvert.INSTANCE.convertToAppExecutionResp(execution); + + // 获取表单变量数据 + List variables = activityFormVariableService.list( + new LambdaQueryWrapper() + .eq(MpActivityFormVariableEntity::getExecutionId, executionId) + ); + + // 转换为Map形式的表单数据 + Map formData = new HashMap<>(); + for (MpActivityFormVariableEntity variable : variables) { + // 根据数据类型转换值 + Object value = convertValueByType(variable.getVariableValue(), variable.getDataType()); + formData.put(variable.getVariableCode(), value); + } + + resp.setFormData(formData); + return resp; + } + + /** + * 根据数据类型转换值 + */ + private Object convertValueByType(String value, String dataType) { + if (value == null) { + return null; + } + + switch (dataType) { + case "boolean": + return Boolean.parseBoolean(value); + case "number": + try { + // 尝试解析为整数或浮点数 + if (value.contains(".")) { + return Double.parseDouble(value); + } else { + return Long.parseLong(value); + } + } catch (NumberFormatException e) { + return value; // 如果无法解析为数字,则返回原始字符串 + } + case "string": + default: + return value; + } + } + + /** + * 根据值判断数据类型 + */ + private String getDataType(Object value) { + if (value instanceof Boolean) { + return "boolean"; + } else if (value instanceof Number) { + return "number"; + } else if (value instanceof String) { + return "string"; + } else { + return "string"; + } + } + + @Override + public PageListBean getExecutionList(AppActivityFormExecutionQueryReq query, Integer userId) { + Page page = new Page<>(query.getPageNo(), query.getPageSize()); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(MpActivityFormExecutionEntity::getSubmitterId, userId) + .eq(query.getActivityId() != null, MpActivityFormExecutionEntity::getActivityId, query.getActivityId()) + .eq(query.getAgentId() != null, MpActivityFormExecutionEntity::getAgentId, query.getAgentId()) + .orderByDesc(MpActivityFormExecutionEntity::getId); + + Page pageResult = activityFormExecutionService.page(page, wrapper); + List records = pageResult.getRecords().stream() + .map(AppActivityFormConvert.INSTANCE::convertToAppExecutionResp) + .collect(Collectors.toList()); + + return PageConverterUtils.convertPageListBean(pageResult, records); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/impl/AppAgentEmployeeRelationServiceImpl.java b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/impl/AppAgentEmployeeRelationServiceImpl.java index 26996a3..12e007a 100644 --- a/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/impl/AppAgentEmployeeRelationServiceImpl.java +++ b/seer-mp/seer-mp-service-app/src/main/java/com/seer/teach/mp/app/service/impl/AppAgentEmployeeRelationServiceImpl.java @@ -17,9 +17,7 @@ import com.seer.teach.mp.app.service.IAppAgentEmployeeRelationService; import com.seer.teach.mp.entity.MpAgentEmployeeRelationEntity; import com.seer.teach.mp.service.IMpAgentEmployeeRelationService; import com.seer.teach.user.api.UserInfoServiceApi; -import com.seer.teach.user.api.UserRelationServiceApi; import com.seer.teach.user.api.dto.UserInfoDTO; -import com.seer.teach.user.api.dto.UserRelationDTO; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormExecutionService.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormExecutionService.java new file mode 100644 index 0000000..f3113f7 --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormExecutionService.java @@ -0,0 +1,16 @@ +package com.seer.teach.mp.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.seer.teach.mp.entity.MpActivityFormExecutionEntity; + +/** + *

+ * 活动表单执行实例表 服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IMpActivityFormExecutionService extends IService { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormFieldService.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormFieldService.java new file mode 100644 index 0000000..bbcf27f --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormFieldService.java @@ -0,0 +1,16 @@ +package com.seer.teach.mp.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.seer.teach.mp.entity.MpActivityFormFieldEntity; + +/** + *

+ * 活动表单字段定义表 服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IMpActivityFormFieldService extends IService { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormRelationService.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormRelationService.java new file mode 100644 index 0000000..b180139 --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormRelationService.java @@ -0,0 +1,50 @@ +package com.seer.teach.mp.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.seer.teach.mp.entity.MpActivityFormRelationEntity; + +import java.util.Optional; + +/** + *

+ * 活动与表单模板关联表 服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IMpActivityFormRelationService extends IService { + + /** + * 根据活动ID获取关联的主要表单模板ID + * + * @param activityId 活动ID + * @return 表单模板ID,如果不存在则返回null + */ + Integer getPrimaryTemplateIdByActivityId(Integer activityId); + + /** + * 根据活动ID获取关联的表单模板数量 + * + * @param activityId 活动ID + * @return 表单模板数量 + */ + long getCountByActivityId(Integer activityId); + + /** + * 根据活动ID和模板ID建立关联 + * + * @param activityId 活动ID + * @param formId 表单ID + * @return 操作是否成功 + */ + boolean createRelation(Integer activityId, Integer formId); + + /** + * 获取指定活动ID的最新版本 + * + * @param activityId 活动ID + * @return 最新版本号 + */ + Optional getLatestVersionByActivityId(Integer activityId); +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormService.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormService.java new file mode 100644 index 0000000..4032bb3 --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormService.java @@ -0,0 +1,16 @@ +package com.seer.teach.mp.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.seer.teach.mp.entity.MpActivityFormEntity; + +/** + *

+ * 活动表单模板表 服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IMpActivityFormService extends IService { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormVariableService.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormVariableService.java new file mode 100644 index 0000000..ccee0be --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/IMpActivityFormVariableService.java @@ -0,0 +1,16 @@ +package com.seer.teach.mp.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.seer.teach.mp.entity.MpActivityFormVariableEntity; + +/** + *

+ * 活动表单变量表 服务类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +public interface IMpActivityFormVariableService extends IService { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormExecutionServiceImpl.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormExecutionServiceImpl.java new file mode 100644 index 0000000..5c162b4 --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormExecutionServiceImpl.java @@ -0,0 +1,24 @@ +package com.seer.teach.mp.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.seer.teach.mp.entity.MpActivityFormExecutionEntity; +import com.seer.teach.mp.mapper.MpActivityFormExecutionMapper; +import com.seer.teach.mp.service.IMpActivityFormExecutionService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 活动表单执行实例表 服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MpActivityFormExecutionServiceImpl extends ServiceImpl implements IMpActivityFormExecutionService { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormFieldServiceImpl.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormFieldServiceImpl.java new file mode 100644 index 0000000..9367704 --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormFieldServiceImpl.java @@ -0,0 +1,24 @@ +package com.seer.teach.mp.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.seer.teach.mp.entity.MpActivityFormFieldEntity; +import com.seer.teach.mp.mapper.MpActivityFormFieldMapper; +import com.seer.teach.mp.service.IMpActivityFormFieldService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 活动表单字段定义表 服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MpActivityFormFieldServiceImpl extends ServiceImpl implements IMpActivityFormFieldService { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormRelationServiceImpl.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormRelationServiceImpl.java new file mode 100644 index 0000000..3d404f8 --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormRelationServiceImpl.java @@ -0,0 +1,73 @@ +package com.seer.teach.mp.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.seer.teach.mp.entity.MpActivityFormRelationEntity; +import com.seer.teach.mp.mapper.MpActivityFormRelationMapper; +import com.seer.teach.mp.service.IMpActivityFormRelationService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +/** + *

+ * 活动与表单模板关联表 服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MpActivityFormRelationServiceImpl extends ServiceImpl implements IMpActivityFormRelationService { + + @Override + public Integer getPrimaryTemplateIdByActivityId(Integer activityId) { + MpActivityFormRelationEntity relation = this.getOne( + new LambdaQueryWrapper() + .eq(MpActivityFormRelationEntity::getActivityId, activityId) + ); + return relation != null ? relation.getFormId() : null; + } + + @Override + public long getCountByActivityId(Integer activityId) { + return super.count(new LambdaQueryWrapper().eq(MpActivityFormRelationEntity::getActivityId, activityId)); + } + + @Override + public boolean createRelation(Integer activityId, Integer formId) { + // 检查是否已经存在关联 + MpActivityFormRelationEntity existing = this.getOne( + new LambdaQueryWrapper() + .eq(MpActivityFormRelationEntity::getActivityId, activityId) + .eq(MpActivityFormRelationEntity::getFormId, formId) + ); + + if (existing != null) { + return this.updateById(existing); + } else { + // 创建新的关联 + MpActivityFormRelationEntity relation = new MpActivityFormRelationEntity(); + relation.setActivityId(activityId); + relation.setFormId(formId); + + return this.save(relation); + } + } + + @Override + public Optional getLatestVersionByActivityId(Integer activityId) { + MpActivityFormRelationEntity relation = this.getOne( + new LambdaQueryWrapper() + .eq(MpActivityFormRelationEntity::getActivityId, activityId) + .orderByDesc(MpActivityFormRelationEntity::getId) + .last("LIMIT 1") + ); + log.info("getLatestVersionByActivityId: {}", relation); + return Optional.ofNullable(relation); + } +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormServiceImpl.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormServiceImpl.java new file mode 100644 index 0000000..9c12cd2 --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormServiceImpl.java @@ -0,0 +1,24 @@ +package com.seer.teach.mp.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.seer.teach.mp.entity.MpActivityFormEntity; +import com.seer.teach.mp.mapper.MpActivityFormMapper; +import com.seer.teach.mp.service.IMpActivityFormService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 活动表单模板表 服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MpActivityFormServiceImpl extends ServiceImpl implements IMpActivityFormService { + +} \ No newline at end of file diff --git a/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormVariableServiceImpl.java b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormVariableServiceImpl.java new file mode 100644 index 0000000..3b05ed5 --- /dev/null +++ b/seer-mp/seer-mp-service/src/main/java/com/seer/teach/mp/service/impl/MpActivityFormVariableServiceImpl.java @@ -0,0 +1,24 @@ +package com.seer.teach.mp.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.seer.teach.mp.entity.MpActivityFormVariableEntity; +import com.seer.teach.mp.mapper.MpActivityFormVariableMapper; +import com.seer.teach.mp.service.IMpActivityFormVariableService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + *

+ * 活动表单变量表 服务实现类 + *

+ * + * @author Lingma + * @since 2026-01-10 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class MpActivityFormVariableServiceImpl extends ServiceImpl implements IMpActivityFormVariableService { + +} \ No newline at end of file