From 80d1cebc0fe70561c9a953a0bd4ebf4de24eb6d7 Mon Sep 17 00:00:00 2001 From: PengJ <2413927716@qq.com> Date: Fri, 6 Feb 2026 17:49:43 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E7=A7=AF=E5=88=86=E9=93=B6=E8=A1=8C?= =?UTF-8?q?=E3=80=91=E7=A7=AF=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bank/constant/HealthBankConstants.java | 2 +- .../renkang/bank/enums/PointsSourceEnum.java | 12 +- .../bank/model/dto/PointsRulePageDTO.java | 25 + .../bank/model/dto/UpdUserPointsDTO.java | 40 ++ .../bank/model/dto/UserPointsPageDTO.java | 42 ++ .../bank/model/dto/UserPointsRankingDTO.java | 22 + .../com/renkang/bank/model/po/PointsRule.java | 11 +- .../com/renkang/bank/model/po/UserPoints.java | 20 +- .../bank/model/po/UserPointsDetails.java | 4 +- .../bank/model/vo/UserPointRankingVO.java | 40 ++ .../bank/model/vo/UserPointRecordVO.java | 44 ++ .../bank/model/vo/UserPointsInfoVO.java | 42 ++ .../bank/model/vo/UserPointsListVO.java | 35 ++ .../bank/model/vo/UserPointsMonitorVO.java | 53 ++ .../bank/model/vo/UserPointsTaskVO.java | 39 ++ .../bank/controller/PointsRuleController.java | 97 ++++ .../bank/controller/UserPointsController.java | 91 ++++ .../renkang/bank/mapper/PointsRuleMapper.java | 16 + .../bank/mapper/UserPointsDetailsMapper.java | 16 + .../renkang/bank/mapper/UserPointsMapper.java | 14 + .../bank/mapper/xml/PointsRuleMapper.xml | 39 ++ .../mapper/xml/UserPointsDetailsMapper.xml | 35 ++ .../bank/service/IPointsRuleService.java | 23 + .../bank/service/IUserPointsService.java | 33 ++ .../service/impl/PointsRuleServiceImpl.java | 80 ++++ .../service/impl/UserPointsServiceImpl.java | 452 ++++++++++++++++++ .../common/export/GenericExportHandler.java | 124 +++++ .../java/org/jeecg/enums/ExportExcelEnum.java | 44 ++ .../impl/HealthUserEmployeeExServiceImpl.java | 1 - .../service/impl/LoginAnYanServiceImpl.java | 6 +- 30 files changed, 1487 insertions(+), 15 deletions(-) create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/PointsRulePageDTO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UpdUserPointsDTO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UserPointsPageDTO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UserPointsRankingDTO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointRankingVO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointRecordVO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsInfoVO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsListVO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsMonitorVO.java create mode 100644 health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsTaskVO.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/controller/PointsRuleController.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/controller/UserPointsController.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/PointsRuleMapper.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/UserPointsDetailsMapper.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/UserPointsMapper.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/xml/PointsRuleMapper.xml create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/xml/UserPointsDetailsMapper.xml create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/IPointsRuleService.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/IUserPointsService.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/impl/PointsRuleServiceImpl.java create mode 100644 health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/impl/UserPointsServiceImpl.java create mode 100644 jeecg-boot-base-core/src/main/java/org/jeecg/common/export/GenericExportHandler.java create mode 100644 jeecg-boot-base-core/src/main/java/org/jeecg/enums/ExportExcelEnum.java diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/constant/HealthBankConstants.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/constant/HealthBankConstants.java index 1b0f9fd..2ea6128 100644 --- a/health-bank/health-bank-api/src/main/java/com/renkang/bank/constant/HealthBankConstants.java +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/constant/HealthBankConstants.java @@ -12,5 +12,5 @@ public interface HealthBankConstants { /** *积分变化-扣减积分 */ - Integer CHANGE_TYPE_DEDUCT_ = 2; + Integer CHANGE_TYPE_DEDUCT = 2; } diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/enums/PointsSourceEnum.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/enums/PointsSourceEnum.java index 4b84aee..5e8bc4c 100644 --- a/health-bank/health-bank-api/src/main/java/com/renkang/bank/enums/PointsSourceEnum.java +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/enums/PointsSourceEnum.java @@ -9,7 +9,8 @@ import lombok.Getter; */ @Getter public enum PointsSourceEnum { - TYPE_1_SURVEY(1, "积分打卡", "survey"), + // 积分变更类型 + TYPE_1_SURVEY(1, "survey", "积分打卡"), TYPE_2_USE(2, "use", "礼品兑换"), TYPE_2_VIOLATION(2, "violation", "违规扣除"), TYPE_2_EXPIRED(2, "expired", "过期清除"); @@ -31,4 +32,13 @@ public enum PointsSourceEnum { this.source = source; this.desc = desc; } + + public static PointsSourceEnum getBySource(String source) { + for (PointsSourceEnum value : PointsSourceEnum.values()) { + if (value.source.equals(source)) { + return value; + } + } + return null; + } } diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/PointsRulePageDTO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/PointsRulePageDTO.java new file mode 100644 index 0000000..2cdbc20 --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/PointsRulePageDTO.java @@ -0,0 +1,25 @@ +package com.renkang.bank.model.dto; + +import com.renkang.bank.model.po.PointsRule; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.jeecg.base.PageInfo; + +/** + * @author pj + * @version 1.0 + * @description: 积分规则分页dto + * @date 2026/2/5 18:11 + */ +@Data +public class PointsRulePageDTO extends PageInfo { + + @Schema(title = "健康分类") + private Integer ruleCategory; + + @Schema(title = "健康行为") + private String ruleDesc; + + @Schema(title = "状态1-启用,2停用") + private Integer status; +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UpdUserPointsDTO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UpdUserPointsDTO.java new file mode 100644 index 0000000..6f2d6cd --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UpdUserPointsDTO.java @@ -0,0 +1,40 @@ +package com.renkang.bank.model.dto; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author pj + * @version 1.0 + * @description: 更新用户积分DTO + * @date 2026/2/6 9:00 + */ +@Data +public class UpdUserPointsDTO { + + /** + * 积分标识(积分打卡:survey,礼品兑换:use,违规扣除:violation,过期清除:expired) + */ + private String sourceType; + + /** + * 业务ID(积分任务id,兑换商品id等) + */ + private Long businessId; + + /** + * 操作积分(扣减) + */ + private BigDecimal points; + + /** + * 操作备注(扣减积分的说明等) + */ + private String remark; + + /** + * 用户id(扣减的目标用户id) + */ + private String userId; +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UserPointsPageDTO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UserPointsPageDTO.java new file mode 100644 index 0000000..9d5387a --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UserPointsPageDTO.java @@ -0,0 +1,42 @@ +package com.renkang.bank.model.dto; + +import com.renkang.bank.model.po.PointsRule; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.jeecg.base.PageInfo; + +/** + * @author pj + * @version 1.0 + * @description: 积分规则分页dto + * @date 2026/2/5 18:11 + */ +@Data +public class UserPointsPageDTO extends PageInfo { + + @Schema(title = "姓名") + private String realName; + + @Schema(title = "员工编号") + private String workNo; + + @Schema(title = "所属单位") + private String orgCode; + + @Schema(title = "所属部门") + private String deptCode; + + @Schema(title = "1收入,2支出") + private Integer changeType; + + @Schema(title = "健康行为") + private String ruleDesc; + + @Schema(title = "打卡日期(开始)") + private String startDate; + + @Schema(title = "打卡日期(结束)") + private String endDate; + + private String userId; +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UserPointsRankingDTO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UserPointsRankingDTO.java new file mode 100644 index 0000000..52c47c3 --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/dto/UserPointsRankingDTO.java @@ -0,0 +1,22 @@ +package com.renkang.bank.model.dto; + +import com.renkang.bank.model.po.PointsRule; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.jeecg.base.PageInfo; + +/** + * @author pj + * @version 1.0 + * @description: 积分规则分页dto + * @date 2026/2/5 18:11 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class UserPointsRankingDTO extends PageInfo { + + @Schema(title = "榜单类型,0总榜,1周榜,2月榜") + private String rankType; + +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/PointsRule.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/PointsRule.java index 71ff7a1..fd319c9 100644 --- a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/PointsRule.java +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/PointsRule.java @@ -11,6 +11,8 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.FieldNameConstants; +import org.jeecg.common.aspect.annotation.Dict; +import org.jeecgframework.poi.excel.annotation.Excel; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; @@ -39,23 +41,28 @@ public class PointsRule implements Serializable { @JsonFormat(shape = JsonFormat.Shape.STRING) private Long id; + @Excel(name = "行为周期", width = 15, replace = {"次_1", "日_2", "周_3", "月_4", "季度_5", "年_6"}, orderNum = "3") @Schema(title = "问答频次(1-单次,2-日/次,3-周/次,4-月/次,5-季度/次,6-年/次)") private Integer frequency; + @Excel(name = "健康分类", width = 15, dicCode = "points_rule_category", orderNum = "1") + @Dict(dicCode = "points_rule_category") @Schema(title = "规则类别") private Integer ruleCategory; + @Excel(name = "健康行为", width = 15, orderNum = "2") @Schema(title = "规则描述") private String ruleDesc; @Schema(title = "图标") private String icon; + @Excel(name = "奖励积分", width = 15, orderNum = "4") @Schema(title = "奖励积分") private BigDecimal points; - @Schema(title = "状态0-启用,1停用") - private Integer status = 0; + @Schema(title = "状态1-启用,2停用") + private Integer status = 1; @Schema(title = "删除标识0-正常,1已删除") @TableLogic diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/UserPoints.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/UserPoints.java index db0597e..152d551 100644 --- a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/UserPoints.java +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/UserPoints.java @@ -14,6 +14,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; + /** * 用户积分汇总表 -产生过积分的用户每人一条数据 * @@ -45,24 +46,33 @@ public class UserPoints implements Serializable { @Schema(title = "历史获得的积分总和") private BigDecimal addPointsSum; + /** + * 记录所有扣除积分的总和,包含兑换消耗、手动扣除的积分 + */ @Schema(title = "历史扣除积分总和") private BigDecimal deductPointsSum; - @Schema(title = "状态(0-正常,1-冻结)") - private Integer status = 0; + /** + * 积分兑换记录总和,只记录积分兑换 + */ + @Schema(title = "历史兑换积分总和") + private BigDecimal exchangePointsSum; + + @Schema(title = "状态(1-正常,2-冻结)") + private Integer status = 1; /** * 注意:该字段记录最后一次获得积分当天收获的积分总和,该归档字段的更新会减少后期对积分明细表的查询次数 */ @Schema(title = "最新一天获取积分的总和") private BigDecimal latestAddDaySum; /** - *注意:该字段记录最后一次消费积分当天收获的积分总和,该归档字段的更新会减少后期对积分明细表的查询次数 + * 注意:该字段记录最后一次消费积分当天收获的积分总和,该归档字段的更新会减少后期对积分明细表的查询次数 */ @Schema(title = "最新一天消耗积分的总和") private BigDecimal latestDeductDaySum; - @DateTimeFormat(pattern = "yyyy-MM-dd") - @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @Schema(title = "最新获得积分的日期") private Date lastAddDate; diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/UserPointsDetails.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/UserPointsDetails.java index d0b4978..4f03f14 100644 --- a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/UserPointsDetails.java +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/po/UserPointsDetails.java @@ -25,7 +25,7 @@ import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor -@TableName("bank_user_points") +@TableName("bank_user_points_details") @Schema(title = "用户积分详情表", description = "用户积分详情表") public class UserPointsDetails implements Serializable { private static final long serialVersionUID = 1L; @@ -56,7 +56,7 @@ public class UserPointsDetails implements Serializable { /** * @see PointsSourceEnum 来源详见枚举类 */ - @Schema(title = "来源(survey-问卷积分,use-礼品兑换,violation-违规扣除,expired-过期清除)") + @Schema(title = "来源(survey-积分打卡,use-礼品兑换,violation-违规扣除,expired-过期清除)") private String source; @Schema(title = "关联业务ID(规则ID,礼品兑换订单Id等)") diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointRankingVO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointRankingVO.java new file mode 100644 index 0000000..afb702e --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointRankingVO.java @@ -0,0 +1,40 @@ +package com.renkang.bank.model.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author pj + * @version 1.0 + * @description: 用户积分榜单VO + * @date 2026/2/6 10:41 + */ +@Data +public class UserPointRankingVO { + + @Schema(title = "排名") + private Integer ranking; + + @Schema(title = "用户id") + private String userId; + + @Schema(title = "姓名") + private String realName; + + @Schema(title = "头像") + private String avatar; + + @Schema(title = "单位名称") + private String orgName; + + @Schema(title = "部门名称") + private String deptName; + + @Schema(title = "性别") + private Integer sex; + + @Schema(title = "积分") + private BigDecimal pointSum; +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointRecordVO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointRecordVO.java new file mode 100644 index 0000000..b2fca08 --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointRecordVO.java @@ -0,0 +1,44 @@ +package com.renkang.bank.model.vo; + +import cn.hutool.core.date.DateUtil; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author pj + * @version 1.0 + * @description: 用户积分明细VO + * @date 2026/2/6 10:41 + */ +@Data +public class UserPointRecordVO { + + @Schema(title = "记录id") + private Long id; + + @Schema(title = "得分说明") + private String businessInfo; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @Schema(title = "创建时间") + private Date createTime; + + @Schema(title = "本次积分变化") + private BigDecimal points; + + @Schema(title = "补充信息") + private String remark; + + public String getCreateMonthStr() { + if (createTime != null) { + return DateUtil.format(createTime, "yyyy年-MM月"); + } + return null; + } +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsInfoVO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsInfoVO.java new file mode 100644 index 0000000..65368a4 --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsInfoVO.java @@ -0,0 +1,42 @@ +package com.renkang.bank.model.vo; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author pj + * @version 1.0 + * @description: 用户积分信息vo + * @date 2026/2/6 9:31 + */ +@Data +public class UserPointsInfoVO { + + @Schema(title = "可用积分") + @JsonSetter(nulls = Nulls.SKIP) + private BigDecimal points = BigDecimal.ZERO; + + @Schema(title = "累计积分") + @JsonSetter(nulls = Nulls.SKIP) + private BigDecimal addPointsSum = BigDecimal.ZERO; + + @Schema(title = "累计兑换") + @JsonSetter(nulls = Nulls.SKIP) + private BigDecimal exchangePointsSum = BigDecimal.ZERO; + + public BigDecimal getPoints() { + return points == null ? BigDecimal.ZERO : points; + } + + public BigDecimal getAddPointsSum() { + return addPointsSum == null ? BigDecimal.ZERO : addPointsSum; + } + + public BigDecimal getExchangePointsSum() { + return exchangePointsSum == null ? BigDecimal.ZERO : exchangePointsSum; + } +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsListVO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsListVO.java new file mode 100644 index 0000000..ff22190 --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsListVO.java @@ -0,0 +1,35 @@ +package com.renkang.bank.model.vo; + +import com.renkang.bank.model.po.UserPoints; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author pj + * @version 1.0 + * @description: 用户积分信息列表VO + * @date 2026/2/5 18:51 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class UserPointsListVO extends UserPoints { + + @Schema(title = "姓名") + private String realName; + + @Schema(title = "员工编号") + private String workNo; + + @Schema(title = "所属单位名称") + private String orgName; + + @Schema(title = "所属部门名称") + private String deptName; + + @Schema(title = "性别") + private String sexName; + + @Schema(title = "年龄") + private Integer age; +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsMonitorVO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsMonitorVO.java new file mode 100644 index 0000000..07f64bc --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsMonitorVO.java @@ -0,0 +1,53 @@ +package com.renkang.bank.model.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author pj + * @version 1.0 + * @description: 员工打卡监测VO + * @date 2026/2/5 18:51 + */ +@Data +public class UserPointsMonitorVO { + + @Schema(title = "用户id") + private String userId; + + @Schema(title = "姓名") + private String realName; + + @Schema(title = "员工编号") + private String workNo; + + @Schema(title = "所属单位名称") + private String orgName; + + @Schema(title = "所属部门名称") + private String deptName; + + @Schema(title = "性别") + private String sexName; + + @Schema(title = "年龄") + private Integer age; + + @Schema(title = "健康行为") + private String businessInfo; + + @Schema(title = "补充信息") + private String remark; + + @Schema(title = "周期") + private Integer frequency; + + @Schema(title = "获取积分") + private BigDecimal points; + + @Schema(title = "打卡时间") + private Date createTime; +} diff --git a/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsTaskVO.java b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsTaskVO.java new file mode 100644 index 0000000..b032f6b --- /dev/null +++ b/health-bank/health-bank-api/src/main/java/com/renkang/bank/model/vo/UserPointsTaskVO.java @@ -0,0 +1,39 @@ +package com.renkang.bank.model.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.jeecg.common.aspect.annotation.Dict; + +import java.math.BigDecimal; + +/** + * @author pj + * @version 1.0 + * @description: 用户积分任务VO + * @date 2026/2/6 9:54 + */ +@Data +public class UserPointsTaskVO { + + @Schema(title = "规则id") + private Long ruleId; + + @Schema(title = "问答频次(1-单次,2-日/次,3-周/次,4-月/次,5-季度/次,6-年/次)") + private Integer frequency; + + @Dict(dicCode = "points_rule_category") + @Schema(title = "规则类别") + private Integer ruleCategory; + + @Schema(title = "规则描述") + private String ruleDesc; + + @Schema(title = "图标") + private String icon; + + @Schema(title = "奖励积分") + private BigDecimal points; + + @Schema(title = "打卡状态,0未打卡,1已打卡") + private Integer clockInStatus; +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/controller/PointsRuleController.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/controller/PointsRuleController.java new file mode 100644 index 0000000..0333d1e --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/controller/PointsRuleController.java @@ -0,0 +1,97 @@ +package com.renkang.bank.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.renkang.bank.model.dto.PointsRulePageDTO; +import com.renkang.bank.model.po.PointsRule; +import com.renkang.bank.service.IPointsRuleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.apache.commons.lang.StringUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author pj + * @version 1.0 + * @description: 积分规则 + * @date 2026/2/5 17:53 + */ +@Tag(name = "积分规则") +@RestController +@RequestMapping("/bank/pointsRule") +public class PointsRuleController extends JeecgController { + + @Autowired + private IPointsRuleService iPointsRuleService; + + @Operation(summary = "积分规则-分页列表", description = "积分规则-分页列表") +// @RequiresPermissions("bank:points_rule:add") + @PostMapping(value = "/pageList") + public Result> pageList(@RequestBody PointsRulePageDTO dto) { + return Result.OK(iPointsRuleService.pageList(dto)); + } + + @Operation(summary = "积分规则-添加", description = "积分规则-添加") +// @RequiresPermissions("bank:points_rule:add") + @PostMapping(value = "/add") + public Result add(@RequestBody PointsRule pointsRule) { + return Result.OK("添加成功", iPointsRuleService.add(pointsRule)); + } + + @Operation(summary = "积分规则-修改", description = "积分规则-修改") +// @RequiresPermissions("bank:points_rule:edit") + @PostMapping(value = "/edit") + public Result edit(@RequestBody PointsRule pointsRule) { + return Result.OK("修改成功", iPointsRuleService.edit(pointsRule)); + } + + @Operation(summary = "积分规则-修改状态", description = "积分规则-修改状态") +// @RequiresPermissions("bank:points_rule:edit") + @GetMapping(value = "/editStatus") + public Result editStatus(@RequestParam(name = "id") Long id, @RequestParam(name = "status") Integer status) { + return Result.OK("修改成功", iPointsRuleService.editStatus(id, status)); + } + + @Operation(summary = "积分规则-详情", description = "积分规则-详情") +// @RequiresPermissions("bank:points_rule:byId") + @GetMapping(value = "/byId") + public Result byId(@RequestParam(name = "id") String id) { + return Result.OK(iPointsRuleService.byId(id)); + } + + @Operation(summary = "积分规则-删除", description = "积分规则-删除") +// @RequiresPermissions("bank:points_rule:del") + @GetMapping(value = "/delete") + public Result delete(@RequestParam(name = "id") String id) { + return Result.OK("删除成功", iPointsRuleService.delete(id)); + } + + @Operation(summary = "积分规则-批量删除", description = "积分规则-批量删除") +// @RequiresPermissions("bank:points_rule:del") + @GetMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids") String ids) { + if (StringUtils.isBlank(ids)) { + return Result.error("请选择需要删除的积分规则"); + } + return Result.OK("删除成功", iPointsRuleService.deleteBatch(ids)); + } + + /** + * 导出excel + * + * @param request + * @param conHealthInfo + */ + @Operation(summary = "积分规则-导出", description = "积分规则-导出") +// @RequiresPermissions("bank:points_rule:exportXls") + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, PointsRule conHealthInfo) { + return super.exportXls(request, conHealthInfo, PointsRule.class, "积分规则"); + } + +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/controller/UserPointsController.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/controller/UserPointsController.java new file mode 100644 index 0000000..3d1b165 --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/controller/UserPointsController.java @@ -0,0 +1,91 @@ +package com.renkang.bank.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.renkang.bank.model.dto.UpdUserPointsDTO; +import com.renkang.bank.model.dto.UserPointsPageDTO; +import com.renkang.bank.model.dto.UserPointsRankingDTO; +import com.renkang.bank.model.po.UserPointsDetails; +import com.renkang.bank.model.vo.*; +import com.renkang.bank.service.IUserPointsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.jeecg.common.api.vo.Result; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author pj + * @version 1.0 + * @description: 用户积分汇总表 + * @date 2026/2/5 16:42 + */ +@Tag(name = "用户积分信息") +@RestController +@RequestMapping("/bank/userPoints") +public class UserPointsController { + + @Autowired + private IUserPointsService iUserPointsService; + + @Operation(summary = "测试积分变更", description = "测试积分变更") + @PostMapping(value = "/updateUserPoints") + public Result updateUserPoints(@RequestBody UpdUserPointsDTO dto) { + return Result.OK(iUserPointsService.updateUserPoints(dto)); + } + + @Operation(summary = "用户积分信息-分页列表", description = "用户积分信息-分页列表") + @PostMapping(value = "/pageList") + public Result> pageList(@RequestBody UserPointsPageDTO dto) { + return Result.OK(iUserPointsService.pageList(dto)); + } + + @Operation(summary = "用户积分信息-积分明细", description = "用户积分信息-积分明细") + @PostMapping(value = "/detailPageList") + public Result> detailPageList(@RequestBody UserPointsPageDTO dto) { + return Result.OK(iUserPointsService.detailPageList(dto)); + } + + @Operation(summary = "用户积分信息-扣除积分", description = "用户积分信息-扣除积分") + @PostMapping(value = "/deductPoint") + public Result deductPoint(@RequestBody UpdUserPointsDTO dto) { + return Result.OK(iUserPointsService.deductPoint(dto)); + } + + @Operation(summary = "用户积分信息-员工打卡监测", description = "用户积分信息-员工打卡监测") + @PostMapping(value = "/clockInMonitor") + public Result> clockInMonitor(@RequestBody UserPointsPageDTO dto) { + return Result.OK(iUserPointsService.clockInMonitor(dto)); + } + + @Operation(summary = "用户积分信息-app我的积分", description = "用户积分信息-app我的积分") + @GetMapping(value = "/app/myPoints") + public Result myPoints() { + return Result.OK(iUserPointsService.myPoints()); + } + + @Operation(summary = "用户积分信息-app积分任务", description = "用户积分信息-app积分任务") + @GetMapping(value = "/app/pointsTaskList") + public Result> pointsTaskList() { + return Result.OK(iUserPointsService.pointsTaskList()); + } + + @Operation(summary = "用户积分信息-app积分打卡", description = "用户积分信息-app积分打卡") + @PostMapping(value = "/app/pointCheckIn") + public Result pointCheckIn(@RequestBody UpdUserPointsDTO dto) { + return Result.OK(iUserPointsService.pointCheckIn(dto)); + } + + @Operation(summary = "用户积分信息-app积分明细", description = "用户积分信息-app积分明细") + @PostMapping(value = "/app/pointRecord") + public Result> pointRecord(@RequestBody UserPointsPageDTO dto) { + return Result.OK(iUserPointsService.pointRecord(dto)); + } + + @Operation(summary = "用户积分信息-app积分榜单", description = "用户积分信息-app积分榜单") + @PostMapping(value = "/app/pointRanking") + public Result> pointRanking(@RequestBody UserPointsRankingDTO dto) { + return Result.OK(iUserPointsService.pointRanking(dto)); + } +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/PointsRuleMapper.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/PointsRuleMapper.java new file mode 100644 index 0000000..66b41d0 --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/PointsRuleMapper.java @@ -0,0 +1,16 @@ +package com.renkang.bank.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.renkang.bank.model.po.PointsRule; +import com.renkang.bank.model.vo.UserPointsTaskVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface PointsRuleMapper extends MPJBaseMapper { + + List pointsTaskList(@Param("userId") String userId); + +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/UserPointsDetailsMapper.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/UserPointsDetailsMapper.java new file mode 100644 index 0000000..fb0d8a8 --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/UserPointsDetailsMapper.java @@ -0,0 +1,16 @@ +package com.renkang.bank.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.github.yulichang.base.MPJBaseMapper; +import com.renkang.bank.model.po.UserPointsDetails; +import com.renkang.bank.model.vo.UserPointRankingVO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Date; + +@Mapper +public interface UserPointsDetailsMapper extends MPJBaseMapper { + + IPage pointRanking(IPage page, Date startTime, Date endTime, String secondOrgCode); + +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/UserPointsMapper.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/UserPointsMapper.java new file mode 100644 index 0000000..a2a681b --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/UserPointsMapper.java @@ -0,0 +1,14 @@ +package com.renkang.bank.mapper; + +import com.github.yulichang.base.MPJBaseMapper; +import com.renkang.bank.model.po.UserPoints; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author: pj + * @description: 用户积分 + * @date 2026/2/5 16:47 + */ +@Mapper +public interface UserPointsMapper extends MPJBaseMapper { +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/xml/PointsRuleMapper.xml b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/xml/PointsRuleMapper.xml new file mode 100644 index 0000000..4ab314d --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/xml/PointsRuleMapper.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/xml/UserPointsDetailsMapper.xml b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/xml/UserPointsDetailsMapper.xml new file mode 100644 index 0000000..ca5340e --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/mapper/xml/UserPointsDetailsMapper.xml @@ -0,0 +1,35 @@ + + + + + + + \ No newline at end of file diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/IPointsRuleService.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/IPointsRuleService.java new file mode 100644 index 0000000..4f61c50 --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/IPointsRuleService.java @@ -0,0 +1,23 @@ +package com.renkang.bank.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.renkang.bank.model.dto.PointsRulePageDTO; +import com.renkang.bank.model.po.PointsRule; + +public interface IPointsRuleService extends IService { + + IPage pageList(PointsRulePageDTO dto); + + int add(PointsRule pointsRule); + + int edit(PointsRule pointsRule); + + PointsRule byId(String id); + + int delete(String id); + + int editStatus(Long id, Integer status); + + int deleteBatch(String ids); +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/IUserPointsService.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/IUserPointsService.java new file mode 100644 index 0000000..f7b9e05 --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/IUserPointsService.java @@ -0,0 +1,33 @@ +package com.renkang.bank.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.renkang.bank.model.dto.UpdUserPointsDTO; +import com.renkang.bank.model.dto.UserPointsPageDTO; +import com.renkang.bank.model.dto.UserPointsRankingDTO; +import com.renkang.bank.model.po.UserPointsDetails; +import com.renkang.bank.model.vo.*; + +import java.util.List; + +public interface IUserPointsService { + + boolean updateUserPoints(UpdUserPointsDTO dto); + + IPage pageList(UserPointsPageDTO dto); + + IPage detailPageList(UserPointsPageDTO dto); + + boolean deductPoint(UpdUserPointsDTO dto); + + IPage clockInMonitor(UserPointsPageDTO dto); + + UserPointsInfoVO myPoints(); + + List pointsTaskList(); + + boolean pointCheckIn(UpdUserPointsDTO dto); + + IPage pointRecord(UserPointsPageDTO dto); + + IPage pointRanking(UserPointsRankingDTO dto); +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/impl/PointsRuleServiceImpl.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/impl/PointsRuleServiceImpl.java new file mode 100644 index 0000000..dfd3ed6 --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/impl/PointsRuleServiceImpl.java @@ -0,0 +1,80 @@ +package com.renkang.bank.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.renkang.bank.mapper.PointsRuleMapper; +import com.renkang.bank.model.dto.PointsRulePageDTO; +import com.renkang.bank.model.po.PointsRule; +import com.renkang.bank.service.IPointsRuleService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang.StringUtils; +import org.jeecg.global.GlobalUtils; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Date; + +/** + * @author pj + * @version 1.0 + * @description: 积分规则 + * @date 2026/2/5 18:01 + */ +@Service +@RequiredArgsConstructor +public class PointsRuleServiceImpl extends ServiceImpl implements IPointsRuleService { + + @Override + public IPage pageList(PointsRulePageDTO dto) { + Page page = new Page<>(dto.getPageNo(), dto.getPageSize()); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.like(StringUtils.isNotBlank(dto.getRuleDesc()), PointsRule::getRuleDesc, dto.getRuleDesc()); + queryWrapper.eq(ObjectUtil.isNotNull(dto.getRuleCategory()), PointsRule::getRuleDesc, dto.getRuleCategory()); + queryWrapper.eq(ObjectUtil.isNotNull(dto.getStatus()), PointsRule::getRuleDesc, dto.getStatus()); + queryWrapper.orderByDesc(PointsRule::getCreateTime); + return baseMapper.selectPage(page, queryWrapper); + } + + @Override + public int add(PointsRule pointsRule) { + String userId = GlobalUtils.getLoginUser().getId(); + Date date = new Date(); + pointsRule.setCreateUser(userId); + pointsRule.setLastModifyDate(date); + pointsRule.setCreateTime(date); + return baseMapper.insert(pointsRule); + } + + @Override + public int edit(PointsRule pointsRule) { + pointsRule.setLastModifyDate(new Date()); + return baseMapper.updateById(pointsRule); + } + + @Override + public PointsRule byId(String id) { + return baseMapper.selectById(id); + } + + @Override + public int delete(String id) { + return baseMapper.deleteById(id); + } + + @Override + public int editStatus(Long id, Integer status) { + return baseMapper.update(new LambdaUpdateWrapper() + .eq(PointsRule::getId, id) + .set(PointsRule::getStatus, status) + ); + } + + @Override + public int deleteBatch(String ids) { + return baseMapper.deleteBatchIds(Arrays.asList(ids.split(","))); + } +} diff --git a/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/impl/UserPointsServiceImpl.java b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/impl/UserPointsServiceImpl.java new file mode 100644 index 0000000..2960c1e --- /dev/null +++ b/health-bank/health-bank-biz/src/main/java/com/renkang/bank/service/impl/UserPointsServiceImpl.java @@ -0,0 +1,452 @@ +package com.renkang.bank.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.yulichang.wrapper.MPJLambdaWrapper; +import com.renkang.bank.constant.HealthBankConstants; +import com.renkang.bank.enums.PointsSourceEnum; +import com.renkang.bank.mapper.PointsRuleMapper; +import com.renkang.bank.mapper.UserPointsDetailsMapper; +import com.renkang.bank.mapper.UserPointsMapper; +import com.renkang.bank.model.dto.UpdUserPointsDTO; +import com.renkang.bank.model.dto.UserPointsPageDTO; +import com.renkang.bank.model.dto.UserPointsRankingDTO; +import com.renkang.bank.model.po.PointsRule; +import com.renkang.bank.model.po.UserPoints; +import com.renkang.bank.model.po.UserPointsDetails; +import com.renkang.bank.model.vo.*; +import com.renkang.bank.service.IUserPointsService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.jeecg.common.exception.ExceptionAssertsUtil; +import org.jeecg.common.system.api.ISysBaseAPI; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.global.GlobalUtils; +import org.jeecg.modules.manager.ISysCache; +import org.jeecg.modules.system.entity.SysDepart; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author pj + * @version 1.0 + * @description: 用户积分 + * @date 2026/2/5 16:49 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class UserPointsServiceImpl extends ServiceImpl implements IUserPointsService { + + private final PointsRuleMapper pointsRuleMapper; + private final UserPointsDetailsMapper userPointsDetailsMapper; + private final ISysBaseAPI iSysBaseAPI; + private final ISysCache sysCache; + + @Override + public IPage pageList(UserPointsPageDTO dto) { + Page page = new Page<>(dto.getPageNo(), dto.getPageSize()); + MPJLambdaWrapper queryWrapper = new MPJLambdaWrapper<>(); + if (StringUtils.isNotBlank(dto.getRealName()) || StringUtils.isNotBlank(dto.getWorkNo())) { + //根据姓名和工号查询用户 + List userIdList = iSysBaseAPI.getUserIdsByDepartAndUsername(null, dto.getRealName(), null, dto.getWorkNo()); + queryWrapper.in(!userIdList.isEmpty(), UserPoints::getUserId, userIdList); + } + // 动态排序 + if (StringUtils.isNotBlank(dto.getColumn())) { + // 驼峰转下划线 + String column = StrUtil.toUnderlineCase(dto.getColumn()); + if ("asc".equalsIgnoreCase(dto.getOrder())) { + queryWrapper.orderByAsc(column); + } else { + queryWrapper.orderByDesc(column); + } + } else { + // 默认排序 + queryWrapper.orderByDesc(UserPoints::getLastAddDate); + } + if (StringUtils.isNotBlank(dto.getOrgCode())) { + queryWrapper.likeRight(UserPoints::getOrgCode, dto.getOrgCode()); + } + if (StringUtils.isNotBlank(dto.getDeptCode())) { + queryWrapper.likeRight(UserPoints::getOrgCode, dto.getDeptCode()); + } + Page voPage = baseMapper.selectJoinPage(page, UserPointsListVO.class, queryWrapper); + List userIds = voPage.getRecords().stream().map(UserPoints::getUserId).collect(Collectors.toList()); + if (!userIds.isEmpty()) { + List loginUsers = iSysBaseAPI.listUserByIdsNew(userIds); + voPage.getRecords().forEach(vo -> { + LoginUser loginUser = loginUsers.stream().filter(user -> user.getId().equals(vo.getUserId())).findFirst().orElse(null); + if (loginUser != null) { + vo.setRealName(loginUser.getRealname()); + vo.setWorkNo(loginUser.getWorkNo()); + vo.setSexName(ObjectUtil.isNotNull(loginUser.getSex()) && loginUser.getSex().equals(1) ? "女" : "男"); + vo.setAge(ObjectUtil.isNotNull(loginUser.getAge()) && loginUser.getAge() > 0 ? loginUser.getAge() : null); + SysDepart secondDepart = sysCache.getDepartByOrgCode(GlobalUtils.getSecondDepartOrgCode(vo.getOrgCode())); + if (ObjUtil.isNotEmpty(secondDepart)) { + vo.setDeptName(secondDepart.getDepartName()); + } + SysDepart thirdDepart = sysCache.getDepartByOrgCode(GlobalUtils.getThirdDepartOrgCode(vo.getOrgCode())); + if (ObjUtil.isNotEmpty(thirdDepart)) { + vo.setOrgName(thirdDepart.getDepartName()); + } + } + }); + } + return voPage; + } + + @Override + public IPage detailPageList(UserPointsPageDTO dto) { + if (StringUtils.isBlank(dto.getUserId())) { + ExceptionAssertsUtil.fail("用户id不能为空"); + } + if (ObjectUtil.isNull(dto.getChangeType())) { + ExceptionAssertsUtil.fail("收支类型不能为空"); + } + Page page = new Page<>(dto.getPageNo(), dto.getPageSize()); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.select(UserPointsDetails::getId, UserPointsDetails::getBusinessInfo, + UserPointsDetails::getPoints, UserPointsDetails::getCreateTime, UserPointsDetails::getChangeType); + queryWrapper.eq(UserPointsDetails::getUserId, dto.getUserId()); + queryWrapper.eq(UserPointsDetails::getChangeType, dto.getChangeType()); + queryWrapper.orderByDesc(UserPointsDetails::getCreateTime); + return userPointsDetailsMapper.selectPage(page, queryWrapper); + } + + @Override + public boolean deductPoint(UpdUserPointsDTO dto) { + dto.setSourceType(PointsSourceEnum.TYPE_2_VIOLATION.getSource()); + return updateUserPoints(dto); + } + + @Override + public IPage clockInMonitor(UserPointsPageDTO dto) { + Page page = new Page<>(dto.getPageNo(), dto.getPageSize()); + MPJLambdaWrapper queryWrapper = new MPJLambdaWrapper<>(); + queryWrapper.selectAll(UserPointsDetails.class); + queryWrapper.select(PointsRule::getFrequency); + queryWrapper.eq(UserPointsDetails::getChangeType, 1); + if (StringUtils.isNotBlank(dto.getRealName()) || StringUtils.isNotBlank(dto.getWorkNo())) { + //根据姓名和工号查询用户 + List userIdList = iSysBaseAPI.getUserIdsByDepartAndUsername(null, dto.getRealName(), null, dto.getWorkNo()); + queryWrapper.in(!userIdList.isEmpty(), UserPoints::getUserId, userIdList); + } + // 动态排序 + + queryWrapper.orderByDesc(UserPointsDetails::getCreateTime); + if (StringUtils.isNotBlank(dto.getOrgCode())) { + queryWrapper.likeRight(UserPoints::getOrgCode, dto.getOrgCode()); + } + if (StringUtils.isNotBlank(dto.getDeptCode())) { + queryWrapper.likeRight(UserPoints::getOrgCode, dto.getDeptCode()); + } + queryWrapper.leftJoin(PointsRule.class, PointsRule::getId, UserPointsDetails::getBusinessId); + Page voPage = userPointsDetailsMapper.selectJoinPage(page, UserPointsMonitorVO.class, queryWrapper); + List userIds = voPage.getRecords().stream().map(UserPointsMonitorVO::getUserId).collect(Collectors.toList()); + if (!userIds.isEmpty()) { + List loginUsers = iSysBaseAPI.listUserByIdsNew(userIds); + voPage.getRecords().forEach(vo -> { + LoginUser loginUser = loginUsers.stream().filter(user -> user.getId().equals(vo.getUserId())).findFirst().orElse(null); + if (loginUser != null) { + vo.setRealName(loginUser.getRealname()); + vo.setWorkNo(loginUser.getWorkNo()); + vo.setSexName(ObjectUtil.isNotNull(loginUser.getSex()) && loginUser.getSex().equals(1) ? "女" : "男"); + vo.setAge(ObjectUtil.isNotNull(loginUser.getAge()) && loginUser.getAge() > 0 ? loginUser.getAge() : null); + SysDepart secondDepart = sysCache.getDepartByOrgCode(GlobalUtils.getSecondDepartOrgCode(loginUser.getOrgCode())); + if (ObjUtil.isNotEmpty(secondDepart)) { + vo.setDeptName(secondDepart.getDepartName()); + } + SysDepart thirdDepart = sysCache.getDepartByOrgCode(GlobalUtils.getThirdDepartOrgCode(loginUser.getOrgCode())); + if (ObjUtil.isNotEmpty(thirdDepart)) { + vo.setOrgName(thirdDepart.getDepartName()); + } + } + }); + } + return voPage; + } + + /** + * 更新用户积分 + * + * @param dto + * @return + */ + @Override + public boolean updateUserPoints(UpdUserPointsDTO dto) { + LoginUser loginUser = GlobalUtils.getLoginUser(); + log.info("------用户:{}({})开始更新积分,入参:{}------", loginUser.getRealname(), loginUser.getUsername(), dto); + PointsSourceEnum sourceEnum = PointsSourceEnum.getBySource(dto.getSourceType()); + if (sourceEnum == null) { + log.error("积分类型不存在"); + ExceptionAssertsUtil.fail("积分类型不存在"); + } + String userId; + if (dto.getSourceType().equals(PointsSourceEnum.TYPE_2_VIOLATION.getSource())) { + if (StringUtils.isBlank(dto.getUserId())) { + log.error("扣减用户id不能为空"); + ExceptionAssertsUtil.fail("扣减用户id不能为空"); + } + //违规扣除 + userId = dto.getUserId(); + } else { + userId = GlobalUtils.getLoginUser().getId(); + } + UserPoints userPoints = baseMapper.selectOne(new LambdaQueryWrapper() + .eq(UserPoints::getUserId, userId) + ); + boolean isAdd = false; + Date date = new Date(); + UserPointsDetails userPointsDetails = new UserPointsDetails(); + if (userPoints == null) { + isAdd = true; + userPoints = new UserPoints(); + userPoints.setUserId(userId); + userPoints.setOrgCode(loginUser.getOrgCode()); + userPoints.setCreateTime(date); + userPointsDetails.setBeforePoints(new BigDecimal(0)); + } else { + userPointsDetails.setBeforePoints(userPoints.getPoints()); + } + userPointsDetails.setUserId(userId); + switch (sourceEnum) { + case TYPE_1_SURVEY: + // 积分打卡 + PointsRule pointsRule = pointsRuleMapper.selectById(dto.getBusinessId()); + if (pointsRule == null) { + log.error("积分规则不存在"); + ExceptionAssertsUtil.fail("积分规则不存在"); + } + checkUserPoints(pointsRule, userId); + userPointsDetails.setPoints(pointsRule.getPoints()); + userPointsDetails.setChangeType(HealthBankConstants.CHANGE_TYPE_ADD); + userPointsDetails.setSource(sourceEnum.getSource()); + userPointsDetails.setBusinessId(dto.getBusinessId()); + userPointsDetails.setBusinessInfo(pointsRule.getRuleDesc()); + userPointsDetails.setOperatorId(userId); + if (StringUtils.isNotBlank(dto.getRemark())) { + userPointsDetails.setRemark(dto.getRemark()); + } + if (isAdd) { + userPoints.setPoints(pointsRule.getPoints()); + userPoints.setAddPointsSum(userPoints.getPoints()); + userPoints.setDeductPointsSum(BigDecimal.valueOf(0)); + userPoints.setLatestAddDaySum(userPoints.getPoints()); + userPoints.setLatestDeductDaySum(BigDecimal.valueOf(0)); + userPoints.setLastAddDate(date); + } else { + userPoints.setPoints(userPoints.getPoints().add(pointsRule.getPoints())); + userPoints.setAddPointsSum(userPoints.getAddPointsSum().add(pointsRule.getPoints())); + List details = userPointsDetailsMapper.selectList(new LambdaQueryWrapper() + .eq(UserPointsDetails::getUserId, userId) + .eq(UserPointsDetails::getChangeType, HealthBankConstants.CHANGE_TYPE_ADD) + .apply("DATE_FORMAT(create_time, '%Y-%m-%d') = '" + DateUtil.today() + "'") + ); + double sum = details.stream().map(UserPointsDetails::getPoints).mapToDouble(BigDecimal::doubleValue).sum(); + userPoints.setLatestAddDaySum(new BigDecimal(sum).add(pointsRule.getPoints())); + } + break; + case TYPE_2_USE: + // 礼品兑换 + userPoints.setLastDeductDate(date); + break; + case TYPE_2_VIOLATION: + // 违规扣除 + if (isAdd) { + ExceptionAssertsUtil.fail("用户积分不存在"); + } + userPoints.setDeductPointsSum(userPoints.getDeductPointsSum().add(dto.getPoints())); + userPoints.setPoints(userPoints.getPoints().subtract(dto.getPoints())); + userPointsDetails.setPoints(dto.getPoints()); + userPointsDetails.setRemark(dto.getRemark()); + userPointsDetails.setSource(sourceEnum.getSource()); + userPointsDetails.setChangeType(HealthBankConstants.CHANGE_TYPE_DEDUCT); + userPointsDetails.setOperatorId(GlobalUtils.getLoginUser().getId()); + break; + case TYPE_2_EXPIRED: + // 过期清除 + break; + default: + break; + } + userPointsDetails.setCreateTime(date); + userPointsDetails.setAfterPoints(userPoints.getPoints()); + userPoints.setLastVaryDate(date); + boolean b = this.saveOrUpdate(userPoints); + if (b) { + b = userPointsDetailsMapper.insert(userPointsDetails) > 0; + } + log.info("======用户:{}({})更新积分结果:{}======", loginUser.getRealname(), loginUser.getUsername(), b); + return b; + } + + /** + * 检查用户积分 + * + * @param pointsRule 积分规则 + * @param userId 用户ID + */ + public void checkUserPoints(PointsRule pointsRule, String userId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(UserPointsDetails::getUserId, userId); + wrapper.eq(UserPointsDetails::getBusinessId, pointsRule.getId()); + Long c; + Date date = new Date(); + switch (pointsRule.getFrequency()) { + // 单次:检查用户是否已经获得过该积分 + case 1: + break; + // 日/次:检查用户当天是否已经获得过该积分 + case 2: + DateTime startOfDay = DateUtil.beginOfDay(date); + DateTime endOfDay = DateUtil.endOfDay(date); + wrapper.between(UserPointsDetails::getCreateTime, startOfDay, endOfDay); + c = userPointsDetailsMapper.selectCount(wrapper); + if (c > 0) { + ExceptionAssertsUtil.fail("本日已获得该积分"); + } + break; + // 周/次:检查用户本周是否已经获得过该积分 + case 3: + DateTime startOfWeek = DateUtil.beginOfWeek(date); + DateTime endOfWeek = DateUtil.endOfWeek(date); + wrapper.between(UserPointsDetails::getCreateTime, startOfWeek, endOfWeek); + c = userPointsDetailsMapper.selectCount(wrapper); + if (c > 0) { + ExceptionAssertsUtil.fail("本周已获得该积分"); + } + break; + // 月/次:检查用户本月是否已经获得过该积分 + case 4: + DateTime startOfMonth = DateUtil.beginOfMonth(date); + DateTime endOfMonth = DateUtil.endOfMonth(date); + wrapper.between(UserPointsDetails::getCreateTime, startOfMonth, endOfMonth); + c = userPointsDetailsMapper.selectCount(wrapper); + if (c > 0) { + ExceptionAssertsUtil.fail("本月已获得该积分"); + } + break; + // 季度/次:检查用户本季度是否已经获得过该积分 + case 5: + DateTime startOfQuarter = DateUtil.beginOfQuarter(date); + DateTime endOfQuarter = DateUtil.endOfQuarter(date); + wrapper.between(UserPointsDetails::getCreateTime, startOfQuarter, endOfQuarter); + c = userPointsDetailsMapper.selectCount(wrapper); + if (c > 0) { + ExceptionAssertsUtil.fail("本季度已获得该积分"); + } + break; + // 年/次:检查用户本年度是否已经获得过该积分 + case 6: + DateTime startOfYear = DateUtil.beginOfYear(date); + DateTime endOfYear = DateUtil.endOfYear(date); + wrapper.between(UserPointsDetails::getCreateTime, startOfYear, endOfYear); + c = userPointsDetailsMapper.selectCount(wrapper); + if (c > 0) { + ExceptionAssertsUtil.fail("本年度已获得该积分"); + } + break; + default: + // 未知规则类型,默认不处理 + break; + } + } + + @Override + public UserPointsInfoVO myPoints() { + String userId = GlobalUtils.getLoginUser().getId(); + UserPoints userPoints = baseMapper.selectOne(new LambdaQueryWrapper() + .eq(UserPoints::getUserId, userId) + ); + UserPointsInfoVO vo = new UserPointsInfoVO(); + if (userPoints != null) { + vo.setPoints(userPoints.getPoints()); + vo.setAddPointsSum(userPoints.getAddPointsSum()); + vo.setExchangePointsSum(userPoints.getExchangePointsSum()); + } + return vo; + } + + @Override + public List pointsTaskList() { + String userId = GlobalUtils.getLoginUser().getId(); + return pointsRuleMapper.pointsTaskList(userId); + } + + @Override + public boolean pointCheckIn(UpdUserPointsDTO dto) { + dto.setSourceType(PointsSourceEnum.TYPE_1_SURVEY.getSource()); + return updateUserPoints(dto); + } + + @Override + public IPage pointRecord(UserPointsPageDTO dto) { + if (ObjectUtil.isNull(dto.getChangeType())) { + ExceptionAssertsUtil.fail("收支类型不能为空"); + } + String userId = GlobalUtils.getLoginUser().getId(); + Page page = new Page<>(dto.getPageNo(), dto.getPageSize()); + MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>(); + wrapper.eq(UserPointsDetails::getUserId, userId); + wrapper.eq(UserPointsDetails::getChangeType, dto.getChangeType()); + wrapper.orderByDesc(UserPointsDetails::getCreateTime); + return userPointsDetailsMapper.selectJoinPage(page, UserPointRecordVO.class, wrapper); + } + + @Override + public IPage pointRanking(UserPointsRankingDTO dto) { + String orgCode = GlobalUtils.getLoginUser().getOrgCode(); + String secondOrgCode = GlobalUtils.getSecondDepartOrgCode(orgCode); + Page page = new Page<>(dto.getPageNo(), dto.getPageSize()); + Date startTime = null; + Date endTime = null; + Date now = new Date(); + if (StringUtils.isNotBlank(dto.getRankType())) { + if ("1".equals(dto.getRankType())) { + // 获取本周的开始时间(周一) + startTime = DateUtil.beginOfWeek(now, true); + // 获取本周的结束时间(周日) + endTime = DateUtil.endOfWeek(now, true); + } else if ("2".equals(dto.getRankType())) { + // 获取本月的开始时间 + startTime = DateUtil.beginOfMonth(now); + // 获取本月的结束时间 + endTime = DateUtil.endOfMonth(now); + } + } + IPage voiPage = userPointsDetailsMapper.pointRanking(page, startTime, endTime, secondOrgCode); + List userIds = voiPage.getRecords().stream().map(UserPointRankingVO::getUserId).collect(Collectors.toList()); + List loginUsers = iSysBaseAPI.listUserByIdsNew(userIds); + voiPage.getRecords().forEach(vo -> { + loginUsers.forEach(loginUser -> { + if (vo.getUserId().equals(loginUser.getId())) { + vo.setRealName(loginUser.getRealname()); + vo.setAvatar(loginUser.getAvatar()); + vo.setSex(loginUser.getSex()); + SysDepart secondDepart = sysCache.getDepartByOrgCode(GlobalUtils.getSecondDepartOrgCode(loginUser.getOrgCode())); + if (ObjUtil.isNotEmpty(secondDepart)) { + vo.setDeptName(secondDepart.getDepartName()); + } + SysDepart thirdDepart = sysCache.getDepartByOrgCode(GlobalUtils.getThirdDepartOrgCode(loginUser.getOrgCode())); + if (ObjUtil.isNotEmpty(thirdDepart)) { + vo.setOrgName(thirdDepart.getDepartName()); + } + } + }); + }); + return voiPage; + } +} diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/export/GenericExportHandler.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/export/GenericExportHandler.java new file mode 100644 index 0000000..7afb29c --- /dev/null +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/export/GenericExportHandler.java @@ -0,0 +1,124 @@ +package org.jeecg.common.export; + +import cn.hutool.core.collection.CollUtil; +import org.jeecg.enums.ExportExcelEnum; +import org.slf4j.Logger; +import org.springframework.beans.BeanUtils; +import org.springframework.core.task.AsyncTaskExecutor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +/** + * @author PengJ + * @description: 通用导出工具类 + * @date 2025/11/18 15:05 + */ +public class GenericExportHandler implements PoiExportHandler { + + /** + * 源数据类型 + */ + private final Class exportClass; + /** + * 导出编码 + */ + private final String code; + /** + * 导出标题 + */ + private final String title; + /** + * 保存路径 + */ + private final String bizPath; + /** + * 异步任务执行器 + */ + private final AsyncTaskExecutor asyncTaskExecutor; + /** + * 日志 + */ + private final Logger logger; + /** + * 数据提供者 + */ + private final Function> dataProvider; + + public GenericExportHandler(Class exportClass, + ExportExcelEnum excelEnum, + AsyncTaskExecutor asyncTaskExecutor, + Logger logger, + Function> dataProvider) { + this.exportClass = exportClass; + this.code = excelEnum.getExpTaskCode(); + this.title = excelEnum.getTitle(); + this.bizPath = excelEnum.getBizPath(); + this.asyncTaskExecutor = asyncTaskExecutor; + this.logger = logger; + this.dataProvider = dataProvider; + } + + @Override + public Class getExportClass() { + return exportClass; + } + + @Override + public String getCode() { + return code; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public AsyncTaskExecutor getAsyncTaskExecutor() { + return asyncTaskExecutor; + } + + @Override + public List getData(F filter) { + return dataProvider.apply(filter); + } + + @Override + public Logger getLogger() { + return logger; + } + + @Override + public String getBizPath() { + return bizPath; + } + + /** + * 处理数据 - 将 VO 转换为 Excel 对象 + * + * @param data 源数据列表 + * @param targetClass 目标类(通常是Excel实体类) + * @param 源数据类型 + * @param 目标数据类型 + * @return 转换后的目标数据列表 + */ + public static List handleData(List data, Class targetClass) { + if (CollUtil.isEmpty(data)) { + return Collections.emptyList(); + } + List list = new ArrayList<>(); + data.forEach(f -> { + try { + R target = targetClass.newInstance(); + BeanUtils.copyProperties(f, target); + list.add(target); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException("Failed to copy properties", e); + } + }); + return list; + } +} diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/enums/ExportExcelEnum.java b/jeecg-boot-base-core/src/main/java/org/jeecg/enums/ExportExcelEnum.java new file mode 100644 index 0000000..140e59e --- /dev/null +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/enums/ExportExcelEnum.java @@ -0,0 +1,44 @@ +package org.jeecg.enums; + +import lombok.Getter; + +/** + * @author PengJ + * @description: 导出/导出Excel枚举类 + * @date 2025/11/18 16:24 + */ +@Getter +public enum ExportExcelEnum { + /** + * 积分规则 + */ + BANK_POINTS_RULE("bcsStationExportCode", "站点数据", "/bcs/station", null), + ; + + /** + * 导出任务code + */ + public final String expTaskCode; + + /** + * 文件名称 + */ + public final String title; + + /** + * 文件路径 + */ + public final String bizPath; + + /** + * 导入任务code + */ + public final String impTaskCode; + + ExportExcelEnum(String expTaskCode, String title, String bizPath, String impTaskCode) { + this.expTaskCode = expTaskCode; + this.title = title; + this.bizPath = bizPath; + this.impTaskCode = impTaskCode; + } +} diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/HealthUserEmployeeExServiceImpl.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/HealthUserEmployeeExServiceImpl.java index a1292cc..dd45a20 100644 --- a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/HealthUserEmployeeExServiceImpl.java +++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/HealthUserEmployeeExServiceImpl.java @@ -830,7 +830,6 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl addUserInfo(UserEmployee userEmployee) { // 密码解密 String key = RSAEncryptUtils.decrypt1(userEmployee.getPassword(), CommonConstant.PRIVATE_KEY); diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/LoginAnYanServiceImpl.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/LoginAnYanServiceImpl.java index ea4f4dd..19fde70 100644 --- a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/LoginAnYanServiceImpl.java +++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/LoginAnYanServiceImpl.java @@ -122,12 +122,12 @@ public class LoginAnYanServiceImpl implements ILoginAnYanService { try { // 授权成功获取用户信息(统一认证的平台接口没有做统一封装,成功和失败均返回一个不同的json字符串, 这里只能判断没有获取到用户信息则认为是失败) anYanUserInfo = anYanClient.getAnYanUserInfo(anYanAuthResult.getAccess_token(), username); - if (anYanUserInfo == null || anYanUserInfo.getEmployeeUnitDTO() == null) { - return Result.error("登录失败,请先联系本单位掌油管理员确认个人机构信息"); - } } catch (Exception e) { log.error("获取用户信息异常: {}", e.getMessage()); } + if (anYanUserInfo == null || anYanUserInfo.getEmployeeUnitDTO() == null) { + return Result.error("登录失败,请先联系本单位掌油管理员确认个人机构信息"); + } try { // 检查并更新用户信息