Pārlūkot izejas kodu

Merge branch 'nf_midjourney_alpha' into dev

zwhui 2 gadi atpakaļ
vecāks
revīzija
d1c91fa5fe

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/MidjourneySessionMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.MidjourneySession;
+
+/**
+ * @author zwhui
+ * @date 2024/8/14 17:08
+ */
+public interface MidjourneySessionMapper extends BaseMapper<MidjourneySession> {
+}

+ 80 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneySession.java

@@ -0,0 +1,80 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+/**
+ * @author zwhui
+ * @date 2024/8/14 17:07
+ */
+@Data
+@TableName("midjourney_session")
+@SearchBean(tables = "midjourney_session")
+public class MidjourneySession extends BaseEntity {
+
+    /**
+     * 邮箱
+     */
+    private String email;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 状态 1有效 1无效
+     */
+    private Integer status;
+
+    /**
+     * 是否为plus会员
+     */
+    @TableField("isPlus")
+    private Integer isPlus;
+
+    /**
+     * accountId
+     */
+    @TableField("accountId")
+    private Long accountId;
+
+    @TableField("isCar")
+    private Boolean isCar;
+
+    /**
+     * 车id
+     */
+    @TableField("carID")
+    private String carId;
+
+    /**
+     * 车名称
+     */
+    private String carName;
+
+    /**
+     * 官方session
+     */
+    @TableField("officialSession")
+    private String officialSession;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 排序
+     */
+    private Integer sort;
+
+    /**
+     * 快速时长
+     */
+    private Long fastTime;
+
+
+}

+ 7 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjouneyCarInfoView.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.views;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.ejlchina.searcher.bean.DbField;
 import com.ejlchina.searcher.bean.SearchBean;
 import lombok.Data;
@@ -46,6 +47,12 @@ public class MidjouneyCarInfoView {
     @DbField("mj.fastTime")
     private Long fastTime;
 
+    /**
+     * 任务数
+     */
+    @TableField(exist = false)
+    private Long taskNum;
+
     /**
      * 得分
      */

+ 80 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyCarSessionView.java

@@ -0,0 +1,80 @@
+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
+ * 文件名: ChatgptCarSessionView
+ * 创建者: JavaZou
+ * 创建时间:2024/4/12 10:28
+ */
+@Getter
+@Setter
+@SearchBean(tables = "midjourney_session cs")
+public class MidjourneyCarSessionView {
+	@DbField("cs.id")
+	private Long id;
+
+	/**
+	 * 账号
+	 */
+	@DbField("cs.email")
+	private String email;
+
+	@DbField("cs.password")
+	private String password;
+
+	@DbField("cs.carID")
+	private String carId;
+
+
+	/**
+	 * 状态 1有效 1无效
+	 */
+	@DbField("cs.status")
+	private Integer status;
+
+	/**
+	 * 是否为plus会员
+	 */
+	@DbField("isPlus")
+	private Integer isPlus;
+
+	/**
+	 * 车名称
+	 */
+	@DbField("cs.car_name")
+	private String carName;
+
+	/**
+	 * 官方session
+	 */
+	@DbField("cs.officialSession")
+	private String officialSession;
+
+	/**
+	 * 分数
+	 */
+	@DbField("cs.score")
+	private Double score;
+
+	/**
+	 * 备注
+	 */
+	@DbField("cs.remark")
+	private String remark;
+
+	/**
+	 * 快速时长
+	 */
+	@DbField("cs.fastTime")
+	private Long fastTime;
+
+	@DbField("cs.created_time")
+	private Date createdTime;
+}

+ 52 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyUserConversationRecordHistoryView.java

@@ -0,0 +1,52 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2024/4/10 11:37
+ */
+@Data
+@SearchBean(tables = "(SELECT MAX(id) id from midjourney_user_conversation_record as r\n" +
+        "GROUP BY r.car_id) t left join midjourney_user_conversation_record as r on t.id = r.id"
+        ,orderBy = "r.created_time desc"
+)
+public class MidjourneyUserConversationRecordHistoryView {
+
+    @DbField("r.user_token")
+    private String userToken;
+    /**
+     * 提示词
+     */
+    @DbField("r.prompt")
+    private String prompt;
+
+    /**
+     * 对话id
+     */
+    @DbField("r.conversation_id")
+    private String conversationId;
+
+    /**
+     * 对话时间
+     */
+    @DbField("r.created_time")
+    private Date conversationTime;
+
+    /**
+     * 车队id
+     */
+    @DbField("r.car_id")
+    private String carId;
+
+    /**
+     * 车队名称
+     */
+    @DbField("r.car_name")
+    private String carName;
+
+}

+ 28 - 5
netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyUserView.java

@@ -1,9 +1,11 @@
 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.Data;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 /**
@@ -11,7 +13,9 @@ import java.util.Date;
  * @date 2024/4/28 17:43
  */
 @Data
-@SearchBean(tables = "midjourney_user mu left join groups_relation gr on mu.relation_id = gr.id ")
+@SearchBean(tables = "midjourney_user mu left join groups_relation gr on mu.relation_id = gr.id " +
+        " left join groups_trips gt on gt.id = gr.groups_id" +
+        " left join goods_don_sku sku on sku.id = gt.sku_id")
 public class MidjourneyUserView {
 
 
@@ -21,20 +25,39 @@ public class MidjourneyUserView {
     @DbField("mu.relation_id")
     private Long relationId;
 
+    @DbField("mu.is_car")
+    private Boolean isCar;
+
     @DbField("gr.user_id")
     private Long userId;
 
     @DbField("mu.mj_fast_num")
-    private Integer mjFastNum;
+    private Integer mjUserFastNum;
 
     @DbField("mu.mj_relax_num")
+    private Integer mjUserRelaxNum;
+
+    /**
+     * sku mj fast次数
+     */
+    @DbField("sku.mj_fast_num")
+    private Integer mjFastNum;
+
+    /**
+     * sku mj relax次数
+     */
+    @DbField("sku.mj_relax_num")
     private Integer mjRelaxNum;
 
     @DbField("mu.expire_time")
     private Date expireTime;
 
+    @DbField("gt.sku_id")
+    private Long skuId;
 
-
-
-
+    /**
+     * mj 套餐包最低单价
+     */
+    @DbIgnore
+    private BigDecimal mjPackagePrice;
 }

+ 1 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -846,6 +846,7 @@ public class RedisService {
         MIDJOURNEY_ACCOUNT_USED("midjourney:account:used:", "midjourney account used", 60 * 60 * 48L),
         APPLY_MONEY_DAY_LIMIT_KEY("apply_money_day_limit_key:%s:%s:%s", "每日提现次数限制", 60 * 60 * 24L),
         NETFLIX_SET_LIMIT_TIME("netflix_set_limit_time", "奈飞设置限制", 30l),
+        MIDJOURNEY_CAR_TASK("midjourney:car:task","midjourney car 任务数", 48 * 60 * 60L),
         ;
 
         private String name;

+ 75 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/mj/MidJourneyController.java

@@ -1,11 +1,22 @@
 package com.cyksj.web.controller.manage.mj;
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+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.mapper.MidjourneySessionMapper;
+import com.cyksj.model.entity.ChatgptSession;
 import com.cyksj.model.entity.MidjourneyAccount;
+import com.cyksj.model.entity.MidjourneySession;
 import com.cyksj.model.manage.views.AccountView;
+import com.cyksj.model.views.ChatgptCarSessionView;
 import com.cyksj.model.views.MidjourneyAccountView;
+import com.cyksj.model.views.MidjourneyCarSessionView;
+import com.cyksj.redis.RedisService;
 import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -17,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.Optional;
 
 /**
  * @author zwhui
@@ -34,6 +46,10 @@ public class MidJourneyController {
 
     private final MidjourneyAccountService midjourneyAccountService;
 
+    private final MidjourneySessionMapper midjourneySessionMapper;
+
+    private final RedisService redisService;
+
 
     /**
      * 移入MJ账号池
@@ -103,4 +119,63 @@ public class MidJourneyController {
 
 
 
+    /**
+     * 获取镜像车队账号列表
+     */
+    @GetMapping("/get/midjourneyCar")
+    public Result<SearchResult<MidjourneyCarSessionView>> getMirrorCarSession() {
+        SearchResult<MidjourneyCarSessionView> search = beanSearcher.search(MidjourneyCarSessionView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .orderBy(MidjourneyCarSessionView::getId).desc()
+                .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+    /**
+     * 编辑镜像车队账号列表
+     */
+    @PutMapping("/update/midjourneyCar")
+    public Result<String> updateMirrorCarSession(@RequestBody MidjourneySession midjourneySession) {
+        Integer selectCount = midjourneySessionMapper.selectCount(Wrappers.lambdaQuery(MidjourneySession.class)
+                .and(e -> e.eq(MidjourneySession::getEmail, midjourneySession.getEmail())
+                        .or().eq(MidjourneySession::getCarId, midjourneySession.getCarId()))
+                .ne(MidjourneySession::getId, midjourneySession.getId()));
+        if (selectCount > 0) {
+            throw BusinessRuntimeException.getInstance("请检验车队ID或账号是否已存在");
+        }
+        midjourneySessionMapper.updateById(midjourneySession);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 删除镜像车队账号
+     */
+    @DeleteMapping("/delete/midjourneyCar/{id}")
+    public Result<String> deleteMirrorCarSession(@PathVariable Long id) {
+        Optional.ofNullable(midjourneySessionMapper.selectById(id))
+                .ifPresent(e -> {
+                    String carId = e.getCarId();
+                    if (StrUtil.isNotBlank(carId)) {
+                        midjourneySessionMapper.deleteById(e.getId());
+                        String carKey = RedisService.key.MIDJOURNEY_CAR_TASK.getName() + carId;
+                        //从zSet中删除车队
+                        redisService.del(carKey);
+                    }
+                });
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    /**
+     * 新增镜像车队账号
+     */
+    @PostMapping("/post/midjourney/car/session")
+    public Result<String> postMirrorCarSession(@RequestBody MidjourneySession midjourneySession) {
+        Integer selectCount = midjourneySessionMapper.selectCount(Wrappers.lambdaQuery(MidjourneySession.class)
+                .eq(MidjourneySession::getCarId, midjourneySession.getCarId()).or().eq(MidjourneySession::getEmail, midjourneySession.getEmail()));
+        if (selectCount > 0) {
+            throw BusinessRuntimeException.getInstance("请检验车队ID或账号是否已存在");
+        }
+        midjourneySessionMapper.insert(midjourneySession);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
 }

+ 76 - 8
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java

@@ -1,21 +1,36 @@
 package com.cyksj.web.controller.mirror;
 
+import cn.hutool.core.collection.CollectionUtil;
+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.mapper.UpgradePackageMapper;
+import com.cyksj.model.entity.ChatgptUser;
 import com.cyksj.model.entity.MidjourneyUser;
-import com.cyksj.model.views.ChatgptCarInfoView;
+import com.cyksj.model.entity.UpgradePackage;
+import com.cyksj.model.views.ChatGptUserConversationRecordHistoryView;
+import com.cyksj.model.views.MidjouneyCarInfoView;
+import com.cyksj.model.views.MidjourneyUserConversationRecordHistoryView;
 import com.cyksj.model.views.MidjourneyUserView;
+import com.cyksj.redis.RedisService;
 import com.cyksj.service.midjourney.MidjourneyService;
+import com.cyksj.service.user.UserBindRelationService;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 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.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Comparator;
+import java.util.List;
 
 /** server/镜像服务/mj绘画
  * @author zwhui
@@ -34,6 +49,12 @@ public class MidjourneyController {
 
     private final BeanSearcher beanSearcher;
 
+    private final UpgradePackageMapper upgradePackageMapper;
+
+    private final UserBindRelationService userBindRelationService;
+
+    private final RedisService redisService;
+
 
     //-------------------------alpha -----------------------
 
@@ -43,31 +64,63 @@ public class MidjourneyController {
      * @param relationId
      * @return
      */
-    @GetMapping("/gpt/cars")
-    public Result<SearchResult<ChatgptCarInfoView>> getCarInfoList(Long relationId, @RequestParam(defaultValue = "true") Boolean isPlus) {
+    @GetMapping("/mj/cars")
+    public Result<SearchResult<MidjouneyCarInfoView>> getCarInfoList(Long relationId,Boolean taskNumAsc) {
         long userId = StpUserUtil.getLoginIdAsLong();
         //查看用户是否存在车票
         MidjourneyUser midjourneyUser = midjourneyService.getUser(userId, relationId);
         if (midjourneyUser == null) {
             throw BusinessRuntimeException.getInstance("您还未购买车票");
         }
-        SearchResult<ChatgptCarInfoView> carInfoList = beanSearcher.search(ChatgptCarInfoView.class,MapUtils.flatBuilder(request.getParameterMap()).build());
-
+        SearchResult<MidjouneyCarInfoView> carInfoList = beanSearcher.search(MidjouneyCarInfoView.class,MapUtils.flatBuilder(request.getParameterMap()).build());
+        carInfoList.getDataList().forEach(midjouneyCarInfoView -> {
+            midjouneyCarInfoView.setTaskNum(getCarConversationCount(midjouneyCarInfoView.getCarId(), 5L));
+        });
+        if(taskNumAsc){
+            carInfoList.getDataList().sort(Comparator.comparing(MidjouneyCarInfoView::getTaskNum));
+        }else {
+            carInfoList.getDataList().sort(Comparator.comparing(MidjouneyCarInfoView::getTaskNum).reversed());
+        }
         return GatewayResponse.SUCCESS.newBuilder().toResult(carInfoList);
     }
+    /**
+     * 获取指定车队ID在滑动窗口内的提问次数
+     *
+     * @param carId 车队ID
+     * @return 滑动窗口内的请求次数
+     */
+    private Long getCarConversationCount(String carId, Long limitTime) {
+        // 定义键名
+        String key = RedisService.key.MIDJOURNEY_CAR_TASK.getName() + carId;
+        long timestamp = System.currentTimeMillis();
+
+        long windowStartMillis = timestamp - (limitTime * 60 * 1000);
 
+        // 清除时间窗口之前的请求记录(可选,根据需要决定是否在此处清理过期记录)
+        redisService.zRemoveRangeByScore(key, 0, windowStartMillis);
+
+        // 获取当前窗口内的请求次数
+        Long currentSize = redisService.zCard(key);
+        return currentSize != null ? currentSize : 0L;
+    }
     /**
      * 获取mj车票信息
      */
-    @GetMapping("/gpt/userInfo")
+    @GetMapping("/mj/userInfo")
     public Result<MidjourneyUserView> getUserInfo(Long relationId) {
         long userId = StpUserUtil.getLoginIdAsLong();
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
         MidjourneyUserView search = beanSearcher.searchFirst(MidjourneyUserView.class, MapUtils.flatBuilder(request.getParameterMap())
-                .field(MidjourneyUserView::getUserId, userId).field(MidjourneyUserView::getRelationId, relationId)
+                .field(MidjourneyUserView::getUserId, userIdList).op(Operator.InList)
+                .field(MidjourneyUserView::getRelationId, relationId)
                 .build());
         if (search == null) {
             throw BusinessRuntimeException.getInstance("您还未购买车票");
         }
+        List<UpgradePackage> upgradePackages = upgradePackageMapper.selectList(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + search.getSkuId() + "\"')").eq(UpgradePackage::getStatus, Boolean.TRUE).eq(UpgradePackage::getDeleted, Boolean.TRUE));
+        if (CollectionUtil.isNotEmpty(upgradePackages)){
+            upgradePackages.stream().map(e -> e.getPrice().divide(BigDecimal.valueOf(e.getNum()), 2, RoundingMode.HALF_UP)).min(BigDecimal::compareTo).ifPresent(search::setMjPackagePrice);
+        }
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
@@ -75,7 +128,7 @@ public class MidjourneyController {
 
 
     /**
-     * 根据userToken GPT车队跳转登录
+     * 根据userToken mj车队跳转登录
      *
      * @param carId 车队id
      */
@@ -87,4 +140,19 @@ public class MidjourneyController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(url);
     }
 
+    /**
+     * 获取车队历史记录
+     */
+    @GetMapping("/get/car/history")
+    public Result<SearchResult<MidjourneyUserConversationRecordHistoryView>> getCarHistory(Long relationId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        MidjourneyUser midjourneyUser = midjourneyService.getUser(userId, relationId);
+        if (midjourneyUser == null) {
+            throw BusinessRuntimeException.getInstance("车票出现了异常.");
+        }
+        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()).field("userToken", midjourneyUser.getUserToken());
+        SearchResult<MidjourneyUserConversationRecordHistoryView> search = beanSearcher.search(MidjourneyUserConversationRecordHistoryView.class, builder.build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
 }