diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/ApplicationVersionApi.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/ApplicationVersionApi.java
index e3e0dfd5..b2fb2369 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/ApplicationVersionApi.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/ApplicationVersionApi.java
@@ -1,82 +1,84 @@
-// package cn.axzo.nanopart.api;
-//
-// import cn.axzo.framework.domain.web.result.ApiPageResult;
-// import cn.axzo.framework.domain.web.result.ApiResult;
-// import cn.axzo.nanopart.api.request.CreateApplicationVersionReq;
-// import cn.axzo.nanopart.api.request.GetVersionUpdateRemindContentReq;
-// import cn.axzo.nanopart.api.request.PageApplicationVersionReq;
-// import cn.axzo.nanopart.api.request.UpdateApplicationVersionReq;
-// import cn.axzo.nanopart.api.response.GetVersionUpdateRemindContentResp;
-// import cn.axzo.nanopart.api.response.PageApplicationVersionResp;
-// import org.springframework.cloud.openfeign.FeignClient;
-// import org.springframework.web.bind.annotation.GetMapping;
-// import org.springframework.web.bind.annotation.PostMapping;
-// import org.springframework.web.bind.annotation.RequestBody;
-// import org.springframework.web.bind.annotation.RequestParam;
-//
-// import javax.validation.Valid;
-//
-// /**
-// * @author chenwenjian
-// * @version 1.0
-// * @date 2024/4/2 10:21
-// */
-// @FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
-// public interface ApplicationVersionApi {
-//
-// /**
-// * 创建
-// *
-// * 版本号+平台+操作系统,不可重复
-// *
-// *
-// * @param req {@link CreateApplicationVersionReq}
-// * @return 版本记录id
-// */
-// @PostMapping("/api/applicationVersion/create")
-// ApiResult create(@RequestBody @Valid CreateApplicationVersionReq req);
-//
-// /**
-// * 更新
-// *
-// * @param req {@link UpdateApplicationVersionReq}
-// * @return void
-// */
-// @PostMapping("/api/applicationVersion/update")
-// ApiResult update(@RequestBody @Valid UpdateApplicationVersionReq req);
-//
-// /**
-// * 删除
-// *
-// * @param id 版本记录id
-// * @return void
-// */
-// @GetMapping("/api/applicationVersion/delete")
-// ApiResult deleteById(@RequestParam("id") Long id, @RequestParam("personId") Long personId);
-//
-// /**
-// * 分页查询
-// *
-// * @param req {@link PageApplicationVersionReq}
-// * @return 按照版本号字典序倒排
-// */
-// @PostMapping("/api/applicationVersion/page")
-// ApiPageResult page(@RequestBody @Valid PageApplicationVersionReq req);
-//
-// /**
-// * 获取版本更新提醒内容
-// *
-// * 1. 获取最新配置的提示内容记录
-// * - 对于cms,直接返回最新配置(版本号最高)的一条记录()看是否配置了弹窗提示
-// * - 对于app,根据版本号和操作系统,看该版本号是否配置了弹窗提示
-// * 2. 检查当前用户是否已经提示
-// * - 若已提示则不再提示,直接返回null
-// * - 若还没有提示,则返回该条提示内容记录
-// *
-// *
-// * @param req {@link GetVersionUpdateRemindContentReq}
-// * @return 版本更新提醒内容
-// */
-// @PostMapping("/api/applicationVersion/getVersionUpdateRemindContent")
-// ApiResult getVersionUpdateRemindContent(@RequestBody @Valid GetVersionUpdateRemindContentReq req);
-// }
+package cn.axzo.nanopart.api;
+
+import cn.axzo.framework.domain.web.result.ApiPageResult;
+import cn.axzo.framework.domain.web.result.ApiResult;
+import cn.axzo.nanopart.api.request.CreateApplicationVersionReq;
+import cn.axzo.nanopart.api.request.GetVersionUpdateRemindContentReq;
+import cn.axzo.nanopart.api.request.PageApplicationVersionReq;
+import cn.axzo.nanopart.api.request.UpdateApplicationVersionReq;
+import cn.axzo.nanopart.api.response.GetVersionUpdateRemindContentResp;
+import cn.axzo.nanopart.api.response.PageApplicationVersionResp;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.validation.Valid;
+
+/**
+ * 版本记录相关api
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/2 10:21
+ */
+@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
+public interface ApplicationVersionApi {
+
+ /**
+ * 创建
+ *
+ * 版本号+平台+操作系统,不可重复
+ *
+ *
+ * @param req {@link CreateApplicationVersionReq}
+ * @return 版本记录id
+ */
+ @PostMapping("/api/applicationVersion/create")
+ ApiResult create(@RequestBody @Valid CreateApplicationVersionReq req);
+
+ /**
+ * 更新
+ *
+ * @param req {@link UpdateApplicationVersionReq}
+ * @return void
+ */
+ @PostMapping("/api/applicationVersion/update")
+ ApiResult update(@RequestBody @Valid UpdateApplicationVersionReq req);
+
+ /**
+ * 删除
+ *
+ * @param id 版本记录id
+ * @return void
+ */
+ @GetMapping("/api/applicationVersion/delete")
+ ApiResult deleteById(@RequestParam("id") Long id, @RequestParam(value = "personId") Long personId);
+
+ /**
+ * 分页查询
+ *
+ * @param req {@link PageApplicationVersionReq}
+ * @return 按照版本号字典序倒排
+ */
+ @PostMapping("/api/applicationVersion/page")
+ ApiPageResult page(@RequestBody @Valid PageApplicationVersionReq req);
+
+ /**
+ * 获取版本更新提醒内容
+ *
+ * 1. 获取最新配置的提示内容记录
+ * - 对于cms,直接返回最新配置(版本号最高)的一条记录()看是否配置了弹窗提示
+ * - 对于app,根据版本号和操作系统,看该版本号是否配置了弹窗提示
+ * 2. 检查当前用户是否已经提示
+ * - 若已提示则不再提示,直接返回null
+ * - 若还没有提示,则返回该条提示内容记录并记录为已提示
+ *
+ *
+ * @param req {@link GetVersionUpdateRemindContentReq}
+ * @return 版本更新提醒内容
+ */
+ @PostMapping("/api/applicationVersion/getVersionUpdateRemindContent")
+ ApiResult getVersionUpdateRemindContent(@RequestBody @Valid GetVersionUpdateRemindContentReq req);
+}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/BannerApi.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/BannerApi.java
index 47ef264c..c30edfbf 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/BannerApi.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/BannerApi.java
@@ -1,72 +1,72 @@
-// package cn.axzo.nanopart.api;
-//
-// import cn.axzo.framework.domain.web.result.ApiPageResult;
-// import cn.axzo.framework.domain.web.result.ApiResult;
-// import cn.axzo.nanopart.api.request.CreateBannerReq;
-// import cn.axzo.nanopart.api.request.DetailBannerReq;
-// import cn.axzo.nanopart.api.request.PageBannerReq;
-// import cn.axzo.nanopart.api.request.UpdateBannerReq;
-// import cn.axzo.nanopart.api.request.UpdateStatusReq;
-// import cn.axzo.nanopart.api.response.DetailBannerResp;
-// import cn.axzo.nanopart.api.response.PageBannerResp;
-// import org.springframework.cloud.openfeign.FeignClient;
-// import org.springframework.web.bind.annotation.PostMapping;
-// import org.springframework.web.bind.annotation.RequestBody;
-//
-// import javax.validation.Valid;
-//
-// /**
-// * @author chenwenjian
-// * @version 1.0
-// * @date 2024/4/2 10:19
-// */
-// @FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
-// public interface BannerApi {
-//
-// /**
-// * 分页查询banner
-// *
-// * @param req {@link PageBannerReq}
-// * @return 按照站点code(code)自增排序后列表 {@link PageBannerResp}
-// */
-// @PostMapping("/api/banner/page")
-// ApiPageResult page(@RequestBody @Valid PageBannerReq req);
-//
-// /**
-// * 创建banner
-// *
-// * @param req {@link CreateBannerReq}
-// * @return bannerId
-// */
-// @PostMapping("/api/banner/create")
-// ApiResult create(@RequestBody @Valid CreateBannerReq req);
-//
-// /**
-// * 更新banner
-// *
-// * @param req {@link UpdateBannerReq}
-// * @return void
-// */
-// @PostMapping("/api/banner/update")
-// ApiResult update(@RequestBody @Valid UpdateBannerReq req);
-//
-// /**
-// * 更新banner状态
-// *
-// * @param req {@link UpdateStatusReq}
-// * @return void
-// */
-// @PostMapping("/api/banner/updateStatus")
-// ApiResult updateStatus(@RequestBody @Valid UpdateStatusReq req);
-//
-// /**
-// * 详情
-// *
-// * @param req 广告位唯一的id或code {@link DetailBannerReq}
-// * @return {@link DetailBannerResp}
-// */
-// @PostMapping("/api/banner/detail")
-// ApiResult detail(@RequestBody @Valid DetailBannerReq req);
-//
-//
-// }
+package cn.axzo.nanopart.api;
+
+import cn.axzo.framework.domain.web.result.ApiPageResult;
+import cn.axzo.framework.domain.web.result.ApiResult;
+import cn.axzo.nanopart.api.request.CreateBannerReq;
+import cn.axzo.nanopart.api.request.DetailBannerReq;
+import cn.axzo.nanopart.api.request.PageBannerReq;
+import cn.axzo.nanopart.api.request.UpdateBannerReq;
+import cn.axzo.nanopart.api.request.UpdateStatusReq;
+import cn.axzo.nanopart.api.response.DetailBannerResp;
+import cn.axzo.nanopart.api.response.PageBannerResp;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import javax.validation.Valid;
+
+/**
+ * 广告位相关 api
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/2 10:19
+ */
+@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
+public interface BannerApi {
+
+ /**
+ * 分页查询banner
+ *
+ * @param req {@link PageBannerReq}
+ * @return 按照站点code(code)自增排序后列表 {@link PageBannerResp}
+ */
+ @PostMapping("/api/banner/page")
+ ApiPageResult page(@RequestBody @Valid PageBannerReq req);
+
+ /**
+ * 创建banner
+ *
+ * @param req {@link CreateBannerReq}
+ * @return bannerId
+ */
+ @PostMapping("/api/banner/create")
+ ApiResult create(@RequestBody @Valid CreateBannerReq req);
+
+ /**
+ * 更新banner
+ *
+ * @param req {@link UpdateBannerReq}
+ * @return void
+ */
+ @PostMapping("/api/banner/update")
+ ApiResult update(@RequestBody @Valid UpdateBannerReq req);
+
+ /**
+ * 更新banner状态
+ *
+ * @param req {@link UpdateStatusReq}
+ * @return void
+ */
+ @PostMapping("/api/banner/updateStatus")
+ ApiResult updateStatus(@RequestBody @Valid UpdateStatusReq req);
+
+ /**
+ * 详情
+ *
+ * @param req 广告位唯一的id或code {@link DetailBannerReq}
+ * @return {@link DetailBannerResp}
+ */
+ @PostMapping("/api/banner/detail")
+ ApiResult detail(@RequestBody @Valid DetailBannerReq req);
+}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/BannerOperationLogApi.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/BannerOperationLogApi.java
index 4955eede..ca1cfa2c 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/BannerOperationLogApi.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/BannerOperationLogApi.java
@@ -1,28 +1,30 @@
-// package cn.axzo.nanopart.api;
-//
-// import cn.axzo.framework.domain.web.result.ApiPageResult;
-// import cn.axzo.nanopart.api.request.PageBannerOperationLogReq;
-// import cn.axzo.nanopart.api.response.PageBannerOperationLogResp;
-// import org.springframework.cloud.openfeign.FeignClient;
-// import org.springframework.web.bind.annotation.PostMapping;
-// import org.springframework.web.bind.annotation.RequestBody;
-//
-// import javax.validation.Valid;
-//
-// /**
-// * @author chenwenjian
-// * @version 1.0
-// * @date 2024/4/2 10:21
-// */
-// @FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
-// public interface BannerOperationLogApi {
-//
-// /**
-// * 分页查询
-// *
-// * @param req {@link PageBannerOperationLogReq}
-// * @return 按照操作时间倒叙排序
-// */
-// @PostMapping("/api/bannerOperationLog/page")
-// ApiPageResult page(@RequestBody @Valid PageBannerOperationLogReq req);
-// }
+package cn.axzo.nanopart.api;
+
+import cn.axzo.framework.domain.web.result.ApiPageResult;
+import cn.axzo.nanopart.api.request.PageBannerOperationLogReq;
+import cn.axzo.nanopart.api.response.PageBannerOperationLogResp;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import javax.validation.Valid;
+
+/**
+ * 广告位和素材操作日志
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/2 10:21
+ */
+@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
+public interface BannerOperationLogApi {
+
+ /**
+ * 分页查询
+ *
+ * @param req {@link PageBannerOperationLogReq}
+ * @return 按照操作时间倒叙排序
+ */
+ @PostMapping("/api/bannerOperationLog/page")
+ ApiPageResult page(@RequestBody @Valid PageBannerOperationLogReq req);
+}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/MaterialApi.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/MaterialApi.java
index 603cf2ef..eb08ba74 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/MaterialApi.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/MaterialApi.java
@@ -1,8 +1,15 @@
package cn.axzo.nanopart.api;
+import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
+import cn.axzo.nanopart.api.request.CreateMaterialReq;
+import cn.axzo.nanopart.api.request.DetailMaterialReq;
import cn.axzo.nanopart.api.request.ListMaterialByBannerCodeReq;
+import cn.axzo.nanopart.api.request.PageMaterialReq;
+import cn.axzo.nanopart.api.request.UpdateMaterialReq;
+import cn.axzo.nanopart.api.request.UpdateStatusReq;
import cn.axzo.nanopart.api.response.MaterialResp;
+import cn.axzo.nanopart.api.response.PageMaterialResp;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -11,6 +18,8 @@ import javax.validation.Valid;
import java.util.List;
/**
+ * 素材管理相关 api
+ *
* @author chenwenjian
* @version 1.0
* @date 2024/4/2 10:20
@@ -18,59 +27,56 @@ import java.util.List;
@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
public interface MaterialApi {
- // /**
- // * 分页查询
- // *
- // * @param req {@link PageMaterialReq}}
- // * @return 根据上下架状态(上架→下架)。优先级正序(数字由小到大)排列后素材列表
- // */
- // @PostMapping("/api/material/page")
- // ApiPageResult page(@RequestBody @Valid PageMaterialReq req);
- //
- // /**
- // * 创建
- // *
- // * @param req {@link CreateMaterialReq}
- // * @return 素材id
- // */
- // @PostMapping("/api/material/create")
- // ApiResult create(@RequestBody @Valid CreateMaterialReq req);
- //
- // /**
- // * 更新
- // *
- // * @param req {@link UpdateMaterialReq}
- // * @return 无
- // */
- // @PostMapping("/api/material/update")
- // ApiResult update(@RequestBody @Valid UpdateMaterialReq req);
- //
- // /**
- // * 更新banner状态
- // *
- // * @param req {@link UpdateStatusReq}
- // * @return void
- // */
- // @PostMapping("/api/material/updateStatus")
- // ApiResult updateStatus(@RequestBody @Valid UpdateStatusReq req);
- //
- // /**
- // * 详情
- // *
- // * @param req {@link UpdateMaterialReq}
- // * @return 素材详情
- // */
- // @PostMapping("/api/material/detail")
- // ApiResult detail(@RequestBody @Valid DetailMaterialReq req);
+ /**
+ * 分页查询
+ *
+ * @param req {@link PageMaterialReq}}
+ * @return 根据上下架状态(上架→下架)。优先级正序(数字由小到大)排列后素材列表
+ */
+ @PostMapping("/api/material/page")
+ ApiPageResult page(@RequestBody @Valid PageMaterialReq req);
+
+ /**
+ * 创建
+ *
+ * @param req {@link CreateMaterialReq}
+ * @return 素材id
+ */
+ @PostMapping("/api/material/create")
+ ApiResult create(@RequestBody @Valid CreateMaterialReq req);
+
+ /**
+ * 更新
+ *
+ * @param req {@link UpdateMaterialReq}
+ * @return 无
+ */
+ @PostMapping("/api/material/update")
+ ApiResult update(@RequestBody @Valid UpdateMaterialReq req);
+
+ /**
+ * 更新banner状态
+ *
+ * @param req {@link UpdateStatusReq}
+ * @return 无
+ */
+ @PostMapping("/api/material/updateStatus")
+ ApiResult updateStatus(@RequestBody @Valid UpdateStatusReq req);
+
+ /**
+ * 详情
+ *
+ * @param req {@link UpdateMaterialReq}
+ * @return 素材详情
+ */
+ @PostMapping("/api/material/detail")
+ ApiResult detail(@RequestBody @Valid DetailMaterialReq req);
/**
* 根据广告位编码(bannerCode)查询素材
*
- * 对于cms和cmp需要传入当前登录人所在的workspaceId,ouId和所担任的jobCode
- *
- *
* 1. 通过广告位code获取该广告位下的所有素材(默认查询上架状态且在有效期范围内的素材)
- * 2. 根据广告位投放人群进行过滤
+ * 2. 根据广告位投放人群进行过滤(对于cms/cmp需要根据当前登录人登录企业情况进行过滤)
* 3. 根据广告位投放规则频次进行过滤
* 4. 将最终的素材根据优先级(priority)升序,创建时间(createAt)降序排序
*
@@ -80,5 +86,4 @@ public interface MaterialApi {
*/
@PostMapping("/api/material/listByBannerCode")
ApiResult> listMaterialByBannerCode(@RequestBody @Valid ListMaterialByBannerCodeReq req);
-
}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/constant/NanopartConstant.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/constant/NanopartConstant.java
index 8cab11ce..633285d6 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/constant/NanopartConstant.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/constant/NanopartConstant.java
@@ -10,4 +10,14 @@ package cn.axzo.nanopart.api.constant;
public class NanopartConstant {
public static final String BASIC_FEIGN_PACKAGE = "cn.axzo";
+
+ /**
+ * 请求上下文日志ID
+ */
+ public static final String CONTEXT_TRACE_ID = "ctxLogId";
+
+ /**
+ * 版本号简单校验正则表达式
+ */
+ public static final String VERSION_SIMPLE_PATTERN = "^\\d+\\.\\d+\\.\\d+$";
}
\ No newline at end of file
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/dto/AspectRatioDto.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/dto/AspectRatioDto.java
index 4b194606..d321f84d 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/dto/AspectRatioDto.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/dto/AspectRatioDto.java
@@ -39,6 +39,9 @@ public class AspectRatioDto {
if (this.getWidth() <= 0 || this.getWidth() > 100) {
throw new ServiceException("请设置合适的占位图宽高比例");
}
+ }else {
+ this.setWidth(0);
+ this.setHeight(0);
}
}
}
\ No newline at end of file
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/dto/JoinedWorkspaceOuJob.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/dto/JoinedWorkspaceOuJob.java
index 69b2b1c4..e5677c0b 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/dto/JoinedWorkspaceOuJob.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/dto/JoinedWorkspaceOuJob.java
@@ -16,6 +16,7 @@ import java.util.Map;
@NoArgsConstructor
@AllArgsConstructor
public class JoinedWorkspaceOuJob {
+
/**
* 加入的项目部及在该项目部下担任的所有岗位
*/
@@ -26,4 +27,14 @@ public class JoinedWorkspaceOuJob {
*/
private Map> ouJobMap;
+ /**
+ * 加入的单位及在该单位加入的项目部
+ */
+ private Map> ouWorkspaceMap;
+
+ /**
+ * 加入的项目部及在该项目部加入的单位
+ */
+ private Map> workspaceOuMap;
+
}
\ No newline at end of file
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/DisplayTimeTypeEnum.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/DisplayTimeTypeEnum.java
new file mode 100644
index 00000000..97fdd80c
--- /dev/null
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/DisplayTimeTypeEnum.java
@@ -0,0 +1,43 @@
+package cn.axzo.nanopart.api.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+
+import java.sql.Time;
+import java.util.Arrays;
+
+/**
+ * 广告位展示时间段类型
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/12 17:17
+ */
+@Getter
+@AllArgsConstructor
+public enum DisplayTimeTypeEnum {
+
+ ALL_DAY("ALL_DAY", "全天", Time.valueOf("00:00:00").getTime(), Time.valueOf("23:59:59").getTime()),
+ WORKING("WORKING", "上班时间(5:00-18:00)", Time.valueOf("05:00:00").getTime(), Time.valueOf("18:00:00").getTime()),
+ BREAKING("BREAKING", "休息时间(18:00-22:00)", Time.valueOf("18:00:00").getTime(), Time.valueOf("22:00:00").getTime()),
+ CUSTOM("CUSTOM", "自定义", null, null);
+
+ private final String name;
+
+ private final String desc;
+
+ private final Long startTime;
+
+ private final Long endTime;
+
+ public static DisplayTimeTypeEnum getType(String name) {
+ if (StringUtils.isEmpty(name)) {
+ return null;
+ }
+ return Arrays.stream(values())
+ .filter(item -> item.name.equals(name))
+ .findFirst()
+ .orElse(null);
+ }
+}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/LogOperationTypeEnum.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/LogOperationTypeEnum.java
new file mode 100644
index 00000000..28b65ad2
--- /dev/null
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/LogOperationTypeEnum.java
@@ -0,0 +1,41 @@
+package cn.axzo.nanopart.api.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+
+/**
+ * 素材或广告位操作日志类型
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/18 10:39
+ */
+@Getter
+@AllArgsConstructor
+public enum LogOperationTypeEnum {
+
+ CREATE("create", "新增"),
+
+ UPDATE("update", "编辑"),
+
+ DELETE("delete", "删除"),
+
+ UPDATE_STATUS("updateStatus", "更新状态");
+
+ private final String type;
+
+ private final String desc;
+
+ public static LogOperationTypeEnum getLogOperationType(String type) {
+ if (StringUtils.isEmpty(type)) {
+ return null;
+ }
+ return Arrays.stream(values())
+ .filter(item -> item.type.equals(type))
+ .findFirst()
+ .orElse(null);
+ }
+}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/MaterialDisplayFrequencyTypeEnum.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/MaterialDisplayFrequencyTypeEnum.java
index 01bbb829..861f4ad1 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/MaterialDisplayFrequencyTypeEnum.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/MaterialDisplayFrequencyTypeEnum.java
@@ -16,6 +16,7 @@ import java.util.Arrays;
@Getter
@AllArgsConstructor
public enum MaterialDisplayFrequencyTypeEnum {
+ NO_LIMIT("NO_LIMIT", "不限制"),
VALIDITY_PERIOD("VALIDITY_PERIOD", "有效期内"),
EVERY_DAY("EVERY_DAY", "每天"),
EVERY_WEEK("EVERY_WEEK", "每周"),
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/MaterialTargetUserTypeEnum.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/MaterialTargetUserTypeEnum.java
index 38fa3299..1bf47878 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/MaterialTargetUserTypeEnum.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/MaterialTargetUserTypeEnum.java
@@ -1,14 +1,14 @@
package cn.axzo.nanopart.api.enums;
import cn.axzo.nanopart.api.dto.JoinedWorkspaceOuJob;
+import cn.hutool.json.JSONUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.stream.Collectors;
/**
@@ -18,34 +18,138 @@ import java.util.stream.Collectors;
* @version 1.0
* @date 2024/4/9 16:46
*/
+@Slf4j
@Getter
@AllArgsConstructor
public enum MaterialTargetUserTypeEnum {
- ALL("ALL_USER", "全部用户") {
+ ALL("ALL", "全部用户") {
@Override
- public boolean isDeliverRequired(List workspaceIds, List ouIds, List jobCodes, JoinedWorkspaceOuJob workspaceOuJob) {
+ public boolean isDeliverRequired(List workspaceIds, List ouIds, List jobCodes,
+ Long loginWorkspaceId, Long loginOuid,
+ JoinedWorkspaceOuJob workspaceOuJob) {
+ log.info("投放全部用户");
return true;
}
},
PROJECT("PROJECT", "按照项目部") {
@Override
- public boolean isDeliverRequired(List workspaceIds, List ouIds, List jobCodes, JoinedWorkspaceOuJob workspaceOuJob) {
- // 若workspaceIds和jobCodes都为空,则表示不限制,否则需要满足配置的workspaceIds和jobCodes与用户加入的workspaceJob的key,value均存在交集
+ public boolean isDeliverRequired(List workspaceIds, List ouIds, List jobCodes,
+ Long loginWorkspaceId, Long loginOuid,
+ JoinedWorkspaceOuJob workspaceOuJob) {
+
Map> workspaceJobMap = workspaceOuJob.getWorkspaceJobMap();
- return CollectionUtils.isEmpty(workspaceIds) ? CollectionUtils.isEmpty(jobCodes) || jobCodes.stream().anyMatch(jobCode -> workspaceJobMap.values().stream().flatMap(List::stream).distinct().collect(Collectors.toList()).contains(jobCode))
- : workspaceIds.stream().anyMatch(workspaceId -> workspaceJobMap.get(workspaceId).stream().anyMatch(jobCodes::contains));
+ log.info("投放项目部:{},投放岗位岗位:{},当前登录单位:{},用户加入项目部及担任岗位:{},单位加入的项目部:{},项目部下的单位:{}",
+ JSONUtil.toJsonStr(ouIds), JSONUtil.toJsonStr(jobCodes),
+ loginOuid,
+ JSONUtil.toJsonStr(workspaceJobMap),
+ JSONUtil.toJsonStr(workspaceOuJob.getOuWorkspaceMap()),
+ JSONUtil.toJsonStr(workspaceOuJob.getWorkspaceOuMap()));
+
+ // 配置全部项目部
+ if (CollectionUtils.isEmpty(workspaceIds)) {
+ // 未加入任何项目部
+ if (Objects.isNull(workspaceJobMap) || workspaceJobMap.isEmpty()) {
+ return false;
+ }
+
+ if (CollectionUtils.isEmpty(jobCodes)) {
+ return true;
+ }else {
+ if (Objects.isNull(loginOuid) || loginOuid == 0 || CollectionUtils.isEmpty(workspaceOuJob.getOuWorkspaceMap().get(loginOuid))){
+ return jobCodes.stream().anyMatch(jobCode -> workspaceJobMap.values().stream().anyMatch(jobCodeList -> jobCodeList.contains(jobCode)));
+ }else {
+ return workspaceOuJob.getOuWorkspaceMap().get(loginOuid).stream().anyMatch(w -> !CollectionUtils.isEmpty(workspaceJobMap.get(w)) && jobCodes.stream().anyMatch(jobCode -> workspaceJobMap.get(w).contains(jobCode)));
+ }
+ }
+ }
+
+ // 若配置了具体项目部
+ if (Objects.isNull(loginOuid) || loginOuid == 0L) {
+ // 加入的全部项目部与配置的项目部有交集
+ if (workspaceIds.stream().anyMatch(workspaceJobMap::containsKey)) {
+ if (CollectionUtils.isEmpty(jobCodes)) {
+ return true;
+ }
+ return workspaceIds.stream().anyMatch(workspaceId -> workspaceJobMap.get(workspaceId).stream().anyMatch(jobCodes::contains));
+ }
+ return false;
+ } else {
+ // 给定了具体登录单位
+ // 登录了具体的单位且以纯单位身份登录
+ if (CollectionUtils.isEmpty(workspaceOuJob.getOuWorkspaceMap().get(loginOuid))) {
+ return false;
+ }
+ // 以项目部下单位登录
+ // 加入的全部项目部与配置的项目部有交集
+ if (workspaceIds.stream().anyMatch(w -> workspaceOuJob.getOuWorkspaceMap().get(loginOuid).stream().anyMatch(w::equals))) {
+ if (CollectionUtils.isEmpty(jobCodes)) {
+ return true;
+ }
+ return workspaceIds.stream().anyMatch(workspaceId -> workspaceJobMap.get(workspaceId).stream().anyMatch(jobCodes::contains));
+ }
+ return false;
+ }
}
},
- UNIT("UNIT", "按照企业") {
+ UNIT("UNIT", "按照单位") {
@Override
- public boolean isDeliverRequired(List workspaceIds, List ouIds, List jobCodes, JoinedWorkspaceOuJob workspaceOuJob) {
- // 若workspaceIds和jobCodes都为空,则表示不限制,否则需要满足配置的workspaceIds和jobCodes与用户加入的workspaceJob的key,value均存在交集
+ public boolean isDeliverRequired(List workspaceIds, List ouIds, List jobCodes,
+ Long loginWorkspaceId, Long loginOuid,
+ JoinedWorkspaceOuJob workspaceOuJob) {
+
Map> ouJobMap = workspaceOuJob.getOuJobMap();
- return CollectionUtils.isEmpty(ouIds) ? CollectionUtils.isEmpty(jobCodes) || jobCodes.stream().anyMatch(jobCode -> ouJobMap.values().stream().flatMap(List::stream).distinct().collect(Collectors.toList()).contains(jobCode))
- : ouIds.stream().anyMatch(ouId -> ouJobMap.get(ouId).stream().anyMatch(jobCodes::contains));
+ log.info("投放单位:{},投放岗位岗位:{},当前登录单位:{},用户加入单位及担任岗位:{}",
+ JSONUtil.toJsonStr(ouIds), JSONUtil.toJsonStr(jobCodes),
+ loginOuid,
+ JSONUtil.toJsonStr(ouJobMap));
+ // 判断配置的单位和岗位是否为空
+ if (CollectionUtils.isEmpty(ouIds)) {
+ // 若配置的单位为空(即配置了全部单位)
+ if (CollectionUtils.isEmpty(jobCodes)) {
+ // 若配置的岗位也为空(即配置了所有岗位),则不限制投放
+ return true;
+ } else {
+ // 若配置了具体岗位,检查用户加入的所有单位下的岗位是否包含任一配置岗位
+ if (Objects.isNull(loginOuid) || loginOuid == 0L) {
+ return jobCodes.stream().anyMatch(jobCode -> ouJobMap.values().stream()
+ .flatMap(List::stream)
+ .distinct()
+ .collect(Collectors.toList())
+ .contains(jobCode));
+ } else {
+ return jobCodes.stream().anyMatch(jobCode -> ouJobMap.get(loginOuid).stream().anyMatch(jobCodes::contains));
+ }
+
+ }
+ }
+
+ // 若配置了具体单位
+ if (Objects.isNull(loginOuid) || loginOuid == 0L) {
+ // 若登录单位为空(工人APP登录),检查用户加入的单位是否与配置单位有交集
+ if (ouIds.stream().anyMatch(ouJobMap::containsKey)) {
+ if (CollectionUtils.isEmpty(jobCodes)) {
+ return true;
+ }
+ return ouIds.stream().anyMatch(o -> ouJobMap.get(o).stream().anyMatch(jobCodes::contains));
+ }
+ return false;
+ } else {
+ // 若登录单位不为空(管理APP或CMS登录),检查登录单位是否与配置单位有交集
+ if (!ouIds.contains(loginOuid)) {
+ return false;
+ }
+
+ if (CollectionUtils.isEmpty(jobCodes)) {
+ // 若配置了所有岗位,由于登录单位已满足条件,此时无需再检查岗位
+ return true;
+ } else {
+ // 若配置了具体岗位,检查登录单位下担任的岗位是否包含任一配置岗位
+ return !CollectionUtils.isEmpty(ouJobMap.get(loginOuid)) && jobCodes.stream().anyMatch(jobCode -> ouJobMap.get(loginOuid).stream().anyMatch(jobCodes::contains));
+ }
+ }
}
};
@@ -54,15 +158,19 @@ public enum MaterialTargetUserTypeEnum {
private final String desc;
/**
- * 是否需要投放
+ * 根据目标人权类型确认是否需要投放
*
- * @param workspaceIds 配置的投放项目部
- * @param ouIds 配置的投放单位
- * @param jobCodes 配置的投放岗位
- * @param workspaceOuJob 用户参与的项目部和单位及其岗位
+ * @param workspaceIds 配置的投放项目部
+ * @param ouIds 配置的投放单位
+ * @param jobCodes 配置的投放岗位
+ * @param loginWorkspaceId 当前登录的项目部
+ * @param loginOuid 当前登录的单位
+ * @param workspaceOuJob 用户参与的项目部和单位及其岗位
* @return 是否需要投放
*/
- public abstract boolean isDeliverRequired(List workspaceIds, List ouIds, List jobCodes, JoinedWorkspaceOuJob workspaceOuJob);
+ public abstract boolean isDeliverRequired(List workspaceIds, List ouIds, List jobCodes,
+ Long loginWorkspaceId, Long loginOuid,
+ JoinedWorkspaceOuJob workspaceOuJob);
public static MaterialTargetUserTypeEnum getByCode(String code) {
if (StringUtils.isEmpty(code)) {
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/OpSystemTypeEnum.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/OpSystemTypeEnum.java
index 004f6042..094aa5b7 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/OpSystemTypeEnum.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/OpSystemTypeEnum.java
@@ -17,9 +17,9 @@ import java.util.Arrays;
@AllArgsConstructor
public enum OpSystemTypeEnum {
- ANDROID("Android", "安卓"),
+ ANDROID("ANDROID", "安卓"),
- IOS("iOS", "苹果"),
+ IOS("IOS", "苹果"),
PC("PC", "电脑");
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/RecodeTypeEnum.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/RecodeTypeEnum.java
index bd8ab20c..032d14b5 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/RecodeTypeEnum.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/enums/RecodeTypeEnum.java
@@ -15,9 +15,9 @@ import java.util.Arrays;
@AllArgsConstructor
public enum RecodeTypeEnum {
- BANNER("BANNER", "广告位操作类型"),
+ BANNER("BANNER", "广告"),
- MATERIAL("MATERIAL", "素材操作类型"),
+ MATERIAL("MATERIAL", "素材"),
;
private final String type;
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateApplicationVersionReadLogReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateApplicationVersionReadLogReq.java
new file mode 100644
index 00000000..77b0ef56
--- /dev/null
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateApplicationVersionReadLogReq.java
@@ -0,0 +1,53 @@
+package cn.axzo.nanopart.api.request;
+
+import cn.axzo.nanopart.api.enums.OpSystemTypeEnum;
+import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/12 10:15
+ */
+@Data
+@Builder
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+public class CreateApplicationVersionReadLogReq {
+
+ /**
+ * 阅读人
+ */
+ @NotNull(message = "阅读人不能为空")
+ private Long personId;
+
+ /**
+ * 版本id
+ */
+ @NotNull(message = "版本记录id不能为空")
+ private Long versionId;
+
+ /**
+ * 版本号
+ */
+ private String version;
+
+ /**
+ * 平台
+ * {@link PlatformTypeEnum}
+ */
+ private PlatformTypeEnum platform;
+
+ /**
+ * 操作系统
+ * {@link OpSystemTypeEnum}
+ */
+ private OpSystemTypeEnum opSystem;
+}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateApplicationVersionReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateApplicationVersionReq.java
index d4f38a20..8c25823d 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateApplicationVersionReq.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateApplicationVersionReq.java
@@ -2,7 +2,7 @@ package cn.axzo.nanopart.api.request;
import cn.axzo.nanopart.api.enums.OpSystemTypeEnum;
import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
-import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.JSONArray;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -46,7 +46,7 @@ public class CreateApplicationVersionReq {
/**
* 发布时间
*/
- @NotNull(message ="发版时间不能为空")
+ @NotNull(message = "发版时间不能为空")
private Date releaseTime;
/**
@@ -57,11 +57,19 @@ public class CreateApplicationVersionReq {
/**
* 跳转地址
- * eg: {
- * "H5": "http://www.baidu.com/defalut.html"
- * }
+ * eg:
+ * [
+ * {
+ * "label": "H5",
+ * "value": "http://www.baidu.com/defalut.html"
+ * },
+ * {
+ * "label": "iOS",
+ * "value": "http://www.baidu.com/defalut.html"
+ * }
+ * ]
*/
- private JSONObject jumpUrl;
+ private JSONArray jumpUrl;
/**
* 更新后是否弹窗提醒,0不提醒,1提醒,默认0
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateBannerReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateBannerReq.java
index 1942f586..cfb5944b 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateBannerReq.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateBannerReq.java
@@ -2,9 +2,9 @@ package cn.axzo.nanopart.api.request;
import cn.axzo.nanopart.api.dto.AspectRatioDto;
import cn.axzo.nanopart.api.enums.CarouselStatusEnum;
+import cn.axzo.nanopart.api.enums.DisplayTimeTypeEnum;
import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
import cn.axzo.nanopart.api.enums.StatusEnum;
-import com.alibaba.fastjson.JSONArray;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -12,11 +12,10 @@ import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
-import java.time.LocalTime;
+import java.util.List;
/**
* @author chenwenjian
@@ -33,12 +32,14 @@ public class CreateBannerReq {
/**
* 广告位名称
*/
+ @Length(max = 50)
+ @NotBlank(message = "广告位名称不能为空")
private String name;
/**
* 广告位编码
*/
- @Length(max = 8)
+ @Length(max = 20)
@NotBlank(message = "站点code不能为空")
private String code;
@@ -52,7 +53,8 @@ public class CreateBannerReq {
/**
* 标签,内置标签:“弹窗”,“banner”
*/
- private JSONArray tag;
+ @NotEmpty(message = "标签不能为空")
+ private List tag;
/**
* 轮播状态,取值:OPENED, CLOSED,默认为ClOSED
@@ -63,9 +65,6 @@ public class CreateBannerReq {
/**
* 最大轮播数量,限制【1-6】
*/
- @Min(value = 1, message = "轮播上线数量不能小于1")
- @Max(value = 6, message = "轮播上限数量不能超过6")
- @NotNull(message = "轮播上限数量不能为空")
private int maxCarouselLimit;
/**
@@ -81,21 +80,23 @@ public class CreateBannerReq {
/**
* 播放时长,0表示关闭状态,范围【1-120】s
*/
- @Min(value = 0)
- @Max(value = 120)
private float playDuration;
+ /**
+ * 展示时间段类型,取值:全天:ALL_DAY,上班时间:WORKING,休息时间:BREAKING,自定义:CUSTOM,默认全天
+ */
+ @NotNull(message = "展示时间段类型不能为空")
+ private DisplayTimeTypeEnum displayTimeType = DisplayTimeTypeEnum.ALL_DAY;
+
/**
* 展示时间段-开始时间
*/
- @NotNull(message = "展示时间段不能为空")
- private LocalTime startTime;
+ private Long startTime;
/**
* 展示时间段-结束时间
*/
- @NotNull(message = "展示时间段不能为空")
- private LocalTime endTime;
+ private Long endTime;
/**
* 长宽比,默认选择不限制,即limit=false
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateMaterialPutLogReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateMaterialPutLogReq.java
new file mode 100644
index 00000000..448d924b
--- /dev/null
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateMaterialPutLogReq.java
@@ -0,0 +1,40 @@
+package cn.axzo.nanopart.api.request;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/11 10:38
+ */
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+public class CreateMaterialPutLogReq {
+
+ /**
+ * 请求id
+ */
+ private String requestId;
+
+ /**
+ * 用户personId
+ */
+ private Long personId;
+
+ /**
+ * 广告位编码
+ */
+ private String bannerCode;
+
+ /**
+ * 投放的素材id列表
+ */
+ private List materialIds;
+}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateMaterialReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateMaterialReq.java
index 33d3bdc9..3ef1bfdd 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateMaterialReq.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/CreateMaterialReq.java
@@ -2,7 +2,9 @@ package cn.axzo.nanopart.api.request;
import cn.axzo.nanopart.api.enums.MaterialDisplayFrequencyTypeEnum;
import cn.axzo.nanopart.api.enums.MaterialTargetUserTypeEnum;
+import cn.axzo.nanopart.api.enums.MaterialTypeEnum;
import cn.axzo.nanopart.api.enums.StatusEnum;
+import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -33,24 +35,27 @@ public class CreateMaterialReq {
/**
* 广告位编码
*/
- @Length(max = 150, message = "bannerCode长度不能超过150")
+
@NotBlank(message = "bannerCode不能为空")
private String bannerCode;
/**
* 名称
*/
+ @Length(max = 150, message = "素材名称长度不能超过150字")
@NotBlank(message = "素材名称不能为空")
private String name;
/**
* 有效期-开始时间
*/
+ @NotNull(message = "有效期-开始时间不能为空")
private Date startTime;
/**
* 有效期-结束时间
*/
+ @NotNull(message = "有效期-结束时间不能为空")
private Date endTime;
/**
@@ -66,6 +71,11 @@ public class CreateMaterialReq {
*/
private StatusEnum status;
+ /**
+ * 素材类型,取值:IMAGE, VIDEO, AUDIO
+ */
+ private MaterialTypeEnum materialType;
+
/**
* 占位图,支持jpg、jpeg、png、gif,限定大小为200k
* eg: {
@@ -91,27 +101,25 @@ public class CreateMaterialReq {
/**
* 跳转地址
- * eg: {
- * "APP": {
- * "Android": "http://www.baidu.com/defalut.html",
- * "iOS": "http://www.baidu.com/defalut.html",
- * "h5": "http://www.baidu.com/defalut.html"
+ * eg:
+ * [
+ * {
+ * "label": "H5",
+ * "value": "http://www.baidu.com/defalut.html"
* },
- * "Applet": {
- * "applet": "http://www.baidu.com/defalut.html",
- * "h5": "http://www.baidu.com/defalut.html"
- * },
- * "PC": {
- * "h5": "http://www.baidu.com/defalut.html"
- * }
+ * {
+ * "label": "iOS",
+ * "value": "http://www.baidu.com/defalut.html"
* }
+ * ]
*/
- private JSONObject jumpUrl;
+ private JSONArray jumpUrl;
/**
* 目标投放对象类型呢,取值:ALL_USER, PROJECT, UNIT
* {@link MaterialTargetUserTypeEnum}
*/
+ @NotNull(message = "目标投放对象类型不能为空")
private MaterialTargetUserTypeEnum targetUserType;
/**
@@ -130,9 +138,10 @@ public class CreateMaterialReq {
private List ouIds;
/**
- * 单用户显示频次类型,有效期内:VALIDITY_PERIOD,每天:EVERY_DAY,每周:EVERY_WEEK,每月:EVERY_MONTH
+ * 单用户显示频次类型,不限:NO_LIMIT,有效期内:VALIDITY_PERIOD,每天:EVERY_DAY,每周:EVERY_WEEK,每月:EVERY_MONTH
* {@link MaterialDisplayFrequencyTypeEnum}
*/
+ @NotNull(message = "单用户显示频次类型不能为空")
private MaterialDisplayFrequencyTypeEnum displayFrequencyType;
/**
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/GetApplicationVersionReadLogReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/GetApplicationVersionReadLogReq.java
new file mode 100644
index 00000000..e416be7d
--- /dev/null
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/GetApplicationVersionReadLogReq.java
@@ -0,0 +1,41 @@
+package cn.axzo.nanopart.api.request;
+
+import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/11 14:18
+ */
+@Data
+@Builder
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+public class GetApplicationVersionReadLogReq {
+
+ /**
+ * 阅读人
+ */
+ private Long personId;
+
+ /**
+ * 版本id
+ */
+ private Long versionId;
+
+ /**
+ * 版本号
+ */
+ private String version;
+
+ /**
+ * 平台
+ */
+ private PlatformTypeEnum platform;
+}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/ListMaterialByBannerCodeReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/ListMaterialByBannerCodeReq.java
index 87103b14..ba4d5766 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/ListMaterialByBannerCodeReq.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/ListMaterialByBannerCodeReq.java
@@ -7,7 +7,6 @@ import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
-import java.util.List;
/**
* @author chenwenjian
@@ -30,24 +29,23 @@ public class ListMaterialByBannerCodeReq {
/**
* 当前登录人的personId
*/
- // @NotNull(message = "personId不能为空")
private Long personId;
/**
- * 项目部id,用于筛选相关运营素材是否配置给了该项目部人员
+ * 当前登录项目部id,用于筛选相关运营素材是否配置给了该项目部人员
*/
- private List workspaceIds;
+ private Long workspaceId;
/**
- * 单位id,用于筛选相关运营素材是否配置给了该单位人员
+ * 当前登录单位id,用于筛选相关运营素材是否配置给了该单位人员
*/
- private List ouIds;
+ private Long ouId;
/**
* 岗位编码,搭配{@code workspaceIds}或{@code unitIds}使用
* 用于筛选相关运营素材是否配置给了指定项目部下指定岗位人员
* 或指定单位下指定岗位人员
*/
- private List jobCodes;
+ private String jobCode;
}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/UpdateApplicationVersionReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/UpdateApplicationVersionReq.java
index 7e2f51ab..d9d2eec3 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/UpdateApplicationVersionReq.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/UpdateApplicationVersionReq.java
@@ -1,6 +1,6 @@
package cn.axzo.nanopart.api.request;
-import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.JSONArray;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -46,11 +46,18 @@ public class UpdateApplicationVersionReq {
/**
* 跳转地址
- * eg: {
- * "H5": "http://www.baidu.com/defalut.html"
- * }
+ * eg: [
+ * {
+ * "label": "H5",
+ * "value": "http://www.baidu.com/defalut.html"
+ * },
+ * {
+ * "label": "iOS",
+ * "value": "http://www.baidu.com/defalut.html"
+ * }
+ * ]
*/
- private JSONObject jumpUrl;
+ private JSONArray jumpUrl;
/**
* 更新后是否弹窗提醒,0不提醒,1提醒,默认0
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/UpdateBannerReq.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/UpdateBannerReq.java
index 959e4576..c608bc3b 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/UpdateBannerReq.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/request/UpdateBannerReq.java
@@ -2,18 +2,17 @@ package cn.axzo.nanopart.api.request;
import cn.axzo.nanopart.api.dto.AspectRatioDto;
import cn.axzo.nanopart.api.enums.CarouselStatusEnum;
+import cn.axzo.nanopart.api.enums.DisplayTimeTypeEnum;
import cn.axzo.nanopart.api.enums.StatusEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
+import org.hibernate.validator.constraints.Length;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
-import java.time.LocalTime;
/**
* @author chenwenjian
@@ -36,6 +35,7 @@ public class UpdateBannerReq {
/**
* 广告位名称
*/
+ @Length(max = 50)
@NotBlank(message = "广告位名称不能为空")
private String name;
@@ -43,34 +43,43 @@ public class UpdateBannerReq {
* 轮播状态,取值:OPENED, CLOSED,默认为ClOSED
* {@link CarouselStatusEnum}
*/
- @NotNull(message = "轮播状态不能为空")
private CarouselStatusEnum carouselStatus;
/**
* 最大轮播数量,限制【1-6】
*/
- @Min(value = 1)
- @Max(value = 6)
private int maxCarouselLimit;
/**
* 播放时长,0表示关闭状态,范围【1-120】s
*/
- @Min(value = 0)
- @Max(value = 120)
private float playDuration;
+ /**
+ * 展示时间段类型,取值:全天:ALL_DAY,上班时间:WORKING,休息时间:BREAKING,自定义:CUSTOM,默认全天
+ */
+ @NotNull(message = "展示时间段类型不能为空")
+ private DisplayTimeTypeEnum displayTimeType = DisplayTimeTypeEnum.ALL_DAY;
+
/**
* 展示时间段-开始时间
*/
- @NotNull(message = "展示时间段不能为空")
- private LocalTime startTime;
+ private Long startTime;
/**
* 展示时间段-结束时间
*/
- @NotNull(message = "展示时间段不能为空")
- private LocalTime endTime;
+ private Long endTime;
+
+ /**
+ * iOS适配版本,搭配展示终端(terminal)为APP时使用
+ */
+ private String iosVersion;
+
+ /**
+ * Android适配版本,搭配展示终端(terminal)为APP时使用
+ */
+ private String androidVersion;
/**
* 长宽比
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/DetailBannerResp.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/DetailBannerResp.java
index 3d89f62e..e358c351 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/DetailBannerResp.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/DetailBannerResp.java
@@ -1,14 +1,13 @@
package cn.axzo.nanopart.api.response;
import cn.axzo.nanopart.api.enums.CarouselStatusEnum;
+import cn.axzo.nanopart.api.enums.DisplayTimeTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
-import java.time.LocalTime;
-
/**
* @author chenwenjian
* @version 1.0
@@ -37,14 +36,19 @@ public class DetailBannerResp extends PageBannerResp {
*/
private float playDuration;
+ /**
+ * 展示时间段类型,取值:全天:ALL_DAY,上班时间:WORKING,休息时间:BREAKING,自定义:CUSTOM,默认全天
+ */
+ private DisplayTimeTypeEnum displayTimeType;
+
/**
* 展示时间段-开始时间
*/
- private LocalTime startTime;
+ private Long startTime;
/**
* 展示时间段-结束时间
*/
- private LocalTime endTime;
+ private Long endTime;
}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/GetVersionUpdateRemindContentResp.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/GetVersionUpdateRemindContentResp.java
index aa013e33..8b08c237 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/GetVersionUpdateRemindContentResp.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/GetVersionUpdateRemindContentResp.java
@@ -2,6 +2,7 @@ package cn.axzo.nanopart.api.response;
import cn.axzo.nanopart.api.enums.OpSystemTypeEnum;
import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
+import com.alibaba.fastjson.JSONArray;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -48,4 +49,25 @@ public class GetVersionUpdateRemindContentResp {
* 版本描述
*/
private String description;
+
+ /**
+ * 跳转地址
+ * eg:
+ * [
+ * {
+ * "label": "H5",
+ * "value": "http://www.baidu.com/defalut.html"
+ * },
+ * {
+ * "label": "iOS",
+ * "value": "http://www.baidu.com/defalut.html"
+ * }
+ * ]
+ */
+ private JSONArray jumpUrl;
+
+ /**
+ * 图片地址url
+ */
+ private String imageUrl;
}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/MaterialResp.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/MaterialResp.java
index cd5047db..7e026a24 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/MaterialResp.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/MaterialResp.java
@@ -3,6 +3,8 @@ package cn.axzo.nanopart.api.response;
import cn.axzo.nanopart.api.enums.MaterialDisplayFrequencyTypeEnum;
import cn.axzo.nanopart.api.enums.MaterialTargetUserTypeEnum;
import cn.axzo.nanopart.api.enums.MaterialTypeEnum;
+import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
+import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -11,6 +13,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
+import java.util.Date;
import java.util.List;
/**
@@ -27,7 +30,7 @@ import java.util.List;
public class MaterialResp extends PageMaterialResp {
/**
- * 素材类型,取值:IMAGE, VIDEO, APPLET
+ * 素材类型,取值:IMAGE, VIDEO, AUDIO
*/
private MaterialTypeEnum materialType;
@@ -53,22 +56,19 @@ public class MaterialResp extends PageMaterialResp {
/**
* 跳转地址
- * eg: {
- * "APP": {
- * "Android": "http://www.baidu.com/defalut.html",
- * "iOS": "http://www.baidu.com/defalut.html",
- * "h5": "http://www.baidu.com/defalut.html"
- * },
- * "Applet": {
- * "applet": "http://www.baidu.com/defalut.html",
- * "h5": "http://www.baidu.com/defalut.html"
- * },
- * "PC": {
- * "h5": "http://www.baidu.com/defalut.html"
- * }
- * }
+ * eg:
+ * [
+ * {
+ * "label": "H5",
+ * "value": "http://www.baidu.com/defalut.html"
+ * },
+ * {
+ * "label": "iOS",
+ * "value": "http://www.baidu.com/defalut.html"
+ * }
+ * ]
*/
- private JSONObject jumpUrl;
+ private JSONArray jumpUrl;
/**
* 目标投放对象类型呢,取值:ALL_USER, PROJECT, UNIT
@@ -108,9 +108,43 @@ public class MaterialResp extends PageMaterialResp {
*/
private Long createBy;
+ /**
+ * 创建人姓名
+ */
+ private String createByName;
+
/**
* 更新人
*/
private Long updateBy;
+ /**
+ * 更新人姓名
+ */
+ private String updateByName;
+
+ /**
+ * 所属终端,取值:CMS:安心筑CMS,CM,CMP:安心筑工人端APP,安心筑管理端APP
+ *
+ * 素材
+ *
+ * {@link PlatformTypeEnum}
+ */
+ private PlatformTypeEnum terminal;
+
+ /**
+ * 创建时间
+ */
+ private Date createAt;
+
+ /**
+ * 目标投放项目部或企业
+ */
+ private String targetWorkspaceOrUnit;
+
+ /**
+ * 目标投放岗位
+ */
+ private String targetUserJobCode;
+
}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/PageApplicationVersionResp.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/PageApplicationVersionResp.java
index 5688270f..30380e15 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/PageApplicationVersionResp.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/PageApplicationVersionResp.java
@@ -2,7 +2,7 @@ package cn.axzo.nanopart.api.response;
import cn.axzo.nanopart.api.enums.OpSystemTypeEnum;
import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
-import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.JSONArray;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -23,6 +23,8 @@ import java.util.Date;
@AllArgsConstructor
public class PageApplicationVersionResp {
+ private Long id;
+
/**
* 版本号
*/
@@ -52,11 +54,19 @@ public class PageApplicationVersionResp {
/**
* 跳转地址
- * eg: {
- * "H5": "http://www.baidu.com/defalut.html"
- * }
+ * eg:
+ * [
+ * {
+ * "label": "H5",
+ * "value": "http://www.baidu.com/defalut.html"
+ * },
+ * {
+ * "label": "iOS",
+ * "value": "http://www.baidu.com/defalut.html"
+ * }
+ * ]
*/
- private JSONObject jumpUrl;
+ private JSONArray jumpUrl;
/**
* 更新后是否弹窗提醒,0不提醒,1提醒,默认0
@@ -71,5 +81,5 @@ public class PageApplicationVersionResp {
/**
* 更新人
*/
- private Long updateBy;
+ private String updateBy;
}
diff --git a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/PageBannerOperationLogResp.java b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/PageBannerOperationLogResp.java
index a7d42bd2..79e1a00a 100644
--- a/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/PageBannerOperationLogResp.java
+++ b/banner/banner-api/src/main/java/cn/axzo/nanopart/api/response/PageBannerOperationLogResp.java
@@ -44,6 +44,11 @@ public class PageBannerOperationLogResp {
*/
private Long updateBy;
+ /**
+ * 操作人名称
+ */
+ private String updateByName;
+
/**
* 操作类型
*/
@@ -58,4 +63,14 @@ public class PageBannerOperationLogResp {
* 旧数据
*/
private JSONObject oldData;
+
+ /**
+ * 操作类型
+ */
+ private String operationTypeDesc;
+
+ /**
+ * 操作内容
+ */
+ private String operationContent;
}
diff --git a/banner/banner-server/pom.xml b/banner/banner-server/pom.xml
index 64eb92b9..639ccf06 100644
--- a/banner/banner-server/pom.xml
+++ b/banner/banner-server/pom.xml
@@ -74,5 +74,10 @@
cn.axzo.maokai
maokai-api
+
+
+ cn.axzo.basics
+ basics-profiles-api
+
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/common/ApplicationVersionValidator.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/common/ApplicationVersionValidator.java
new file mode 100644
index 00000000..e60ecd36
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/common/ApplicationVersionValidator.java
@@ -0,0 +1,32 @@
+package cn.axzo.nanopart.server.common;
+
+import cn.axzo.framework.domain.ServiceException;
+import cn.axzo.nanopart.api.constant.NanopartConstant;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * TODO 待统一优化,需要统一版本号命名规则
+ * 版本号规则校验器
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/17 20:21
+ */
+@Slf4j
+public class ApplicationVersionValidator {
+
+ /**
+ * 对给定版本号进行简单正则校验
+ *
+ * @param version 版本号
+ */
+ public static void checkVersionSimple(String version) {
+ if (StringUtils.isNotBlank(version)) {
+ if (!version.matches(NanopartConstant.VERSION_SIMPLE_PATTERN)) {
+ log.warn("版本号校验不通过,version = {}",version);
+ throw new ServiceException("请输入正确的版本号");
+ }
+ }
+ }
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/ApplicationVersionController.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/ApplicationVersionController.java
index 1e2bd3ed..6dd0da2c 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/ApplicationVersionController.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/ApplicationVersionController.java
@@ -1,57 +1,65 @@
-// package cn.axzo.nanopart.server.controller;
-//
-// import cn.axzo.framework.domain.web.result.ApiPageResult;
-// import cn.axzo.framework.domain.web.result.ApiResult;
-// import cn.axzo.nanopart.api.ApplicationVersionApi;
-// import cn.axzo.nanopart.api.request.CreateApplicationVersionReq;
-// import cn.axzo.nanopart.api.request.GetVersionUpdateRemindContentReq;
-// import cn.axzo.nanopart.api.request.PageApplicationVersionReq;
-// import cn.axzo.nanopart.api.request.UpdateApplicationVersionReq;
-// import cn.axzo.nanopart.api.response.GetVersionUpdateRemindContentResp;
-// import cn.axzo.nanopart.api.response.PageApplicationVersionResp;
-// import cn.axzo.nanopart.server.service.ApplicationVersionService;
-// import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-// import lombok.RequiredArgsConstructor;
-// import lombok.extern.slf4j.Slf4j;
-// import org.springframework.web.bind.annotation.RestController;
-//
-// /**
-// * @author chenwenjian
-// * @version 1.0
-// * @date 2024/4/3 16:39
-// */
-// @Slf4j
-// @RestController
-// @RequiredArgsConstructor
-// public class ApplicationVersionController implements ApplicationVersionApi {
-//
-// private final ApplicationVersionService applicationVersionService;
-//
-// @Override
-// public ApiResult create(CreateApplicationVersionReq req) {
-// return ApiResult.ok(applicationVersionService.create(req));
-// }
-//
-// @Override
-// public ApiResult update(UpdateApplicationVersionReq req) {
-// applicationVersionService.update(req);
-// return ApiResult.ok();
-// }
-//
-// @Override
-// public ApiResult deleteById(Long id, Long personId) {
-// applicationVersionService.deleteById(id, personId);
-// return ApiResult.ok();
-// }
-//
-// @Override
-// public ApiPageResult page(PageApplicationVersionReq req) {
-// Page pageData = applicationVersionService.page(req);
-// return ApiPageResult.ok(pageData);
-// }
-//
-// @Override
-// public ApiResult getVersionUpdateRemindContent(GetVersionUpdateRemindContentReq req) {
-// return ApiResult.ok(applicationVersionService.getVersionUpdateRemindContent(req));
-// }
-// }
+package cn.axzo.nanopart.server.controller;
+
+import cn.axzo.framework.domain.ServiceException;
+import cn.axzo.framework.domain.web.result.ApiPageResult;
+import cn.axzo.framework.domain.web.result.ApiResult;
+import cn.axzo.nanopart.api.ApplicationVersionApi;
+import cn.axzo.nanopart.api.request.CreateApplicationVersionReq;
+import cn.axzo.nanopart.api.request.GetVersionUpdateRemindContentReq;
+import cn.axzo.nanopart.api.request.PageApplicationVersionReq;
+import cn.axzo.nanopart.api.request.UpdateApplicationVersionReq;
+import cn.axzo.nanopart.api.response.GetVersionUpdateRemindContentResp;
+import cn.axzo.nanopart.api.response.PageApplicationVersionResp;
+import cn.axzo.nanopart.server.service.ApplicationVersionService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Objects;
+
+/**
+ * 版本记录操作
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/3 16:39
+ */
+@Slf4j
+@RestController
+@RequiredArgsConstructor
+public class ApplicationVersionController implements ApplicationVersionApi {
+
+ private final ApplicationVersionService applicationVersionService;
+
+ @Override
+ public ApiResult create(CreateApplicationVersionReq req) {
+ return ApiResult.ok(applicationVersionService.create(req));
+ }
+
+ @Override
+ public ApiResult update(UpdateApplicationVersionReq req) {
+ applicationVersionService.update(req);
+ return ApiResult.ok();
+ }
+
+ @Override
+ public ApiResult deleteById(Long id, Long personId) {
+ applicationVersionService.deleteById(id, personId);
+ return ApiResult.ok();
+ }
+
+ @Override
+ public ApiPageResult page(PageApplicationVersionReq req) {
+ Page pageData = applicationVersionService.page(req);
+ return ApiPageResult.ok(pageData);
+ }
+
+ @Override
+ public ApiResult getVersionUpdateRemindContent(GetVersionUpdateRemindContentReq req) {
+ if (Objects.isNull(req.getPersonId()) || req.getPersonId() == 0) {
+ throw new ServiceException("personId不能为空");
+ }
+ return ApiResult.ok(applicationVersionService.getVersionUpdateRemindContent(req));
+ }
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/BannerController.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/BannerController.java
index e93d61c5..cffed1c8 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/BannerController.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/BannerController.java
@@ -1,58 +1,60 @@
-// package cn.axzo.nanopart.server.controller;
-//
-// import cn.axzo.framework.domain.web.result.ApiPageResult;
-// import cn.axzo.framework.domain.web.result.ApiResult;
-// import cn.axzo.nanopart.api.BannerApi;
-// import cn.axzo.nanopart.api.request.CreateBannerReq;
-// import cn.axzo.nanopart.api.request.DetailBannerReq;
-// import cn.axzo.nanopart.api.request.PageBannerReq;
-// import cn.axzo.nanopart.api.request.UpdateBannerReq;
-// import cn.axzo.nanopart.api.request.UpdateStatusReq;
-// import cn.axzo.nanopart.api.response.DetailBannerResp;
-// import cn.axzo.nanopart.api.response.PageBannerResp;
-// import cn.axzo.nanopart.server.service.BannerService;
-// import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-// import lombok.RequiredArgsConstructor;
-// import lombok.extern.slf4j.Slf4j;
-// import org.springframework.web.bind.annotation.RestController;
-//
-// /**
-// * @author chenwenjian
-// * @version 1.0
-// * @date 2024/4/3 16:30
-// */
-// @Slf4j
-// @RestController
-// @RequiredArgsConstructor
-// public class BannerController implements BannerApi {
-//
-// private final BannerService bannerService;
-//
-// @Override
-// public ApiPageResult page(PageBannerReq req) {
-// Page pageData = bannerService.page(req);
-// return ApiPageResult.ok(pageData);
-// }
-//
-// @Override
-// public ApiResult create(CreateBannerReq req) {
-// return ApiResult.ok(bannerService.create(req));
-// }
-//
-// @Override
-// public ApiResult update(UpdateBannerReq req) {
-// bannerService.update(req);
-// return ApiResult.ok();
-// }
-//
-// @Override
-// public ApiResult updateStatus(UpdateStatusReq req) {
-// bannerService.updateStatus(req);
-// return ApiResult.ok();
-// }
-//
-// @Override
-// public ApiResult detail(DetailBannerReq req) {
-// return ApiResult.ok(bannerService.detail(req));
-// }
-// }
+package cn.axzo.nanopart.server.controller;
+
+import cn.axzo.framework.domain.web.result.ApiPageResult;
+import cn.axzo.framework.domain.web.result.ApiResult;
+import cn.axzo.nanopart.api.BannerApi;
+import cn.axzo.nanopart.api.request.CreateBannerReq;
+import cn.axzo.nanopart.api.request.DetailBannerReq;
+import cn.axzo.nanopart.api.request.PageBannerReq;
+import cn.axzo.nanopart.api.request.UpdateBannerReq;
+import cn.axzo.nanopart.api.request.UpdateStatusReq;
+import cn.axzo.nanopart.api.response.DetailBannerResp;
+import cn.axzo.nanopart.api.response.PageBannerResp;
+import cn.axzo.nanopart.server.service.BannerService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 广告位操作
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/3 16:30
+ */
+@Slf4j
+@RestController
+@RequiredArgsConstructor
+public class BannerController implements BannerApi {
+
+ private final BannerService bannerService;
+
+ @Override
+ public ApiPageResult page(PageBannerReq req) {
+ Page pageData = bannerService.page(req);
+ return ApiPageResult.ok(pageData);
+ }
+
+ @Override
+ public ApiResult create(CreateBannerReq req) {
+ return ApiResult.ok(bannerService.create(req));
+ }
+
+ @Override
+ public ApiResult update(UpdateBannerReq req) {
+ bannerService.update(req);
+ return ApiResult.ok();
+ }
+
+ @Override
+ public ApiResult updateStatus(UpdateStatusReq req) {
+ bannerService.updateStatus(req);
+ return ApiResult.ok();
+ }
+
+ @Override
+ public ApiResult detail(DetailBannerReq req) {
+ return ApiResult.ok(bannerService.detail(req));
+ }
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/BannerOperationLogController.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/BannerOperationLogController.java
index cc1328da..44e511a9 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/BannerOperationLogController.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/BannerOperationLogController.java
@@ -1,24 +1,38 @@
-// package cn.axzo.nanopart.server.controller;
-//
-// import cn.axzo.framework.domain.web.result.ApiPageResult;
-// import cn.axzo.nanopart.api.BannerOperationLogApi;
-// import cn.axzo.nanopart.api.request.PageBannerOperationLogReq;
-// import cn.axzo.nanopart.api.response.PageBannerOperationLogResp;
-// import lombok.RequiredArgsConstructor;
-// import lombok.extern.slf4j.Slf4j;
-// import org.springframework.web.bind.annotation.RestController;
-//
-// /**
-// * @author chenwenjian
-// * @version 1.0
-// * @date 2024/4/3 16:40
-// */
-// @Slf4j
-// @RestController
-// @RequiredArgsConstructor
-// public class BannerOperationLogController implements BannerOperationLogApi {
-// @Override
-// public ApiPageResult page(PageBannerOperationLogReq req) {
-// return null;
-// }
-// }
+package cn.axzo.nanopart.server.controller;
+
+import cn.axzo.framework.domain.web.result.ApiPageResult;
+import cn.axzo.nanopart.api.BannerOperationLogApi;
+import cn.axzo.nanopart.api.request.PageBannerOperationLogReq;
+import cn.axzo.nanopart.api.response.PageBannerOperationLogResp;
+import cn.axzo.nanopart.server.service.BannerOperationLogService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 广告位和素材操作日志
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/3 16:40
+ */
+@Slf4j
+@RestController
+@RequiredArgsConstructor
+public class BannerOperationLogController implements BannerOperationLogApi {
+
+ private final BannerOperationLogService bannerOperationLogService;
+
+ /**
+ * 分页查询
+ *
+ * @param req {@link PageBannerOperationLogReq}
+ * @return 按照时间倒序排序后的列表
+ */
+ @Override
+ public ApiPageResult page(PageBannerOperationLogReq req) {
+ Page pageData = bannerOperationLogService.page(req);
+ return ApiPageResult.ok(pageData);
+ }
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/MaterialController.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/MaterialController.java
index b5a36755..07bda5ff 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/MaterialController.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/controller/MaterialController.java
@@ -1,17 +1,31 @@
package cn.axzo.nanopart.server.controller;
+import cn.axzo.framework.domain.ServiceException;
+import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.api.MaterialApi;
+import cn.axzo.nanopart.api.constant.NanopartConstant;
+import cn.axzo.nanopart.api.request.CreateMaterialReq;
+import cn.axzo.nanopart.api.request.DetailMaterialReq;
import cn.axzo.nanopart.api.request.ListMaterialByBannerCodeReq;
+import cn.axzo.nanopart.api.request.PageMaterialReq;
+import cn.axzo.nanopart.api.request.UpdateMaterialReq;
+import cn.axzo.nanopart.api.request.UpdateStatusReq;
import cn.axzo.nanopart.api.response.MaterialResp;
+import cn.axzo.nanopart.api.response.PageMaterialResp;
+import cn.axzo.nanopart.server.service.MaterialService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
-import java.util.Collections;
+import javax.servlet.http.HttpServletRequest;
import java.util.List;
+import java.util.Objects;
/**
+ * 素材操作
+ *
* @author chenwenjian
* @version 1.0
* @date 2024/4/3 16:31
@@ -21,38 +35,56 @@ import java.util.List;
@RequiredArgsConstructor
public class MaterialController implements MaterialApi {
- // private final MaterialService materialService;
- //
- // @Override
- // public ApiPageResult page(PageMaterialReq req) {
- // Page pageData = materialService.page(req);
- // return ApiPageResult.ok(pageData);
- // }
- //
- // @Override
- // public ApiResult create(CreateMaterialReq req) {
- // return ApiResult.ok(materialService.create(req));
- // }
- //
- // @Override
- // public ApiResult update(UpdateMaterialReq req) {
- // materialService.update(req);
- // return ApiResult.ok();
- // }
- //
- // @Override
- // public ApiResult updateStatus(UpdateStatusReq req) {
- // materialService.updateStatus(req);
- // return ApiResult.ok();
- // }
- //
- // @Override
- // public ApiResult detail(DetailMaterialReq req) {
- // return ApiResult.ok(materialService.detail(req));
- // }
+ private final MaterialService materialService;
+
+ private final HttpServletRequest request;
+ @Override
+ public ApiPageResult page(PageMaterialReq req) {
+ Page pageData = materialService.page(req);
+ return ApiPageResult.ok(pageData);
+ }
+
+ @Override
+ public ApiResult create(CreateMaterialReq req) {
+ return ApiResult.ok(materialService.create(req));
+ }
+
+ @Override
+ public ApiResult update(UpdateMaterialReq req) {
+ materialService.update(req);
+ return ApiResult.ok();
+ }
+
+ @Override
+ public ApiResult updateStatus(UpdateStatusReq req) {
+ materialService.updateStatus(req);
+ return ApiResult.ok();
+ }
+
+ @Override
+ public ApiResult detail(DetailMaterialReq req) {
+ return ApiResult.ok(materialService.detail(req));
+ }
+
+ /**
+ * 根据广告位编码(bannerCode)查询素材
+ *
+ * 1. 通过广告位code获取该广告位下的所有素材(默认查询上架状态且在有效期范围内的素材)
+ * 2. 根据广告位投放人群进行过滤(对于cms/cmp需要根据当前登录人登录企业情况进行过滤)
+ * 3. 根据广告位投放规则频次进行过滤
+ * 4. 将最终的素材根据优先级(priority)升序,创建时间(createAt)降序排序
+ *
+ *
+ * @param req {@link ListMaterialByBannerCodeReq}
+ * @return 根据优先级(priority)升序,创建时间(createAt)降序排序后的列表
+ */
@Override
public ApiResult> listMaterialByBannerCode(ListMaterialByBannerCodeReq req) {
- return ApiResult.ok(Collections.emptyList());
+ String traceId = request.getHeader(NanopartConstant.CONTEXT_TRACE_ID);
+ if (Objects.isNull(req.getPersonId()) || req.getPersonId() == 0L) {
+ throw new ServiceException("personId不能为空");
+ }
+ return ApiResult.ok(materialService.listMaterialByBannerCode(req, traceId));
}
}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/ApplicationVersion.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/ApplicationVersion.java
index 18232ccb..eefe4e14 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/ApplicationVersion.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/ApplicationVersion.java
@@ -3,6 +3,7 @@ package cn.axzo.nanopart.server.domain;
import cn.axzo.nanopart.api.enums.OpSystemTypeEnum;
import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
+import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -64,12 +65,20 @@ public class ApplicationVersion extends BaseEntity {
/**
* 跳转地址
- * eg: {
- * "H5": "http://www.baidu.com/defalut.html"
- * }
+ * eg:
+ * [
+ * {
+ * "label": "H5",
+ * "value": "http://www.baidu.com/defalut.html"
+ * },
+ * {
+ * "label": "iOS",
+ * "value": "http://www.baidu.com/defalut.html"
+ * }
+ * ]
*/
@TableField(value = "jump_url", typeHandler = FastjsonTypeHandler.class)
- private JSONObject jumpUrl;
+ private JSONArray jumpUrl;
/**
* 更新后是否弹窗提醒,0不提醒,1提醒,默认0
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/ApplicationVersionReadLog.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/ApplicationVersionReadLog.java
new file mode 100644
index 00000000..80e4b66b
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/ApplicationVersionReadLog.java
@@ -0,0 +1,70 @@
+package cn.axzo.nanopart.server.domain;
+
+import cn.axzo.nanopart.api.enums.OpSystemTypeEnum;
+import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
+import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/11 14:10
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName(value = "application_version_read_log", autoResultMap = true)
+public class ApplicationVersionReadLog extends BaseEntity {
+
+ /**
+ * 阅读人
+ */
+ @TableField(value = "person_id")
+ private Long personId;
+
+ /**
+ * 版本id
+ */
+ @TableField(value = "version_id")
+ private Long versionId;
+
+ /**
+ * 版本号
+ */
+ @TableField(value = "version")
+ private String version;
+
+ /**
+ * 平台
+ */
+ @TableField(value = "platform")
+ private PlatformTypeEnum platform;
+
+ /**
+ * 操作系统
+ * {@link OpSystemTypeEnum}
+ */
+ @TableField(value = "op_system")
+ private OpSystemTypeEnum opSystem;
+
+ /**
+ * 创建人
+ */
+ @TableField(value = "create_by")
+ private Long createBy;
+
+ /**
+ * 更新人
+ */
+ @TableField(value = "update_by")
+ private Long updateBy;
+
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/Banner.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/Banner.java
index f92bb340..90c67baa 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/Banner.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/Banner.java
@@ -1,8 +1,9 @@
package cn.axzo.nanopart.server.domain;
-import cn.axzo.nanopart.api.enums.StatusEnum;
import cn.axzo.nanopart.api.enums.CarouselStatusEnum;
+import cn.axzo.nanopart.api.enums.DisplayTimeTypeEnum;
import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
+import cn.axzo.nanopart.api.enums.StatusEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
@@ -17,7 +18,7 @@ import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
-import java.time.LocalTime;
+import java.sql.Time;
/**
* 运营广告位
@@ -66,17 +67,23 @@ public class Banner extends BaseEntity {
@TableField(value = "status")
private StatusEnum status;
+ /**
+ * 展示时间段类型,取值:全天:ALL_DAY,上班时间:WORKING,休息时间:BREAKING,自定义:CUSTOM
+ */
+ @TableField(value = "display_time_type")
+ private DisplayTimeTypeEnum displayTimeType;
+
/**
* 展示时间段-开始时间
*/
@TableField(value = "start_time")
- private LocalTime startTime;
+ private Time startTime;
/**
* 展示时间段-结束时间
*/
@TableField(value = "end_time")
- private LocalTime endTime;
+ private Time endTime;
/**
* 轮播状态,取值:OPENED, CLOSED
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/Material.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/Material.java
index 801c60d4..54b40a3c 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/Material.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/Material.java
@@ -6,6 +6,7 @@ import cn.axzo.nanopart.api.enums.MaterialTypeEnum;
import cn.axzo.nanopart.api.enums.StatusEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.pokonyan.config.mybatisplus.type.LongListTypeHandler;
+import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -72,7 +73,7 @@ public class Material extends BaseEntity {
private StatusEnum status;
/**
- * 素材类型,取值:IMAGE, VIDEO, APPLET
+ * 素材类型,取值:IMAGE, VIDEO, AUDIO
*/
@TableField(value = "material_type")
private MaterialTypeEnum materialType;
@@ -103,23 +104,20 @@ public class Material extends BaseEntity {
/**
* 跳转地址
- * eg: {
- * "APP": {
- * "Android": "http://www.baidu.com/defalut.html",
- * "iOS": "http://www.baidu.com/defalut.html",
- * "h5": "http://www.baidu.com/defalut.html"
- * },
- * "Applet": {
- * "applet": "http://www.baidu.com/defalut.html",
- * "h5": "http://www.baidu.com/defalut.html"
- * },
- * "PC": {
- * "h5": "http://www.baidu.com/defalut.html"
- * }
- * }
+ * eg:
+ * [
+ * {
+ * "label": "H5",
+ * "value": "http://www.baidu.com/defalut.html"
+ * },
+ * {
+ * "label": "iOS",
+ * "value": "http://www.baidu.com/defalut.html"
+ * }
+ * ]
*/
@TableField(value = "jump_url", typeHandler = FastjsonTypeHandler.class)
- private JSONObject jumpUrl;
+ private JSONArray jumpUrl;
/**
* 目标投放对象类型呢,取值:ALL_USER, PROJECT, UNIT
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/MaterialPutLog.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/MaterialPutLog.java
new file mode 100644
index 00000000..8b228394
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/domain/MaterialPutLog.java
@@ -0,0 +1,53 @@
+package cn.axzo.nanopart.server.domain;
+
+import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
+import cn.axzo.pokonyan.config.mybatisplus.type.LongListTypeHandler;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * 素材投放日志记录
+ *
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/10 18:36
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName(value = "material_put_log", autoResultMap = true)
+public class MaterialPutLog extends BaseEntity {
+
+ /**
+ * 请求id
+ */
+ @TableField(value = "request_id")
+ private String requestId;
+
+ /**
+ * 用户personId
+ */
+ @TableField(value = "person_id")
+ private Long personId;
+
+ /**
+ * 广告位编码
+ */
+ @TableField(value = "banner_code")
+ private String bannerCode;
+
+ /**
+ * 投放的素材id列表
+ */
+ @TableField(value = "material_ids", typeHandler = LongListTypeHandler.class)
+ private List materialIds;
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/mapper/ApplicationVersionReadLogDao.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/mapper/ApplicationVersionReadLogDao.java
new file mode 100644
index 00000000..da87e7fc
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/mapper/ApplicationVersionReadLogDao.java
@@ -0,0 +1,14 @@
+package cn.axzo.nanopart.server.mapper;
+
+import cn.axzo.nanopart.server.domain.ApplicationVersionReadLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/11 14:14
+ */
+@Mapper
+public interface ApplicationVersionReadLogDao extends BaseMapper {
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/mapper/MaterialPutLogDao.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/mapper/MaterialPutLogDao.java
new file mode 100644
index 00000000..0e28378d
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/mapper/MaterialPutLogDao.java
@@ -0,0 +1,14 @@
+package cn.axzo.nanopart.server.mapper;
+
+import cn.axzo.nanopart.server.domain.MaterialPutLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/10 18:40
+ */
+@Mapper
+public interface MaterialPutLogDao extends BaseMapper {
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/rpc/ProfileGateway.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/rpc/ProfileGateway.java
new file mode 100644
index 00000000..6843625a
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/rpc/ProfileGateway.java
@@ -0,0 +1,63 @@
+package cn.axzo.nanopart.server.rpc;
+
+import cn.axzo.basics.profiles.api.UserProfileServiceApi;
+import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
+import cn.azxo.framework.common.logger.MethodAroundLog;
+import cn.azxo.framework.common.model.CommonResponse;
+import cn.hutool.core.collection.CollectionUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/17 19:39
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class ProfileGateway {
+
+ private final UserProfileServiceApi userProfileServiceApi;
+
+ /**
+ * 通过personId获取用户档案
+ *
+ * @param personId
+ * @return
+ */
+ @MethodAroundLog(target = "pudge", source = "nanopart", value = "获取用户档案")
+ public PersonProfileDto getProfile(Long personId) {
+ if (Objects.isNull(personId)) {
+ return null;
+ }
+ CommonResponse personProfile = userProfileServiceApi.getPersonProfile(personId);
+ if (Objects.nonNull(personProfile) && personProfile.getCode() == 200) {
+ return personProfile.getData();
+ }
+ return null;
+ }
+
+ /**
+ * 通过personId获取用户档案
+ *
+ * @param personIds
+ * @return
+ */
+ @MethodAroundLog(target = "pudge", source = "nanopart", value = "获取用户档案")
+ public List getProfiles(List personIds) {
+ if (CollectionUtil.isEmpty(personIds)) {
+ return Collections.emptyList();
+ }
+ CommonResponse> personProfiles = userProfileServiceApi.getPersonProfiles(personIds);
+ if (Objects.nonNull(personProfiles) && personProfiles.getCode() == 200) {
+ return personProfiles.getData();
+ }
+ return Collections.emptyList();
+ }
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/ApplicationVersionReadLogService.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/ApplicationVersionReadLogService.java
new file mode 100644
index 00000000..1ec38e73
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/ApplicationVersionReadLogService.java
@@ -0,0 +1,16 @@
+package cn.axzo.nanopart.server.service;
+
+import cn.axzo.nanopart.api.request.CreateApplicationVersionReadLogReq;
+import cn.axzo.nanopart.server.domain.ApplicationVersionReadLog;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/11 14:15
+ */
+public interface ApplicationVersionReadLogService {
+
+ Long create(CreateApplicationVersionReadLogReq req);
+
+ ApplicationVersionReadLog getByIdWithPersonId(Long personId, Long id);
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/ApplicationVersionService.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/ApplicationVersionService.java
index 169dd283..4118d7f4 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/ApplicationVersionService.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/ApplicationVersionService.java
@@ -23,4 +23,5 @@ public interface ApplicationVersionService {
Page page(PageApplicationVersionReq req);
GetVersionUpdateRemindContentResp getVersionUpdateRemindContent(GetVersionUpdateRemindContentReq req);
+
}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/BannerOperationLogService.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/BannerOperationLogService.java
index 0bb491c2..b08f6af9 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/BannerOperationLogService.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/BannerOperationLogService.java
@@ -1,6 +1,9 @@
package cn.axzo.nanopart.server.service;
import cn.axzo.nanopart.api.request.CreateBannerOperationLogReq;
+import cn.axzo.nanopart.api.request.PageBannerOperationLogReq;
+import cn.axzo.nanopart.api.response.PageBannerOperationLogResp;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* @author chenwenjian
@@ -10,4 +13,6 @@ import cn.axzo.nanopart.api.request.CreateBannerOperationLogReq;
public interface BannerOperationLogService {
Long create(CreateBannerOperationLogReq req);
+
+ Page page(PageBannerOperationLogReq req);
}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/MaterialPutLogService.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/MaterialPutLogService.java
new file mode 100644
index 00000000..5dd70ab0
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/MaterialPutLogService.java
@@ -0,0 +1,13 @@
+package cn.axzo.nanopart.server.service;
+
+import cn.axzo.nanopart.api.request.CreateMaterialPutLogReq;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/10 18:41
+ */
+public interface MaterialPutLogService {
+
+ Long create(CreateMaterialPutLogReq req);
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/MaterialService.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/MaterialService.java
index 49b812de..4a993d32 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/MaterialService.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/MaterialService.java
@@ -28,7 +28,7 @@ public interface MaterialService {
* @param req {@link ListMaterialByBannerCodeReq}
* @return 根据优先级(priority)升序,创建时间(createAt)降序排序后的列表
*/
- List listMaterialByBannerCode(ListMaterialByBannerCodeReq req);
+ List listMaterialByBannerCode(ListMaterialByBannerCodeReq req,String traceId);
Page page(PageMaterialReq req);
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/ApplicationVersionReadLogServiceImpl.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/ApplicationVersionReadLogServiceImpl.java
new file mode 100644
index 00000000..2ee6f45c
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/ApplicationVersionReadLogServiceImpl.java
@@ -0,0 +1,39 @@
+package cn.axzo.nanopart.server.service.impl;
+
+import cn.axzo.nanopart.api.request.CreateApplicationVersionReadLogReq;
+import cn.axzo.nanopart.server.domain.ApplicationVersionReadLog;
+import cn.axzo.nanopart.server.mapper.ApplicationVersionReadLogDao;
+import cn.axzo.nanopart.server.service.ApplicationVersionReadLogService;
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/11 14:15
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class ApplicationVersionReadLogServiceImpl extends ServiceImpl implements ApplicationVersionReadLogService {
+
+ @Override
+ public Long create(CreateApplicationVersionReadLogReq req) {
+ ApplicationVersionReadLog versionReadLog = BeanUtil.copyProperties(req, ApplicationVersionReadLog.class);
+ save(versionReadLog);
+ return versionReadLog.getId();
+ }
+
+ @Override
+ public ApplicationVersionReadLog getByIdWithPersonId(Long personId, Long id) {
+ return lambdaQuery()
+ .eq(ApplicationVersionReadLog::getIsDelete, 0)
+ .eq(ApplicationVersionReadLog::getPersonId, personId)
+ .eq(ApplicationVersionReadLog::getVersionId, id)
+ .last("limit 1")
+ .one();
+ }
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/ApplicationVersionServiceImpl.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/ApplicationVersionServiceImpl.java
index 078c6802..e18ba6d5 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/ApplicationVersionServiceImpl.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/ApplicationVersionServiceImpl.java
@@ -1,19 +1,43 @@
package cn.axzo.nanopart.server.service.impl;
+import cn.axzo.basics.common.BeanMapper;
+import cn.axzo.basics.profiles.dto.basic.BasicDto;
+import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
+import cn.axzo.framework.domain.ServiceException;
+import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
+import cn.axzo.nanopart.api.request.CreateApplicationVersionReadLogReq;
import cn.axzo.nanopart.api.request.CreateApplicationVersionReq;
import cn.axzo.nanopart.api.request.GetVersionUpdateRemindContentReq;
import cn.axzo.nanopart.api.request.PageApplicationVersionReq;
import cn.axzo.nanopart.api.request.UpdateApplicationVersionReq;
import cn.axzo.nanopart.api.response.GetVersionUpdateRemindContentResp;
import cn.axzo.nanopart.api.response.PageApplicationVersionResp;
-import cn.axzo.nanopart.server.mapper.ApplicationVersionDao;
import cn.axzo.nanopart.server.domain.ApplicationVersion;
+import cn.axzo.nanopart.server.domain.ApplicationVersionReadLog;
+import cn.axzo.nanopart.server.mapper.ApplicationVersionDao;
+import cn.axzo.nanopart.server.rpc.ProfileGateway;
+import cn.axzo.nanopart.server.service.ApplicationVersionReadLogService;
import cn.axzo.nanopart.server.service.ApplicationVersionService;
+import cn.axzo.pokonyan.dao.converter.PageConverter;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
/**
* @author chenwenjian
@@ -22,31 +46,188 @@ import org.springframework.stereotype.Service;
*/
@Slf4j
@Service
+@RefreshScope
@RequiredArgsConstructor
public class ApplicationVersionServiceImpl extends ServiceImpl implements ApplicationVersionService {
+ private final ApplicationVersionReadLogService applicationVersionReadLogService;
+
+ private final ProfileGateway profileGateway;
+
+ @Value("${versionRemindImg.app}")
+ private String appVersionRemindImage;
+
+ @Value("${versionRemindImg.cms}")
+ private String cmsVersionRemindImage;
+
+ /**
+ * 创建版本信息
+ *
+ * @param req {@link CreateApplicationVersionReq}
+ * @return 版本信息id
+ */
@Override
public Long create(CreateApplicationVersionReq req) {
- return null;
+ checkDuplicateVersion(req);
+ ApplicationVersion version = BeanUtil.copyProperties(req, ApplicationVersion.class);
+ save(version);
+ return version.getId();
}
+ /**
+ * 更新版本信息
+ *
+ * @param req {@link UpdateApplicationVersionReq}
+ */
@Override
public void update(UpdateApplicationVersionReq req) {
-
+ LambdaUpdateWrapper lambdaUpdateWrapper = buildLambdaUpdateWrapper(req);
+ update(lambdaUpdateWrapper);
}
+ /**
+ * 删除版本信息记录
+ *
+ * @param id 版本记录id
+ * @param personId 操作人personId
+ */
@Override
public void deleteById(Long id, Long personId) {
-
+ update(buildDeleteLambdaUpdateWrapper(id, personId));
}
+ /**
+ * 分页查询版本信息
+ *
+ * @param req {@link PageApplicationVersionReq}
+ * @return 按照版本记录倒排的记录列表
+ */
@Override
public Page page(PageApplicationVersionReq req) {
+ LambdaQueryWrapper lambdaQueryWrapper = buildPageLambdaQueryWrapper(req);
+ Page versionPage = page(new Page<>(req.getPageNumber(), req.getPageSize()), lambdaQueryWrapper);
+ if (Objects.isNull(versionPage) || versionPage.getTotal() == 0) {
+ return new Page<>();
+ }
+
+ List personIds = versionPage.getRecords().stream()
+ .map(ApplicationVersion::getUpdateBy)
+ .distinct()
+ .collect(Collectors.toList());
+
+ List profiles = profileGateway.getProfiles(personIds);
+ Map personProfileDtoMap = profiles.stream().collect(Collectors.toMap(BasicDto::getId, Function.identity()));
+ return PageConverter.convert(versionPage, record -> BeanMapper.copyBean(record, PageApplicationVersionResp.class, (source, target) -> {
+ PersonProfileDto person = personProfileDtoMap.get(source.getUpdateBy());
+ target.setUpdateBy(Objects.isNull(person.getRealName())? "-" : person.getRealName());
+ }));
+ }
+
+ /**
+ * 获取版本更新提醒内容
+ *
+ * @param req {@link GetVersionUpdateRemindContentReq}
+ * @return 对应端的版本更新记录信息 {@link GetVersionUpdateRemindContentResp}
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public GetVersionUpdateRemindContentResp getVersionUpdateRemindContent(GetVersionUpdateRemindContentReq req) {
+ // 获取对应平台配置的版本信息
+ ApplicationVersion version = lambdaQuery()
+ .eq(ApplicationVersion::getIsDelete, 0)
+ .eq(Objects.nonNull(req.getPlatform()), ApplicationVersion::getPlatform, req.getPlatform())
+ .eq(Objects.nonNull(req.getOpSystem()), ApplicationVersion::getOpSystem, req.getOpSystem())
+ .eq(StringUtils.isNotBlank(req.getVersion()), ApplicationVersion::getVersion, req.getVersion())
+ .orderByDesc(ApplicationVersion::getVersion)
+ .orderByDesc(ApplicationVersion::getReleaseTime)
+ .last("limit 1")
+ .one();
+ if (Objects.isNull(version) || version.getRemind() == 0) {
+ return null;
+ }
+ // 校验该用户是否已经提示
+ ApplicationVersionReadLog versionReadLog = applicationVersionReadLogService.getByIdWithPersonId(req.getPersonId(),version.getId());
+ if (Objects.isNull(versionReadLog)) {
+ // 该用户未提示
+ applicationVersionReadLogService.create(CreateApplicationVersionReadLogReq.builder()
+ .personId(req.getPersonId())
+ .versionId(version.getId())
+ .version(version.getVersion())
+ .platform(version.getPlatform())
+ .opSystem(version.getOpSystem())
+ .build());
+ GetVersionUpdateRemindContentResp versionRemindContent = BeanUtil.copyProperties(version, GetVersionUpdateRemindContentResp.class);
+ versionRemindContent.setImageUrl(Objects.equals(PlatformTypeEnum.CMS.getName(), version.getPlatform().getName()) ? cmsVersionRemindImage : appVersionRemindImage);
+ return versionRemindContent;
+ }
return null;
}
- @Override
- public GetVersionUpdateRemindContentResp getVersionUpdateRemindContent(GetVersionUpdateRemindContentReq req) {
- return null;
+ /**
+ * 校验版本号是否重复
+ *
+ * 版本号+平台+操作系统,不可重复
+ *
+ *
+ * @param req {@link CreateApplicationVersionReq}
+ */
+ private void checkDuplicateVersion(CreateApplicationVersionReq req) {
+ ApplicationVersion version = lambdaQuery()
+ .eq(ApplicationVersion::getVersion, req.getVersion())
+ .eq(ApplicationVersion::getPlatform, req.getPlatform())
+ .eq(ApplicationVersion::getOpSystem, req.getOpSystem())
+ .eq(ApplicationVersion::getIsDelete, 0)
+ .orderByDesc(ApplicationVersion::getReleaseTime)
+ .one();
+ if (Objects.nonNull(version)) {
+ throw new ServiceException("版本号重复");
+ }
+ }
+
+ /**
+ * 构建更新条件
+ *
+ * @param req {@link UpdateApplicationVersionReq}
+ * @return {@link LambdaUpdateWrapper}
+ */
+ private LambdaUpdateWrapper buildLambdaUpdateWrapper(UpdateApplicationVersionReq req) {
+ return new LambdaUpdateWrapper()
+ .eq(ApplicationVersion::getIsDelete, 0)
+ .eq(ApplicationVersion::getId, req.getId())
+ .set(ApplicationVersion::getVersion, req.getVersion())
+ .set(ApplicationVersion::getReleaseTime, req.getReleaseTime())
+ .set(ApplicationVersion::getDescription, req.getDescription())
+ .set(ApplicationVersion::getJumpUrl, JSONUtil.toJsonStr(req.getJumpUrl()))
+ .set(ApplicationVersion::getRemind, req.getRemind());
+ }
+
+ /**
+ * 构建分页查询条件
+ *
+ * @param req {@link PageApplicationVersionReq}
+ * @return {@link LambdaQueryWrapper}
+ */
+ private LambdaQueryWrapper buildPageLambdaQueryWrapper(PageApplicationVersionReq req) {
+ return new LambdaQueryWrapper()
+ .eq(ApplicationVersion::getIsDelete, 0)
+ .eq(Objects.nonNull(req.getPlatform()), ApplicationVersion::getPlatform, req.getPlatform())
+ .eq(Objects.nonNull(req.getOpSystem()), ApplicationVersion::getOpSystem, req.getOpSystem())
+ .eq(StringUtils.isNotBlank(req.getVersion()), ApplicationVersion::getVersion, req.getVersion())
+ .orderByDesc(ApplicationVersion::getVersion)
+ .orderByDesc(ApplicationVersion::getReleaseTime);
+ }
+
+ /**
+ * 构建删除版本信息的条件
+ *
+ * @param id 版本记录id
+ * @param personId 操作人personId
+ * @return 删除条件
+ */
+ private LambdaUpdateWrapper buildDeleteLambdaUpdateWrapper(Long id, Long personId) {
+ return new LambdaUpdateWrapper()
+ .eq(ApplicationVersion::getId, id)
+ .set(ApplicationVersion::getCreateBy, personId)
+ .set(ApplicationVersion::getIsDelete, 1);
}
}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/BannerOperationLogServiceImpl.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/BannerOperationLogServiceImpl.java
index 4c16b8a9..cddcad92 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/BannerOperationLogServiceImpl.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/BannerOperationLogServiceImpl.java
@@ -1,15 +1,22 @@
package cn.axzo.nanopart.server.service.impl;
import cn.axzo.nanopart.api.request.CreateBannerOperationLogReq;
-import cn.axzo.nanopart.server.mapper.BannerOperationLogDao;
+import cn.axzo.nanopart.api.request.PageBannerOperationLogReq;
+import cn.axzo.nanopart.api.response.PageBannerOperationLogResp;
import cn.axzo.nanopart.server.domain.BannerOperationLog;
+import cn.axzo.nanopart.server.mapper.BannerOperationLogDao;
import cn.axzo.nanopart.server.service.BannerOperationLogService;
+import cn.axzo.pokonyan.dao.converter.PageConverter;
import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
+import java.util.Objects;
+
/**
* @author chenwenjian
* @version 1.0
@@ -19,10 +26,42 @@ import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class BannerOperationLogServiceImpl extends ServiceImpl implements BannerOperationLogService {
+
@Override
public Long create(CreateBannerOperationLogReq req) {
BannerOperationLog bannerOperationLog = BeanUtil.copyProperties(req, BannerOperationLog.class);
this.save(bannerOperationLog);
return bannerOperationLog.getId();
}
+
+ /**
+ * 分页查询
+ *
+ * @param req {@link PageBannerOperationLogReq}
+ * @return 按照时间倒序排序后的列表
+ */
+ @Override
+ public Page page(PageBannerOperationLogReq req) {
+ LambdaQueryWrapper pageLambdaQueryWrapper = buildPageLambdaQueryWrapper(req);
+ Page logPage = page(new Page<>(req.getPageNumber(), req.getPageSize()), pageLambdaQueryWrapper);
+ if (Objects.isNull(logPage) || logPage.getTotal() == 0) {
+ return new Page<>();
+ }
+ return PageConverter.convert(logPage, record -> BeanUtil.copyProperties(record, PageBannerOperationLogResp.class));
+ }
+
+ /**
+ * 构建分页查询条件
+ *
+ * @param req {@link PageBannerOperationLogReq}
+ * @return {@link LambdaQueryWrapper}
+ */
+ private LambdaQueryWrapper buildPageLambdaQueryWrapper(PageBannerOperationLogReq req) {
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
+ return lambdaQueryWrapper
+ .eq(BannerOperationLog::getIsDelete, 0)
+ .eq(Objects.nonNull(req.getRecodeType()), BannerOperationLog::getRecodeType, req.getRecodeType())
+ .eq(Objects.nonNull(req.getRecodeId()), BannerOperationLog::getRecodeId, req.getRecodeId())
+ .between(Objects.nonNull(req.getStartTime()) && Objects.nonNull(req.getEndTime()), BannerOperationLog::getUpdateBy, req.getStartTime(), req.getEndTime());
+ }
}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/BannerServiceImpl.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/BannerServiceImpl.java
index 371b1112..2b0b8312 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/BannerServiceImpl.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/BannerServiceImpl.java
@@ -1,6 +1,8 @@
package cn.axzo.nanopart.server.service.impl;
import cn.axzo.framework.domain.ServiceException;
+import cn.axzo.nanopart.api.enums.DisplayTimeTypeEnum;
+import cn.axzo.nanopart.api.enums.PlatformTypeEnum;
import cn.axzo.nanopart.api.enums.RecodeTypeEnum;
import cn.axzo.nanopart.api.request.CreateBannerOperationLogReq;
import cn.axzo.nanopart.api.request.CreateBannerReq;
@@ -10,14 +12,17 @@ import cn.axzo.nanopart.api.request.UpdateBannerReq;
import cn.axzo.nanopart.api.request.UpdateStatusReq;
import cn.axzo.nanopart.api.response.DetailBannerResp;
import cn.axzo.nanopart.api.response.PageBannerResp;
-import cn.axzo.nanopart.server.mapper.BannerDao;
+import cn.axzo.nanopart.server.common.ApplicationVersionValidator;
import cn.axzo.nanopart.server.domain.Banner;
+import cn.axzo.nanopart.server.mapper.BannerDao;
import cn.axzo.nanopart.server.service.BannerOperationLogService;
import cn.axzo.nanopart.server.service.BannerService;
import cn.axzo.pokonyan.dao.converter.PageConverter;
import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -27,6 +32,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import java.sql.Time;
import java.util.Objects;
/**
@@ -39,7 +45,7 @@ import java.util.Objects;
@RequiredArgsConstructor
public class BannerServiceImpl extends ServiceImpl implements BannerService {
- private BannerOperationLogService bannerOperationLogService;
+ private final BannerOperationLogService bannerOperationLogService;
/**
* 分页查询banner
@@ -49,10 +55,10 @@ public class BannerServiceImpl extends ServiceImpl implements
*/
@Override
public Page page(PageBannerReq req) {
- LambdaQueryChainWrapper pageLambdaQueryChain = buildPageLambdaQueryChain(req);
+ LambdaQueryWrapper pageLambdaQueryWrapper = buildPageLambdaQueryWrapper(req);
- Page bannerPage = page(new Page<>(req.getPageNumber(), req.getPageSize()), pageLambdaQueryChain);
- if (bannerPage.getTotal() == 0) {
+ Page bannerPage = page(new Page<>(req.getPageNumber(), req.getPageSize()), pageLambdaQueryWrapper);
+ if (Objects.isNull(bannerPage) || bannerPage.getTotal() == 0) {
return new Page<>();
}
return PageConverter.convert(bannerPage, record -> BeanUtil.toBean(record, PageBannerResp.class));
@@ -69,13 +75,16 @@ public class BannerServiceImpl extends ServiceImpl implements
// 校验占位图宽高比例
req.getAspectRatio().checkAspectRatio();
+ // 展示时间段类型校验
+ checkDisplayTimeType(req);
+
Banner oldBanner = this.selectById(req.getId());
if (Objects.isNull(oldBanner)) {
return;
}
- LambdaUpdateChainWrapper updateLambdaQueryChain = buildUpdateLambdaQueryChain(req);
- update(updateLambdaQueryChain);
+ LambdaUpdateWrapper lambdaUpdateWrapper = buildUpdateLambdaQueryWrapper(req);
+ update(lambdaUpdateWrapper);
Banner newBanner = this.selectById(req.getId());
@@ -146,6 +155,14 @@ public class BannerServiceImpl extends ServiceImpl implements
// 对站点code进行校重
checkBannerCodeDuplicate(req.getCode());
+ // 展示时间段类型校验
+ checkDisplayTimeType(req);
+
+ if (PlatformTypeEnum.CM.getName().equals(req.getTerminal().getName()) || PlatformTypeEnum.CMP.getName().equals(req.getTerminal().getName())){
+ ApplicationVersionValidator.checkVersionSimple(req.getIosVersion());
+ ApplicationVersionValidator.checkVersionSimple(req.getAndroidVersion());
+ }
+
// 校验占位图宽高比例
req.getAspectRatio().checkAspectRatio();
@@ -213,18 +230,56 @@ public class BannerServiceImpl extends ServiceImpl implements
}
}
+ /**
+ * 校验展示时间段类型
+ *
+ * 此处不抽取Create和Update共同类型,所以这么写
+ *
+ *
+ * @param obj {@link CreateBannerReq} 或 {@link UpdateBannerReq}}
+ */
+ private void checkDisplayTimeType(Object obj) {
+ if (obj instanceof CreateBannerReq) {
+ CreateBannerReq req = (CreateBannerReq) obj;
+ // 为自定义时间段
+ if (Objects.equals(req.getDisplayTimeType().getName(), DisplayTimeTypeEnum.CUSTOM.getName())) {
+ if (Objects.isNull(req.getStartTime()) || Objects.isNull(req.getEndTime())) {
+ throw new RuntimeException("请设置展示时间段");
+ }
+ return;
+ }
+ // 此处为防止选定展示时间段类型后又手动设置了起止时间
+ req.setStartTime(req.getDisplayTimeType().getStartTime());
+ req.setEndTime(req.getDisplayTimeType().getEndTime());
+ } else if (obj instanceof UpdateBannerReq) {
+ UpdateBannerReq req = (UpdateBannerReq) obj;
+ if (Objects.equals(req.getDisplayTimeType().getName(), DisplayTimeTypeEnum.CUSTOM.getName())) {
+ if (Objects.isNull(req.getStartTime()) || Objects.isNull(req.getEndTime())) {
+ throw new RuntimeException("请设置展示时间段");
+ }
+ return;
+ }
+ // 此处为防止选定展示时间段类型后又手动设置了起止时间
+ req.setStartTime(req.getDisplayTimeType().getStartTime());
+ req.setEndTime(req.getDisplayTimeType().getEndTime());
+ }
+ }
+
/**
* 构建分页查询条件
*
* @param req {@link PageBannerReq}
- * @return {@link LambdaQueryChainWrapper}
+ * @return {@link LambdaQueryWrapper}
*/
- private LambdaQueryChainWrapper buildPageLambdaQueryChain(PageBannerReq req) {
- return lambdaQuery()
+ private LambdaQueryWrapper buildPageLambdaQueryWrapper(PageBannerReq req) {
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper();
+ return lambdaQueryWrapper
.like(StringUtils.isNotEmpty(req.getName()), Banner::getName, req.getName())
.eq(Objects.nonNull(req.getTerminal()), Banner::getTerminal, req.getTerminal())
.eq(Objects.nonNull(req.getStatus()), Banner::getStatus, req.getStatus())
.eq(Banner::getIsDelete, 0)
+ .orderByDesc(Banner::getStatus)
+ .orderByDesc(Banner::getCreateAt)
.orderByAsc(Banner::getCode);
}
@@ -234,17 +289,21 @@ public class BannerServiceImpl extends ServiceImpl implements
* @param req {@link UpdateBannerReq}
* @return {@link LambdaUpdateChainWrapper}
*/
- private LambdaUpdateChainWrapper buildUpdateLambdaQueryChain(UpdateBannerReq req) {
- return lambdaUpdate()
+ private LambdaUpdateWrapper buildUpdateLambdaQueryWrapper(UpdateBannerReq req) {
+ LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+ return lambdaUpdateWrapper
.eq(Banner::getId, req.getId())
.set(StringUtils.isNotBlank(req.getName()), Banner::getName, req.getName())
.set(Objects.nonNull(req.getStatus()), Banner::getStatus, req.getStatus())
.set(Objects.nonNull(req.getCarouselStatus()), Banner::getCarouselStatus, req.getCarouselStatus())
.set(Banner::getMaxCarouselLimit, req.getMaxCarouselLimit())
.set(Banner::getPlayDuration, req.getPlayDuration())
- .set(Banner::getStartTime, req.getStartTime())
- .set(Banner::getEndTime, req.getEndTime())
- .set(Banner::getAspectRatio, req.getAspectRatio())
+ .set(Banner::getDisplayTimeType,req.getDisplayTimeType())
+ .set(Banner::getStartTime, new Time(req.getStartTime()))
+ .set(Banner::getEndTime, new Time(req.getEndTime()))
+ .set(Banner::getAspectRatio, JSONUtil.toJsonStr(req.getAspectRatio()))
+ .set(Banner::getIosVersion, req.getIosVersion())
+ .set(Banner::getAndroidVersion, req.getAndroidVersion())
.set(Banner::getUpdateBy, req.getUpdateBy());
}
}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/MaterialPutLogServiceImpl.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/MaterialPutLogServiceImpl.java
new file mode 100644
index 00000000..1700f916
--- /dev/null
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/MaterialPutLogServiceImpl.java
@@ -0,0 +1,35 @@
+package cn.axzo.nanopart.server.service.impl;
+
+import cn.axzo.nanopart.api.request.CreateMaterialPutLogReq;
+import cn.axzo.nanopart.server.domain.MaterialPutLog;
+import cn.axzo.nanopart.server.mapper.MaterialPutLogDao;
+import cn.axzo.nanopart.server.service.MaterialPutLogService;
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chenwenjian
+ * @version 1.0
+ * @date 2024/4/10 18:41
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class MaterialPutLogServiceImpl extends ServiceImpl implements MaterialPutLogService {
+
+ /**
+ * 创建
+ *
+ * @param req {@link CreateMaterialPutLogReq}
+ * @return {@link Long}
+ */
+ @Override
+ public Long create(CreateMaterialPutLogReq req) {
+ MaterialPutLog materialPutLog = BeanUtil.copyProperties(req, MaterialPutLog.class);
+ save(materialPutLog);
+ return materialPutLog.getId();
+ }
+}
diff --git a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/MaterialServiceImpl.java b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/MaterialServiceImpl.java
index f6d2430b..2cd53482 100644
--- a/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/MaterialServiceImpl.java
+++ b/banner/banner-server/src/main/java/cn/axzo/nanopart/server/service/impl/MaterialServiceImpl.java
@@ -11,6 +11,7 @@ import cn.axzo.nanopart.api.enums.MaterialDisplayFrequencyTypeEnum;
import cn.axzo.nanopart.api.enums.RecodeTypeEnum;
import cn.axzo.nanopart.api.enums.StatusEnum;
import cn.axzo.nanopart.api.request.CreateBannerOperationLogReq;
+import cn.axzo.nanopart.api.request.CreateMaterialPutLogReq;
import cn.axzo.nanopart.api.request.CreateMaterialReq;
import cn.axzo.nanopart.api.request.DetailMaterialReq;
import cn.axzo.nanopart.api.request.ListMaterialByBannerCodeReq;
@@ -27,27 +28,38 @@ import cn.axzo.nanopart.server.rpc.OrganizationalJobGateway;
import cn.axzo.nanopart.server.rpc.OrganizationalNodeUserGateway;
import cn.axzo.nanopart.server.service.BannerOperationLogService;
import cn.axzo.nanopart.server.service.BannerService;
+import cn.axzo.nanopart.server.service.MaterialPutLogService;
import cn.axzo.nanopart.server.service.MaterialService;
+import cn.axzo.pokonyan.config.redis.RedisClient;
import cn.axzo.pokonyan.dao.converter.PageConverter;
import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
-import java.time.LocalDateTime;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -57,6 +69,7 @@ import java.util.stream.Collectors;
*/
@Slf4j
@Service
+@RefreshScope
@RequiredArgsConstructor
public class MaterialServiceImpl extends ServiceImpl implements MaterialService {
@@ -64,13 +77,20 @@ public class MaterialServiceImpl extends ServiceImpl impl
private final BannerOperationLogService bannerOperationLogService;
+ private final MaterialPutLogService materialPutLogService;
+
private final OrganizationalNodeUserGateway organizationalNodeUserGateway;
private final OrganizationalJobGateway organizationalJobGateway;
private final CooperateShipGateway cooperateShipGateway;
- // private final
+ /**
+ * 素材投放频次缓存key有效期,
+ * 单位:天,默认为90天
+ */
+ @Value("${materialDisplayFrequencyKeyTtl: 90}")
+ private Long materialDisplayFrequencyKeyTtl;
/**
* 根据广告位编码(bannerCode)查询素材
@@ -81,15 +101,12 @@ public class MaterialServiceImpl extends ServiceImpl impl
* @param req {@link ListMaterialByBannerCodeReq}
* @return 根据优先级(priority)升序,创建时间(createAt)降序排序后的列表
*/
+ @Transactional(rollbackFor = Exception.class)
@Override
- public List listMaterialByBannerCode(ListMaterialByBannerCodeReq req) {
- // 获取广告位并校验
- Banner banner = bannerService.selectByCode(req.getBannerCode());
- if (Objects.isNull(banner)) {
- throw new ServiceException("广告位不存在");
- }
- if (banner.getStatus() != StatusEnum.ONLINE) {
- throw new ServiceException("广告位已停用");
+ public List listMaterialByBannerCode(ListMaterialByBannerCodeReq req, String traceId) {
+ // 获取广告位并校验(是否存在,是否启用,是否在有效期)
+ if (Objects.isNull(validateBanner(req.getBannerCode()))) {
+ return Collections.emptyList();
}
// 获取该广告位下已上架且在有效期内的所有素材
@@ -97,52 +114,39 @@ public class MaterialServiceImpl extends ServiceImpl impl
if (CollectionUtils.isEmpty(materialList)) {
return Collections.emptyList();
}
+ log.info("上架且有效广告位:{}", JSONUtil.toJsonStr(materialList));
// 获取当前登录用户加入的所有项目部,单位及其在项目部或在单位下担任的岗位
JoinedWorkspaceOuJob personJoinedWorkspaceOuJob = getPersonJoinedWorkspaceOuJob(req.getPersonId());
- if (Objects.isNull(personJoinedWorkspaceOuJob)) {
- // 理论上不会走到这里,因为登录用户必然加入了一个项目部或单位
- throw new ServiceException("数据异常");
- }
- // 根据素材投放人群和投放规则频次进行过滤
+ // 根据素材投放规则进行过滤
List list = materialList.stream()
.filter(m -> {
- m.getTargetUserType().isDeliverRequired(m.getWorkspaceIds(), m.getOuIds(), m.getJobCodes(), personJoinedWorkspaceOuJob);
-
- // 频次过滤,这个人
- // RedisClient.KeyOps.hasKey();
- return false;
+ // 投放人群过滤
+ return m.getTargetUserType()
+ .isDeliverRequired(m.getWorkspaceIds(), m.getOuIds(), m.getJobCodes(),
+ req.getWorkspaceId(), req.getOuId(),
+ personJoinedWorkspaceOuJob)
+ &&
+ // 投放频次过滤
+ filterByDisplayFrequency(req, m);
})
.collect(Collectors.toList());
+ if (CollectionUtils.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+
+ // 记录素材投放日志
+ CreateMaterialPutLogReq materialPutLogReq = new CreateMaterialPutLogReq();
+ materialPutLogReq.setRequestId(traceId)
+ .setPersonId(req.getPersonId())
+ .setBannerCode(req.getBannerCode())
+ .setMaterialIds(list.stream().map(Material::getId).collect(Collectors.toList()));
+ materialPutLogService.create(materialPutLogReq);
return BeanUtil.copyToList(list, MaterialResp.class);
}
- /**
- * 构建素材投放频次记录缓存key
- *
- *
- * 1.含义:指定素材给指定人按照投放频次类型投放次数
- * 2.组成:namespace:bannerCode:materialId:personId:频次类型转换后的值
- * 3.频次类型转换规则示例:投放频次类型参考{@link MaterialDisplayFrequencyTypeEnum}
- * 有效期内:VALIDITY_PERIOD -> 有效期
- * 每天:EVERY_DAY -> 当天
- * 每周:EVERY_WEEK -> 当周第一天
- * 每月:EVERY_MONTH -> 当月第一天
- *
- *
- * @param material 素材信息
- * @param personId 投放人Id
- * @return key
- */
- public static String buildMaterialDisplayFrequencyKey(Material material, Long personId) {
- LocalDateTime now = LocalDateTime.now();
-
- // return String.format("nanopart:%s:%s", materialId, bannerId);
- return null;
- }
-
/**
* 分页查询
*
@@ -151,7 +155,7 @@ public class MaterialServiceImpl extends ServiceImpl impl
*/
@Override
public Page page(PageMaterialReq req) {
- LambdaQueryChainWrapper pageQueryLambdaWrapper = buildPageQueryLambdaWrapper(req);
+ LambdaQueryWrapper pageQueryLambdaWrapper = buildPageQueryLambdaWrapper(req);
Page materialPage = page(new Page<>(req.getPageNumber(), req.getPageSize()), pageQueryLambdaWrapper);
if (materialPage.getTotal() == 0) {
@@ -203,7 +207,7 @@ public class MaterialServiceImpl extends ServiceImpl impl
@Override
public void update(UpdateMaterialReq req) {
Material oldMaterial = this.getById(req.getId());
- if (Objects.isNull(oldMaterial) || oldMaterial.getIsDelete() == 0) {
+ if (Objects.isNull(oldMaterial) || oldMaterial.getIsDelete() != 0) {
throw new ServiceException("素材不存在");
}
@@ -242,7 +246,7 @@ public class MaterialServiceImpl extends ServiceImpl impl
Material newMaterial = this.getById(req.getId());
// 记录操作日志
CreateBannerOperationLogReq updateLogReq = new CreateBannerOperationLogReq()
- .setRecodeType(RecodeTypeEnum.BANNER)
+ .setRecodeType(RecodeTypeEnum.MATERIAL)
.setRecodeId(req.getId())
.setOperationType("updateStatus")
.setOldData((JSONObject) JSONObject.toJSON(oldMaterial))
@@ -263,23 +267,93 @@ public class MaterialServiceImpl extends ServiceImpl impl
if (Objects.isNull(req.getId()) || req.getId() == 0) {
return null;
}
- return BeanUtil.copyProperties(getById(req.getId()), MaterialResp.class);
+
+ Material material = getById(req.getId());
+ if (Objects.isNull(material)) {
+ return null;
+ }
+ // 获取所属广告位
+ Banner banner = bannerService.selectByCode(material.getBannerCode());
+ if (Objects.isNull(banner)) {
+ log.warn("广告位不存在,广告位code:{},素材id:{}", material.getBannerCode(), material.getId());
+ throw new ServiceException("数据异常");
+ }
+ MaterialResp materialResp = BeanUtil.copyProperties(material, MaterialResp.class);
+ materialResp.setTerminal(banner.getTerminal());
+ return materialResp;
+ }
+
+ /**
+ * 对于给定bannerCode校验其存在性和状态有效性
+ *
+ * @param bannerCode 广告位code
+ * @return 若存在且有效返回广告位对象,否则否则返回null
+ */
+ private Banner validateBanner(String bannerCode) {
+ if (StringUtils.isEmpty(bannerCode)) {
+ return null;
+ }
+ Banner banner = bannerService.selectByCode(bannerCode);
+ if (Objects.isNull(banner)) {
+ log.warn("广告位不存在,广告位code:{}", bannerCode);
+ return null;
+ }
+ if (banner.getStatus() != StatusEnum.ONLINE) {
+ log.warn("广告位已停用,广告位code:{}", bannerCode);
+ return null;
+ }
+ LocalTime now = LocalTime.now();
+ // 当前不在广告位配置的展示时间范围内
+ if (now.isBefore(banner.getStartTime().toLocalTime()) || now.isAfter(banner.getEndTime().toLocalTime())) {
+ log.warn("当前时间不在广告位配置的展示时间范围内,广告位code:{},当前时间:{},广告位开始时间:{},广告位结束时间:{}", bannerCode, now, banner.getStartTime(), banner.getEndTime());
+ return null;
+ }
+ return banner;
+ }
+
+ /**
+ * 根据素材投放频次规则进行过滤
+ *
+ * @param req {@link ListMaterialByBannerCodeReq}
+ * @param m {@link Material}
+ * @return true:符合投放规则,即为达到最大投放次数限制;false:不符合投放规则,已到达最大投放次数限制
+ */
+ private boolean filterByDisplayFrequency(ListMaterialByBannerCodeReq req, Material m) {
+ boolean displayFrequencyFilter;
+ String key = buildMaterialDisplayFrequencyKey(m, req.getPersonId());
+ if (RedisClient.KeyOps.hasKey(key)) {
+ int frequency = Integer.parseInt(RedisClient.StringOps.get(key));
+ log.info("{素材投放key:{},value:{}", key, frequency);
+ displayFrequencyFilter = MaterialDisplayFrequencyTypeEnum.NO_LIMIT.getCode().equals(m.getDisplayFrequencyType().getCode()) || frequency < m.getMaxDisplayFrequency();
+ if (displayFrequencyFilter) {
+ // 本次需要投放
+ RedisClient.StringOps.incrBy(key, 1L);
+ }
+ } else {
+ displayFrequencyFilter = true;
+ RedisClient.StringOps.set(key, String.valueOf(1));
+ // key失效时间,有效期天数加上配置的有效期天数
+ long intervalDays = (m.getEndTime().getTime() - m.getStartTime().getTime()) / (1000 * 60 * 60 * 24);
+ RedisClient.KeyOps.expire(key, intervalDays + materialDisplayFrequencyKeyTtl, TimeUnit.DAYS);
+ }
+ return displayFrequencyFilter;
}
/**
* 构建分页查询条件
*
* @param req {@link PageMaterialReq}
- * @return {@link LambdaQueryChainWrapper}
+ * @return {@link LambdaQueryWrapper}
*/
- private LambdaQueryChainWrapper buildPageQueryLambdaWrapper(PageMaterialReq req) {
- return lambdaQuery()
+ private LambdaQueryWrapper buildPageQueryLambdaWrapper(PageMaterialReq req) {
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
+ return lambdaQueryWrapper
.eq(Material::getIsDelete, 0)
.eq(StringUtils.isNotEmpty(req.getBannerCode()), Material::getBannerCode, req.getBannerCode())
.like(StringUtils.isNotEmpty(req.getName()), Material::getName, req.getName())
.eq(Objects.nonNull(req.getStatus()), Material::getStatus, req.getStatus())
- .le(Objects.nonNull(req.getStartTime()), Material::getStartTime, req.getStartTime())
- .ge(Objects.nonNull(req.getEndTime()), Material::getEndTime, req.getEndTime())
+ .ge(Objects.nonNull(req.getStartTime()), Material::getStartTime, req.getStartTime())
+ .le(Objects.nonNull(req.getEndTime()), Material::getEndTime, req.getEndTime())
.orderByDesc(Material::getStatus)
.orderByAsc(Material::getPriority)
.orderByDesc(Material::getCreateAt);
@@ -289,16 +363,17 @@ public class MaterialServiceImpl extends ServiceImpl impl
* 构建通过BannerCode查询素材的wrapper
*
* @param req {@link ListMaterialByBannerCodeReq}
- * @return {@link LambdaQueryChainWrapper}
+ * @return {@link LambdaQueryWrapper}
*/
- private LambdaQueryChainWrapper buildListByBannerCodeQueryWrapper(ListMaterialByBannerCodeReq req) {
+ private LambdaQueryWrapper buildListByBannerCodeQueryWrapper(ListMaterialByBannerCodeReq req) {
Date now = new Date(System.currentTimeMillis());
- return lambdaQuery()
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
+ return lambdaQueryWrapper
.eq(Material::getIsDelete, 0)
.eq(Material::getBannerCode, req.getBannerCode())
.eq(Material::getStatus, StatusEnum.ONLINE)
- .ge(Material::getStartTime, now)
- .le(Material::getEndTime, now)
+ .le(Material::getStartTime, now)
+ .ge(Material::getEndTime, now)
.orderByAsc(Material::getPriority)
.orderByDesc(Material::getCreateAt);
}
@@ -357,10 +432,22 @@ public class MaterialServiceImpl extends ServiceImpl impl
// Map>
Map> ouIdToTopNodeIdMap = genericQuery.stream()
- .filter(c -> c.getWorkspaceId() == 1)
+ .filter(c -> c.getWorkspaceType() == 1)
.collect(Collectors.groupingBy(CooperateShipResp::getOrganizationalUnitId,
Collectors.mapping(CooperateShipResp::getOrganizationalNodeId, Collectors.toList())));
+ // 单位加入的项目部,Map>
+ Map> ouIdToWorkspaceMap = genericQuery.stream()
+ .filter(c -> c.getWorkspaceType() == 2)
+ .collect(Collectors.groupingBy(CooperateShipResp::getOrganizationalUnitId,
+ Collectors.mapping(CooperateShipResp::getWorkspaceId, Collectors.toList())));
+
+ // 项目部下的单位 Map
+ Map> workspaceToOuIdMap = genericQuery.stream()
+ .filter(c -> c.getWorkspaceType() == 2)
+ .collect(Collectors.groupingBy(CooperateShipResp::getWorkspaceId,
+ Collectors.mapping(CooperateShipResp::getOrganizationalUnitId, Collectors.toList())));
+
// Map
Map> workspaceToJobCodeMap = workspaceToTopNodeIdMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
@@ -381,7 +468,49 @@ public class MaterialServiceImpl extends ServiceImpl impl
.distinct()
.collect(Collectors.toList())));
- return new JoinedWorkspaceOuJob(workspaceToJobCodeMap, ouIdToJobCodeMap);
+ return new JoinedWorkspaceOuJob(workspaceToJobCodeMap, ouIdToJobCodeMap,ouIdToWorkspaceMap,workspaceToOuIdMap);
+ }
+
+ /**
+ * 构建素材投放频次记录缓存key
+ *
+ *
+ * 1.含义:指定素材给指定人按照投放频次类型投放次数
+ * 2.组成:namespace:bannerCode:materialId:personId:频次类型转换后的值
+ * 3.频次类型转换规则示例:投放频次类型参考{@link MaterialDisplayFrequencyTypeEnum}
+ * 有效期内:VALIDITY_PERIOD -> 有效期
+ * 每天:EVERY_DAY -> 当天
+ * 每周:EVERY_WEEK -> 当周第一天
+ * 每月:EVERY_MONTH -> 当月第一天
+ *
+ *
+ * @param material 素材信息
+ * @param personId 投放人Id
+ * @return key
+ */
+ public static String buildMaterialDisplayFrequencyKey(Material material, Long personId) {
+ String prefix = String.format("nanopart:%s:%s:%s:", material.getBannerCode(), material.getId(), personId);
+ String datePattern = "yyyy_MM_dd";
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern(datePattern);
+ LocalDate now = LocalDate.now();
+ String suffix = "";
+ switch (material.getDisplayFrequencyType()) {
+ case NO_LIMIT:
+ suffix = String.join("_", MaterialDisplayFrequencyTypeEnum.NO_LIMIT.getCode());
+ break;
+ case VALIDITY_PERIOD:
+ suffix = String.join("_", "P", DateUtil.format(material.getStartTime(), datePattern), DateUtil.format(material.getEndTime(), datePattern));
+ break;
+ case EVERY_DAY:
+ suffix = String.join("_", "D", now.format(formatter));
+ break;
+ case EVERY_WEEK:
+ suffix = String.join("_", "W", now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).format(formatter));
+ break;
+ case EVERY_MONTH:
+ suffix = String.join("_", "M", now.with(TemporalAdjusters.firstDayOfMonth()).format(formatter));
+ }
+ return prefix + suffix;
}
}
diff --git a/nanopart-server/src/main/resources/application.yml b/nanopart-server/src/main/resources/application.yml
index 1fd01c81..644e549c 100644
--- a/nanopart-server/src/main/resources/application.yml
+++ b/nanopart-server/src/main/resources/application.yml
@@ -21,7 +21,7 @@ mybatis-plus:
logic-delete-value: id #逻辑已删除值(默认为 1)
logic-not-delete-value: 0 #逻辑未删除值(默认为 0)
logic-delete-field: isDelete #逻辑删除字段
- type-enums-package: cn.axzo.nanopart.api.constant.enums,cn.axzo.nanopart.api.enums
+ type-enums-package: cn.axzo.nanopart.api.constant.enums;cn.axzo.nanopart.api.enums
logging:
level: