[Claude Workbench] Initial commit - preserving existing code

This commit is contained in:
Claude Workbench
2025-11-14 17:41:15 +08:00
commit 0f7bc05697
587 changed files with 103215 additions and 0 deletions

View File

@@ -0,0 +1,590 @@
# 速创生图接口调用示例
## 一、数据库配置说明
### 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 推送任务完成通知