添加交易圈管理功能

This commit is contained in:
easonzhu 2025-01-29 19:31:02 +08:00
parent ca9064a58e
commit 3b67d2606d
17 changed files with 1564 additions and 4 deletions

View File

@ -434,4 +434,11 @@ public class CacheKey {
public static final String LIVE_LIST = "live_list|";
}
public static final String GROUP = "group";
public static class GroupKey {
public static final String GROUP_INFO = "group:info:";
public static final String MAIN_GROUP_LIST = "group:main:list:";
}
}

View File

@ -34,6 +34,7 @@ public enum ProductType {
SERIAL(33, "合集"),
PAGE(34, "落地页"),
SHORT_VIDEO(35, "短视频"),
GROUP(41, "交易圈"),
;
public final Integer value;

View File

@ -27,9 +27,9 @@ public class CodeGenerator {
public static void main(String[] args) {
DataSourceConfig dsc = new DataSourceConfig
.Builder("jdbc:mysql://172.16.8.64/video_demo_wx?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8",
"root",
"123456")
.Builder("jdbc:mysql://47.96.178.171:3306/advisor_video?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8",
"eason",
"mysql2025easonzhu")
// .Builder("jdbc:mysql://172.16.9.44:3306/db_crm_dyqh?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false",
// "taf",
// "taf2015")
@ -38,7 +38,7 @@ public class CodeGenerator {
AutoGenerator mpg = new AutoGenerator(dsc);
String moduleName = scanner("模块名");
String projectPath = System.getProperty("user.dir") + "/AdvisorServer";
String projectPath = System.getProperty("user.dir") + "";
// 全局配置
GlobalConfig globalConfig = new GlobalConfig

View File

@ -0,0 +1,43 @@
package com.upchina.common.state;
import com.upchina.group.constant.GroupInfoStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GroupStateMachine {
@Bean
public StateMachine<GroupInfoStatus> groupSM() {
StateMachine<GroupInfoStatus> groupSM = new StateMachine<>();
// 待提交 -> 编辑 -> 待提交
groupSM.add(GroupInfoStatus.TO_COMMIT, GroupInfoStatus.EVENT_UPDATE, GroupInfoStatus.TO_COMMIT);
// 待提交 -> 提交 -> 待审核
groupSM.add(GroupInfoStatus.TO_COMMIT, GroupInfoStatus.EVENT_SUBMIT, GroupInfoStatus.TO_AUDIT);
// 待审核 -> 撤回 -> 待提交
groupSM.add(GroupInfoStatus.TO_AUDIT, GroupInfoStatus.EVENT_RECALL, GroupInfoStatus.TO_COMMIT);
// 待审核 -> 通过 -> 已审核(已上架)
groupSM.add(GroupInfoStatus.TO_AUDIT, GroupInfoStatus.EVENT_PASS, GroupInfoStatus.AUDITED);
// 待审核 -> 驳回 -> 已驳回
groupSM.add(GroupInfoStatus.TO_AUDIT, GroupInfoStatus.EVENT_REJECT, GroupInfoStatus.REJECTED);
// 已审核(已上架) -> 已下架
groupSM.add(GroupInfoStatus.AUDITED, GroupInfoStatus.EVENT_SOLD_OUT, GroupInfoStatus.SOLD_OUT);
// 已驳回 -> 编辑 -> 已驳回
groupSM.add(GroupInfoStatus.REJECTED, GroupInfoStatus.EVENT_UPDATE, GroupInfoStatus.REJECTED);
// 已驳回 -> 提交 -> 待审核
groupSM.add(GroupInfoStatus.REJECTED, GroupInfoStatus.EVENT_SUBMIT, GroupInfoStatus.TO_AUDIT);
// 已下架 > 上架 -> 已审核(已上架)
groupSM.add(GroupInfoStatus.SOLD_OUT, GroupInfoStatus.EVENT_PUT_ON, GroupInfoStatus.AUDITED);
// 已下架 -> 编辑 -> 已下架
groupSM.add(GroupInfoStatus.SOLD_OUT, GroupInfoStatus.EVENT_UPDATE, GroupInfoStatus.SOLD_OUT);
// 已下架 -> 删除 -> 已删除
groupSM.add(GroupInfoStatus.SOLD_OUT, GroupInfoStatus.EVENT_DELETE, GroupInfoStatus.DELETED);
return groupSM;
}
}

View File

@ -0,0 +1,42 @@
package com.upchina.group.constant;
public enum GroupInfoStatus {
TO_COMMIT(1, "待提交"),
TO_AUDIT(2, "待审核"),
AUDITED(3, "已上架"),
REJECTED(4, "已驳回"),
SOLD_OUT(5, "已下架"),
DELETED(6, "已删除"),
// 动作
EVENT_UPDATE(100, "编辑"),
EVENT_SUBMIT(101, "提交"),
EVENT_RECALL(102, "撤回"),
EVENT_PASS(103, "通过"),
EVENT_REJECT(104, "驳回"),
EVENT_PUT_ON(105, "上架"),
EVENT_SOLD_OUT(106, "下架"),
EVENT_DELETE(107, "删除"),
;
public final Integer value;
public final String name;
GroupInfoStatus(Integer value, String name) {
this.value = value;
this.name = name;
}
public static GroupInfoStatus fromValue(Integer value) {
if (value == null) {
return null;
}
for (GroupInfoStatus status : values()) {
if (status.value.equals(value)) {
return status;
}
}
return null;
}
}

View File

@ -0,0 +1,76 @@
package com.upchina.group.controller.admin;
import com.upchina.common.annotation.Operation;
import com.upchina.common.constant.ProductType;
import com.upchina.common.query.OnlyIdQuery;
import com.upchina.common.result.CommonResult;
import com.upchina.common.result.Pager;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.common.vo.InsertIdVO;
import com.upchina.group.query.ListGroupQuery;
import com.upchina.group.query.SaveGroupQuery;
import com.upchina.group.query.UpdateGroupQuery;
import com.upchina.group.query.UpdateGroupStatusQuery;
import com.upchina.group.service.GroupInfoService;
import com.upchina.group.vo.GroupVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "交易圈admin接口")
@RestController
public class AdminGroupController {
@Resource
private GroupInfoService groupInfoService;
@ApiOperation("后台保存交易圈")
@PostMapping("/admin/group/info/save")
@Operation(module = ProductType.GROUP)
public CommonResult<InsertIdVO> save(@Validated @RequestBody @ApiParam(required = true) SaveGroupQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
InsertIdVO vo = groupInfoService.save(query, backendUserVO);
return CommonResult.success(vo);
}
@ApiOperation("后台更新交易圈")
@PostMapping("/admin/group/info/update")
@Operation(module = ProductType.GROUP, statusKey = "event")
public CommonResult<Void> update(@Validated @RequestBody @ApiParam(required = true) UpdateGroupQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
groupInfoService.update(query, backendUserVO);
return CommonResult.success();
}
@ApiOperation("后台更新交易圈状态")
@PostMapping("/admin/group/info/updateStatus")
@Operation(module = ProductType.GROUP, statusKey = "event")
public CommonResult<Void> updateStatus(@Validated @RequestBody @ApiParam(required = true) UpdateGroupStatusQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
groupInfoService.updateStatus(query, backendUserVO);
return CommonResult.success();
}
@ApiOperation("后台查询交易圈列表")
@PostMapping("/admin/group/info/list")
public CommonResult<Pager<GroupVO>> list(@Validated @RequestBody @ApiParam(required = true) ListGroupQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
Pager<GroupVO> page = groupInfoService.list(query, backendUserVO);
return CommonResult.success(page);
}
@ApiOperation("后台查询交易圈详情")
@PostMapping("/admin/group/info/get")
public CommonResult<GroupVO> get(@Validated @RequestBody @ApiParam(required = true) OnlyIdQuery query,
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
GroupVO vo = groupInfoService.get(query, backendUserVO);
return CommonResult.success(vo);
}
}

View File

@ -0,0 +1,42 @@
package com.upchina.group.controller.app;
import com.upchina.common.query.OnlyIdQuery;
import com.upchina.common.result.AppPager;
import com.upchina.common.result.CommonResult;
import com.upchina.common.vo.FrontUserVO;
import com.upchina.group.query.ListGroupAppQuery;
import com.upchina.group.service.GroupInfoService;
import com.upchina.group.vo.GroupVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "交易圈app接口")
@RestController
public class AppGroupController {
@Resource
private GroupInfoService groupInfoService;
@ApiOperation("app查询交易圈详情")
@PostMapping("/app/group/info/get")
public CommonResult<GroupVO> get(@Validated @RequestBody @ApiParam(required = true) OnlyIdQuery query,
@RequestAttribute(value = "frontUser", required = false) FrontUserVO frontUserVO) {
GroupVO vo = groupInfoService.getForApp(query, frontUserVO);
return CommonResult.success(vo);
}
@ApiOperation("app首页查询交易圈列表")
@PostMapping("/app/group/info/list")
public CommonResult<AppPager<GroupVO>> list(@Validated @RequestBody @ApiParam(required = true) ListGroupAppQuery query) {
AppPager<GroupVO> page = groupInfoService.listForApp(query);
return CommonResult.success(page);
}
}

View File

@ -0,0 +1,401 @@
package com.upchina.group.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* <p>
* 交易圈
* </p>
*
* @author easonzhu
* @since 2025-01-29
*/
public class GroupInfo implements Serializable {
/**
* ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 投顾ID
*/
@TableField("advisor_id")
private Integer advisorId;
/**
* 交易圈名称
*/
private String name;
/**
* 简介
*/
private String remark;
/**
* 适用人群
*/
@TableField("applicable_user")
private String applicableUser;
/**
* 详情
*/
private String detail;
/**
* 适用人群
*/
@TableField("welcome_message")
private String welcomeMessage;
/**
* 私聊状态 1:开启 2:关闭
*/
@TableField("private_chat_status")
private Integer privateChatStatus;
/**
* 落地页ID
*/
@TableField("page_id")
private Integer pageId;
/**
* 原价
*/
@TableField("original_price")
private BigDecimal originalPrice;
/**
* 活动价
*/
@TableField("activity_price")
private BigDecimal activityPrice;
/**
* 支付链接URL
*/
@TableField("payment_url")
private String paymentUrl;
/**
* 权限号
*/
@TableField("authority_id")
private String authorityId;
/**
* 成员人数限制 最大/默认1000
*/
@TableField("member_limit")
private Integer memberLimit;
/**
* 封面图片
*/
@TableField("cover_image")
private String coverImage;
/**
* 状态 1待提交 2:待审核; 3:已上架; 4:已驳回, 5:已下架
*/
private Integer status;
/**
* 审核意见
*/
private String reason;
/**
* 风险等级
*/
@TableField("risk_level")
private Integer riskLevel;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField("update_time")
private LocalDateTime updateTime;
/**
* 发布时间
*/
@TableField("audit_time")
private LocalDateTime auditTime;
/**
* 创建人
*/
@TableField("create_user_id")
private Integer createUserId;
/**
* 审核人
*/
@TableField("audit_user_id")
private Integer auditUserId;
/**
* 首页推荐权重 0:不推荐 >0:推荐
*/
@TableField("is_recommend")
private Integer isRecommend;
/**
* 首页是否显示 1:显示 2:不显示
*/
@TableField("is_display")
private Integer isDisplay;
/**
* 首页文案
*/
@TableField("main_page_text")
private String mainPageText;
/**
* 企业微信ID
*/
@TableField("wechat_work_id")
private Integer wechatWorkId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAdvisorId() {
return advisorId;
}
public void setAdvisorId(Integer advisorId) {
this.advisorId = advisorId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getApplicableUser() {
return applicableUser;
}
public void setApplicableUser(String applicableUser) {
this.applicableUser = applicableUser;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getWelcomeMessage() {
return welcomeMessage;
}
public void setWelcomeMessage(String welcomeMessage) {
this.welcomeMessage = welcomeMessage;
}
public Integer getPrivateChatStatus() {
return privateChatStatus;
}
public void setPrivateChatStatus(Integer privateChatStatus) {
this.privateChatStatus = privateChatStatus;
}
public Integer getPageId() {
return pageId;
}
public void setPageId(Integer pageId) {
this.pageId = pageId;
}
public BigDecimal getOriginalPrice() {
return originalPrice;
}
public void setOriginalPrice(BigDecimal originalPrice) {
this.originalPrice = originalPrice;
}
public BigDecimal getActivityPrice() {
return activityPrice;
}
public void setActivityPrice(BigDecimal activityPrice) {
this.activityPrice = activityPrice;
}
public String getPaymentUrl() {
return paymentUrl;
}
public void setPaymentUrl(String paymentUrl) {
this.paymentUrl = paymentUrl;
}
public String getAuthorityId() {
return authorityId;
}
public void setAuthorityId(String authorityId) {
this.authorityId = authorityId;
}
public Integer getMemberLimit() {
return memberLimit;
}
public void setMemberLimit(Integer memberLimit) {
this.memberLimit = memberLimit;
}
public String getCoverImage() {
return coverImage;
}
public void setCoverImage(String coverImage) {
this.coverImage = coverImage;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public Integer getRiskLevel() {
return riskLevel;
}
public void setRiskLevel(Integer riskLevel) {
this.riskLevel = riskLevel;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
public LocalDateTime getAuditTime() {
return auditTime;
}
public void setAuditTime(LocalDateTime auditTime) {
this.auditTime = auditTime;
}
public Integer getCreateUserId() {
return createUserId;
}
public void setCreateUserId(Integer createUserId) {
this.createUserId = createUserId;
}
public Integer getAuditUserId() {
return auditUserId;
}
public void setAuditUserId(Integer auditUserId) {
this.auditUserId = auditUserId;
}
public Integer getIsRecommend() {
return isRecommend;
}
public void setIsRecommend(Integer isRecommend) {
this.isRecommend = isRecommend;
}
public Integer getIsDisplay() {
return isDisplay;
}
public void setIsDisplay(Integer isDisplay) {
this.isDisplay = isDisplay;
}
public String getMainPageText() {
return mainPageText;
}
public void setMainPageText(String mainPageText) {
this.mainPageText = mainPageText;
}
public Integer getWechatWorkId() {
return wechatWorkId;
}
public void setWechatWorkId(Integer wechatWorkId) {
this.wechatWorkId = wechatWorkId;
}
@Override
public String toString() {
return "GroupInfo{" +
"id=" + id +
", advisorId=" + advisorId +
", name=" + name +
", remark=" + remark +
", applicableUser=" + applicableUser +
", detail=" + detail +
", welcomeMessage=" + welcomeMessage +
", privateChatStatus=" + privateChatStatus +
", pageId=" + pageId +
", originalPrice=" + originalPrice +
", activityPrice=" + activityPrice +
", paymentUrl=" + paymentUrl +
", authorityId=" + authorityId +
", memberLimit=" + memberLimit +
", coverImage=" + coverImage +
", status=" + status +
", reason=" + reason +
", riskLevel=" + riskLevel +
", createTime=" + createTime +
", updateTime=" + updateTime +
", auditTime=" + auditTime +
", createUserId=" + createUserId +
", auditUserId=" + auditUserId +
", isRecommend=" + isRecommend +
", isDisplay=" + isDisplay +
", mainPageText=" + mainPageText +
", wechatWorkId=" + wechatWorkId +
"}";
}
}

View File

@ -0,0 +1,65 @@
package com.upchina.group.entity;
import com.google.common.collect.ComparisonChain;
import java.io.Serializable;
import java.time.LocalDateTime;
public class GroupSortEntity implements Serializable, Comparable<GroupSortEntity> {
private Integer id;
private Integer weight;
private LocalDateTime publishTime;
public GroupSortEntity() {
}
public GroupSortEntity(Integer id, Integer weight, LocalDateTime publishTime) {
this.id = id;
this.weight = weight;
this.publishTime = publishTime;
}
public GroupSortEntity(GroupInfo group) {
this.id = group.getId();
this.weight = group.getIsRecommend();
this.publishTime = group.getAuditTime();
}
@Override
public int compareTo(GroupSortEntity o) {
// 倒序 -
return -ComparisonChain.start()
.compare(this.weight == null ? (Integer) 0 : this.weight, o.weight == null ? (Integer) 0 : o.weight)
.compare(this.publishTime, o.publishTime)
.compare(this.id, o.id).result();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public LocalDateTime getPublishTime() {
return publishTime;
}
public void setPublishTime(LocalDateTime publishTime) {
this.publishTime = publishTime;
}
}

View File

@ -0,0 +1,16 @@
package com.upchina.group.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.upchina.group.entity.GroupInfo;
/**
* <p>
* 交易圈 Mapper 接口
* </p>
*
* @author easonzhu
* @since 2025-01-29
*/
public interface GroupInfoMapper extends BaseMapper<GroupInfo> {
}

View File

@ -0,0 +1,65 @@
package com.upchina.group.query;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
public class ListGroupAppQuery {
@ApiModelProperty("投顾ID")
@NotNull(message = "投顾ID不能为空")
private Integer id;
@ApiModelProperty("最后一条记录ID")
private Integer lastId;
@ApiModelProperty("最后一条记录发布时间")
private LocalDateTime lastPublishTime;
@ApiModelProperty("最后一条记录权重")
private Integer lastWeight;
@ApiModelProperty("每页大小")
private Integer size = 10;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getLastId() {
return lastId;
}
public void setLastId(Integer lastId) {
this.lastId = lastId;
}
public LocalDateTime getLastPublishTime() {
return lastPublishTime;
}
public void setLastPublishTime(LocalDateTime lastPublishTime) {
this.lastPublishTime = lastPublishTime;
}
public Integer getLastWeight() {
return lastWeight;
}
public void setLastWeight(Integer lastWeight) {
this.lastWeight = lastWeight;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
}

View File

@ -0,0 +1,62 @@
package com.upchina.group.query;
import com.upchina.common.query.PageQuery;
import io.swagger.annotations.ApiModelProperty;
public class ListGroupQuery extends PageQuery {
@ApiModelProperty("交易圈名称")
private String name;
@ApiModelProperty("状态")
private Integer status;
@ApiModelProperty("用户类型")
private Integer userType;
@ApiModelProperty("投顾ID")
private Integer advisorId;
@ApiModelProperty("是否显示")
private Integer isDisplay;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getUserType() {
return userType;
}
public void setUserType(Integer userType) {
this.userType = userType;
}
public Integer getAdvisorId() {
return advisorId;
}
public void setAdvisorId(Integer advisorId) {
this.advisorId = advisorId;
}
public Integer getIsDisplay() {
return isDisplay;
}
public void setIsDisplay(Integer isDisplay) {
this.isDisplay = isDisplay;
}
}

View File

@ -0,0 +1,223 @@
package com.upchina.group.query;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.group.constant.GroupInfoStatus;
import com.upchina.group.entity.GroupInfo;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
public class SaveGroupQuery {
@ApiModelProperty("投顾ID")
@NotNull
private Integer advisorId;
@ApiModelProperty("交易圈名称")
@NotBlank
private String name;
@ApiModelProperty("简介")
@NotBlank
private String remark;
@ApiModelProperty("适用人群")
@NotBlank
private String applicableUser;
@ApiModelProperty("详情")
private String detail;
@ApiModelProperty("欢迎语")
private String welcomeMessage;
@ApiModelProperty("私聊状态 1:开启 2:关闭")
@NotNull
private Integer privateChatStatus;
@ApiModelProperty("落地页ID")
private Integer pageId;
@ApiModelProperty("原价")
@NotNull(message = "原价不能为空")
private BigDecimal originalPrice;
@ApiModelProperty("活动价")
@NotNull(message = "活动价不能为空")
private BigDecimal activityPrice;
@ApiModelProperty("支付链接")
private String paymentUrl;
@ApiModelProperty("权限号")
private String authorityId;
@ApiModelProperty("成员人数限制")
private Integer memberLimit;
@ApiModelProperty("封面图片")
@NotBlank
private String coverImage;
@ApiModelProperty("风险等级")
private Integer riskLevel;
@ApiModelProperty("企业微信ID")
private Integer wechatWorkId;
public GroupInfo toPO(BackendUserVO backendUserVO, Integer advisorId) {
GroupInfo groupInfo = new GroupInfo();
groupInfo.setAdvisorId(advisorId);
groupInfo.setName(name);
groupInfo.setRemark(remark);
groupInfo.setApplicableUser(applicableUser);
groupInfo.setDetail(detail);
groupInfo.setWelcomeMessage(welcomeMessage);
groupInfo.setPrivateChatStatus(privateChatStatus);
groupInfo.setPageId(pageId);
groupInfo.setOriginalPrice(originalPrice);
groupInfo.setActivityPrice(activityPrice);
groupInfo.setPaymentUrl(paymentUrl);
groupInfo.setAuthorityId(authorityId);
groupInfo.setMemberLimit(memberLimit);
groupInfo.setCoverImage(coverImage);
groupInfo.setStatus(GroupInfoStatus.TO_COMMIT.value);
groupInfo.setRiskLevel(riskLevel);
groupInfo.setCreateTime(LocalDateTime.now());
groupInfo.setUpdateTime(LocalDateTime.now());
groupInfo.setCreateUserId(backendUserVO.getUserId());
groupInfo.setWechatWorkId(wechatWorkId);
return groupInfo;
}
public Integer getAdvisorId() {
return advisorId;
}
public void setAdvisorId(Integer advisorId) {
this.advisorId = advisorId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getApplicableUser() {
return applicableUser;
}
public void setApplicableUser(String applicableUser) {
this.applicableUser = applicableUser;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getWelcomeMessage() {
return welcomeMessage;
}
public void setWelcomeMessage(String welcomeMessage) {
this.welcomeMessage = welcomeMessage;
}
public Integer getPrivateChatStatus() {
return privateChatStatus;
}
public void setPrivateChatStatus(Integer privateChatStatus) {
this.privateChatStatus = privateChatStatus;
}
public Integer getPageId() {
return pageId;
}
public void setPageId(Integer pageId) {
this.pageId = pageId;
}
public BigDecimal getOriginalPrice() {
return originalPrice;
}
public void setOriginalPrice(BigDecimal originalPrice) {
this.originalPrice = originalPrice;
}
public BigDecimal getActivityPrice() {
return activityPrice;
}
public void setActivityPrice(BigDecimal activityPrice) {
this.activityPrice = activityPrice;
}
public String getPaymentUrl() {
return paymentUrl;
}
public void setPaymentUrl(String paymentUrl) {
this.paymentUrl = paymentUrl;
}
public String getAuthorityId() {
return authorityId;
}
public void setAuthorityId(String authorityId) {
this.authorityId = authorityId;
}
public Integer getMemberLimit() {
return memberLimit;
}
public void setMemberLimit(Integer memberLimit) {
this.memberLimit = memberLimit;
}
public String getCoverImage() {
return coverImage;
}
public void setCoverImage(String coverImage) {
this.coverImage = coverImage;
}
public Integer getRiskLevel() {
return riskLevel;
}
public void setRiskLevel(Integer riskLevel) {
this.riskLevel = riskLevel;
}
public Integer getWechatWorkId() {
return wechatWorkId;
}
public void setWechatWorkId(Integer wechatWorkId) {
this.wechatWorkId = wechatWorkId;
}
}

View File

@ -0,0 +1,31 @@
package com.upchina.group.query;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.group.entity.GroupInfo;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
public class UpdateGroupQuery extends SaveGroupQuery {
@ApiModelProperty("ID")
@NotNull(message = "ID不能为空")
private Integer id;
@Override
public GroupInfo toPO(BackendUserVO backendUserVO, Integer advisorId) {
GroupInfo groupInfo = super.toPO(backendUserVO, advisorId);
groupInfo.setId(id);
groupInfo.setUpdateTime(LocalDateTime.now());
return groupInfo;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}

View File

@ -0,0 +1,60 @@
package com.upchina.group.query;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.group.constant.GroupInfoStatus;
import com.upchina.group.entity.GroupInfo;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
public class UpdateGroupStatusQuery {
@ApiModelProperty("ID")
@NotNull(message = "ID不能为空")
private Integer id;
@ApiModelProperty("状态 101:提交 102:撤回 103:通过 103:驳回 105:上架 106:下架 107:删除")
@NotNull(message = "状态不能为空")
private Integer event;
@ApiModelProperty("审核意见")
private String reason;
public GroupInfo toPO(GroupInfoStatus targetStatus, BackendUserVO backendUserVO) {
GroupInfo groupInfo = new GroupInfo();
groupInfo.setId(id);
groupInfo.setStatus(targetStatus.value);
groupInfo.setReason(reason);
groupInfo.setUpdateTime(LocalDateTime.now());
if (GroupInfoStatus.AUDITED.equals(targetStatus)) {
groupInfo.setAuditTime(LocalDateTime.now());
groupInfo.setAuditUserId(backendUserVO.getUserId());
}
return groupInfo;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getEvent() {
return event;
}
public void setEvent(Integer event) {
this.event = event;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}

View File

@ -0,0 +1,289 @@
package com.upchina.group.service;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hazelcast.map.IMap;
import com.upchina.advisor.entity.AdvisorBasic;
import com.upchina.advisor.service.AdvisorInfoService;
import com.upchina.common.config.cache.CacheKey;
import com.upchina.common.constant.IsDisplay;
import com.upchina.common.handler.BizException;
import com.upchina.common.query.OnlyIdQuery;
import com.upchina.common.result.AppPager;
import com.upchina.common.result.Pager;
import com.upchina.common.result.ResponseStatus;
import com.upchina.common.service.AppUserService;
import com.upchina.common.service.CacheService;
import com.upchina.common.service.SensitiveWordService;
import com.upchina.common.state.StateMachine;
import com.upchina.common.vo.AuthResultVO;
import com.upchina.common.vo.BackendUserVO;
import com.upchina.common.vo.FrontUserVO;
import com.upchina.common.vo.InsertIdVO;
import com.upchina.course.service.PageService;
import com.upchina.group.constant.GroupInfoStatus;
import com.upchina.group.entity.GroupInfo;
import com.upchina.group.entity.GroupSortEntity;
import com.upchina.group.mapper.GroupInfoMapper;
import com.upchina.group.query.*;
import com.upchina.group.vo.GroupVO;
import com.upchina.rbac.entity.UserDept;
import com.upchina.rbac.service.AuthService;
import com.upchina.rbac.service.UserService;
import com.upchina.video.constant.VideoUserType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class GroupInfoService {
@Resource
private GroupInfoMapper groupInfoMapper;
@Resource
private SensitiveWordService sensitiveWordService;
@Resource
private StateMachine<GroupInfoStatus> groupSM;
@Resource
private AdvisorInfoService advisorInfoService;
@Resource
private UserService userService;
@Resource
private AuthService authService;
@Resource
private PageService pageService;
@Resource
private CacheService cacheService;
@Resource
private AppUserService appUserService;
@Resource
private IMap<String, Object> groupCache;
@Transactional(rollbackFor = Exception.class)
public InsertIdVO save(SaveGroupQuery query, BackendUserVO backendUserVO) {
sensitiveWordService.check(query.getName(), query.getRemark(), query.getDetail());
Integer advisorId = getAdvisorId(query.getAdvisorId(), backendUserVO);
GroupInfo groupInfo = query.toPO(backendUserVO, advisorId);
groupInfoMapper.insert(groupInfo);
return new InsertIdVO(groupInfo.getId());
}
@Transactional(rollbackFor = Exception.class)
public void update(UpdateGroupQuery query, BackendUserVO backendUserVO) {
sensitiveWordService.check(query.getName(), query.getRemark(), query.getDetail());
GroupInfo groupInfoInDB = groupInfoMapper.selectById(query.getId());
if (groupInfoInDB == null) {
throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR);
}
// 状态机扭转,判断是否能够编辑
GroupInfoStatus dbStatus = GroupInfoStatus.fromValue(groupInfoInDB.getStatus());
groupSM.send(dbStatus, GroupInfoStatus.EVENT_UPDATE);
GroupInfo groupInfo = query.toPO(backendUserVO, groupInfoInDB.getAdvisorId());
groupInfoMapper.updateById(groupInfo);
clearCache(query.getId());
}
@Transactional(rollbackFor = Exception.class)
public void updateStatus(UpdateGroupStatusQuery query, BackendUserVO backendUserVO) {
GroupInfo groupInfoInDB = groupInfoMapper.selectById(query.getId());
if (groupInfoInDB == null) {
throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR);
}
// 状态机扭转
GroupInfoStatus dbStatus = GroupInfoStatus.fromValue(groupInfoInDB.getStatus());
GroupInfoStatus targetStatus = groupSM.send(dbStatus, GroupInfoStatus.fromValue(query.getEvent()));
GroupInfo groupInfo = query.toPO(targetStatus, backendUserVO);
groupInfoMapper.updateById(groupInfo);
clearCache(query.getId());
}
public Pager<GroupVO> list(ListGroupQuery query, BackendUserVO backendUserVO) {
String name = query.getName();
Integer status = query.getStatus();
Integer userType = query.getUserType();
Integer advisorId = query.getAdvisorId();
Integer isDisplay = query.getIsDisplay();
Set<Integer> authSet = authService.getAuthByUserType(VideoUserType.format(userType), backendUserVO, true);
if (authSet != null && authSet.isEmpty()) {
return null;
}
LambdaQueryWrapper<GroupInfo> wrapper = Wrappers.<GroupInfo>lambdaQuery()
.in(Objects.nonNull(authSet), GroupInfo::getAdvisorId, authSet)
.eq(advisorId != null && advisorId != 0, GroupInfo::getAdvisorId, advisorId)
.like(StrUtil.isNotEmpty(name), GroupInfo::getName, name)
.eq(status != null && status != 0, GroupInfo::getStatus, status)
.eq(isDisplay != null && isDisplay != 0, GroupInfo::getIsDisplay, isDisplay)
.ne(!VideoUserType.MANAGER_USER.value.equals(userType), GroupInfo::getStatus, GroupInfoStatus.DELETED.value)
.orderByDesc(GroupInfo::getId);
Page<GroupInfo> page = groupInfoMapper.selectPage(query.toPage(), wrapper);
Map<Integer, AdvisorBasic> advisorMap = advisorInfoService.getAdvisorMap();
Map<Integer, String> userNameMap = userService.getUserMap().values().stream()
.collect(Collectors.toMap(UserDept::getUserId, UserDept::getName));
List<GroupVO> list = page.getRecords().stream().map(groupInfo -> new GroupVO(
groupInfo,
advisorMap.get(groupInfo.getAdvisorId()),
userNameMap.get(groupInfo.getCreateUserId()),
userNameMap.get(groupInfo.getAuditUserId()),
pageService.getForApp(groupInfo.getPageId())
)).collect(Collectors.toList());
return new Pager<>(list, page.getTotal());
}
public GroupVO get(OnlyIdQuery query, BackendUserVO backendUserVO) {
Integer id = query.getId();
GroupInfo groupInfo = getEntity(id, backendUserVO);
if (groupInfo == null) {
return null;
}
Map<Integer, AdvisorBasic> advisorMap = advisorInfoService.getAdvisorMap();
Map<Integer, String> userNameMap = userService.getUserMap().values().stream()
.collect(Collectors.toMap(UserDept::getUserId, UserDept::getName));
return new GroupVO(
groupInfo,
advisorMap.get(groupInfo.getAdvisorId()),
userNameMap.get(groupInfo.getCreateUserId()),
userNameMap.get(groupInfo.getAuditUserId()),
groupInfo.getPageId() == null ? null : pageService.get(new OnlyIdQuery(groupInfo.getPageId()), null)
);
}
/**
* APP端查询交易圈详情
*/
public GroupVO getForApp(OnlyIdQuery query, FrontUserVO frontUserVO) {
GroupVO vo = cacheService.get(groupCache, CacheKey.GroupKey.GROUP_INFO + query.getId(), () -> get(query, null));
if (vo == null) {
return null;
}
// 防止落地页修改后未更新缓存
if (vo.getPage() != null) {
vo.setPage(pageService.getForApp(vo.getPage().getId()));
}
if (frontUserVO != null) {
AuthResultVO authResultVo = appUserService.checkAuth(vo.getAuthorityId(), frontUserVO);
vo.setAuthResultVo(authResultVo);
}
return vo;
}
/**
* APP端查询交易圈列表
*/
public AppPager<GroupVO> listForApp(ListGroupAppQuery query) {
Integer id = query.getId();
Integer lastId = query.getLastId();
LocalDateTime lastPublishTime = query.getLastPublishTime();
Integer lastWeight = query.getLastWeight();
Integer size = query.getSize();
NavigableSet<GroupSortEntity> sortedSet = cacheService.get(groupCache, CacheKey.GroupKey.MAIN_GROUP_LIST + id, () -> {
LambdaQueryWrapper<GroupInfo> wrapper = Wrappers.<GroupInfo>lambdaQuery()
.eq(GroupInfo::getAdvisorId, id)
.eq(GroupInfo::getStatus, GroupInfoStatus.AUDITED.value)
.eq(GroupInfo::getIsDisplay, IsDisplay.YES.value)
.orderByDesc(GroupInfo::getIsRecommend, GroupInfo::getAuditTime);
List<GroupInfo> list = groupInfoMapper.selectList(wrapper);
NavigableSet<GroupSortEntity> set = new TreeSet<>();
list.stream().map(GroupSortEntity::new).forEach(set::add);
return set;
});
GroupSortEntity lastEntity = lastId == null || lastWeight == null || lastPublishTime == null ? null : new GroupSortEntity(lastId, lastWeight, lastPublishTime);
if (lastEntity != null) {
sortedSet = sortedSet.tailSet(lastEntity, false);
}
List<GroupVO> voList = new ArrayList<>(size);
Iterator<GroupSortEntity> iterator = sortedSet.iterator();
while (iterator.hasNext() && voList.size() < size) {
GroupSortEntity entity = iterator.next();
GroupVO vo = getForApp(new OnlyIdQuery(entity.getId()), null);
if (vo != null) {
voList.add(vo);
}
}
return new AppPager<>(voList, iterator.hasNext());
}
private GroupInfo getEntity(Integer id, BackendUserVO backendUserVO) {
GroupInfo groupInfo = groupInfoMapper.selectById(id);
if (groupInfo == null) {
return null;
}
checkAdvisorId(groupInfo.getAdvisorId(), backendUserVO);
return groupInfo;
}
/**
* 检查投顾ID
*
* @param advisorId 投顾ID
* @param backendUserVO 后台用户
*/
private void checkAdvisorId(Integer advisorId, BackendUserVO backendUserVO) {
if (advisorId == null || backendUserVO == null) {
return;
}
// 数据权限检查
if (backendUserVO.getAdvisorId() != null) {
if (!backendUserVO.getAdvisorId().equals(advisorId)) {
throw new BizException(ResponseStatus.DATA_PERMISSION_ERROR);
}
} else {
Set<Integer> authSet = authService.getAuthByUserType(VideoUserType.MANAGER_USER, backendUserVO, true);
if (authSet != null && !authSet.contains(advisorId)) {
throw new BizException(ResponseStatus.DATA_PERMISSION_ERROR);
}
}
}
/**
* 获取投顾ID
*
* @param advisorId 投顾ID
* @param backendUserVO 后台用户
* @return 投顾ID
*/
private Integer getAdvisorId(Integer advisorId, BackendUserVO backendUserVO) {
if (backendUserVO.getAdvisorId() != null) {
// 投顾老师只能用自己创建课程
advisorId = backendUserVO.getAdvisorId();
} else {
// 其他角色必须指定投顾ID
if (advisorId == null) {
throw new BizException(ResponseStatus.PARM_ERROR, "投顾ID不能为空");
}
// 其他角色指定的投顾ID必须符合数据权限
Set<Integer> authSet = authService.getAuthByUserType(VideoUserType.MANAGER_USER, backendUserVO, true);
if (authSet != null && !authSet.contains(advisorId)) {
throw new BizException(ResponseStatus.DATA_PERMISSION_ERROR, "投顾不可选用");
}
}
return advisorId;
}
private void clearCache(Integer id) {
groupCache.delete(CacheKey.GroupKey.GROUP_INFO + id);
}
}

View File

@ -0,0 +1,137 @@
package com.upchina.group.vo;
import com.upchina.advisor.entity.AdvisorBasic;
import com.upchina.common.vo.AuthResultVO;
import com.upchina.course.vo.PageVO;
import com.upchina.group.entity.GroupInfo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@ApiModel("交易圈详情")
public class GroupVO {
@ApiModelProperty("ID")
private Integer id;
@ApiModelProperty("投顾ID")
private Integer advisorId;
@ApiModelProperty("投顾信息")
private AdvisorBasic advisor;
@ApiModelProperty("交易圈名称")
private String name;
@ApiModelProperty("简介")
private String remark;
@ApiModelProperty("适用人群")
private String applicableUser;
@ApiModelProperty("详情")
private String detail;
@ApiModelProperty("欢迎语")
private String welcomeMessage;
@ApiModelProperty("私聊状态")
private Integer privateChatStatus;
@ApiModelProperty("落地页")
private PageVO page;
@ApiModelProperty("原价")
private BigDecimal originalPrice;
@ApiModelProperty("活动价")
private BigDecimal activityPrice;
@ApiModelProperty("支付链接")
private String paymentUrl;
@ApiModelProperty("权限号")
private String authorityId;
@ApiModelProperty("成员人数限制")
private Integer memberLimit;
@ApiModelProperty("封面图片")
private String coverImage;
@ApiModelProperty("状态")
private Integer status;
@ApiModelProperty("审核意见")
private String reason;
@ApiModelProperty("风险等级")
private Integer riskLevel;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("发布时间")
private LocalDateTime auditTime;
@ApiModelProperty("创建人")
private String createUserName;
@ApiModelProperty("审核人")
private String auditUserName;
@ApiModelProperty("首页推荐权重")
private Integer isRecommend;
@ApiModelProperty("首页是否显示")
private Integer isDisplay;
@ApiModelProperty("首页文案")
private String mainPageText;
@ApiModelProperty("企业微信ID")
private Integer wechatWorkId;
@ApiModelProperty("权限结果")
private AuthResultVO authResultVo;
public GroupVO(GroupInfo groupInfo, AdvisorBasic advisor, String createUserName, String auditUserName, PageVO page) {
this.id = groupInfo.getId();
this.advisorId = groupInfo.getAdvisorId();
this.advisor = advisor;
this.name = groupInfo.getName();
this.remark = groupInfo.getRemark();
this.applicableUser = groupInfo.getApplicableUser();
this.detail = groupInfo.getDetail();
this.welcomeMessage = groupInfo.getWelcomeMessage();
this.privateChatStatus = groupInfo.getPrivateChatStatus();
this.page = page;
this.originalPrice = groupInfo.getOriginalPrice();
this.activityPrice = groupInfo.getActivityPrice();
this.paymentUrl = groupInfo.getPaymentUrl();
this.authorityId = groupInfo.getAuthorityId();
this.memberLimit = groupInfo.getMemberLimit();
this.coverImage = groupInfo.getCoverImage();
this.status = groupInfo.getStatus();
this.reason = groupInfo.getReason();
this.riskLevel = groupInfo.getRiskLevel();
this.createTime = groupInfo.getCreateTime();
this.updateTime = groupInfo.getUpdateTime();
this.auditTime = groupInfo.getAuditTime();
this.createUserName = createUserName;
this.auditUserName = auditUserName;
this.isRecommend = groupInfo.getIsRecommend();
this.isDisplay = groupInfo.getIsDisplay();
this.mainPageText = groupInfo.getMainPageText();
this.wechatWorkId = groupInfo.getWechatWorkId();
}
}