Explorar el Código

fix 新增wss

chenbiao hace 2 años
padre
commit
d31b5e5fca
Se han modificado 17 ficheros con 665 adiciones y 226 borrados
  1. 17 0
      midjourney/src/main/java/com/yhlxj/dao/mapper/MidjourneyPaintingPlazaMapper.java
  2. 14 0
      midjourney/src/main/java/com/yhlxj/dao/mapper/midjourney/MidjourneyUserMapper.java
  3. 5 0
      midjourney/src/main/java/com/yhlxj/dao/model/entity/GroupsRelation.java
  4. 39 0
      midjourney/src/main/java/com/yhlxj/dao/model/entity/MidjourneyPaintingPlaza.java
  5. 9 0
      midjourney/src/main/java/com/yhlxj/dao/model/entity/MidjourneyUser.java
  6. 59 0
      midjourney/src/main/java/com/yhlxj/dao/model/enums/WsMessageTypeEnum.java
  7. 2 0
      midjourney/src/main/java/com/yhlxj/dao/model/response/SubmitResult.java
  8. 29 0
      midjourney/src/main/java/com/yhlxj/dao/model/views/MidjourneyPaintingUserView.java
  9. 30 0
      midjourney/src/main/java/com/yhlxj/dao/model/views/MidjourneyUserPaintingDayRecordView.java
  10. 36 0
      midjourney/src/main/java/com/yhlxj/dao/model/views/MidjourneyUserPaintingRecordView.java
  11. 1 1
      midjourney/src/main/java/com/yhlxj/service/midjourney/MidjourneyService.java
  12. 92 44
      midjourney/src/main/java/com/yhlxj/service/midjourney/impl/MidjourneyServiceImpl.java
  13. 177 87
      midjourney/src/main/java/com/yhlxj/web/mirror/MidjourneyController.java
  14. 0 93
      midjourney/src/main/java/com/yhlxj/web/mirror/MirrorController.java
  15. 13 0
      midjourney/src/main/java/com/yhlxj/web/wss/WssSendable.java
  16. 141 0
      midjourney/src/main/java/com/yhlxj/web/wss/WssSession.java
  17. 1 1
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java

+ 17 - 0
midjourney/src/main/java/com/yhlxj/dao/mapper/MidjourneyPaintingPlazaMapper.java

@@ -0,0 +1,17 @@
+package com.yhlxj.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yhlxj.dao.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);
+}

+ 14 - 0
midjourney/src/main/java/com/yhlxj/dao/mapper/midjourney/MidjourneyUserMapper.java

@@ -2,10 +2,24 @@ package com.yhlxj.dao.mapper.midjourney;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.yhlxj.dao.model.entity.MidjourneyUser;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
 
 /**
  * @author zwhui
  * @date 2024/4/16 17:46
  */
 public interface MidjourneyUserMapper extends BaseMapper<MidjourneyUser> {
+
+    @Update("update midjourney_user set mj_fast_num = mj_fast_num + #{num} where id = #{id}")
+    int incrFastNum(@Param("id") Long id, @Param("num") Integer num);
+
+    @Update("update midjourney_user set mj_fast_num = mj_fast_num - #{num} where id = #{id} and mj_fast_num = #{mjFastNum} and mj_fast_num > 0")
+    int decFastNum(@Param("id") Long id, @Param("num") Integer num, @Param("mjFastNum") Integer mjFastNum);
+
+    @Update("update midjourney_user set mj_relax_num = mj_relax_num + #{num} where id = #{id}")
+    int incrRelaxNum(@Param("id") Long id, @Param("num") Integer num);
+
+    @Update("update midjourney_user set mj_relax_num = mj_relax_num - #{num} where id = #{id} and mj_relax_num = #{relaxNum} and mj_relax_num > 0")
+    int decRelaxNum(@Param("id") Long id, @Param("num") Integer num, @Param("relaxNum") Integer relaxNum);
 }

+ 5 - 0
midjourney/src/main/java/com/yhlxj/dao/model/entity/GroupsRelation.java

@@ -104,6 +104,11 @@ public class GroupsRelation extends BaseEntity {
     @DbIgnore
     private Integer maxNum;
 
+    /**
+     * 车票获取类型 默认1购买,2.体验
+     */
+    private Integer aqType;
+
 
     @AllArgsConstructor
     @Getter

+ 39 - 0
midjourney/src/main/java/com/yhlxj/dao/model/entity/MidjourneyPaintingPlaza.java

@@ -0,0 +1,39 @@
+package com.yhlxj.dao.model.entity;
+
+import com.yhlxj.dao.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;
+}

+ 9 - 0
midjourney/src/main/java/com/yhlxj/dao/model/entity/MidjourneyUser.java

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

+ 59 - 0
midjourney/src/main/java/com/yhlxj/dao/model/enums/WsMessageTypeEnum.java

@@ -0,0 +1,59 @@
+package com.yhlxj.dao.model.enums;
+
+import lombok.Getter;
+
+import java.util.stream.Stream;
+
+/**
+ * @author chan
+ * @date 2024/6/27 18:43
+ */
+@Getter
+public enum WsMessageTypeEnum {
+
+
+    PING("ping"), PONG("pong"), MESSAGE("message"),
+
+    //客服端反馈子类型
+    CLIENT_Union_ID("task_id"),//开始连接
+    CLIENT_CLOSE("close"),//关闭连接
+    CLIENT_DAILY_RESULT("daily_result"),//完成
+    CLIENT_TUNNELID_CHANGED("tunnelId_changed"),//信道变更,暂未使用
+    CLIENT_RESURGENCE("resurgence"),//客服端复活
+
+    //服务端发送子类型
+    SERVER_HAS_CHALLENGE("has_challenge"),
+    CONNECTION_TIMED_OUT("connection_timed_out"),
+    SERVER_QUESTION("question"),//服务端发送问题
+    SERVER_TUNNELID_CHANGED_DONE("tunnelId_change_done"),//信道切换完成
+    SERVER_GET_ANSWER("getAnswer"),
+    SERVER_ERROR("error"),//错误信息
+    SERVER_FAIL("fail"),//错误信息
+    ;
+
+    public final String type;
+
+    WsMessageTypeEnum(String type) {
+        this.type = type;
+    }
+
+    /**
+     * @author chan 验证枚举
+     * @return boolean
+     **/
+    public static boolean valid(String type) {
+        return Stream.of(WsMessageTypeEnum.values()).anyMatch(val -> val.getType().equals(type));
+    }
+
+    /**
+     *
+     * @author chan
+     * @param type
+     * @return
+     */
+    @SuppressWarnings("rawtypes")
+    public static WsMessageTypeEnum getMessageType(String type){
+        return Stream.of(WsMessageTypeEnum.values())
+                .filter(enums-> enums.getType().equals(type)).findFirst().get();
+    }
+}

+ 2 - 0
midjourney/src/main/java/com/yhlxj/dao/model/response/SubmitResult.java

@@ -22,6 +22,8 @@ public class SubmitResult {
      */
     private String result;
 
+    private Long instanceId;
+
     /**
      * 扩展字段
      */

+ 29 - 0
midjourney/src/main/java/com/yhlxj/dao/model/views/MidjourneyPaintingUserView.java

@@ -0,0 +1,29 @@
+package com.yhlxj.dao.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
midjourney/src/main/java/com/yhlxj/dao/model/views/MidjourneyUserPaintingDayRecordView.java

@@ -0,0 +1,30 @@
+package com.yhlxj.dao.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
midjourney/src/main/java/com/yhlxj/dao/model/views/MidjourneyUserPaintingRecordView.java

@@ -0,0 +1,36 @@
+package com.yhlxj.dao.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;
+}

+ 1 - 1
midjourney/src/main/java/com/yhlxj/service/midjourney/MidjourneyService.java

@@ -25,7 +25,7 @@ public interface MidjourneyService {
 
     List<MidjourneyUserConversation> listConversationByIds(Integer mode, List<Long> ids) throws Exception;
 
-    SubmitResult submitAction(MidjourneyUser user, Long taskId, String customId, Long num, String botType) throws Exception;
+    Object submitAction(MidjourneyUser user, Long taskId, String customId, Long num, String botType) throws Exception;
 
     MidjourneyUserConversation cancelConversation(MidjourneyUser user, Long id);
 

+ 92 - 44
midjourney/src/main/java/com/yhlxj/service/midjourney/impl/MidjourneyServiceImpl.java

@@ -1,6 +1,7 @@
 package com.yhlxj.service.midjourney.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpUtil;
@@ -32,10 +33,11 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import javax.imageio.stream.FileImageOutputStream;
-import java.io.IOException;
+import java.io.*;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 /**
@@ -80,6 +82,9 @@ public class MidjourneyServiceImpl implements MidjourneyService {
             imagineParam.put("base64Array", base64Array);
         }
         SubmitResult result = submit(user.getMode(),"imagine", null,imagineParam);
+        if (user.getMode() == 2) {
+            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
+        }
         return saveConversation(user.getId(), user.getMode(),result,"IMAGINE", StringUtils.EMPTY, botType);
     }
 
@@ -95,6 +100,9 @@ public class MidjourneyServiceImpl implements MidjourneyService {
             conversation.setChannelId(properties.get("discordChannelId") == null ? null : Long.parseLong(properties.get("discordChannelId").toString()))
                     .setInstanceId(properties.get("discordInstanceId") == null ? null : Long.parseLong(properties.get("discordInstanceId").toString()));
         }
+        if (conversation.getInstanceId() == null) {
+            conversation.setInstanceId(result.getInstanceId());
+        }
         conversationMapper.insert(conversation);
         return conversation;
     }
@@ -107,6 +115,9 @@ public class MidjourneyServiceImpl implements MidjourneyService {
                 .put("base64", base64)
                 .build();
         SubmitResult result = submit(user.getMode(),"describe", null, param);
+        if (user.getMode() == 2) {
+            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
+        }
         return saveConversation(user.getId(), user.getMode(),result,"DESCRIBE", StringUtils.EMPTY, botType);
     }
 
@@ -120,6 +131,9 @@ public class MidjourneyServiceImpl implements MidjourneyService {
             param.put("dimensions", dimensions);
         }
         SubmitResult result = submit(user.getMode(),"blend", null, param);
+        if (user.getMode() == 2) {
+            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
+        }
         return saveConversation(user.getId(), user.getMode(),result,"BLEND", StringUtils.EMPTY, botType);
     }
 
@@ -136,54 +150,61 @@ public class MidjourneyServiceImpl implements MidjourneyService {
             param.put("maskBase64", maskBase64);
         }
         SubmitResult result = submit(user.getMode(),"modal", null, param);
+        if (user.getMode() == 2) {
+            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
+        }
         return saveConversation(user.getId(),  user.getMode(),result,"MODAL", StringUtils.EMPTY, StringUtils.EMPTY);
     }
 
     @Override
-    public MidjourneyUserConversation submitShorten(MidjourneyUser user, String prompt, String botType) throws Exception {
+    public MidjourneyUserConversation submitShorten(MidjourneyUser user, String botType, String prompt) throws Exception {
         Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
                 .put("prompt", prompt)
                 .put("state", user.getId())
                 .build();
         SubmitResult result = submit(user.getMode(),"shorten", null, param);
+        if (user.getMode() == 2) {
+            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
+        }
         return saveConversation(user.getId(), user.getMode(), result,"SHORTEN", StringUtils.EMPTY, botType);
     }
 
     /**
      * 恢复次数
      */
-    public Long recoverUserLimit(Long id,Integer mode,Long num){
+    public void recoverUserLimit(Long id,Integer mode,Long num){
         if (mode == 1){
-            num =  redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + id, 1L);
+            redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + id, 1L);
+            midjourneyUserMapper.incrFastNum(id, 1);
         }
         if (mode == 2){
-            if (num != null) {
-                num = redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + id, 1L);
+            if (num != null){
+                redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + id, 1L);
+                midjourneyUserMapper.incrRelaxNum(id, 1);
             }
         }
-        return num;
-    }
-    /**
-     * 同步数据库
-     */
-    public void syncUser(Long id,Integer mode,Long num){
-        log.info("同步次数 id:{},mode:{},num:{}",id,mode,num);
-        if (num == null){
-            return;
-        }
-        LambdaUpdateWrapper<MidjourneyUser> wrapper = Wrappers.lambdaUpdate(MidjourneyUser.class)
-                .eq(MidjourneyUser::getId, id);
-        if (mode == 1){
-            wrapper.set(MidjourneyUser::getMjFastNum, num);
-        }
-        if (mode == 2){
-            wrapper.set(MidjourneyUser::getMjRelaxNum, num);
-        }
-        midjourneyUserMapper.update(null, wrapper);
     }
+//    /**
+//     * 同步数据库
+//     */
+//    public void syncUser(Long id,Integer mode,Long num){
+//        log.info("同步次数 id:{},mode:{},num:{}",id,mode,num);
+//        if (num == null){
+//            return;
+//        }
+//        LambdaUpdateWrapper<MidjourneyUser> wrapper = Wrappers.lambdaUpdate(MidjourneyUser.class)
+//                .eq(MidjourneyUser::getId, id);
+//        if (mode == 1){
+//            wrapper.set(MidjourneyUser::getMjFastNum, num);
+//        }
+//        if (mode == 2){
+//            wrapper.set(MidjourneyUser::getMjRelaxNum, num);
+//        }
+//        midjourneyUserMapper.update(null, wrapper);
+//    }
 
     @Override
-    public SubmitResult submitAction(MidjourneyUser user, Long taskId, String customId, Long num, String botType) throws Exception {
+    public Object submitAction(MidjourneyUser user, Long taskId, String customId, Long num, String botType) throws Exception {
         MidjourneyUserConversation conversation = conversationMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUserConversation.class).eq(MidjourneyUserConversation::getTaskId, taskId).last("limit 1"));
         if (conversation == null) {
             throw BusinessRuntimeException.getInstance("关联任务不存在或已失效");
@@ -191,12 +212,16 @@ public class MidjourneyServiceImpl implements MidjourneyService {
         if (!user.getMode().equals(conversation.getMode())) {
             throw BusinessRuntimeException.getInstance("当前出图模式与关联任务出图模式不符");
         }
+        AtomicBoolean modalFlag = new AtomicBoolean(false);
         if (StringUtils.isNotBlank(conversation.getButtons())){
             List<MessageButton> messageButtons = Jsons.parseList(conversation.getButtons(), MessageButton.class);
             messageButtons.forEach(button -> {
                 if (button.getCustomId().equals(customId)) {
                     log.info("action customId:{}", customId);
                     button.setStyle(3);
+                    if (!"Vary (Region)".equals(button.getLabel()) && !"Custom Zoom".equals(button.getLabel())) {
+                        modalFlag.set(true);
+                    }
                 }
             });
             conversation.setButtons(Jsons.toJson(messageButtons));
@@ -213,10 +238,19 @@ public class MidjourneyServiceImpl implements MidjourneyService {
                 .build();
         SubmitResult result = submit(user.getMode(),"action", conversation.getInstanceId(),param);
         if (result.getCode() == 21) {
-            // 以上操作有弹窗确认,恢复次数
-            recoverUserLimit(user.getId(), user.getMode(),num);
+            if (user.getMode() == 2 && modalFlag.get()){
+                MidjourneyUserConversation modal = submitModal(user, Long.valueOf(result.getResult()), conversation.getPrompt(), null);
+                log.info("action-modal:{}", modal);
+                return modal;
+            }else {
+                // 以上操作有弹窗确认,恢复次数
+                recoverUserLimit(user.getId(), user.getMode(),num);
+            }
         }else {
-            syncUser(user.getId(), user.getMode(),num);
+            //syncUser(user.getId(), user.getMode(),num);
+            if (!customId.contains("upsample") && user.getMode() == 2) {
+                redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
+            }
         }
         saveConversation(user.getId(), user.getMode(), result,"ACTION", StringUtils.EMPTY, botType);
         return result;
@@ -246,6 +280,11 @@ public class MidjourneyServiceImpl implements MidjourneyService {
             if (code == 3) {
                 if(mode == 2 && StringUtils.isNotBlank(accountWithMinUsage)){
                     redisService.hdel(RedisService.key.MIDJOURNEY_ACCOUNT.getName(),accountWithMinUsage);
+                    String finalAccountWithMinUsage = accountWithMinUsage;
+                    TASK_EXECUTOR.execute(() -> {
+                        MidjourneyAccount account = midjourneyAccountService.getOne(Wrappers.lambdaQuery(MidjourneyAccount.class).eq(MidjourneyAccount::getInstanceId, finalAccountWithMinUsage).last("limit 1"));
+                        midjourneyAccountService.updateStatus(account.getId());
+                    });
                 }
                 throw BusinessRuntimeException.getInstance("账号不存在");
             }
@@ -253,11 +292,15 @@ public class MidjourneyServiceImpl implements MidjourneyService {
                 throw BusinessRuntimeException.getInstance(submitResult.getDescription());
             }
             if (code == 24) {
-                throw BusinessRuntimeException.getInstance("prompt包含敏感词");
+                JSONObject jsonObject = JSONUtil.parseObj(submitResult.getResult());
+                throw BusinessRuntimeException.getInstance("prompt包含敏感词:"+jsonObject.getStr("bannedWord"));
             }
             log.error("action:" + action + " error message:" + submitResult.getDescription());
             throw BusinessRuntimeException.getInstance("队列已满,请稍后尝试");
         }
+        if (StringUtils.isNotBlank(accountWithMinUsage) && mode == 2) {
+            submitResult.setInstanceId(Long.valueOf(accountWithMinUsage));
+        }
         return submitResult;
     }
 
@@ -268,9 +311,9 @@ public class MidjourneyServiceImpl implements MidjourneyService {
             Map<Object, Object> accountsUsage = redisService.hmget(key);
 
             if (accountsUsage == null || accountsUsage.isEmpty()) {
-                Map<Object, Object> map = midjourneyAccountService.list(Wrappers.lambdaQuery(MidjourneyAccount.class).eq(MidjourneyAccount::getStatus,Boolean.TRUE)).stream().collect(Collectors.toMap(k -> k.getInstanceId().toString(), v -> 0));
+                accountsUsage = midjourneyAccountService.list(Wrappers.lambdaQuery(MidjourneyAccount.class).eq(MidjourneyAccount::getStatus,Boolean.TRUE)).stream().collect(Collectors.toMap(k -> k.getInstanceId().toString(), v -> 0));
                 // 保存所有账号ID和使用次数
-                redisService.hmset(key, map);
+                redisService.hmset(key, accountsUsage);
             }
 
             // 找到使用次数最少的账号ID
@@ -287,17 +330,13 @@ public class MidjourneyServiceImpl implements MidjourneyService {
                     }
                 }
             }
-            // 增加使用次数
-            if (minAccountId != null) {
-                redisService.hincr(key, minAccountId, 1.0);
-            }
             return minAccountId;
         } catch (Exception e) {
             throw BusinessRuntimeException.getInstance("获取账号失败");
         }
     }
     private String getActionUrl(String action) {
-         switch (action) {
+        switch (action) {
             case "imagine":
                 return "/mj/submit/imagine";
             case "action":
@@ -356,14 +395,11 @@ public class MidjourneyServiceImpl implements MidjourneyService {
             MidjourneyUserConversation dbConversation = conversationMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUserConversation.class).eq(MidjourneyUserConversation::getTaskId, conversation.getTaskId())
                     .eq(MidjourneyUserConversation::getUserId, userId).orderByDesc(MidjourneyUserConversation::getId).last("limit 1"));
             if (dbConversation != null) {
-                if ("SUCCESS".equals(dbConversation.getStatus())) {
+                if ("SUCCESS".equals(dbConversation.getStatus()) || "FAILURE".equals(dbConversation.getStatus()) || "MODAL".equals(dbConversation.getStatus())) {
                     return;
                 }
                 conversation.setId(dbConversation.getId());
                 conversationMapper.updateById(conversation);
-                if (dbConversation.getMode() == 2){
-                    redisService.hdecr(RedisService.key.MIDJOURNEY_ACCOUNT.getName() , dbConversation.getInstanceId().toString(), 1.0);
-                }
                 TASK_EXECUTOR.execute(() -> {
                     try {
                         String imageUrl = conversation.getImageUrl();
@@ -377,6 +413,16 @@ public class MidjourneyServiceImpl implements MidjourneyService {
                 });
                 //失败返还次数
                 if ("FAILURE".equals(conversation.getStatus())){
+                    if (StringUtils.equals("未知频道",conversation.getFailReason())) {
+                        redisService.hdel(RedisService.key.MIDJOURNEY_ACCOUNT.getName(),dbConversation.getInstanceId());
+                        String finalAccountWithMinUsage = dbConversation.getInstanceId().toString();
+                        TASK_EXECUTOR.execute(() -> {
+                            MidjourneyAccount account = midjourneyAccountService.getOne(Wrappers.lambdaQuery(MidjourneyAccount.class).eq(MidjourneyAccount::getInstanceId, finalAccountWithMinUsage).last("limit 1"));
+                            if (account.getStatus()) {
+                                midjourneyAccountService.updateStatus(account.getId());
+                            }
+                        });
+                    }
                     Object num = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + userId);
                     LambdaUpdateWrapper<MidjourneyUser> wrapper = Wrappers.lambdaUpdate(MidjourneyUser.class)
                             .eq(MidjourneyUser::getId, userId);
@@ -401,13 +447,15 @@ public class MidjourneyServiceImpl implements MidjourneyService {
     private static String uploadPic(String url, String prefix) throws IOException {
         byte[] body = HttpUtil.downloadBytes(url);
         Path tempFile = Files.createTempFile(prefix, ".png");
-        try (FileImageOutputStream imageOutput = new FileImageOutputStream(tempFile.toFile())) {
+        File file = tempFile.toFile();
+        try (FileImageOutputStream imageOutput = new FileImageOutputStream(file)) {
             imageOutput.write(body, 0, body.length);
         }
         Map<String, Object> paramMap = new HashMap<>();
-        paramMap.put("file", tempFile.toFile());
+        paramMap.put("file", file);
         String json = HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap);
         log.info("上传图片结果:url:{},json:{}",url, json);
+        FileUtil.del(file);
         return new JSONObject(json).getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
     }
 
@@ -431,7 +479,7 @@ public class MidjourneyServiceImpl implements MidjourneyService {
         }
         return list;
     }
-    public JSONArray listByIds(Integer mode,List<Long> ids) throws Exception {
+    public JSONArray listByIds(Integer mode, List<Long> ids) throws Exception {
         Map<String, Object> param = MapUtil.builder(new HashMap<String, Object>()).put("ids", ids).build();
         String body = HttpRequest.post((mode == 1 ? FAST_HOST : RELAX_HOST) + "/mj/task/list-by-condition").header("Authorization", FAST_TOKEN).body(Jsons.toJson(param)).execute().body();
         log.info("listByIds body:{}", body);

+ 177 - 87
midjourney/src/main/java/com/yhlxj/web/mirror/MidjourneyController.java

@@ -1,6 +1,6 @@
 package com.yhlxj.web.mirror;
 
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.exception.BusinessRuntimeException;
@@ -11,24 +11,35 @@ import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
+import com.yhlxj.dao.mapper.GroupsRelationMapper;
+import com.yhlxj.dao.mapper.MidjourneyPaintingPlazaMapper;
 import com.yhlxj.dao.mapper.midjourney.MidjourneyUserMapper;
 import com.yhlxj.dao.model.dto.*;
+import com.yhlxj.dao.model.entity.GroupsRelation;
+import com.yhlxj.dao.model.entity.MidjourneyPaintingPlaza;
 import com.yhlxj.dao.model.entity.MidjourneyUser;
 import com.yhlxj.dao.model.entity.MidjourneyUserConversation;
-import com.yhlxj.dao.model.response.SubmitResult;
+import com.yhlxj.dao.model.views.MidjourneyPaintingUserView;
+import com.yhlxj.dao.model.views.MidjourneyUserPaintingDayRecordView;
+import com.yhlxj.dao.model.views.MidjourneyUserPaintingRecordView;
 import com.yhlxj.redis.RedisService;
 import com.yhlxj.service.midjourney.MidjourneyService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
-/**
+/** server/镜像服务/mj绘画
  * @author zwhui
  * @date 2024/4/23 10:31
  */
@@ -38,6 +49,11 @@ import java.util.List;
 @RequestMapping("/applets/midjourney")
 public class MidjourneyController {
 
+    @Value("${midjourney.drawUrl}")
+    private String midjourneyDrawUrl;
+
+    private final HttpServletResponse response;
+
     private final MidjourneyUserMapper midjourneyUserMapper;
 
     private final HttpServletRequest request;
@@ -45,46 +61,43 @@ public class MidjourneyController {
     private final MidjourneyService midjourneyService;
 
     private final BeanSearcher beanSearcher;
-    
+
     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);
+
+        MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
+                .eq(MidjourneyUser::getUserToken, userToken).last("limit 1"));
         if (midjourneyUser == null){
-            midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
-                    .eq(MidjourneyUser::getUserToken, userToken).last("limit 1"));
-            if (midjourneyUser == null){
-                throw new BusinessRuntimeException("账号不存在,请重新登录");
-            }
-            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){
-                redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjFastNum(), RedisService.key.MIDJOURNEY_FAST_LIMIT.getTimeout());
-            }
-            Object relaxNum = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId());
-            if (relaxNum == null){
-                if (midjourneyUser.getMjRelaxNum() != null){
-                    redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjRelaxNum(), RedisService.key.MIDJOURNEY_RELAX_LIMIT.getTimeout());
-                }
-            }
-        }else {
-            Object fastNum = redisService.get(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId());
-            if (fastNum == null){
-                redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjFastNum(), RedisService.key.MIDJOURNEY_FAST_LIMIT.getTimeout());
-            }else {
-                midjourneyUser.setMjFastNum(Integer.parseInt(fastNum.toString()));
-            }
-            Object relaxNum = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId());
-            if (relaxNum == null){
-                if (midjourneyUser.getMjRelaxNum() != null){
-                    redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjRelaxNum(), RedisService.key.MIDJOURNEY_RELAX_LIMIT.getTimeout());
-                }
-            }else {
-                midjourneyUser.setMjRelaxNum(Integer.parseInt(relaxNum.toString()));
-            }
+            throw new BusinessRuntimeException("账号不存在,请重新登录");
+        }
+        if(!redisService.hasKey(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId())){
+            redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(),midjourneyUser.getMjFastNum());
+        }
+
+        if(!redisService.hasKey(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId())){
+            redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(),midjourneyUser.getMjRelaxNum());
         }
+        Long relationId = midjourneyUser.getRelationId();
+        GroupsRelation relation = groupsRelationMapper.selectById(relationId);
+        midjourneyUser.setAqType(relation.getAqType());
+
         return midjourneyUser;
+
+    }
+
+    @GetMapping("/midjourneyMirrorWithToken/{userToken}")
+    public void midjourneyMirrorWithToken(@PathVariable String userToken) throws IOException {
+        Cookie cookie = new Cookie("userToken", userToken);
+        cookie.setMaxAge(31536000);
+        cookie.setPath("/");
+        response.addCookie(cookie);
+        response.sendRedirect(midjourneyDrawUrl);
     }
 
 
@@ -96,25 +109,42 @@ public class MidjourneyController {
         if (user.getExpireTime().before(new Date())){
             throw BusinessRuntimeException.getInstance("账号已过期");
         }
-       if (user.getMode() == 1){
-           num = redisService.decr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + user.getId(), 1L);
-           if (num < 0) {
-               user.setMode(2);
-               redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + user.getId(), 1L);
-           }
-       }
-       if (user.getMode() == 2){
-           Object relax = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId());
-           if (relax != null){
-               num = redisService.decr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId(), 1L);
-               if (num < 0){
-                   redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId(), 1L);
-               }
-           }else {
-               num = null;
-           }
-       }
-       return num;
+        if (user.getMode() == 1){
+
+            num = redisService.decr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + user.getId(), 1L);
+
+            if (num < 0) {
+                user.setMode(2);
+                midjourneyUserMapper.update(null, Wrappers.lambdaUpdate(MidjourneyUser.class).eq(MidjourneyUser::getId, user.getId()).set(MidjourneyUser::getMode, user.getMode()));
+                redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + user.getId(), 1L);
+
+            }else {
+                int i = midjourneyUserMapper.decFastNum(user.getId(), 1, user.getMjFastNum());
+                if (i == 0) {
+                    redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + user.getId(), 1L);
+                    throw BusinessRuntimeException.getInstance("网络异常,请稍后再试");
+                }
+            }
+        }
+        if (user.getMode() == 2){
+            Object relax = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId());
+
+            if (relax != null){
+                num = redisService.decr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId(), 1L);
+                if (num < 0){
+                    redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId(), 1L);
+                }else {
+                    int i = midjourneyUserMapper.decRelaxNum(user.getId(), 1, user.getMjRelaxNum());
+                    if (i == 0) {
+                        redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId(), 1L);
+                        throw BusinessRuntimeException.getInstance("网络异常,请稍后再试");
+                    }
+                }
+            }else {
+                num = null;
+            }
+        }
+        return num;
     }
 
     /**
@@ -123,32 +153,34 @@ public class MidjourneyController {
     public void recoverUserLimit(Long id,Integer mode,Long num){
         if (mode == 1){
             redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + id, 1L);
+            midjourneyUserMapper.incrFastNum(id, 1);
         }
         if (mode == 2){
             if (num != null){
                 redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + id, 1L);
+                midjourneyUserMapper.incrRelaxNum(id, 1);
             }
         }
     }
 
-    /**
-     * 同步数据库
-     */
-    public void syncUser(Long id,Integer mode,Long num){
-        log.info("同步次数 id:{},mode:{},num:{}",id,mode,num);
-        if (num == null){
-            return;
-        }
-        LambdaUpdateWrapper<MidjourneyUser> wrapper = Wrappers.lambdaUpdate(MidjourneyUser.class)
-                .eq(MidjourneyUser::getId, id);
-        if (mode == 1){
-            wrapper.set(MidjourneyUser::getMjFastNum, num);
-        }
-        if (mode == 2){
-            wrapper.set(MidjourneyUser::getMjRelaxNum, num);
-        }
-        midjourneyUserMapper.update(null, wrapper);
-    }
+    ///**
+    // * 同步数据库
+    // */
+    //public void syncUser(Long id,Integer mode,Long num){
+    //    log.info("同步次数 id:{},mode:{},num:{}",id,mode,num);
+    //    if (num == null){
+    //        return;
+    //    }
+    //    LambdaUpdateWrapper<MidjourneyUser> wrapper = Wrappers.lambdaUpdate(MidjourneyUser.class)
+    //            .eq(MidjourneyUser::getId, id);
+    //    if (mode == 1){
+    //        wrapper.set(MidjourneyUser::getMjFastNum, num);
+    //    }
+    //    if (mode == 2){
+    //        wrapper.set(MidjourneyUser::getMjRelaxNum, num);
+    //    }
+    //    midjourneyUserMapper.update(null, wrapper);
+    //}
 
 
     /**
@@ -167,7 +199,7 @@ public class MidjourneyController {
     @PostMapping("/submit/imagine")
     @NoSubmit
     public Result<MidjourneyUserConversation> submitImagine(@RequestBody SubmitImagineDTO submitImagineDTO) {
-        log.info("提交Imagine任务,提示:{},base64数组长度:{}",submitImagineDTO.getPrompt(),submitImagineDTO.getBase64Array());
+        log.info("提交Imagine任务,提示:{}",submitImagineDTO.getPrompt());
         MidjourneyUser user = getUser();
         Long num = checkUserLimit(user);
         if (num != null && num < 0){
@@ -180,7 +212,7 @@ public class MidjourneyController {
             recoverUserLimit(user.getId(), user.getMode(),num);
             throw BusinessRuntimeException.getInstance(e.getMessage());
         }
-        syncUser(user.getId(), user.getMode(), num);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -198,12 +230,12 @@ public class MidjourneyController {
         }
         MidjourneyUserConversation conversation;
         try {
-            conversation = midjourneyService.submitDescribe(user, submitDescribeDTO.getBase64(), submitDescribeDTO.getBotType());
+            conversation = midjourneyService.submitDescribe(user, submitDescribeDTO.getBotType(),submitDescribeDTO.getBase64());
         } catch (Exception e) {
             recoverUserLimit(user.getId(), user.getMode(),num);
             throw BusinessRuntimeException.getInstance(e.getMessage());
         }
-        syncUser(user.getId(), user.getMode(), num);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -226,7 +258,7 @@ public class MidjourneyController {
             recoverUserLimit(user.getId(), user.getMode(),num);
             throw BusinessRuntimeException.getInstance(e.getMessage());
         }
-        syncUser(user.getId(), user.getMode(), num);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -236,7 +268,7 @@ public class MidjourneyController {
     @PostMapping("/submit/modal")
     @NoSubmit
     public Result<MidjourneyUserConversation> submitModal(@RequestBody SubmitModalDTO submitModalDTO) {
-        log.info("提交Modal任务,taskId:{},提示:{},base64数组长度:{}",submitModalDTO.getTaskId(),submitModalDTO.getPrompt(),submitModalDTO.getMaskBase64());
+        log.info("提交Modal任务,taskId:{},提示:{}",submitModalDTO.getTaskId(),submitModalDTO.getPrompt());
         MidjourneyUser user = getUser();
         Long num = checkUserLimit(user);
         if (num != null && num < 0){
@@ -249,7 +281,7 @@ public class MidjourneyController {
             recoverUserLimit(user.getId(), user.getMode(),num);
             throw BusinessRuntimeException.getInstance(e.getMessage());
         }
-        syncUser(user.getId(), user.getMode(), num);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -272,7 +304,7 @@ public class MidjourneyController {
             recoverUserLimit(user.getId(), user.getMode(),num);
             throw BusinessRuntimeException.getInstance(e.getMessage());
         }
-        syncUser(user.getId(), user.getMode(), num);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -281,14 +313,17 @@ public class MidjourneyController {
      */
     @PostMapping("/submit/action")
     @NoSubmit
-    public Result<SubmitResult> action(@RequestBody SubmitActionDTO actionDTO) {
+    public Result<Object> action(@RequestBody SubmitActionDTO actionDTO) {
         log.info("任务id:{},执行动作:{}",actionDTO.getTaskId(),actionDTO.getCustomId());
         MidjourneyUser user = getUser();
-        Long num = checkUserLimit(user);
-        if (num != null && num < 0){
-            throw BusinessRuntimeException.getInstance("次数已用完");
+        Long num = 0L;
+        if (!actionDTO.getCustomId().contains("BOOKMARK")) {
+            num = checkUserLimit(user);
+            if (num != null && num < 0) {
+                throw BusinessRuntimeException.getInstance("次数已用完");
+            }
         }
-        SubmitResult conversation;
+        Object conversation;
         try {
             conversation = midjourneyService.submitAction(user, actionDTO.getTaskId(), actionDTO.getCustomId(),num, actionDTO.getBotType());
         } catch (Exception e) {
@@ -346,7 +381,7 @@ public class MidjourneyController {
         }
         midjourneyUser.setMode(mode);
         midjourneyUserMapper.updateById(midjourneyUser);
-        redisService.del(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken());
+        //redisService.del(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken());
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 
@@ -360,4 +395,59 @@ public class MidjourneyController {
         String json = new String(bytes, StandardCharsets.UTF_8);
         midjourneyService.notifyHook(json);
     }
+
+
+
+    /**
+     * 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);
+    }
 }

+ 0 - 93
midjourney/src/main/java/com/yhlxj/web/mirror/MirrorController.java

@@ -1,93 +0,0 @@
-package com.yhlxj.web.mirror;
-
-import cn.hutool.core.date.DateUtil;
-import com.cyksj.common.EnvCommonService;
-import com.cyksj.common.exception.BusinessRuntimeException;
-import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
-import com.cyksj.dto.Result;
-import com.cyksj.enums.GatewayResponse;
-import com.cyksj.model.entity.ChatgptSession;
-import com.cyksj.model.entity.ChatgptUser;
-import com.cyksj.model.entity.MidjourneyUser;
-import com.cyksj.model.request.gpt.ConversationRequest;
-import com.cyksj.model.response.ConversationLimitResponse;
-import com.cyksj.model.views.ChatGptUserConversationRecordHistoryView;
-import com.cyksj.model.views.ChatGptUserView;
-import com.cyksj.model.views.ChatgptCarInfoView;
-import com.cyksj.model.views.ChatgptConversionLimitView;
-import com.cyksj.service.chatgpt.ChatGptAccountService;
-import com.cyksj.service.midjourney.MidjourneyAccountService;
-import com.cyksj.web.util.StpUserUtil;
-import com.ejlchina.searcher.BeanSearcher;
-import com.ejlchina.searcher.SearchResult;
-import com.ejlchina.searcher.util.MapBuilder;
-import com.ejlchina.searcher.util.MapUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.time.LocalDateTime;
-import java.util.Date;
-import java.util.Set;
-
-/**
- * /server/镜像服务
- *
- * @author chan
- * @date 2024/3/19 14:41
- */
-@Slf4j
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/applets/mirror")
-public class MirrorController {
-
-    private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
-
-
-    private final HttpServletResponse response;
-
-    private final HttpServletRequest request;
-
-    private final BeanSearcher beanSearcher;
-
-    private final MidjourneyAccountService midjourneyAccountService;
-
-    private final EnvCommonService envCommonService;
-
-    @Value("${midjourney.url}")
-    private String midjourneyHost;
-
-    @Value("${midjourney.drawUrl}")
-    private String midjourneyDrawUrl;
-
-    /**
-     * MJ车票跳转登录
-     *
-     * @param relationId 车票id
-     */
-    @GetMapping("/midjourneyMirror/{relationId}")
-    public Result<String> midjourneyMirror(@PathVariable Long relationId) {
-        Long userId = StpUserUtil.getLoginIdAsLong();
-        MidjourneyUser midjourneyUser = midjourneyAccountService.getMidjourneyUserToken(userId, relationId);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyHost + (EnvCommonService.active.equals(envCommonService.getEnv()) ? "/8081":"/8082") +"/api/applets/mirror/midjourneyMirrorWithToken/" + midjourneyUser.getUserToken());
-    }
-
-    @GetMapping("/midjourneyMirrorWithToken/{userToken}")
-    public void midjourneyMirrorWithToken(@PathVariable String userToken) throws IOException {
-        Cookie cookie = new Cookie("userToken", userToken);
-        cookie.setMaxAge(31536000);
-        cookie.setPath("/");
-        cookie.setMaxAge();
-        response.addCookie(cookie);
-        response.sendRedirect(midjourneyDrawUrl);
-    }
-}

+ 13 - 0
midjourney/src/main/java/com/yhlxj/web/wss/WssSendable.java

@@ -0,0 +1,13 @@
+package com.yhlxj.web.wss;
+
+import com.yhlxj.dao.model.enums.WsMessageTypeEnum;
+
+import java.io.IOException;
+
+public interface WssSendable {
+    void sendMessage(WsMessageTypeEnum type, Object object) throws IOException;
+
+    void close() throws IOException;
+
+    boolean isOpen() throws IOException;
+}

+ 141 - 0
midjourney/src/main/java/com/yhlxj/web/wss/WssSession.java

@@ -0,0 +1,141 @@
+package com.yhlxj.web.wss;
+
+import com.alibaba.fastjson.JSONObject;
+import com.yhlxj.dao.model.enums.WsMessageTypeEnum;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.apache.tomcat.websocket.WsSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.websocket.*;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author chan
+ * @date 2024/6/27 18:40
+ */
+@Data
+@AllArgsConstructor
+public class WssSession implements WssSendable {
+    private static Logger logger = LoggerFactory.getLogger(WsSession.class);
+
+    private Session session;
+
+    /**
+     * 发送自定义类型消息
+     *
+     * @param type
+     * @param object
+     */
+    @Override
+    public void sendMessage(WsMessageTypeEnum type, Object object) {
+
+        //组织成形如 message:{"type":"type", "data":{...}}想
+        JSONObject result = new JSONObject();
+        result.put("type", type.type);
+        result.put("content", object);
+
+        logger.info("[WS-SENDMESSAGE],{}", WsMessageTypeEnum.MESSAGE.type + ":" + result.toJSONString());
+        try {
+            getSession().getBasicRemote().sendText(WsMessageTypeEnum.MESSAGE.type + ":" + result.toJSONString());
+        } catch (Exception e) {
+            logger.info("[WS-SENDMESSAGE],[失败],{}", WsMessageTypeEnum.MESSAGE.type + ":" + result.toJSONString());
+        }
+    }
+
+    /**
+     * 发送pong
+     *
+     * @throws IOException
+     */
+    public void pong() throws IOException {
+        getSession().getBasicRemote().sendText(WsMessageTypeEnum.PONG.type);
+    }
+
+
+    //-----------------DELEGATOR---------------------
+
+    public WebSocketContainer getContainer() {
+        return session.getContainer();
+    }
+
+    public void addMessageHandler(MessageHandler messageHandler) throws IllegalStateException {
+        session.addMessageHandler(messageHandler);
+    }
+
+    public Set<MessageHandler> getMessageHandlers() {
+        return session.getMessageHandlers();
+    }
+
+    public void removeMessageHandler(MessageHandler messageHandler) {
+        session.removeMessageHandler(messageHandler);
+    }
+
+    public String getProtocolVersion() {
+        return session.getProtocolVersion();
+    }
+
+    public String getNegotiatedSubprotocol() {
+        return session.getNegotiatedSubprotocol();
+    }
+
+    public List<Extension> getNegotiatedExtensions() {
+        return session.getNegotiatedExtensions();
+    }
+
+    public boolean isSecure() {
+        return session.isSecure();
+    }
+
+    public boolean isOpen() {
+        return session.isOpen();
+    }
+
+    public long getMaxIdleTimeout() {
+        return session.getMaxIdleTimeout();
+    }
+
+    public void setMaxIdleTimeout(long l) {
+        session.setMaxIdleTimeout(l);
+    }
+
+    public void setMaxBinaryMessageBufferSize(int i) {
+        session.setMaxBinaryMessageBufferSize(i);
+    }
+
+    public int getMaxBinaryMessageBufferSize() {
+        return session.getMaxBinaryMessageBufferSize();
+    }
+
+    public void setMaxTextMessageBufferSize(int i) {
+        session.setMaxTextMessageBufferSize(i);
+    }
+
+    public int getMaxTextMessageBufferSize() {
+        return session.getMaxTextMessageBufferSize();
+    }
+
+    public RemoteEndpoint.Async getAsyncRemote() {
+        return session.getAsyncRemote();
+    }
+
+    public RemoteEndpoint.Basic getBasicRemote() {
+        return session.getBasicRemote();
+    }
+
+    public String getId() {
+        return session.getId();
+    }
+
+    public void close() throws IOException {
+        session.close();
+    }
+
+    public void close(CloseReason closeReason) throws IOException {
+        session.close(closeReason);
+    }
+
+}

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java

@@ -240,7 +240,7 @@ public class MidjourneyServiceImpl implements MidjourneyService {
         SubmitResult result = submit(user.getMode(),"action", conversation.getInstanceId(),param);
         if (result.getCode() == 21) {
             if (user.getMode() == 2 && modalFlag.get()){
-                MidjourneyUserConversation modal = submitModal(user, Long.valueOf(result.getResult()), conversation.getPrompt() + " --v 6", null);
+                MidjourneyUserConversation modal = submitModal(user, Long.valueOf(result.getResult()), conversation.getPrompt(), null);
                 log.info("action-modal:{}", modal);
                 return modal;
             }else {