零基础 Coze + 前端 Vue3 边玩边开发:宠物冰球运动员生成器

引言

现如今 AI 应用开发变得越来越"平民化",即使你不懂任何深度学习,也能通过"玩"一些 AI 开发平台来做出一些有趣又智能的小工具。而这其中不得不提的就是**✨字节跳动推出的一站式AI应用开发平台 Coze 了**。

那为什么要选择 Coze 呢?那是因为其强大的低代码开发能力,即使是小白也可通过可视化界面"搭积木"一样编排工作流------比如上传图片、调用大模型、生成新图像等等,并且全程无需写复杂的后端或算法代码,极大降低了 AI 集成门槛💡。

拥有了工作流后,我们就可以使用优秀的现代前端框架 Vue3 ,通过其简洁的语法、响应式数据和组件化思想,让页面交互开发变得高效又直观。不仅向用户展示我们的开发成果,也要"接住"用户操作,最后再把结果展示出来。

本文就以"宠物变冰球运动员"为例,联合 Coze 的"AI 能力"与 Vue3 的"交互表现力" 来手把手教你如何使用这两项技术,从零搭建一个完整的 AI 应用。

项目简介

本项目是一个基于 Vue3 + Coze AI 工作流 的轻量级 Web 应用,实现用户上传一张宠物照片,选择队服编号、颜色、担任的位置、持杆手以及艺术风格,即可生成该宠物化身"冰球运动员"的图像。

核心功能:

  • 文件上传并预览
  • 用户配置参数(队服、风格等)
  • 调用 Coze 工作流进行 AI 处理
  • 返回生成的图像并展示

📂 项目结构说明

arduino 复制代码
project-root/
├── src/
│   ├── components/
│   └── App.vue          # 主页面组件
├── public/
│   └── index.html
├── vite.config.js
└── package.json

我们只用了一个主文件 App.vue 来完成全部功能,适合快速原型开发。

🤖 Coze 平台开发详解(低代码)

整体流程概述:

  1. 开始节点:接收所有输入数据。
  2. 图像理解节点:分析照片内容,提取宠物图片的关键特征。
  3. 特征提取节点:将特征转化为结构化的描述。
  4. 代码节点:处理用户提供的参数或生成默认值来描述一只宠物作为"冰球运动员"的外观和特性
  5. 图像生成节点:结合用户选择和图片特征来生成需要展现给用户的图片
  6. 结束节点:将生成的新图像展示给用户。

从输入图片开始,经过图像理解、特征提取、代码处理与图像生成,最终输出结果的完整流程


一、开始节点:

功能:流程入口,接收用户的原始输入数据,启动后续流程。

操作演示

输入参数

参数名 类型 是否必填 默认值 描述
picture Image --- ---
style String 写实 生成照片的艺术风格
uniform_number Number 10 运动员的号码
uniform_color String 球衣颜色
position Number --- 整数枚举,0、1、2,分别为守门员、前锋、后卫,默认随机
shooting_hand Number --- 持杆手,整数枚举0、1,分别为左手、右手,默认随机

二、图像理解节点:imgUnderstand

功能:使用AI模型分析图像内容。

操作演示

输入

  • text:这应该是一张宠物图片,请详细描述宠物的外貌特征。
  • url:选择从开始取到的图片

输出:通过"查看示例"可以查看输出效果

  • author:作者信息
  • content:图像描述文本
  • msg:返回消息

三、特征提取节点:

功能:对文本进行语义分析,提取关键词或结构化信息。

操作演示

模型:豆包·1.5 · Pro · 32k(默认即可)

技能:无需配置技能

输入 :连接图像理解节点 会自动配置 imgUnderstandcontent 字段为 input 中的变量值

系统提示词:为对话提供系统级指导,在此之中可以使用{{变量名}}等方式引用变量(此处我们导入文字提示词即可)

复制代码
你是动物学家,负责从动物描述中提取出该动物(主要是外表)里最有独特性的特征,例如特征的肤色、表情、神态、动作等等。

用户提示词 :向模型提供用户指令(此处我们导入输入变量input

css 复制代码
{{input}}

输出output(默认即可)


四、代码节点:

功能:执行自定义代码逻辑,这里我们需要处理用户提供的参数或生成默认值

操作演示

输入 :从开始节点 里面导入shooting_handstyleuniform_numberuniform_colorposition

代码逻辑

ts 复制代码
const random = (start: number, end: number) => {
    // 生成一个 [0, 1) 之间的随机数
    const p = Math.random();
    // 线性插值 + 向下取整
    // start * (1 - p) + end * p 只会让数据居于[start, end)之间
    // 再向下取整使数据只为整数并且小于end
    return Math.floor(start * (1 - p) + end * p);
}

//对用户传入的参数进行标准化处理和默认值填充,以便后续用于图像生成 prompt 的构建
async function main({ params }: Args): Promise<Output> {
    if (params.position == null) params.position = random(0, 3);
    if (params.shooting_hand == null) params.shooting_hand = random(0, 2);

    const style = params.style || '写实';
    const uniform_number:string = (params.uniform_number || 10).toString();
    const uniform_color = params.uniform_color || '红';
    const position = params.position  == 0 ? '守门员': (params.position == 1 ? '前锋': '后卫');
    const shooting_hand = params.shooting_hand == 0 ? '左手': '右手';
    const empty_hand = params.shooting_hand ? '左手': '右手';

    // 构建输出对象
    const ret = {
        style,
        uniform_number,
        uniform_color,
        position,
        shooting_hand,
    };

    return ret;
}

输出


五、图像生成节点:

功能:根据描述生成新图像。

操作演示

模型设置 :选择通用即可,比例按照自身喜好调节

参考图 :添加参考图,模型选择"形象一致",参考图选择开始节点中的 picture,程度调为 0.7

程度:决定了参考图对最终生成图像的影响程度。数值范围通常是从0到1,其中0表示完全不考虑参考图,而1表示尽可能地模仿参考图。

输入

  • description:图片描述,导入imgUnderstand节点中的content
  • 代码节点 里面导入处理后的shooting_handstyleuniform_numberuniform_colorposition
  • details:详细信息,导入特征提取节点 中的output

提示词:生成内容的提示词,分为两类

  • 正向提示词:引导生成内容
bash 复制代码
用动物的形象和特征,将该动物**拟人**为一名宠物儿童冰球员,生成{{style}}风格的冰球球员照片,球员身穿
{{uniform_color}}色队服,佩戴同色的冰球头盔,队服号码为{{uniform_number}}号,球员位置是{{position}},
用{{shooting_hand}}握着球杆,另一只手空着。该照片图像风格为{{style}}。

# 动物形象描述
{{description}}

# 独特外貌特征
{{details}}

# 注意
- 照片中应强化动物独特的外貌特征,以增加辨识度
- 如果球员位置是守门员,画面中应该有冰球球门
  • 反向提示词:排除不良或无关元素

    球员双手各握一根球杆
    球员未佩戴头盔
    球员吃东西
    画面中出现除了冰球之外的其他球类
    地点不在冰球赛场
    球员四足站立

输出

  • data:生成图像的二进制数据或URL
  • msg:状态信息

六、结束节点:

功能:工作流的最终节点,返回工作流运行后的结果信息。

操作演示

输出变量 :连接图像生成节点

  • output:最终结果,变量值为图像生成节点 中的data

回答内容:编辑智能体回复的内容,我们这里不修改直接输出图片(不需要流式输出)

lua 复制代码
{{output}}

流式输出:回复内容中的大语言模型的生成内容将会逐字流式输出;关闭后,回复内容将全部生成后一次性输出


测试:

在连接好工作流后,我们当然需要进行测试,以保证节点中没有发生错误

操作演示

后话:

当然,在你测试无误之后,可以点击右上角的发布来向别人分享你第一次创作的工作流。

发布之后,在你资源库中的工作流中就能找到你所发布的资源了。

💻 前端实现详解(Vue3 + JavaScript)

一、 <template> ------ 视觉层布局

首先我们确定组件的主要功能为---用户可以上传一张图片,并根据不同的参数(如队服编号、颜色等)进行个性化设置。

所以我们的UI布局,包括两块区域:输入区域(用于上传图片和选择参数)和 输出区域(展示生成的结果)。

html 复制代码
<template>
  <div class="container">
    <!-- 输入区域 -->
    <div class="input">
      <div class="file-input">
        <input type="file" ref="uploadImage" accept="image/*" @change="updateImageData" required />
      </div>
      <img :src="imgPreview" alt="" v-if="imgPreview" />
      <!-- 用户选择参数区域 -->
      <div class="settings">
        <div class="selection">
          <label>队服编号:</label>
          <input type="number" v-model="uniform_number" />
        </div>
        <div class="selection">
          <label>队服颜色:</label>
          <select v-model="uniform_color">
            <option value="红">红</option>
            <option value="蓝">蓝</option>
            <option value="绿">绿</option>
            <option value="白">白</option>
            <option value="黑">黑</option>
          </select>
        </div>
      </div>
      <div class="settings">
        <div class="selection">
          <label>位置:</label>
          <select v-model="position">
            <option value="0">守门员</option>
            <option value="1">先锋</option>
            <option value="2">后卫</option>
          </select>
        </div>
      </div>
      <div class="selection">
        <label>持杆:</label>
        <select v-model="shooting_hand">
          <option value="0">左手</option>
          <option value="1">右手</option>
        </select>
      </div>
      <div class="selection">
        <label>风格:</label>
        <select v-model="style">
          <option value="写实">写实</option>
          <option value="乐高">乐高</option>
          <option value="国漫">国漫</option>
          <option value="日漫">日漫</option>
          <option value="油画">油画</option>
          <option value="涂鸦">涂鸦</option>
          <option value="素描">素描</option>
        </select>
      </div>
      <div class="generate">
        <button @click="generate">生成</button>
      </div>
    </div>
    <!-- 输出区域 -->
    <div class="output">
      <div class="generated">
        <img :src="imgUrl" alt="" v-if="imgUrl">
        <div v-if="status">{{ status }}</div>
      </div>
    </div>
  </div>
</template>

1、输入部分(input):

html 复制代码
<input type="file" ref="uploadImage" accept="image/*" @change="updateImageData" required />

这段代码实现了 让用户选择本地文件并且触发预览更新

  • type="file":声明这是一个文件上传控件,点击后会弹出系统文件选择对话框。
  • accept="image/*"限制用户只能选择图片文件,防止无效输入。
  • @change="updateImageData":当用户选中一张图片后,会立即触发 updateImageData 方法(用于将图片文件转换为可以直接预览的 URL)
  • ref="uploadImage":为这个 input 元素注册一个 引用标识 ,方便在 <script setup> 中通过声明一个相同名称的 ref 变量 来直接访问该 DOM 元素。
  • required: 表示该字段是必填项
对比 refv-model:
  • v-model:同步"数据值",并且可以自动更新(关心的是"值"本身
  • ref:获取"DOM元素",而且需要手动更新(需要访问 DOM 的原生能力

⚠️并且在 <input type="file">中 无法使用 v-model

因为浏览器出于安全考虑,不允许 JS 设置 file input 的值,只能读取 。所以必须用 ref 来读取用户选中的文件。

html 复制代码
<img :src="imgPreview" alt="" v-if="imgPreview" />

在用户上传图片后,需要及时给予用户反馈(让用户知道自己行为驱动了页面,而不是毫无作用),所以需要展示预览图,让用户知道上传图片成功了。

  • :src="imgPreview":动态绑定响应式变量 imgPreview,用于自动更新图片。
  • v-if="imgPreview":条件渲染,只有当用户成功上传后才能渲染<img>元素,避免未上传时显示空白占位图。

2、用户选择参数部分(settings):

html 复制代码
  <div class="selection">
    <label>队服颜色:</label>
    <select v-model="uniform_color">
      <option value="红">红</option>
      ...
    </select>
  </div>

响应式的选择器,以便于用户选择参数

  • <label>队服颜色:</label>:提供文字说明,告诉用户这个下拉框的作用
  • <select>:HTML 的下拉选择控件
  • v-model="uniform_color"双向绑定 uniform_color 用于同步用户选择数据
  • <option value="红">红</option>:每个 <option> 代表一个可选项,该选项被选中时,赋给 uniform_color 的实际值就为红

3、输出部分(output):

html 复制代码
<img :src="imgUrl" alt="" v-if="imgUrl">

同上,绑定的响应式变量 imgUrl 用于返还 Coze 工作流生成后的图片

html 复制代码
<div v-if="status">{{ status }}</div>

显示当前操作的状态提示信息,为用户提供及时的反馈

  • v-if="status":只有当 status 有内容时才渲染
  • {{ status }}:将 status 的文本内容插入到页面中

二、<script setup> ------ 业务逻辑核心

基于业务需求,我们的开发流程总体为:定义响应式状态(数据层) --> 实现图片预览(本地交互) --> 实现文件上传到 Coze(前置依赖) --> 调用工作流生成图像(核心业务) --> 环境变量与 API 配置(支撑信息)

html 复制代码
<script setup>
import { ref, onMounted } from 'vue'

// --------------- 定义响应式状态 -------------------
const uniform_number = ref(10);
const uniform_color = ref('红');
const position = ref(0);
const shooting_hand = ref(0);
const style = ref('写实')
// 数据状态
const status = ref('');     // 反馈用户当前操作状态(空 / 上传中 / 生成中 / 错误)
const imgUrl = ref('');     // 用于存储最终生成的图片 URL
const imgPreview = ref(''); // 用于本地预览用户上传的原图

// --------------- 图片预览模块 -------------------
const uploadImage = ref(null);

onMounted(() => {
  console.log(uploadImage.value)
})
const updateImageData = () => {
  const input = uploadImage.value;
  if (!input.files || input.files.length === 0) {
    return;
  }
  const file = input.files[0];
  console.log(file);
  const reader = new FileReader();
  reader.readAsDataURL(file); 
  reader.onload = (e) => { 
    imgPreview.value = e.target.result;
  }
}


// --------------- 大厂常用业务请求 ----------------
const patToken = import.meta.env.VITE_PAT_TOKEN;
const uploadUrl = 'https://api.coze.cn/v1/files/upload';
const uploadFile = async () => {
  const formData = new FormData(); 
  const input = uploadImage.value;
  if (!input.files || input.files.length <= 0) return;
  formData.append('file', input.files[0]);

  const res = await fetch(uploadUrl, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${patToken}`
    },
    body: formData
  })

  const ret = await res.json();
  console.log(ret);

  if( ret.code !== 0) {
    status.value = ret.msg; 
    return
  }
  return ret.data.id;
}

// --------------- 生成图片模块 -------------------
const workflowUrl = 'https://api.coze.cn/v1/workflow/run';
const workflow_id = 'XXXXXXX';

const generate = async () => {
  status.value = "图片上传中..."
  const file_id = await uploadFile();
  if (!file_id) return;
  status.value = "图片上传成功,正在生成...";

// workflow 调用 
  const parameters = {
    picture: JSON.stringify({
      file_id
    }),
    style: style.value,
    uniform_color: uniform_color.value,
    uniform_number: uniform_number.value,
    position: position.value,
    shooting_hand: shooting_hand.value,
  }

  const res = await fetch(workflowUrl, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${patToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      workflow_id,
      parameters
    })
  });
  const ret = await res.json();
  if( ret.code !== 0) {
    status.value = ret.msg;
    return;
  }

  const data = JSON.parse(ret.data);
  console.log(data);
  status.value = '';
  imgUrl.value = data.data;
}
</script>

1、定义响应式状态(数据层):

js 复制代码
// 用户选择参数,并且设定初始值
const uniform_number = ref(10);
const uniform_color = ref('红');
const position = ref(0);
const shooting_hand = ref(0);
const style = ref('写实')

// 数据状态
const status = ref(''); // 空 -> 上传中 -> 生成中 -> 生成成功
const imgUrl = ref(''); // 生成图片url

2、图片预览功能(本地交互):

js 复制代码
const uploadImage = ref(null);

onMounted(() => {
  console.log(uploadImage.value)
})
const updateImageData = () => {
  const input = uploadImage.value;
  if (!input.files || input.files.length === 0) {
    return;
  }
  const file = input.files[0];
  // console.log(file);
  const reader = new FileReader();
  reader.readAsDataURL(file); 
  reader.onload = (e) => { 
    imgPreview.value = e.target.result;
  }
}
定义响应式引用
js 复制代码
const uploadImage = ref(null);

标记模板中的 <input type="file">元素,未挂载前为 null,便于访问该DOM元素

生命周期钩子:组件挂载时执行的操作
js 复制代码
// null -> DOM对象 (变化)
onMounted(() => {
  console.log(uploadImage.value)
})

输出 uploadImage.value 到控制台,便于检查此时是否已经正确绑定了 <input> 元素。如果绑定成功,uploadImage.value 就指向上面的 <input> 元素。

更新图片数据方法
js 复制代码
// 用户选择文件后调用
const updateImageData = () => {
  const input = uploadImage.value;
  // console.log(uploadImage.value.files); 
  if (!input.files || input.files.length === 0) {
    return;
  }
  const file = input.files[0];
  // console.log(file);
  const reader = new FileReader();
  reader.readAsDataURL(file); 
  reader.onload = (e) => { 
    imgPreview.value = e.target.result;
  }
}
  • if (!input.files || input.files.length === 0) return;:判断用户上传的文件中是否至少包含一个文件
  • const file = input.files[0];:取出用户上传的第一个文件(因为不知道用户会上传多少文件,但是我们单次只能处理一个)
  • reader.readAsDataURL(file);:用新创建的 FileReader 实例上的 readAsDataURL 方法将文件转换为 Base64 编码的字符串(这种格式可以直接作为图像的URL使用)
  • reader.onload = (e) => { imgPreview.value = e.target.result; }:onload 是一个事件处理器(回调函数),会自动触发 load 事件,这里也就是事件对象 e,而e.target指的是触发该事件的对象(也就是reader),e.target.result就是转换为 Base64 编码的字符串,并且赋值给本地预览的响应式数据 imgPreview,这样页面上就会自动更新

⚠️ 注意:文件读取是异步的 ,不能直接写 let result = reader.readAsDataURL(file),必须用回调或 Promise。


3、文件上传至 Coze 云服务:

js 复制代码
const patToken = import.meta.env.VITE_PAT_TOKEN;
const uploadUrl = 'https://api.coze.cn/v1/files/upload';
// 先上传到coze服务器 
const uploadFile = async () => {
  // 创建一个空表单用于提交数据
  const formData = new FormData(); // FormData专门用于构建form-data格式数据的对象,常用于传输文件
  const input = uploadImage.value;
  if (!input.files || input.files.length <= 0) return;
  formData.append('file', input.files[0]);

  // 向 coze 发送http请求 上传
  const res = await fetch(uploadUrl, {
    method: 'POST', 
    headers: {
      'Authorization': `Bearer ${patToken}`
    },
    body: formData
  })

  // 等待返还内容(异步),并转换为json格式
  const ret = await res.json();
  // console.log(ret);

  // 错误判断
  if( ret.code !== 0) {
    status.value = ret.msg; 
    return;
  }
  return ret.data.id;
}
  • const patToken = import.meta.env.VITE_PAT_TOKEN;:获取认证令牌,在项目根目录中创建.env文件,在其中放置你的私有访问令牌。
  • const uploadUrl = 'https://api.coze.cn/v1/files/upload';:Coze 官方提供的文件上传 API 地址
  • formData.append('file', input.files[0]);:将用户选中的第一个文件附加到表单字段名为 file 的字段上

⚠️ 注意:Coze API 要求字段名必须是 'file',否则会报错

  • const res = await fetch(uploadUrl, {...}):向 Coze 上传文件
响应结构(Coze API 规范):
js 复制代码
  const ret = await res.json();

  // 错误判断
  if( ret.code !== 0) {
    status.value = ret.msg; 
    return;
  }
  return ret.data.id;

Coze 的 API 通常返回如下 JSON 结构:

json 复制代码
{
  "code": 0,
  "msg": "success",
  "data": {
    "id": "file-abc123xyz",   // ← 我们需要的 file_id
    "name": "cat.jpg",
    "size": 123456
  }
}
  • ret.code !== 0:判断是否出错(code === 0 表示成功)。
  • status.value = ret.msg:将错误信息显示给用户。
  • return ret.data.id:成功时返回 file_id(字符串),供后续工作流调用使用。

注: 这个 file_id 是 Coze 系统内部对文件的唯一引用,后续在调用工作流时,只需传递这个 ID,无需再传整个文件。


4、触发 Coze 工作流生成图像(核心业务):

js 复制代码
const workflowUrl = 'https://api.coze.cn/v1/workflow/run';
const workflow_id = 'XXXXXXX';

const generate = async () => {
  status.value = "图片上传中..."
  const file_id = await uploadFile();
  if (!file_id) return;
  status.value = "图片上传成功,正在生成...";

// workflow 调用 
  const parameters = {
    picture: JSON.stringify({
      file_id
    }),
    style: style.value,
    uniform_color: uniform_color.value,
    uniform_number: uniform_number.value,
    position: position.value,
    shooting_hand: shooting_hand.value,
  }

  const res = await fetch(workflowUrl, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${patToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      workflow_id,
      parameters
    })
  });
  const ret = await res.json();
  if( ret.code !== 0) {
    status.value = ret.msg;
    return;
  }

  const data = JSON.parse(ret.data);
  console.log(data);
  status.value = '';
  imgUrl.value = data.data;
}
  • const workflowUrl = 'https://api.coze.cn/v1/workflow/run';:Coze 官方提供的 工作流执行 API 地址
  • const workflow_id = 'XXXXXXX';:你在 Coze 控制台创建的工作流的唯一 ID(在 Coze Bot 或 Workflow 编排界面可找到)
  • const file_id = await uploadFile();:取到返回的 file_id

为什么先上传?

Coze 的工作流无法直接处理前端的本地文件或 Base64,必须使用之前通过接口上传后返回的 file_id

解析最终图片 URL
js 复制代码
const data = JSON.parse(ret.data);
console.log(data);
status.value = '';
imgUrl.value = data.data;

❗ 为什么需要两次 JSON.parse

这是 Coze 工作流 API 的特殊设计

  • 第一层 ret.data 是一个 JSON 字符串 (不是对象!)

    js 复制代码
    ret.data === '{"data":"https://cdn.coze.com/generated.jpg"}'
  • 所以必须用 JSON.parse(ret.data) 得到真正的对象:

    js 复制代码
    const data = { data: "https://cdn.coze.com/generated.jpg" };

最终图片 URL 在 data.data 中。

📌 这是因为 Coze 工作流的输出通常被封装为字符串,确保兼容性


三、CSS 样式优化

css 复制代码
    .container {
      display: flex;
      flex-direction: row;
      align-items: start;
      justify-content: start;
      height: 100vh;
      font-size: .85rem;
    }

    .input {
      display: flex;
      flex-direction: column;
      min-width: 330px;
    }

    .output {
      margin-top: 10px;
      min-height: 300px;
      width: 100%;
      text-align: left;
    }

    .generated {
      width: 400px;
      height: 400px;
      border: solid 1px black;
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .output img {
      width: 100%;
    }

效果演示:

📚 学习资源推荐

类别 推荐内容
Vue3 Vue 官方文档
Coze Coze 开发者中心
REST API MDN Fetch API 文档
前端工程化 Vite、Webpack、JavaScript

📝 最后

这个项目不仅是一个简单的"AI图像生成器",更是现代 Web 开发的一个缩影:前端负责交互与体验,AI 提供智能能力,API 连接两者 😊,这也是当下的趋势:无代码/低代码 + 可视化 AI 编排 + 前端集成

AI 原生应用」的崛起

  • 传统 AI 开发:需要算法工程师 + 后端 + 前端,周期长、成本高。

  • 新范式(Coze 代表):

    • 业务人员/前端开发者 通过拖拽工作流,组合大模型、插件、知识库;
    • 前端直接调用工作流 API,像调用普通接口一样获取 AI 结果;
    • 无需维护后端服务,Coze 托管执行环境。

这就是 "AI as a Service"(AI 即服务)

相关推荐
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅9 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅10 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅10 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊10 小时前
jwt介绍
前端
爱敲代码的小鱼10 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax