修改
This commit is contained in:
2
.env
2
.env
@@ -1,5 +1,7 @@
|
|||||||
# 速创API配置
|
# 速创API配置
|
||||||
API_KEY=G9rXx3Ag2Xfa7Gs8zou6t6HqeZ
|
API_KEY=G9rXx3Ag2Xfa7Gs8zou6t6HqeZ
|
||||||
|
#NlJmFJ3af3EsA1g6DhgBAJgCaN
|
||||||
|
|
||||||
API_BASE_URL=https://api.wuyinkeji.com
|
API_BASE_URL=https://api.wuyinkeji.com
|
||||||
|
|
||||||
# 生图接口
|
# 生图接口
|
||||||
|
|||||||
139
TROUBLESHOOTING.md
Normal file
139
TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# 故障排查指南
|
||||||
|
|
||||||
|
## 查询超时问题诊断
|
||||||
|
|
||||||
|
如果遇到"查询超时,已查询XX次"的问题,请按以下步骤排查:
|
||||||
|
|
||||||
|
### 1. 检查任务ID是否正确
|
||||||
|
|
||||||
|
**症状**:查询时返回404错误或任务未找到
|
||||||
|
|
||||||
|
**解决方法**:
|
||||||
|
- 查看控制台输出的"完整响应数据",确认任务ID是否正确获取
|
||||||
|
- 检查任务ID的类型和格式(应该是数字)
|
||||||
|
- 确认生图接口返回的响应格式是否符合预期
|
||||||
|
|
||||||
|
**调试命令**:
|
||||||
|
```bash
|
||||||
|
# 运行时会输出完整的API响应,检查任务ID字段
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 检查API响应格式
|
||||||
|
|
||||||
|
**症状**:查询返回的数据格式不符合预期
|
||||||
|
|
||||||
|
**解决方法**:
|
||||||
|
- 查看控制台输出的"完整API响应"
|
||||||
|
- 确认 `data.code` 是否为 200
|
||||||
|
- 确认 `data.data.status` 是否存在
|
||||||
|
- 确认 `data.data.image_url` 字段名称是否正确
|
||||||
|
|
||||||
|
**常见问题**:
|
||||||
|
- API响应格式可能已更新,需要调整代码中的字段名
|
||||||
|
- 某些情况下 `image_url` 可能是 `imageUrl` 或其他名称
|
||||||
|
|
||||||
|
### 3. 检查图片生成状态
|
||||||
|
|
||||||
|
**症状**:状态一直显示"排队中"或"生成中",从未变为"成功"
|
||||||
|
|
||||||
|
**可能原因**:
|
||||||
|
1. **图片生成时间过长**:高分辨率(2K/4K)或复杂prompt需要更长时间
|
||||||
|
2. **API服务繁忙**:排队任务较多
|
||||||
|
3. **任务实际已失败**:但状态未更新为失败
|
||||||
|
|
||||||
|
**解决方法**:
|
||||||
|
- 增加 `MAX_QUERY_COUNT` 到 180 或更高
|
||||||
|
- 增加 `QUERY_INTERVAL` 到 10000(10秒)
|
||||||
|
- 检查API服务状态
|
||||||
|
- 尝试降低图片分辨率(使用1K而不是2K)
|
||||||
|
|
||||||
|
### 4. 检查API密钥和权限
|
||||||
|
|
||||||
|
**症状**:返回401或403错误
|
||||||
|
|
||||||
|
**解决方法**:
|
||||||
|
- 确认 `.env` 文件中的 `API_KEY` 正确
|
||||||
|
- 检查API密钥是否过期
|
||||||
|
- 确认账户余额是否充足
|
||||||
|
- 检查API密钥是否有查询接口的权限
|
||||||
|
|
||||||
|
### 5. 检查网络连接
|
||||||
|
|
||||||
|
**症状**:请求超时或网络错误
|
||||||
|
|
||||||
|
**解决方法**:
|
||||||
|
- 检查网络连接
|
||||||
|
- 确认可以访问 `https://api.wuyinkeji.com`
|
||||||
|
- 检查防火墙设置
|
||||||
|
- 尝试增加请求超时时间
|
||||||
|
|
||||||
|
### 6. 手动测试API
|
||||||
|
|
||||||
|
**使用curl测试查询接口**:
|
||||||
|
```bash
|
||||||
|
# 替换 YOUR_API_KEY 和 TASK_ID
|
||||||
|
curl -X GET "https://api.wuyinkeji.com/api/img/drawDetail?id=TASK_ID" \
|
||||||
|
-H "Authorization: YOUR_API_KEY" \
|
||||||
|
-H "Content-Type: application/json;charset:utf-8;"
|
||||||
|
```
|
||||||
|
|
||||||
|
**使用curl测试生图接口**:
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://api.wuyinkeji.com/api/img/nanoBanana-pro" \
|
||||||
|
-H "Authorization: YOUR_API_KEY" \
|
||||||
|
-H "Content-Type: application/json;charset:utf-8;" \
|
||||||
|
-d '{
|
||||||
|
"prompt": "test prompt",
|
||||||
|
"imageSize": "1K",
|
||||||
|
"aspectRatio": "1:1"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. 查看详细日志
|
||||||
|
|
||||||
|
代码已增强日志输出,运行时会显示:
|
||||||
|
- ✅ 任务提交时的完整响应
|
||||||
|
- ✅ 每次查询的详细状态
|
||||||
|
- ✅ 每10次查询的完整API响应
|
||||||
|
- ✅ 所有错误信息
|
||||||
|
|
||||||
|
**关键日志位置**:
|
||||||
|
1. 任务提交后:查看"完整响应数据",确认任务ID
|
||||||
|
2. 查询过程中:查看"查询结果详情",确认状态值
|
||||||
|
3. 错误时:查看"完整错误响应",了解具体错误原因
|
||||||
|
|
||||||
|
### 8. 常见错误码说明
|
||||||
|
|
||||||
|
| 错误码 | 说明 | 解决方法 |
|
||||||
|
|--------|------|----------|
|
||||||
|
| 200 | 成功 | - |
|
||||||
|
| 400 | 请求参数错误 | 检查请求参数格式 |
|
||||||
|
| 401 | 认证失败 | 检查API密钥 |
|
||||||
|
| 403 | 权限不足 | 检查API密钥权限 |
|
||||||
|
| 404 | 任务未找到 | 检查任务ID是否正确 |
|
||||||
|
| 500 | 服务器错误 | 稍后重试或联系API服务商 |
|
||||||
|
|
||||||
|
### 9. 推荐配置
|
||||||
|
|
||||||
|
对于稳定的图片生成,建议使用以下配置:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# 查询间隔:10秒(减少API调用频率)
|
||||||
|
QUERY_INTERVAL=10000
|
||||||
|
|
||||||
|
# 最大查询次数:180次(对应30分钟)
|
||||||
|
MAX_QUERY_COUNT=180
|
||||||
|
|
||||||
|
# 图片尺寸:1K(生成速度更快,适合测试)
|
||||||
|
IMAGE_SIZE=1K
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10. 联系支持
|
||||||
|
|
||||||
|
如果以上方法都无法解决问题:
|
||||||
|
1. 收集完整的日志输出
|
||||||
|
2. 记录任务ID和错误信息
|
||||||
|
3. 联系速创API技术支持
|
||||||
|
4. 提供复现步骤和错误详情
|
||||||
|
|
||||||
@@ -16,9 +16,9 @@ SOURCE_IMAGE_URL=https://your-image-host.com/P1191464.JPG
|
|||||||
IMAGE_SIZE=2K
|
IMAGE_SIZE=2K
|
||||||
ASPECT_RATIO=1:1
|
ASPECT_RATIO=1:1
|
||||||
|
|
||||||
# 查询间隔(毫秒)
|
# 查询间隔(毫秒)- 建议10秒,减少API调用频率
|
||||||
QUERY_INTERVAL=5000
|
QUERY_INTERVAL=10000
|
||||||
|
|
||||||
# 最大查询次数
|
# 最大查询次数 - 建议120-180次(对应20-30分钟)
|
||||||
MAX_QUERY_COUNT=60
|
MAX_QUERY_COUNT=120
|
||||||
|
|
||||||
|
|||||||
232
index.js
232
index.js
@@ -8,7 +8,10 @@ const config = {
|
|||||||
apiKey: process.env.API_KEY,
|
apiKey: process.env.API_KEY,
|
||||||
apiBaseUrl: process.env.API_BASE_URL || 'https://api.wuyinkeji.com',
|
apiBaseUrl: process.env.API_BASE_URL || 'https://api.wuyinkeji.com',
|
||||||
generateApi: process.env.GENERATE_API || '/api/img/nanoBanana-pro',
|
generateApi: process.env.GENERATE_API || '/api/img/nanoBanana-pro',
|
||||||
queryApi: process.env.QUERY_API || '/api/img/drawDetail',
|
// 强制使用正确的查询接口路径,避免配置错误
|
||||||
|
queryApi: (process.env.QUERY_API && process.env.QUERY_API.includes('drawDetail'))
|
||||||
|
? process.env.QUERY_API
|
||||||
|
: '/api/img/drawDetail',
|
||||||
sourceImageUrl: process.env.SOURCE_IMAGE_URL,
|
sourceImageUrl: process.env.SOURCE_IMAGE_URL,
|
||||||
imageSize: process.env.IMAGE_SIZE || '2K',
|
imageSize: process.env.IMAGE_SIZE || '2K',
|
||||||
aspectRatio: process.env.ASPECT_RATIO || '1:1',
|
aspectRatio: process.env.ASPECT_RATIO || '1:1',
|
||||||
@@ -17,6 +20,13 @@ const config = {
|
|||||||
outputDir: path.join(__dirname, 'img_2')
|
outputDir: path.join(__dirname, 'img_2')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 验证查询接口路径
|
||||||
|
if (!config.queryApi.includes('drawDetail')) {
|
||||||
|
console.warn(`⚠️ 警告: 查询接口路径可能不正确: ${config.queryApi}`);
|
||||||
|
console.warn(` 已自动修正为: /api/img/drawDetail`);
|
||||||
|
config.queryApi = '/api/img/drawDetail';
|
||||||
|
}
|
||||||
|
|
||||||
// 确保输出目录存在
|
// 确保输出目录存在
|
||||||
if (!fs.existsSync(config.outputDir)) {
|
if (!fs.existsSync(config.outputDir)) {
|
||||||
fs.mkdirSync(config.outputDir, { recursive: true });
|
fs.mkdirSync(config.outputDir, { recursive: true });
|
||||||
@@ -90,11 +100,33 @@ async function generateImage(prompt, imageConfig) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.data && response.data.code === 200) {
|
if (response.data && response.data.code === 200) {
|
||||||
const taskId = response.data.data?.id || response.data.data?.taskId || response.data.taskId;
|
// 根据API文档,查询接口需要的是 data.id(图片ID),不是 task_id
|
||||||
console.log(`✅ 任务提交成功,任务ID: ${taskId}`);
|
// 优先使用 data.id,这是查询接口需要的ID
|
||||||
return { success: true, taskId, name: prompt.name };
|
const taskId = response.data.data?.id ||
|
||||||
|
response.data.data?.taskId ||
|
||||||
|
response.data.taskId ||
|
||||||
|
response.data.id;
|
||||||
|
|
||||||
|
// 如果获取到的是 task_id(字符串格式),需要找到对应的 id
|
||||||
|
// 因为查询接口需要的是数字 id,而不是 task_id
|
||||||
|
if (!taskId) {
|
||||||
|
console.error(`❌ 无法获取任务ID,完整响应:`, JSON.stringify(response.data, null, 2));
|
||||||
|
return { success: false, error: '无法获取任务ID' };
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`✅ 任务提交成功`);
|
||||||
|
console.log(`📋 完整响应数据:`, JSON.stringify(response.data, null, 2));
|
||||||
|
console.log(`📝 任务ID (用于查询): ${taskId} (类型: ${typeof taskId})`);
|
||||||
|
if (response.data.data?.task_id) {
|
||||||
|
console.log(`📝 任务task_id: ${response.data.data.task_id}`);
|
||||||
|
}
|
||||||
|
console.log(`⚠️ 注意: 查询接口需要使用 data.id (${response.data.data?.id || '未找到'}),而不是 task_id`);
|
||||||
|
|
||||||
|
// 确保使用 data.id 作为查询ID
|
||||||
|
const queryId = response.data.data?.id || taskId;
|
||||||
|
return { success: true, taskId: queryId, name: prompt.name };
|
||||||
} else {
|
} else {
|
||||||
console.error(`❌ 任务提交失败:`, response.data);
|
console.error(`❌ 任务提交失败:`, JSON.stringify(response.data, null, 2));
|
||||||
return { success: false, error: response.data };
|
return { success: false, error: response.data };
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -111,27 +143,46 @@ async function generateImage(prompt, imageConfig) {
|
|||||||
*/
|
*/
|
||||||
async function queryImageResult(taskId, imageName) {
|
async function queryImageResult(taskId, imageName) {
|
||||||
let queryCount = 0;
|
let queryCount = 0;
|
||||||
|
let queryInterval = null;
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
// 执行单次查询的函数
|
||||||
const queryInterval = setInterval(async () => {
|
const performQuery = async () => {
|
||||||
queryCount++;
|
queryCount++;
|
||||||
|
|
||||||
if (queryCount > config.maxQueryCount) {
|
if (queryCount > config.maxQueryCount) {
|
||||||
|
if (queryInterval) {
|
||||||
clearInterval(queryInterval);
|
clearInterval(queryInterval);
|
||||||
reject(new Error(`查询超时,已查询${queryCount}次`));
|
}
|
||||||
return;
|
throw new Error(`查询超时,已查询${queryCount}次`);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 根据API文档: https://api.wuyinkeji.com/doc/9
|
// 根据API文档: https://api.wuyinkeji.com/doc/9
|
||||||
// 接口地址: https://api.wuyinkeji.com/api/img/drawDetail
|
// 接口地址: https://api.wuyinkeji.com/api/img/drawDetail
|
||||||
// 请求方式: GET
|
// 请求方式: GET
|
||||||
// 请求参数: id (必填, int类型) - 图片ID
|
// 请求参数: id (必填, int类型) - 图片ID(注意:是 data.id,不是 task_id)
|
||||||
// 返回格式: data.status (0:排队中,1:生成中,2:成功,3:失败)
|
// 返回格式: data.status (0:排队中,1:生成中,2:成功,3:失败)
|
||||||
// data.image_url (生成的图片地址)
|
// data.image_url (生成的图片地址)
|
||||||
const queryUrl = `${config.apiBaseUrl}${config.queryApi}?id=${taskId}`;
|
|
||||||
|
|
||||||
console.log(`[${queryCount}/${config.maxQueryCount}] 查询任务状态: ID=${taskId}`);
|
// 确保查询接口路径正确
|
||||||
|
const queryApiPath = config.queryApi || '/api/img/drawDetail';
|
||||||
|
if (!queryApiPath.includes('drawDetail')) {
|
||||||
|
console.error(`❌ 警告: 查询接口路径可能不正确: ${queryApiPath}`);
|
||||||
|
console.error(` 正确的路径应该是: /api/img/drawDetail`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保ID是数字类型(查询接口要求int类型)
|
||||||
|
const queryId = typeof taskId === 'string' && /^\d+$/.test(taskId)
|
||||||
|
? parseInt(taskId)
|
||||||
|
: taskId;
|
||||||
|
|
||||||
|
const queryUrl = `${config.apiBaseUrl}${queryApiPath}?id=${queryId}`;
|
||||||
|
|
||||||
|
console.log(`[${queryCount}/${config.maxQueryCount}] 查询任务状态: ID=${queryId} (原始: ${taskId}, 类型: ${typeof queryId})`);
|
||||||
|
console.log(`🔗 查询URL: ${queryUrl}`);
|
||||||
|
if (queryCount === 1) {
|
||||||
|
console.log(`🔑 使用API密钥: ${config.apiKey ? config.apiKey.substring(0, 10) + '...' : '未设置'}`);
|
||||||
|
}
|
||||||
|
|
||||||
const response = await axios.get(queryUrl, {
|
const response = await axios.get(queryUrl, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -143,53 +194,167 @@ async function queryImageResult(taskId, imageName) {
|
|||||||
|
|
||||||
const data = response.data;
|
const data = response.data;
|
||||||
|
|
||||||
|
// 首次查询或每10次查询打印完整响应(用于调试)
|
||||||
|
if (queryCount === 1 || queryCount % 10 === 0) {
|
||||||
|
console.log(`📋 完整API响应 (第${queryCount}次查询):`, JSON.stringify(data, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
// 根据API文档响应格式:
|
// 根据API文档响应格式:
|
||||||
// code: 状态码
|
// code: 状态码
|
||||||
// msg: 状态信息
|
// msg: 状态信息
|
||||||
// data.status: 0:排队中,1:生成中,2:成功,3:失败
|
// data.status: 0:排队中,1:生成中,2:成功,3:失败
|
||||||
// data.image_url: 生成的图片地址
|
// data.image_url: 生成的图片地址
|
||||||
if (data.code === 200 && data.data) {
|
if (data.code === 200 && data.data) {
|
||||||
const status = data.data.status;
|
// 处理 status 可能是数字或字符串的情况
|
||||||
|
const status = parseInt(data.data.status);
|
||||||
const imageUrl = data.data.image_url;
|
const imageUrl = data.data.image_url;
|
||||||
|
|
||||||
// status: 2 表示成功
|
// 添加详细日志
|
||||||
if (status === 2) {
|
const statusText = status === 0 ? '排队中' : status === 1 ? '生成中' : status === 2 ? '成功' : status === 3 ? '失败' : `未知(${status})`;
|
||||||
if (imageUrl) {
|
console.log(`📊 查询结果详情:`, {
|
||||||
|
status: status,
|
||||||
|
statusType: typeof data.data.status,
|
||||||
|
statusText: statusText,
|
||||||
|
hasImageUrl: !!imageUrl,
|
||||||
|
imageUrl: imageUrl ? (imageUrl.length > 100 ? imageUrl.substring(0, 100) + '...' : imageUrl) : '无',
|
||||||
|
imageUrlLength: imageUrl ? imageUrl.length : 0,
|
||||||
|
prompt: data.data.prompt ? (data.data.prompt.substring(0, 50) + '...') : '无',
|
||||||
|
createdAt: data.data.created_at || '无',
|
||||||
|
updatedAt: data.data.updated_at || '无'
|
||||||
|
});
|
||||||
|
|
||||||
|
// status: 2 表示成功(使用宽松比较,支持数字2和字符串"2")
|
||||||
|
if (status === 2 || data.data.status === '2' || data.data.status === 2) {
|
||||||
|
// 检查 imageUrl 是否有效(不能为空字符串、null、undefined)
|
||||||
|
const validImageUrl = imageUrl && typeof imageUrl === 'string' && imageUrl.trim().length > 0;
|
||||||
|
|
||||||
|
if (validImageUrl) {
|
||||||
|
if (queryInterval) {
|
||||||
clearInterval(queryInterval);
|
clearInterval(queryInterval);
|
||||||
|
}
|
||||||
|
const finalImageUrl = imageUrl.trim();
|
||||||
console.log(`✅ 图片生成成功: ${imageName}`);
|
console.log(`✅ 图片生成成功: ${imageName}`);
|
||||||
console.log(`图片URL: ${imageUrl}`);
|
console.log(`图片URL: ${finalImageUrl}`);
|
||||||
resolve({ imageUrl, taskId, imageName });
|
console.log(`图片URL长度: ${finalImageUrl.length}`);
|
||||||
|
return { imageUrl: finalImageUrl, taskId, imageName, success: true };
|
||||||
} else {
|
} else {
|
||||||
console.log(`⏳ 图片生成成功但URL未返回,继续等待...`);
|
console.log(`⚠️ 状态为成功但URL无效,继续等待...`);
|
||||||
|
console.log(` imageUrl值: ${JSON.stringify(imageUrl)}`);
|
||||||
|
console.log(` imageUrl类型: ${typeof imageUrl}`);
|
||||||
|
// 如果状态是2但URL无效,继续等待
|
||||||
|
return { success: false, continue: true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// status: 3 表示失败
|
// status: 3 表示失败
|
||||||
else if (status === 3) {
|
else if (status === 3 || data.data.status === '3') {
|
||||||
|
if (queryInterval) {
|
||||||
clearInterval(queryInterval);
|
clearInterval(queryInterval);
|
||||||
reject(new Error(`图片生成失败: ${data.msg || data.data.msg || '未知错误'}`));
|
}
|
||||||
|
const errorMsg = data.msg || data.data.msg || '未知错误';
|
||||||
|
console.error(`❌ 图片生成失败: ${errorMsg}`);
|
||||||
|
throw new Error(`图片生成失败: ${errorMsg}`);
|
||||||
}
|
}
|
||||||
// status: 0 排队中, 1 生成中
|
// status: 0 排队中, 1 生成中
|
||||||
else {
|
else {
|
||||||
const statusText = status === 0 ? '排队中' : status === 1 ? '生成中' : `未知状态${status}`;
|
console.log(`⏳ ${statusText}... (已等待 ${Math.round(queryCount * config.queryInterval / 1000)} 秒)`);
|
||||||
console.log(`⏳ ${statusText}...`);
|
return { success: false, continue: true };
|
||||||
}
|
}
|
||||||
} else if (data.code !== 200) {
|
} else if (data.code !== 200) {
|
||||||
// API返回错误
|
// API返回错误
|
||||||
console.log(`⚠️ 查询返回错误: ${data.msg || '未知错误'} (code: ${data.code})`);
|
console.error(`⚠️ 查询返回错误: ${data.msg || '未知错误'} (code: ${data.code})`);
|
||||||
// 继续重试,不立即失败
|
console.error(`完整错误响应:`, JSON.stringify(data, null, 2));
|
||||||
|
|
||||||
|
// 如果是认证错误或参数错误,立即失败
|
||||||
|
if (data.code === 401 || data.code === 403 || data.code === 400) {
|
||||||
|
if (queryInterval) {
|
||||||
|
clearInterval(queryInterval);
|
||||||
|
}
|
||||||
|
throw new Error(`API错误: ${data.msg} (code: ${data.code})`);
|
||||||
|
}
|
||||||
|
// 其他错误继续重试
|
||||||
|
return { success: false, continue: true };
|
||||||
} else {
|
} else {
|
||||||
|
// data为空或格式不对
|
||||||
|
console.warn(`⚠️ 响应格式异常:`, JSON.stringify(data, null, 2));
|
||||||
console.log(`⏳ 等待中... (响应: ${data.msg || '处理中'})`);
|
console.log(`⏳ 等待中... (响应: ${data.msg || '处理中'})`);
|
||||||
|
return { success: false, continue: true };
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.response && error.response.status === 404) {
|
if (error.response) {
|
||||||
// 任务可能还在处理中
|
// HTTP错误响应
|
||||||
console.log(`⏳ 任务处理中,继续等待...`);
|
const statusCode = error.response.status;
|
||||||
} else {
|
const errorData = error.response.data;
|
||||||
console.error(`查询时出错:`, error.message);
|
|
||||||
// 不立即失败,继续重试
|
if (statusCode === 404) {
|
||||||
|
// 任务可能还在处理中,或者任务ID不存在
|
||||||
|
console.error(`❌ 任务未找到(404): ID=${taskId} (类型: ${typeof taskId})`);
|
||||||
|
console.error(` 可能的原因:`);
|
||||||
|
console.error(` 1. 任务ID类型错误 - 查询接口需要数字ID,不是task_id字符串`);
|
||||||
|
console.error(` 2. 任务还在处理中,稍后再试`);
|
||||||
|
console.error(` 3. 任务ID不存在或已过期`);
|
||||||
|
console.error(` 提示: 请检查生图接口返回的 data.id 字段(应该是数字)`);
|
||||||
|
|
||||||
|
// 如果是字符串类型的ID,尝试转换为数字
|
||||||
|
if (typeof taskId === 'string' && /^\d+$/.test(taskId)) {
|
||||||
|
console.log(` 尝试将字符串ID转换为数字: ${parseInt(taskId)}`);
|
||||||
|
// 不立即失败,继续重试(可能任务还在处理)
|
||||||
}
|
}
|
||||||
|
} else if (statusCode === 401 || statusCode === 403) {
|
||||||
|
// 认证错误,立即失败
|
||||||
|
if (queryInterval) {
|
||||||
|
clearInterval(queryInterval);
|
||||||
|
}
|
||||||
|
console.error(`❌ 认证失败 (${statusCode}):`, errorData);
|
||||||
|
throw new Error(`认证失败: ${errorData?.msg || error.message}`);
|
||||||
|
} else {
|
||||||
|
console.error(`❌ HTTP错误 (${statusCode}):`, errorData || error.message);
|
||||||
|
}
|
||||||
|
} else if (error.code === 'ECONNABORTED') {
|
||||||
|
console.error(`❌ 请求超时:`, error.message);
|
||||||
|
} else if (error.message && error.message.includes('查询超时')) {
|
||||||
|
// 这是我们的超时错误,直接抛出
|
||||||
|
throw error;
|
||||||
|
} else {
|
||||||
|
console.error(`❌ 查询时出错:`, error.message);
|
||||||
|
if (error.stack) {
|
||||||
|
console.error(`错误堆栈:`, error.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 网络错误等继续重试,不立即失败
|
||||||
|
return { success: false, continue: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
// 立即执行第一次查询,不等待间隔
|
||||||
|
const firstResult = await performQuery();
|
||||||
|
if (firstResult.success) {
|
||||||
|
resolve(firstResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果第一次查询未成功,设置定时器继续查询
|
||||||
|
queryInterval = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
const result = await performQuery();
|
||||||
|
if (result.success) {
|
||||||
|
if (queryInterval) {
|
||||||
|
clearInterval(queryInterval);
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
// 如果 continue 为 true,继续下一次查询
|
||||||
|
} catch (error) {
|
||||||
|
if (queryInterval) {
|
||||||
|
clearInterval(queryInterval);
|
||||||
|
}
|
||||||
|
reject(error);
|
||||||
}
|
}
|
||||||
}, config.queryInterval);
|
}, config.queryInterval);
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,10 +437,13 @@ async function main() {
|
|||||||
console.log('🚀 开始亚马逊产品图生成工作流...\n');
|
console.log('🚀 开始亚马逊产品图生成工作流...\n');
|
||||||
console.log('配置信息:');
|
console.log('配置信息:');
|
||||||
console.log(`- API地址: ${config.apiBaseUrl}`);
|
console.log(`- API地址: ${config.apiBaseUrl}`);
|
||||||
|
console.log(`- 生图接口: ${config.generateApi}`);
|
||||||
|
console.log(`- 查询接口: ${config.queryApi}`);
|
||||||
console.log(`- 源图片: ${config.sourceImageUrl || '使用本地图片'}`);
|
console.log(`- 源图片: ${config.sourceImageUrl || '使用本地图片'}`);
|
||||||
console.log(`- 输出目录: ${config.outputDir}`);
|
console.log(`- 输出目录: ${config.outputDir}`);
|
||||||
console.log(`- 图片尺寸: ${config.imageSize}`);
|
console.log(`- 图片尺寸: ${config.imageSize}`);
|
||||||
console.log(`- 查询间隔: ${config.queryInterval}ms\n`);
|
console.log(`- 查询间隔: ${config.queryInterval}ms`);
|
||||||
|
console.log(`- 最大查询次数: ${config.maxQueryCount}次\n`);
|
||||||
|
|
||||||
if (!config.apiKey) {
|
if (!config.apiKey) {
|
||||||
console.error('❌ 错误: 未设置API_KEY,请在.env文件中配置');
|
console.error('❌ 错误: 未设置API_KEY,请在.env文件中配置');
|
||||||
|
|||||||
Reference in New Issue
Block a user