SpringBoot对接Midjourney Api

提示:SpringBoot对接Midjourney Api

文章目录

目录

文章目录

后端代码

导包

controller层

工具类层

前端代码

申请API

测试结果



后端代码

导包

XML 复制代码
        <!--添加hutool的依赖-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.16</version>
        </dependency>

        <!-- OkHttp -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.3</version>
        </dependency>

        <!-- Gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.9</version>
        </dependency>

controller层

java 复制代码
    @PostMapping("/createimage")
    public Response createimage(String prompt){
        System.out.println(prompt);
        return new Response("0","success",ApiTestUtil.createImage(prompt));
    }

    @PostMapping("/fetch")
    public Response fetch(String jobId){
        String result = ApiTestUtil.fetch(jobId);
        return new Response("0","success",result);
    }

工具类层

java 复制代码
    public static String createImage(String prompt) {
        Map<String, Object> map = new HashMap<>();
        map.put("prompt", prompt);
        map.put("mode", "fast");
        map.put("hookUrl", "");
        String result = HttpRequest.post("https://api.ttapi.io/midjourney/v1/imagine")
                .body(JSONUtil.toJsonStr(map))
                .header("TT-API-KEY", "请替换你自己的key")
                .execute().body();
        System.out.println("绘图请求响应:" + result);
        return result;
    }

    public static String fetch(String jobId){
        String result = HttpRequest.get("https://api.ttapi.io/midjourney/v1/fetch?jobId=" + jobId)
                .header("TT-API-KEY", "请替换你自己的key")
                .execute().body();
        System.out.println("绘图结果:" + result);
        return result;
    }

前端代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>AI Chat Interface</title>
  <!-- 引入 Vue 3 的 CDN -->
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <!-- 引入 Font Awesome for avatars -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
  <style>
    /* 样式 */
    body {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      background-color: #f4f4f9;
      margin: 0;
      padding: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
    }

    .chat-container {
      display: flex;
      flex-direction: column;
      height: 80vh;
      width: 80vw;
      max-width: 600px;
      border: 1px solid #ccc;
      border-radius: 10px;
      overflow: hidden;
      background-color: #fff;
    }

    .chat-window {
      flex: 1;
      padding: 10px;
      overflow-y: auto;
      background-color: #f4f4f9;
      position: relative;
    }

    .chat-message {
      display: flex;
      margin-bottom: 10px;
      align-items: flex-start;
    }

    .message-left {
      flex-direction: row;
    }

    .message-right {
      flex-direction: row-reverse;
    }

    .avatar {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      background-color: #007bff;
      display: flex;
      justify-content: center;
      align-items: center;
      color: white;
      font-weight: bold;
      margin: 0 10px;
      font-size: 20px;
    }

    .message-bubble {
      max-width: 70%;
      padding: 10px;
      border-radius: 20px;
      background-color: #007bff;
      color: white;
      word-wrap: break-word;
    }

    .message-left .message-bubble {
      background-color: #e4e6eb;
      color: black;
    }

    .chat-input {
      display: flex;
      padding: 10px;
      border-top: 1px solid #ccc;
      background-color: #fff;
    }

    .chat-input input {
      flex: 1;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 20px;
      outline: none;
    }

    .chat-input button {
      margin-left: 10px;
      padding: 10px 20px;
      border: none;
      background-color: #007bff;
      color: white;
      border-radius: 20px;
      cursor: pointer;
      outline: none;
    }

    .chat-input button:hover {
      background-color: #0056b3;
    }

    .loading {
      position: relative;
      bottom: -20px;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    /* Loader animation styles */
    .loader {
      position: relative;
      width: 2.5em;
      height: 2.5em;
      transform: rotate(165deg);
    }

    .loader:before, .loader:after {
      content: "";
      position: absolute;
      top: 50%;
      left: 50%;
      display: block;
      width: 0.5em;
      height: 0.5em;
      border-radius: 0.25em;
      transform: translate(-50%, -50%);
    }

    .loader:before {
      animation: before8 2s infinite;
    }

    .loader:after {
      animation: after6 2s infinite;
    }

    @keyframes before8 {
      0% {
        width: 0.5em;
        box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);
      }

      35% {
        width: 2.5em;
        box-shadow: 0 -0.5em rgba(225, 20, 98, 0.75), 0 0.5em rgba(111, 202, 220, 0.75);
      }

      70% {
        width: 0.5em;
        box-shadow: -1em -0.5em rgba(225, 20, 98, 0.75), 1em 0.5em rgba(111, 202, 220, 0.75);
      }

      100% {
        box-shadow: 1em -0.5em rgba(225, 20, 98, 0.75), -1em 0.5em rgba(111, 202, 220, 0.75);
      }
    }

    @keyframes after6 {
      0% {
        height: 0.5em;
        box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);
      }

      35% {
        height: 2.5em;
        box-shadow: 0.5em 0 rgba(61, 184, 143, 0.75), -0.5em 0 rgba(233, 169, 32, 0.75);
      }

      70% {
        height: 0.5em;
        box-shadow: 0.5em -1em rgba(61, 184, 143, 0.75), -0.5em 1em rgba(233, 169, 32, 0.75);
      }

      100% {
        box-shadow: 0.5em 1em rgba(61, 184, 143, 0.75), -0.5em -1em rgba(233, 169, 32, 0.75);
      }
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="chat-container">
      <div class="chat-window">
        <div v-for="(message, index) in messages" :key="index" class="chat-message" :class="{'message-left': message.isUser, 'message-right': !message.isUser}">
          <div class="avatar">
            <i :class="message.isUser ? 'fas fa-user' : 'fas fa-robot'"></i>
          </div>
          <div class="message-bubble">
            <img :src="imageUrl" alt="" style="width: 400px;height: 400px;">
          </div>
        </div>
        <div class="loading" v-if="loading">
          <div style="display: flex; align-items: center; justify-content: center;">
            <div class="loader"></div>
            <div style="margin-left: 10px; font-weight: bold; color: #e64c87;">加载中</div>
          </div>
        </div>
      </div>
      <div class="chat-input">
        <input v-model="userInput" @keydown.enter="sendMessage" placeholder="Type your question..." />
        <button @click="sendMessage">Send</button>
      </div>
    </div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    const { createApp } = Vue;

    createApp({
      data() {
        return {
          userInput: '我需要你给我画一只猫',
          messages: [
          ],
          loading: false,
          jobId:"",
          imageUrl:""
        };
      },
      methods: {
        sendMessage() {
          if (this.userInput.trim()) {
            // 添加用户的消息
            this.messages.push({ text: this.userInput, isUser: true });

            // 模拟AI回复
            this.simulateAIResponse(this.userInput);

            // 清空输入框
            this.userInput = '';
          }
        },
        
        async simulateAIResponse(userText) {
          this.loading = true;
          try {
            const res = await axios.post("http://localhost:8888/createimage", {
              "prompt": this.userInput
            }, { headers: { "Content-Type": "multipart/form-data" } });
            if(res.data.code == 0){
                this.jobId = JSON.parse(res.data.data).data.jobId;
                const result = await axios.post("http://localhost:8888/fetch",{
                    "jobId": this.jobId
            }, { headers: { "Content-Type": "multipart/form-data" } 
                });
                if(result.data.code == 0){
                   this.imageUrl = JSON.parse(result.data.data).data.discordImage
                   this.loading = false;
                }
            }
          } catch (error) {
            console.error("Error fetching AI response:", error);
          }
        },
      },
    }).mount('#app');
  </script>
</body>
</html>

申请API

https://ttapi.io/recharge

测试结果

这个主要对接了前一篇AI对话的博客,有需要自行去查找

参考博客地址:https://zhuanlan.zhihu.com/p/689296056

今日时间2024年8月29日,希望你天天开心,如有不会,请留言

相关推荐
颜淡慕潇14 分钟前
【K8S问题系列 |19 】如何解决 Pod 无法挂载 PVC问题
后端·云原生·容器·kubernetes
ProtonBase20 分钟前
如何从 0 到 1 ,打造全新一代分布式数据架构
java·网络·数据库·数据仓库·分布式·云原生·架构
乐之者v27 分钟前
leetCode43.字符串相乘
java·数据结构·算法
suweijie7684 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿4 小时前
List深拷贝后,数据还是被串改
java
向前看-8 小时前
验证码机制
前端·后端
xlsw_8 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹8 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭9 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫9 小时前
泛型(2)
java