Browse Source

mj试用车票;绘画广场;绘画记录

zoujiajian 2 years ago
parent
commit
c4a2cdec3a
27 changed files with 714 additions and 7 deletions
  1. 5 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 17 0
      netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyPaintingPlazaMapper.java
  3. 2 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserReceiveTrialTicketRecordMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserTrialTicketJumpPayRecordMapper.java
  6. 39 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyPaintingPlaza.java
  7. 8 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUser.java
  8. 22 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserReceiveTrialTicketRecord.java
  9. 16 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserTrialTicketJumpPayRecord.java
  10. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java
  11. 29 0
      netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyPaintingUserView.java
  12. 30 0
      netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyUserPaintingDayRecordView.java
  13. 36 0
      netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyUserPaintingRecordView.java
  14. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java
  15. 6 0
      netflix-dao/src/main/resources/mapper/MidjourneyPaintingPlazaMapper.xml
  16. 9 0
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  17. 0 3
      netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyAccountService.java
  18. 14 0
      netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyPaintingPlazaService.java
  19. 10 2
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java
  20. 33 0
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyPaintingPlazaServiceImpl.java
  21. 15 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  22. 1 0
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  23. 13 0
      netflix-service/src/main/java/com/cyksj/service/ticket/UserReceiveTrialTicketRecordService.java
  24. 148 0
      netflix-service/src/main/java/com/cyksj/service/ticket/impl/UserReceiveTrialTicketRecordServiceImpl.java
  25. 47 0
      netflix-web/src/main/java/com/cyksj/web/controller/group/MidJourneyGuideController.java
  26. 107 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/mj/MidjourneyPaintingController.java
  27. 70 2
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java

+ 5 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -322,4 +322,9 @@ public interface Constant {
 	 * 大学生快递站 体验车票规格
 	 */
 	Long GPT_MIRROR_SKU_ID = 429l;
+
+	/**
+	 * MJ试用规格id
+	 */
+	Long MIDJOURNEY_TRIAL_SKU_ID = 435L;
 }

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyPaintingPlazaMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.MidjourneyPaintingPlaza;
+import org.apache.ibatis.annotations.Update;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyPaintingPlazaMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:22
+ */
+public interface MidjourneyPaintingPlazaMapper extends BaseMapper<MidjourneyPaintingPlaza> {
+
+	@Update("update midjourney_painting_plaza set copy_num = copy_num + 1 where id = #{id}")
+	void updatePaintingCopyNum(Long id);
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java

@@ -91,4 +91,6 @@ public interface OrderDonMapper extends BaseMapper<OrderDon> {
 	BigDecimal getTotalRefundAmountTime(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
 
 	BigDecimal getCouponUsedMoney(Long couponId);
+
+	Integer checkUserHasPaidMjMirror(@Param("list") List<Long> userIdList);
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UserReceiveTrialTicketRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserReceiveTrialTicketRecord;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserReceiveTrialTicketRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:58
+ */
+public interface UserReceiveTrialTicketRecordMapper extends BaseMapper<UserReceiveTrialTicketRecord> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UserTrialTicketJumpPayRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserTrialTicketJumpPayRecord;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserTrialTicketJumpPayRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 18:27
+ */
+public interface UserTrialTicketJumpPayRecordMapper extends BaseMapper<UserTrialTicketJumpPayRecord> {
+}

+ 39 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyPaintingPlaza.java

@@ -0,0 +1,39 @@
+package com.cyksj.model.entity;
+
+import com.cyksj.model.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyPaintingPlaza
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:19
+ */
+@Getter
+@Setter
+public class MidjourneyPaintingPlaza extends BaseEntity {
+	/**
+	 * 提示词
+	 */
+	private String tips;
+
+	/**
+	 * 图片
+	 */
+	private String img;
+
+	/**
+	 * 备注
+	 */
+	private String remark;
+
+	/**
+	 * 复制次数
+	 */
+	private Integer copyNum;
+
+	private Boolean status;
+
+	private Boolean deleted;
+}

+ 8 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUser.java

@@ -6,6 +6,7 @@ package com.cyksj.model.entity;
  */
 
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
 import lombok.Data;
 
@@ -54,4 +55,11 @@ public class MidjourneyUser extends BaseEntity{
      * 当前模式 1:fast 2:relax
      */
     private Integer mode;
+
+    /**
+     * 车票类型 2试用
+     */
+    @DbIgnore
+    @TableField(exist = false)
+    private Integer aqType;
 }

+ 22 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserReceiveTrialTicketRecord.java

@@ -0,0 +1,22 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserReceiveTrialTicketRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:53
+ */
+@Getter
+@Setter
+public class UserReceiveTrialTicketRecord extends BaseEntity{
+	private Long userId;
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	private Long relationId;
+}

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserTrialTicketJumpPayRecord.java

@@ -0,0 +1,16 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserTrialTicketJumpPayRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 18:26
+ */
+@Getter
+@Setter
+public class UserTrialTicketJumpPayRecord extends BaseEntity {
+	private Long orderId;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java

@@ -175,4 +175,9 @@ public class OrderPayRequest {
      * 源订单id
      */
     private Long originalOrderId;
+
+    /**
+     * 是否是试用车票跳转
+     */
+    private Boolean isTrial;
 }

+ 29 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyPaintingUserView.java

@@ -0,0 +1,29 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyPaintingUserView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/4 13:54
+ */
+@Getter
+@Setter
+@SearchBean(tables = "midjourney_painting_plaza mpp",
+		where = "mpp.status is true and mpp.deleted is true",
+		orderBy = "mpp.update_time desc")
+public class MidjourneyPaintingUserView {
+
+	@DbField("mpp.id")
+	private Long id;
+
+	@DbField("mpp.tips")
+	private String tips;
+
+	@DbField("mpp.img")
+	private String img;
+}

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyUserPaintingDayRecordView.java

@@ -0,0 +1,30 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyUserPaintingDayRecordView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/4 15:42
+ */
+@Getter
+@Setter
+@SearchBean(tables = "midjourney_user_conversation mc"
+		, where = "mc.status = 'SUCCESS' :condition:"
+		, groupBy = "DATE_FORMAT(mc.created_time,'%Y-%m-%d')",
+		orderBy = "DATE_FORMAT(mc.created_time,'%Y-%m-%d') desc")
+public class MidjourneyUserPaintingDayRecordView {
+
+	@DbField("DATE_FORMAT(mc.created_time,'%Y-%m-%d')")
+	private String date;
+
+	@DbIgnore
+	private List<MidjourneyUserPaintingRecordView> list;
+}

+ 36 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyUserPaintingRecordView.java

@@ -0,0 +1,36 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyUserPaintingRecordView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/4 15:40
+ */
+@Getter
+@Setter
+@SearchBean(tables = "midjourney_user_conversation mc",
+		where = "mc.status = 'SUCCESS' :condition: :date:")
+public class MidjourneyUserPaintingRecordView {
+
+	/**
+	 * 提示词
+	 */
+	@DbField("mc.prompt")
+	private String prompt;
+
+	@DbField("mc.image_url")
+	private String imageUrl;
+
+	@DbField("bookmark")
+	private Boolean bookmark;
+
+	@DbField("mc.created_time")
+	private Date createdTime;
+}

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java

@@ -160,6 +160,12 @@ public class RenewalView {
     @DbField("gr.yhs_id")
     private Long yhsId;
 
+    /**
+     * 车票获取类型 默认1购买,2.体验
+     */
+    @DbField("gr.aq_type")
+    private Integer aqType;
+
     @DbIgnore
     private Date payTime;
 

+ 6 - 0
netflix-dao/src/main/resources/mapper/MidjourneyPaintingPlazaMapper.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.cyksj.mapper.MidjourneyPaintingPlazaMapper">
+
+
+</mapper>

+ 9 - 0
netflix-dao/src/main/resources/mapper/OrderDonMapper.xml

@@ -513,4 +513,13 @@
         from (select id from coupon_user where coupon_id = #{couponId}) cu
                  inner join order_don o on o.coupon_user_id = cu.id and o.status not in ('close', 'noPayment')
     </select>
+
+    <select id="checkUserHasPaidMjMirror" resultType="java.lang.Integer">
+        select count(1) from order_don where user_id in
+        <foreach collection="list" item="id" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+        and status not in ('close','noPayment','refund') and sku_id in (select id from goods_don_sku where goods_id = 26 and
+        is_mirror = 1)
+    </select>
 </mapper>

+ 0 - 3
netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyAccountService.java

@@ -1,12 +1,9 @@
 package com.cyksj.service.midjourney;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.MidjourneyAccount;
 import com.cyksj.model.entity.MidjourneyUser;
 
-import java.util.List;
-
 /**
  * @author zwhui
  * @date 2024/4/12 15:54

+ 14 - 0
netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyPaintingPlazaService.java

@@ -0,0 +1,14 @@
+package com.cyksj.service.midjourney;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.MidjourneyPaintingPlaza;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyPaintingPlazaService
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:32
+ */
+public interface MidjourneyPaintingPlazaService extends IService<MidjourneyPaintingPlaza> {
+	void saveOrUpdatePainting(MidjourneyPaintingPlaza midjourneyPaintingPlaza);
+}

+ 10 - 2
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java

@@ -233,8 +233,15 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
         midjourneyUser.setImg(getWxImg(user.getHeadimgurl(), user));
         midjourneyUser.setRelationId(groupsRelation.getId());
         midjourneyUser.setUserToken(UUID.randomUUID().toString());
-        midjourneyUser.setMjFastNum(goodsDonSku.getMjFastNum());
-        midjourneyUser.setMjRelaxNum((goodsDonSku.getMjRelaxNum() == null || goodsDonSku.getMjRelaxNum() == 0) ? null : goodsDonSku.getMjRelaxNum());
+        if (groupsRelation.getAqType() == 2) {
+            //fast模式 5次
+            midjourneyUser.setMjFastNum(5);
+            midjourneyUser.setMjRelaxNum(0);
+        } else {
+            midjourneyUser.setMjFastNum(goodsDonSku.getMjFastNum());
+            midjourneyUser.setMjRelaxNum((goodsDonSku.getMjRelaxNum() == null || goodsDonSku.getMjRelaxNum() == 0) ? null : goodsDonSku.getMjRelaxNum());
+        }
+        midjourneyUser.setAqType(groupsRelation.getAqType());
         midjourneyUserMapper.insert(midjourneyUser);
         redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjFastNum(),RedisService.key.MIDJOURNEY_FAST_LIMIT.getTimeout());
         redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken(), midjourneyUser,RedisService.key.MIDJOURNEY_USER.getTimeout());
@@ -249,6 +256,7 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
         midjourneyUser.setImg(getWxImg(user.getHeadimgurl(), user));
         midjourneyUser.setExpireTime(groupsRelation.getExpiryTime());
         midjourneyUserMapper.updateById(midjourneyUser);
+        midjourneyUser.setAqType(groupsRelation.getAqType());
         redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken(), midjourneyUser,RedisService.key.MIDJOURNEY_USER.getTimeout());
     }
 

+ 33 - 0
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyPaintingPlazaServiceImpl.java

@@ -0,0 +1,33 @@
+package com.cyksj.service.midjourney.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.MidjourneyPaintingPlazaMapper;
+import com.cyksj.model.entity.MidjourneyPaintingPlaza;
+import com.cyksj.service.midjourney.MidjourneyPaintingPlazaService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyPaintingPlazaServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:32
+ */
+@Service
+@RequiredArgsConstructor
+public class MidjourneyPaintingPlazaServiceImpl extends ServiceImpl<MidjourneyPaintingPlazaMapper, MidjourneyPaintingPlaza> implements MidjourneyPaintingPlazaService {
+	@Override
+	public void saveOrUpdatePainting(MidjourneyPaintingPlaza midjourneyPaintingPlaza) {
+		String tips = midjourneyPaintingPlaza.getTips();
+		if (StrUtil.isEmpty(tips)) {
+			throw BusinessRuntimeException.getInstance("请输入对应的关键词");
+		}
+		String img = midjourneyPaintingPlaza.getImg();
+		if (StrUtil.isEmpty(img)) {
+			throw BusinessRuntimeException.getInstance("图片不为空");
+		}
+		this.saveOrUpdate(midjourneyPaintingPlaza);
+	}
+}

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -305,6 +305,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final DistributeExtraRebateService distributeExtraRebateService;
 
+	private final UserTrialTicketJumpPayRecordMapper userTrialTicketJumpPayRecordMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -617,6 +619,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		recordOrderDonLocationRelate(orderDon.getId(), payRequest.getIp());
 		//记录补贴订单关联
 		recordOrderDonSubsidyRelate(orderDon.getId(), subsidyId);
+		//试用车票跳转记录
+		recordOrderTrialTicketJumpPay(payRequest.getIsTrial(),orderDon.getId());
 		return orderDon;
 	}
 
@@ -3506,4 +3510,15 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			}
         return beanSearcher.searchFirst(UpgradeOrderDetailView.class, builder.build());
 	}
+
+	/**
+	 * 试用车票跳转购买正式车票订单记录
+	 */
+	public void recordOrderTrialTicketJumpPay(Boolean isTrial, Long orderId) {
+		if (isTrial != null && isTrial) {
+			UserTrialTicketJumpPayRecord userTrialTicketJumpPayRecord = new UserTrialTicketJumpPayRecord();
+			userTrialTicketJumpPayRecord.setOrderId(orderId);
+			userTrialTicketJumpPayRecordMapper.insert(userTrialTicketJumpPayRecord);
+		}
+	}
 }

+ 1 - 0
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -677,6 +677,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 				.field(RenewalView::getUserId, userIds).op(Operator.InList)
 				.field(RenewalView::getExpiryTime, now).op(Operator.GreaterThan)
 				.field(RenewalView::getStatus, List.of("validity", "overdue", "outside")).op(Operator.InList)
+				.field(RenewalView::getAqType, 1)
 				.orderBy(RenewalView::getExpiryTime).asc()
 				.onlySelect(RenewalView::getMonths, RenewalView::getExpiryTime, RenewalView::getRelationId, RenewalView::getAccount, RenewalView::getGoodsId, RenewalView::getTitle, RenewalView::getLogo, RenewalView::getImg, RenewalView::getGroupId, RenewalView::getSkuId, RenewalView::getSpecVal, RenewalView::getGoodsStatus, RenewalView::getSkuStatus)
 				.build());

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/ticket/UserReceiveTrialTicketRecordService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.ticket;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserReceiveTrialTicketRecordService
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:55
+ */
+public interface UserReceiveTrialTicketRecordService {
+	void sendTicketAndRecord(Long userId, Long trialSkuId);
+
+	Boolean isReceiveTrialTicket(long userId, Long trialSkuId);
+}

+ 148 - 0
netflix-service/src/main/java/com/cyksj/service/ticket/impl/UserReceiveTrialTicketRecordServiceImpl.java

@@ -0,0 +1,148 @@
+package com.cyksj.service.ticket.impl;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.*;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.GroupsRelation;
+import com.cyksj.model.entity.GroupsTrips;
+import com.cyksj.model.entity.UserReceiveTrialTicketRecord;
+import com.cyksj.service.groups.GroupsFuncService;
+import com.cyksj.service.ticket.UserReceiveTrialTicketRecordService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.github.rholder.retry.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserReceiveTrialTicketRecordServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:55
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class UserReceiveTrialTicketRecordServiceImpl implements UserReceiveTrialTicketRecordService {
+	private final UserBindRelationService userBindRelationService;
+
+	private final UserReceiveTrialTicketRecordMapper userReceiveTrialTicketRecordMapper;
+
+	private final GroupsMapper groupsMapper;
+
+	private final GroupsRelationMapper groupsRelationMapper;
+
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
+	private final GroupsFuncService groupsFuncService;
+
+	private final OrderDonMapper orderDonMapper;
+
+	@Override
+	public void sendTicketAndRecord(Long userId, Long trialSkuId) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		GoodsDonSku sku = goodsDonSkuMapper.selectById(trialSkuId);
+		if (sku == null) {
+			throw BusinessRuntimeException.getInstance("系统异常,请联系客服..");
+		}
+		Long goodsId = sku.getGoodsId();
+		//是否购买过mj镜像
+		Integer count = orderDonMapper.checkUserHasPaidMjMirror(userIdList);
+		if (count > 0) {
+			throw BusinessRuntimeException.getInstance("您不符合领取条件");
+		}
+
+		Integer selectCount = userReceiveTrialTicketRecordMapper.selectCount(Wrappers.lambdaQuery(UserReceiveTrialTicketRecord.class)
+				.in(UserReceiveTrialTicketRecord::getUserId, userIdList)
+				.eq(UserReceiveTrialTicketRecord::getSkuId, trialSkuId));
+		if (selectCount > 0) {
+			throw BusinessRuntimeException.getInstance("您已领取该试用车票");
+		}
+
+		try {
+			UserReceiveTrialTicketRecord userReceiveTrialTicketRecord = new UserReceiveTrialTicketRecord();
+			userReceiveTrialTicketRecord.setUserId(userId);
+			userReceiveTrialTicketRecord.setGoodsId(goodsId);
+			userReceiveTrialTicketRecord.setSkuId(trialSkuId);
+
+			userReceiveTrialTicketRecordMapper.insert(userReceiveTrialTicketRecord);
+
+			Long relationId = getTrialTicketByUserIdAndGoodsId(userId, trialSkuId);
+			userReceiveTrialTicketRecord.setRelationId(relationId);
+			userReceiveTrialTicketRecordMapper.updateById(userReceiveTrialTicketRecord);
+
+		} catch (DuplicateKeyException e) {
+			throw BusinessRuntimeException.getInstance("您已领取该试用车票");
+		}
+	}
+
+	@Override
+	public Boolean isReceiveTrialTicket(long userId, Long trialSkuId) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		//是否购买过mj镜像
+		Integer count = orderDonMapper.checkUserHasPaidMjMirror(userIdList);
+		if (count > 0) {
+			return true;
+		}
+		Integer selectCount = userReceiveTrialTicketRecordMapper.selectCount(Wrappers.lambdaQuery(UserReceiveTrialTicketRecord.class)
+				.in(UserReceiveTrialTicketRecord::getUserId, userIdList)
+				.eq(UserReceiveTrialTicketRecord::getSkuId, trialSkuId));
+		return selectCount > 0 ? true : false;
+	}
+
+	public Long getTrialTicketByUserIdAndGoodsId(Long userId, Long trialSkuId) {
+		Retryer<Long> build = RetryerBuilder.<Long>newBuilder()
+				.retryIfException()
+				//运行时异常重试
+				.retryIfRuntimeException()
+				//false重试
+				.retryIfResult(res -> res == null)
+				//1s 间隔
+				.withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
+				//停止策略 : 尝试请求3次
+				.withStopStrategy(StopStrategies.stopAfterAttempt(3)).build();
+		try {
+			return build.call(() -> {
+				//体验规格
+				GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(trialSkuId);
+				GroupsRelation relation = null;
+				if (groups != null) {
+					relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId());
+				}
+				if (relation == null) {
+					//生成空车队
+					GoodsDonSku sku = goodsDonSkuMapper.selectById(trialSkuId);
+					relation = groupsFuncService.createNewGroupsTrips(sku);
+				}
+				DateTime startTime = DateTime.now();
+				DateTime expiryTime = DateUtil.offsetDay(startTime, 1);
+				int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+						.set(GroupsRelation::getUserId, userId)
+						.set(GroupsRelation::getStartTime, startTime)
+						.set(GroupsRelation::getExpiryTime, expiryTime)
+						.set(GroupsRelation::getStatus, GroupsRelation.Status.validity)
+						.set(GroupsRelation::getAqType, 2)
+						.eq(GroupsRelation::getId, relation.getId())
+						.eq(GroupsRelation::getUserId, 0));
+				if (update > 0) {
+					groupsMapper.decrAvailableNum(groups.getId());
+					return relation.getId();
+				}
+				log.error("发送用户:{} GPT镜像车票体验失败,进行重试", userId);
+				return null;
+			});
+		} catch (ExecutionException | RetryException e) {
+			log.error("发送用户GPT镜像体验失败:{}", StringUtil.getErrorText(e));
+			return null;
+		}
+	}
+}

+ 47 - 0
netflix-web/src/main/java/com/cyksj/web/controller/group/MidJourneyGuideController.java

@@ -0,0 +1,47 @@
+package com.cyksj.web.controller.group;
+
+import com.cyksj.common.constant.Constant;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.service.ticket.UserReceiveTrialTicketRecordService;
+import com.cyksj.web.util.StpUserUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidJourneyGuideController
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:46
+ */
+@Slf4j
+@RequestMapping("/applets/mj")
+@RestController
+@RequiredArgsConstructor
+public class MidJourneyGuideController {
+	private final UserReceiveTrialTicketRecordService userReceiveTrialTicketRecordService;
+
+	/**
+	 * 领取mj试用车票
+	 */
+	@PostMapping("/receive/trial")
+	public Result<String> receiveTrialTicket() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		userReceiveTrialTicketRecordService.sendTicketAndRecord(userId, Constant.MIDJOURNEY_TRIAL_SKU_ID);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 是否已领取mj试用车票
+	 */
+	@GetMapping("/hasReceived")
+	public Result<Boolean> isReceiveTrialTicket() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		Boolean flag = userReceiveTrialTicketRecordService.isReceiveTrialTicket(userId, Constant.MIDJOURNEY_TRIAL_SKU_ID);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(flag);
+	}
+}

+ 107 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/mj/MidjourneyPaintingController.java

@@ -0,0 +1,107 @@
+package com.cyksj.web.controller.manage.mj;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.MidjourneyPaintingPlaza;
+import com.cyksj.service.midjourney.MidjourneyPaintingPlazaService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyPaintingController
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:24
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/manage/mj/painting")
+public class MidjourneyPaintingController {
+	private final MidjourneyPaintingPlazaService midjourneyPaintingPlazaService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	/**
+	 * 新增记录
+	 */
+	@PostMapping("/post")
+	public Result<String> savePainting(@RequestBody MidjourneyPaintingPlaza midjourneyPaintingPlaza) {
+		midjourneyPaintingPlazaService.saveOrUpdatePainting(midjourneyPaintingPlaza);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除记录
+	 */
+	@DeleteMapping("/delete/{id}")
+	public Result<String> deleteById(@PathVariable Long id) {
+		MidjourneyPaintingPlaza byId = midjourneyPaintingPlazaService.getById(id);
+		if (byId != null && byId.getDeleted()) {
+			byId.setDeleted(false);
+			midjourneyPaintingPlazaService.updateById(byId);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+
+	/**
+	 * 修改记录
+	 */
+	@PutMapping("/update")
+	public Result<String> updatePainting(@RequestBody MidjourneyPaintingPlaza midjourneyPaintingPlaza) {
+		midjourneyPaintingPlazaService.saveOrUpdatePainting(midjourneyPaintingPlaza);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 列表
+	 */
+	@GetMapping("/get")
+	public Result<SearchResult<MidjourneyPaintingPlaza>> saveOrUpdatePainting() {
+		SearchResult<MidjourneyPaintingPlaza> search = beanSearcher.search(MidjourneyPaintingPlaza.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(MidjourneyPaintingPlaza::getDeleted, 1)
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 上下架
+	 */
+	@PutMapping("/update/status/{id}")
+	public Result<String> updateStatus(@PathVariable Long id) {
+		MidjourneyPaintingPlaza byId = midjourneyPaintingPlazaService.getById(id);
+		if (byId != null) {
+			byId.setStatus(!byId.getStatus());
+			midjourneyPaintingPlazaService.updateById(byId);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 批量上下架
+	 */
+	@PutMapping("/update/status")
+	public Result<String> updateStatus(@RequestParam(value = "ids") List<Long> ids, Boolean status) {
+		if (CollUtil.isEmpty(ids) || status == null) {
+			throw BusinessRuntimeException.getInstance("参数错误");
+		}
+		midjourneyPaintingPlazaService.update(null, Wrappers.lambdaUpdate(MidjourneyPaintingPlaza.class)
+				.set(MidjourneyPaintingPlaza::getStatus, status)
+				.in(MidjourneyPaintingPlaza::getId, ids)
+				.ne(MidjourneyPaintingPlaza::getStatus, status));
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+}

+ 70 - 2
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java

@@ -1,14 +1,22 @@
 package com.cyksj.web.controller.mirror;
 
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
-import com.cyksj.model.dto.*;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.MidjourneyPaintingPlazaMapper;
 import com.cyksj.mapper.MidjourneyUserMapper;
+import com.cyksj.model.dto.*;
+import com.cyksj.model.entity.GroupsRelation;
+import com.cyksj.model.entity.MidjourneyPaintingPlaza;
 import com.cyksj.model.entity.MidjourneyUser;
 import com.cyksj.model.entity.MidjourneyUserConversation;
+import com.cyksj.model.views.MidjourneyPaintingUserView;
+import com.cyksj.model.views.MidjourneyUserPaintingDayRecordView;
+import com.cyksj.model.views.MidjourneyUserPaintingRecordView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.midjourney.MidjourneyService;
 import com.ejlchina.searcher.BeanSearcher;
@@ -23,7 +31,7 @@ import javax.servlet.http.HttpServletRequest;
 import java.util.Date;
 import java.util.List;
 
-/**
+/** server/镜像服务/mj绘画
  * @author zwhui
  * @date 2024/4/23 10:31
  */
@@ -43,6 +51,9 @@ public class MidjourneyController {
     
     private final RedisService redisService;
 
+    private final GroupsRelationMapper groupsRelationMapper;
+
+    private final MidjourneyPaintingPlazaMapper midjourneyPaintingPlazaMapper;
     public MidjourneyUser getUser(){
         String userToken = request.getHeader("user-token");
         MidjourneyUser midjourneyUser = (MidjourneyUser) redisService.get(RedisService.key.MIDJOURNEY_USER.getName() + userToken);
@@ -52,6 +63,9 @@ public class MidjourneyController {
             if (midjourneyUser == null){
                 throw new BusinessRuntimeException("账号不存在,请重新登录");
             }
+            Long relationId = midjourneyUser.getRelationId();
+            GroupsRelation relation = groupsRelationMapper.selectById(relationId);
+            midjourneyUser.setAqType(relation.getAqType());
             redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + userToken, midjourneyUser, RedisService.key.MIDJOURNEY_USER.getTimeout());
             Object fastNum = redisService.get(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId());
             if (fastNum == null){
@@ -338,4 +352,58 @@ public class MidjourneyController {
         redisService.del(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken());
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
+
+
+    /**
+     * mj绘画广场
+     */
+    @GetMapping("/get/painting")
+    public Result<SearchResult<MidjourneyPaintingUserView>> getPaintingCollect() {
+        SearchResult<MidjourneyPaintingUserView> search = beanSearcher.search(MidjourneyPaintingUserView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+    /**
+     * 复制mj绘画广场 提示词
+     */
+    @PostMapping("/painting/copy/{id}")
+    public Result<String> resetPaintingCopyNum(@PathVariable Long id) {
+        MidjourneyPaintingPlaza midjourneyPaintingPlaza = midjourneyPaintingPlazaMapper.selectById(id);
+        if (midjourneyPaintingPlaza != null) {
+            midjourneyPaintingPlazaMapper.updatePaintingCopyNum(id);
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 用户绘画记录
+     */
+    @GetMapping("/get/painting/record")
+    public Result<SearchResult<MidjourneyUserPaintingDayRecordView>> getPaintingRecord(String prompt, Boolean bookmark) {
+        MidjourneyUser user = getUser();
+        String condition = String.format(" and mc.user_id = %s", user.getId());
+        if (StrUtil.isNotBlank(prompt)) {
+            condition += String.format(" and mc.prompt like '%%%s%%'", prompt);
+        }
+        if (bookmark != null) {
+            condition += String.format(" and mc.bookmark is %s", bookmark);
+        }
+        SearchResult<MidjourneyUserPaintingDayRecordView> search = beanSearcher.search(MidjourneyUserPaintingDayRecordView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .put("condition", condition)
+                .orderBy(MidjourneyUserPaintingRecordView::getCreatedTime).desc()
+                .build());
+        String dateSql;
+        for (MidjourneyUserPaintingDayRecordView e : search.getDataList()) {
+            String date = e.getDate();
+            dateSql = String.format(" and DATE_FORMAT(mc.created_time,'%%Y-%%m-%%d') = '%s'", date);
+            List<MidjourneyUserPaintingRecordView> list = beanSearcher.searchAll(MidjourneyUserPaintingRecordView.class, MapUtils.builder()
+                    .put("condition", condition)
+                    .put("date", dateSql)
+                    .orderBy(MidjourneyUserPaintingRecordView::getCreatedTime).desc()
+                    .build());
+            e.setList(list);
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
 }