fix: nanobanana 优化请求体

This commit is contained in:
old burden 2026-04-23 17:55:13 +08:00
parent bf9e320817
commit 5d4b6d45e8
5 changed files with 67 additions and 71 deletions

View File

@ -218,7 +218,7 @@ export default {
method: 'POST', method: 'POST',
data: { data: {
text: this.text || this.textPlaceholder, text: this.text || this.textPlaceholder,
firstUrl: [this.firstUrl.url, this.secondUrl.url], imageUrls: [this.firstUrl.url, this.secondUrl.url],
functionType: '13', functionType: '13',
tags: tags.join(',') tags: tags.join(',')
} }

View File

@ -22,6 +22,8 @@
<mf-image-upload <mf-image-upload
listType="draggable" listType="draggable"
uploadHeight="200px" uploadHeight="200px"
:multiple="true"
:limit="9"
:show-file-list="false" :show-file-list="false"
:content="$t('common.uploadPlaceholder')" :content="$t('common.uploadPlaceholder')"
v-model="firstUrl" /> v-model="firstUrl" />
@ -73,23 +75,22 @@
<div class="nano-label">{{ $t('common.aspectRatioLabel') }}</div> <div class="nano-label">{{ $t('common.aspectRatioLabel') }}</div>
<a-select <a-select
v-model="aspectRatio" v-model="aspectRatio"
popup-class-name="image-select-popup"
style="width: 100%"> style="width: 100%">
<a-select-option value="auto">auto</a-select-option> <a-option value="auto">auto</a-option>
<a-select-option value="1:1">1:1</a-select-option> <a-option value="1:1">1:1</a-option>
<a-select-option value="1:4">1:4</a-select-option> <a-option value="1:4">1:4</a-option>
<a-select-option value="1:8">1:8</a-select-option> <a-option value="1:8">1:8</a-option>
<a-select-option value="2:3">2:3</a-select-option> <a-option value="2:3">2:3</a-option>
<a-select-option value="3:2">3:2</a-select-option> <a-option value="3:2">3:2</a-option>
<a-select-option value="3:4">3:4</a-select-option> <a-option value="3:4">3:4</a-option>
<a-select-option value="4:1">4:1</a-select-option> <a-option value="4:1">4:1</a-option>
<a-select-option value="4:3">4:3</a-select-option> <a-option value="4:3">4:3</a-option>
<a-select-option value="4:5">4:5</a-select-option> <a-option value="4:5">4:5</a-option>
<a-select-option value="5:4">5:4</a-select-option> <a-option value="5:4">5:4</a-option>
<a-select-option value="8:1">8:1</a-select-option> <a-option value="8:1">8:1</a-option>
<a-select-option value="9:16">9:16</a-select-option> <a-option value="9:16">9:16</a-option>
<a-select-option value="16:9">16:9</a-select-option> <a-option value="16:9">16:9</a-option>
<a-select-option value="21:9">21:9</a-select-option> <a-option value="21:9">21:9</a-option>
</a-select> </a-select>
</div> </div>
<div class="nano-row"> <div class="nano-row">
@ -99,21 +100,21 @@
</div> </div>
<a-select <a-select
v-model="resolution" v-model="resolution"
popup-class-name="image-select-popup"
style="width: 100%"> style="width: 100%">
<a-select-option value="1K">1K</a-select-option> <a-option value="1K">1K</a-option>
<a-select-option value="2K">2K</a-select-option> <a-option value="2K">2K</a-option>
<a-select-option value="4K">4K</a-select-option> <a-option value="4K">4K</a-option>
</a-select> </a-select>
</div> </div>
<div class="nano-row"> <div
class="nano-row"
v-if="current !== 2">
<div class="nano-label">输出格式</div> <div class="nano-label">输出格式</div>
<a-select <a-select
v-model="outputFormat" v-model="outputFormat"
popup-class-name="image-select-popup"
style="width: 100%"> style="width: 100%">
<a-select-option value="png">png</a-select-option> <a-option value="png">png</a-option>
<a-select-option value="jpg">jpg</a-select-option> <a-option value="jpg">jpg</a-option>
</a-select> </a-select>
</div> </div>
</div> </div>
@ -208,7 +209,7 @@ export default {
data() { data() {
return { return {
prefixCls: 'image', prefixCls: 'image',
firstUrl: '', firstUrl: [],
text: '', text: '',
current: 1, current: 1,
generateLoading: false, generateLoading: false,
@ -318,11 +319,27 @@ export default {
if (this.uploadType === 'upload') { if (this.uploadType === 'upload') {
this.selectedTemplatePreview = '' this.selectedTemplatePreview = ''
this.selectedTemplate = null this.selectedTemplate = null
this.firstUrl = '' this.firstUrl = []
} else { } else {
this.firstUrl = '' this.firstUrl = []
} }
}, },
getImageUrls() {
if (this.$datas.isEmpty(this.firstUrl)) return []
if (Array.isArray(this.firstUrl)) {
return this.firstUrl
.map((item) => item?.serverUrl || item?.url || '')
.filter((url) => !!url)
}
if (typeof this.firstUrl === 'object') {
const url = this.firstUrl.serverUrl || this.firstUrl.url
return url ? [url] : []
}
if (typeof this.firstUrl === 'string') {
return this.firstUrl ? [this.firstUrl] : []
}
return []
},
// //
openTemplateDialog() { openTemplateDialog() {
this.templateDialogVisible = true this.templateDialogVisible = true
@ -430,10 +447,7 @@ export default {
} }
}, },
generateImage() { generateImage() {
if (!this.firstUrl || !this.firstUrl.url) { const imageUrls = this.getImageUrls()
this.$message.error(this.$t('common.uploadImageError'))
return
}
// image-to-image2 (current=2) // image-to-image2 (current=2)
if (this.current === 2 && !this.resolution) { if (this.current === 2 && !this.resolution) {
this.$message.warning(this.$t('common.proResolutionRequired')) this.$message.warning(this.$t('common.proResolutionRequired'))
@ -463,16 +477,19 @@ export default {
}) })
this.generateLoading = true this.generateLoading = true
this.taskIdHint = '' this.taskIdHint = ''
nanoBananaImgToImg({ const requestData = {
functionType: this.current == 1 ? '11' : '12', functionType: this.current == 1 ? '11' : '12',
imageUrl: this.firstUrl.url, imageUrls,
text: this.text, text: this.text,
tags: tags.join(','), tags: tags.join(','),
aspectRatio: this.aspectRatio, aspectRatio: this.aspectRatio,
resolution: this.resolution, resolution: this.resolution,
outputFormat: this.outputFormat,
numImages: 1 numImages: 1
}) }
if (this.current !== 2) {
requestData.outputFormat = this.outputFormat
}
nanoBananaImgToImg(requestData)
.then((res) => { .then((res) => {
this.generateLoading = false this.generateLoading = false
if (res.code == 200) { if (res.code == 200) {
@ -887,22 +904,3 @@ export default {
} }
} }
</style> </style>
<style lang="less">
.image-select-popup {
.arco-select-dropdown-list {
display: block !important;
}
.arco-select-option {
display: flex !important;
width: 100%;
}
.arco-select-option-content {
display: block;
width: 100%;
white-space: normal;
}
}
</style>

View File

@ -164,9 +164,6 @@ public class ByteApiController extends BaseController {
} else if (StringUtils.isNotEmpty(request.getImageUrl())) { } else if (StringUtils.isNotEmpty(request.getImageUrl())) {
imageUrls.add(request.getImageUrl().trim()); imageUrls.add(request.getImageUrl().trim());
} }
if (imageUrls.isEmpty()) {
return AjaxResult.error("请提供 imageUrl 或 imageUrls");
}
AiManager aiManager = managerService.selectAiManagerByType(functionType); AiManager aiManager = managerService.selectAiManagerByType(functionType);
if (aiManager == null) { if (aiManager == null) {
@ -196,7 +193,7 @@ public class ByteApiController extends BaseController {
return AjaxResult.error(-1, "You have a low balance, please recharge"); return AjaxResult.error(-1, "You have a low balance, please recharge");
} }
aiOrder.setText(text); aiOrder.setText(text);
aiOrder.setImg1(imageUrls.get(0)); aiOrder.setImg1(imageUrls.isEmpty() ? null : imageUrls.get(0));
NanoBananaRequest nanoRequest = NanoBananaRequest.forImageToImage( NanoBananaRequest nanoRequest = NanoBananaRequest.forImageToImage(
text, text,
@ -347,9 +344,13 @@ public class ByteApiController extends BaseController {
return AjaxResult.error("text is null"); return AjaxResult.error("text is null");
} }
Object firstUrl = request.getFirstUrl(); List<String> imageUrls = new ArrayList<>();
if (null == firstUrl) { if (request.getImageUrls() != null && !request.getImageUrls().isEmpty()) {
return AjaxResult.error("firstUrl is null"); for (String u : request.getImageUrls()) {
if (StringUtils.isNotEmpty(u)) {
imageUrls.add(u.trim());
}
}
} }
String resolution = StringUtils.isNotBlank(request.getResolution()) String resolution = StringUtils.isNotBlank(request.getResolution())
@ -363,13 +364,7 @@ public class ByteApiController extends BaseController {
} }
aiOrder.setText(text); aiOrder.setText(text);
aiOrder.setImg1(firstUrl.toString()); aiOrder.setImg1(imageUrls.isEmpty() ? null : imageUrls.get(0));
// 4. 组装NanoBanana接口参数 - 图生图
List<String> imageUrls = new ArrayList<>();
if (firstUrl != null) {
imageUrls.add(firstUrl.toString());
}
NanoBananaRequest nanoRequest = NanoBananaRequest.forImageToImage( NanoBananaRequest nanoRequest = NanoBananaRequest.forImageToImage(
text, text,

View File

@ -37,6 +37,9 @@ public class ByteApiRequest {
@ApiModelProperty(name = "分辨率 1K/2K/4K") @ApiModelProperty(name = "分辨率 1K/2K/4K")
private String resolution; private String resolution;
@ApiModelProperty(name = "图生图参考图列表,可为空")
private List<String> imageUrls;
/** /**
* NanoBanana 接口版本v1(/generate)v2(/generate-2)pro(/generate-pro)默认 v2 兼容旧逻辑 * NanoBanana 接口版本v1(/generate)v2(/generate-2)pro(/generate-pro)默认 v2 兼容旧逻辑
*/ */

View File

@ -35,10 +35,10 @@ public class NanoBananaPortalImgRequest {
@ApiModelProperty("标签字符串") @ApiModelProperty("标签字符串")
private String tags; private String tags;
@ApiModelProperty("单张参考图 URL与 imageUrls 二选一") @ApiModelProperty("单张参考图 URL兼容字段,可为空")
private String imageUrl; private String imageUrl;
@ApiModelProperty("多张参考图 URL优先于 imageUrl") @ApiModelProperty("多张参考图 URL优先于 imageUrl,可为空数组")
private List<String> imageUrls; private List<String> imageUrls;
@ApiModelProperty("输出格式png / jpg") @ApiModelProperty("输出格式png / jpg")