# 速创生图接口调用示例 ## 一、数据库配置说明 ### 1. 执行SQL脚本 ```bash # 在MySQL中执行V9脚本 mysql -u root -p 1818ai < V9__add_suchuang_image_models.sql ``` ### 2. 配置结果 执行后会在 `points_config` 表中插入以下模型: #### 文生图模型(4个) | model_name | description | points_cost | task_type | aspectRatio | |------------|-------------|-------------|-----------|-------------| | sc_soraimg_text_auto | 速创生图 文生图-自动比例 | 30 | text_to_image | auto | | sc_soraimg_text_1x1 | 速创生图 文生图-正方形(1:1) | 30 | text_to_image | 1:1 | | sc_soraimg_text_2x3 | 速创生图 文生图-竖图(2:3) | 30 | text_to_image | 2:3 | | sc_soraimg_text_3x2 | 速创生图 文生图-横图(3:2) | 30 | text_to_image | 3:2 | #### 图生图模型(4个) | model_name | description | points_cost | task_type | aspectRatio | |------------|-------------|-------------|-----------|-------------| | sc_soraimg_img2img_auto | 速创生图 图生图-自动比例 | 35 | image_to_image | auto | | sc_soraimg_img2img_1x1 | 速创生图 图生图-正方形(1:1) | 35 | image_to_image | 1:1 | | sc_soraimg_img2img_2x3 | 速创生图 图生图-竖图(2:3) | 35 | image_to_image | 2:3 | | sc_soraimg_img2img_3x2 | 速创生图 图生图-横图(3:2) | 35 | image_to_image | 3:2 | --- ## 二、接口调用示例 ### 前提条件 - 用户已登录,获得 JWT Token - 或使用 API Key 认证 - 用户积分充足 ### 基础URL ``` http://localhost:8081 ``` --- ## 三、文生图调用示例 ### 1. cURL 示例 #### 1.1 正方形图片(1:1) ```bash curl -X POST "http://localhost:8081/user/ai/tasks/submit" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -d '{ "modelName": "sc_soraimg_text_1x1", "prompt": "一个可爱的橘猫在窗台上晒太阳,温馨的室内场景,柔和的光线" }' ``` #### 1.2 横图(3:2) ```bash curl -X POST "http://localhost:8081/user/ai/tasks/submit" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -d '{ "modelName": "sc_soraimg_text_3x2", "prompt": "壮丽的山脉日出,金色阳光洒满山谷,风景摄影风格" }' ``` #### 1.3 竖图(2:3) ```bash curl -X POST "http://localhost:8081/user/ai/tasks/submit" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -d '{ "modelName": "sc_soraimg_text_2x3", "prompt": "高耸的瀑布从山崖飞流而下,竖构图,气势磅礴" }' ``` ### 2. JavaScript Fetch 示例 ```javascript // 文生图 - 正方形 const response = await fetch("http://localhost:8081/user/ai/tasks/submit", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${YOUR_JWT_TOKEN}` }, body: JSON.stringify({ modelName: "sc_soraimg_text_1x1", prompt: "科幻风格的未来城市,霓虹灯光,赛博朋克风格" }) }); const result = await response.json(); console.log("任务编号:", result.data.taskNo); console.log("任务状态:", result.data.status); ``` ### 3. Python Requests 示例 ```python import requests url = "http://localhost:8081/user/ai/tasks/submit" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {YOUR_JWT_TOKEN}" } data = { "modelName": "sc_soraimg_text_1x1", "prompt": "梦幻的樱花树下,粉色花瓣飘落,动漫风格" } response = requests.post(url, json=data, headers=headers) result = response.json() print(f"任务编号: {result['data']['taskNo']}") print(f"任务状态: {result['data']['status']}") ``` --- ## 四、图生图调用示例 ### 1. cURL 示例 #### 1.1 单张参考图 ```bash curl -X POST "http://localhost:8081/user/ai/tasks/submit" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -d '{ "modelName": "sc_soraimg_img2img_1x1", "prompt": "把这张照片转换成可爱的卡通Q版潮玩形象,保留原有特征,增加萌趣感", "imageUrl": "https://oss-1818ai-user-img.oss-cn-hangzhou.aliyuncs.com/user123/photo.jpg" }' ``` #### 1.2 多张参考图(JSON数组) ```bash curl -X POST "http://localhost:8081/user/ai/tasks/submit" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -d '{ "modelName": "sc_soraimg_img2img_3x2", "prompt": "结合这些参考图的风格,创作一幅新的艺术作品", "imageUrl": "[\"https://example.com/ref1.jpg\",\"https://example.com/ref2.jpg\"]" }' ``` ### 2. JavaScript Fetch 示例 ```javascript // 图生图 - 单张参考图 const response = await fetch("http://localhost:8081/user/ai/tasks/submit", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${YOUR_JWT_TOKEN}` }, body: JSON.stringify({ modelName: "sc_soraimg_img2img_1x1", prompt: "将人物转换为油画风格,色彩浓郁,笔触明显", imageUrl: "https://oss-1818ai-user-img.oss-cn-hangzhou.aliyuncs.com/portrait.jpg" }) }); const result = await response.json(); console.log("任务编号:", result.data.taskNo); ``` ```javascript // 图生图 - 多张参考图 const response = await fetch("http://localhost:8081/user/ai/tasks/submit", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${YOUR_JWT_TOKEN}` }, body: JSON.stringify({ modelName: "sc_soraimg_img2img_1x1", prompt: "融合多张参考图的元素,创作新设计", imageUrl: JSON.stringify([ "https://example.com/ref1.jpg", "https://example.com/ref2.jpg", "https://example.com/ref3.jpg" ]) }) }); ``` ### 3. Python Requests 示例 ```python import requests import json # 图生图 - 单张参考图 url = "http://localhost:8081/user/ai/tasks/submit" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {YOUR_JWT_TOKEN}" } data = { "modelName": "sc_soraimg_img2img_1x1", "prompt": "将这张风景照转换为水彩画风格", "imageUrl": "https://oss-1818ai-user-img.oss-cn-hangzhou.aliyuncs.com/landscape.jpg" } response = requests.post(url, json=data, headers=headers) result = response.json() # 图生图 - 多张参考图 data_multi = { "modelName": "sc_soraimg_img2img_3x2", "prompt": "结合参考图风格创作新作品", "imageUrl": json.dumps([ "https://example.com/ref1.jpg", "https://example.com/ref2.jpg" ]) } response = requests.post(url, json=data_multi, headers=headers) ``` --- ## 五、查询任务状态 ### 1. 查询单个任务详情 ```bash curl -X GET "http://localhost:8081/user/ai/tasks/TASK-20251026153045123-4567" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` **响应示例:** ```json { "code": 200, "message": "success", "data": { "taskNo": "TASK-20251026153045123-4567", "modelName": "sc_soraimg_text_1x1", "status": "completed", "taskType": "text_to_image", "progress": 100, "promptSnippet": "一个可爱的橘猫在窗台上晒太阳...", "imageUrl": null, "resultUrl": "https://oss-1818ai-user-img.oss-cn-hangzhou.aliyuncs.com/results/image_xxx.png", "createTime": "2025-10-26T15:30:45", "completeTime": "2025-10-26T15:31:12", "errorMessage": null } } ``` ### 2. 查询任务列表(按类型筛选) #### 查询所有文生图任务 ```bash curl -X GET "http://localhost:8081/user/ai/tasks/list?page=1&size=10&taskType=text_to_image" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` #### 查询所有图生图任务 ```bash curl -X GET "http://localhost:8081/user/ai/tasks/list?page=1&size=10&taskType=image_to_image" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` #### 查询所有生图任务(不区分类型) ```bash curl -X GET "http://localhost:8081/user/ai/tasks/list?page=1&size=10&status=completed" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ### 3. JavaScript 轮询示例 ```javascript // 提交任务后轮询状态 async function submitAndPoll(modelName, prompt, imageUrl = null) { // 1. 提交任务 const submitResponse = await fetch("http://localhost:8081/user/ai/tasks/submit", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${YOUR_JWT_TOKEN}` }, body: JSON.stringify({ modelName, prompt, imageUrl }) }); const submitResult = await submitResponse.json(); const taskNo = submitResult.data.taskNo; console.log(`任务已提交: ${taskNo}`); // 2. 轮询任务状态(每5秒查询一次) const pollInterval = setInterval(async () => { const statusResponse = await fetch( `http://localhost:8081/user/ai/tasks/${taskNo}`, { headers: { "Authorization": `Bearer ${YOUR_JWT_TOKEN}` } } ); const statusResult = await statusResponse.json(); const status = statusResult.data.status; const progress = statusResult.data.progress; console.log(`任务状态: ${status}, 进度: ${progress}%`); if (status === 'completed') { clearInterval(pollInterval); console.log(`任务完成!结果: ${statusResult.data.resultUrl}`); return statusResult.data.resultUrl; } if (status === 'failed') { clearInterval(pollInterval); console.error(`任务失败: ${statusResult.data.errorMessage}`); return null; } }, 5000); } // 使用示例 submitAndPoll("sc_soraimg_text_1x1", "一只可爱的柴犬"); ``` --- ## 六、查询积分余额 ```bash curl -X GET "http://localhost:8081/user/points/consumption/balance" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` **响应示例:** ```json { "code": 200, "message": "success", "data": { "userId": 17563793187762127, "balance": 850, "expireTime": null } } ``` --- ## 七、完整流程示例(前端实现) ```javascript class SuChuangImageGenerator { constructor(token, baseUrl = "http://localhost:8081") { this.token = token; this.baseUrl = baseUrl; } // 提交文生图任务 async generateImage(prompt, aspectRatio = "1:1") { const modelMap = { "auto": "sc_soraimg_text_auto", "1:1": "sc_soraimg_text_1x1", "2:3": "sc_soraimg_text_2x3", "3:2": "sc_soraimg_text_3x2" }; const response = await fetch(`${this.baseUrl}/user/ai/tasks/submit`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${this.token}` }, body: JSON.stringify({ modelName: modelMap[aspectRatio], prompt: prompt }) }); const result = await response.json(); if (result.code === 200) { return result.data.taskNo; } throw new Error(result.message); } // 提交图生图任务 async transformImage(prompt, imageUrl, aspectRatio = "1:1") { const modelMap = { "auto": "sc_soraimg_img2img_auto", "1:1": "sc_soraimg_img2img_1x1", "2:3": "sc_soraimg_img2img_2x3", "3:2": "sc_soraimg_img2img_3x2" }; const response = await fetch(`${this.baseUrl}/user/ai/tasks/submit`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${this.token}` }, body: JSON.stringify({ modelName: modelMap[aspectRatio], prompt: prompt, imageUrl: imageUrl }) }); const result = await response.json(); if (result.code === 200) { return result.data.taskNo; } throw new Error(result.message); } // 查询任务状态 async getTaskStatus(taskNo) { const response = await fetch(`${this.baseUrl}/user/ai/tasks/${taskNo}`, { headers: { "Authorization": `Bearer ${this.token}` } }); const result = await response.json(); if (result.code === 200) { return result.data; } throw new Error(result.message); } // 等待任务完成(带超时) async waitForCompletion(taskNo, timeout = 180000) { const startTime = Date.now(); return new Promise((resolve, reject) => { const interval = setInterval(async () => { try { const task = await this.getTaskStatus(taskNo); if (task.status === 'completed') { clearInterval(interval); resolve(task.resultUrl); } else if (task.status === 'failed') { clearInterval(interval); reject(new Error(task.errorMessage || '任务失败')); } else if (Date.now() - startTime > timeout) { clearInterval(interval); reject(new Error('任务超时')); } } catch (error) { clearInterval(interval); reject(error); } }, 5000); }); } // 查询积分余额 async getBalance() { const response = await fetch(`${this.baseUrl}/user/points/consumption/balance`, { headers: { "Authorization": `Bearer ${this.token}` } }); const result = await response.json(); if (result.code === 200) { return result.data.balance; } throw new Error(result.message); } } // 使用示例 const generator = new SuChuangImageGenerator(YOUR_JWT_TOKEN); // 文生图 generator.generateImage("一只可爱的柴犬", "1:1") .then(taskNo => { console.log(`任务已提交: ${taskNo}`); return generator.waitForCompletion(taskNo); }) .then(imageUrl => { console.log(`图片生成完成: ${imageUrl}`); }) .catch(error => { console.error(`生成失败: ${error.message}`); }); // 图生图 generator.transformImage( "转换为卡通Q版风格", "https://example.com/photo.jpg", "1:1" ).then(taskNo => { console.log(`任务已提交: ${taskNo}`); return generator.waitForCompletion(taskNo); }).then(imageUrl => { console.log(`图片转换完成: ${imageUrl}`); }); ``` --- ## 八、错误处理 ### 常见错误码 | 错误码 | 说明 | 解决方案 | |--------|------|----------| | 401 | 未登录或Token过期 | 重新登录获取Token | | 402 | 积分不足 | 充值积分 | | 400 | 参数错误 | 检查请求参数 | | 500 | 服务器错误 | 联系管理员 | ### 错误处理示例 ```javascript try { const taskNo = await generator.generateImage("测试prompt", "1:1"); const imageUrl = await generator.waitForCompletion(taskNo); console.log("成功:", imageUrl); } catch (error) { if (error.message.includes("积分不足")) { console.error("请先充值积分"); // 跳转到充值页面 } else if (error.message.includes("未登录")) { console.error("请先登录"); // 跳转到登录页面 } else { console.error("生成失败:", error.message); } } ``` --- ## 九、注意事项 1. **积分消耗** - 文生图:30积分/张 - 图生图:35积分/张 - 任务提交时立即扣除积分 - 任务失败会自动退还积分 2. **图片URL要求** - 必须是外网可访问的URL - 支持 https 和 http 协议 - 建议使用自有OSS存储的URL - 图生图支持单张或多张参考图 3. **结果存储** - 生成的图片会自动转存到您的OSS - resultUrl 为永久有效的OSS链接 - 第三方临时URL会被自动替换 4. **任务状态** - created: 已创建 - queued: 排队中 - processing: 生成中 - completed: 已完成 - failed: 失败 5. **超时时间** - 生图任务通常在 30-120 秒内完成 - 建议轮询间隔: 5秒 - 建议超时时间: 180秒 --- ## 十、技术支持 如有问题,请联系技术支持或查看服务器日志: - 日志会记录完整的提交负载和API响应 - 错误信息统一为中文,不会乱码 - 支持 WebSocket 推送任务完成通知