基于多图生成图片模型
This commit is contained in:
@@ -73,3 +73,12 @@ export function removeWatermark(data) {
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 图像处理接口
|
||||||
|
export function imageProcessing(data) {
|
||||||
|
return request({
|
||||||
|
url: '/image-model/image-background',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ export const constantRoutes = [
|
|||||||
path: 'background-model',
|
path: 'background-model',
|
||||||
name: 'BackgroundModel',
|
name: 'BackgroundModel',
|
||||||
component: () => import('@/views/image-model/background-model'),
|
component: () => import('@/views/image-model/background-model'),
|
||||||
meta: { title: '图像背景模型', icon: 'el-icon-picture-outline' }
|
meta: { title: '图像智聚', icon: 'el-icon-picture-outline' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'virtual-model',
|
path: 'virtual-model',
|
||||||
|
|||||||
@@ -1,26 +1,844 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-card class="box-card">
|
<el-card class="box-card">
|
||||||
<div slot="header" class="clearfix">
|
<div class="content">
|
||||||
<span>图像背景模型</span>
|
<el-form :model="form" class="image-form">
|
||||||
|
<!-- 主图选择区域 -->
|
||||||
|
<div class="form-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>主图选择</h3>
|
||||||
|
</div>
|
||||||
|
<div class="section-content">
|
||||||
|
<div class="two-column-layout">
|
||||||
|
<!-- 左列:下拉框和提示词 -->
|
||||||
|
<div class="left-column">
|
||||||
|
<div class="selector-wrapper">
|
||||||
|
<el-select
|
||||||
|
v-model="form.baseImageId"
|
||||||
|
placeholder="请选择主图"
|
||||||
|
class="image-select"
|
||||||
|
:loading="imageListLoading"
|
||||||
|
@change="handleBaseImageChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in imageList"
|
||||||
|
:key="item.uuid"
|
||||||
|
:label="item.imageName"
|
||||||
|
:value="item.uuid"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<!-- 右列:图片预览 -->
|
||||||
<el-empty description="功能建设中,敬请期待" />
|
<div class="right-column">
|
||||||
|
<div v-if="selectedImage" class="image-preview">
|
||||||
|
<img
|
||||||
|
:src="selectedImage.materialTempUrl"
|
||||||
|
:alt="selectedImage.imageName"
|
||||||
|
class="preview-image"
|
||||||
|
@error="handleImageError"
|
||||||
|
>
|
||||||
|
<div class="image-details">
|
||||||
|
<p><strong>{{ selectedImage.imageName }}</strong></p>
|
||||||
|
<p>{{ selectedImage.ownerName }}</p>
|
||||||
|
<p>{{ getImageTypeText(selectedImage.imageType) }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 参考图选择区域 -->
|
||||||
|
<div class="form-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>参考图选择</h3>
|
||||||
|
</div>
|
||||||
|
<div class="section-content">
|
||||||
|
<div class="two-column-layout">
|
||||||
|
<!-- 左列:下拉框和提示词 -->
|
||||||
|
<div class="left-column">
|
||||||
|
<div class="selector-wrapper">
|
||||||
|
<el-select
|
||||||
|
v-model="form.refImageId"
|
||||||
|
placeholder="请选择参考图"
|
||||||
|
class="image-select"
|
||||||
|
:loading="imageListLoading"
|
||||||
|
@change="handleRefImageChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in imageList"
|
||||||
|
:key="item.uuid"
|
||||||
|
:label="item.imageName"
|
||||||
|
:value="item.uuid"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="prompt-container">
|
||||||
|
<el-input
|
||||||
|
v-model="form.refPrompt"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入参考图提示词"
|
||||||
|
class="prompt-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右列:图片预览 -->
|
||||||
|
<div class="right-column">
|
||||||
|
<div v-if="selectedRefImage" class="image-preview">
|
||||||
|
<img
|
||||||
|
:src="selectedRefImage.materialTempUrl"
|
||||||
|
:alt="selectedRefImage.imageName"
|
||||||
|
class="preview-image"
|
||||||
|
@error="handleImageError"
|
||||||
|
>
|
||||||
|
<div class="image-details">
|
||||||
|
<p><strong>{{ selectedRefImage.imageName }}</strong></p>
|
||||||
|
<p>{{ selectedRefImage.ownerName }}</p>
|
||||||
|
<p>{{ getImageTypeText(selectedRefImage.imageType) }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 前景边缘图1选择区域 -->
|
||||||
|
<div class="form-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>前景边缘图1选择</h3>
|
||||||
|
</div>
|
||||||
|
<div class="section-content">
|
||||||
|
<div class="two-column-layout">
|
||||||
|
<!-- 左列:下拉框和提示词 -->
|
||||||
|
<div class="left-column">
|
||||||
|
<div class="selector-wrapper">
|
||||||
|
<el-select
|
||||||
|
v-model="form.foregroundEdge1Id"
|
||||||
|
placeholder="请选择前景边缘图1"
|
||||||
|
class="image-select"
|
||||||
|
:loading="imageListLoading"
|
||||||
|
@change="handleForegroundEdge1Change"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in imageList"
|
||||||
|
:key="item.uuid"
|
||||||
|
:label="item.imageName"
|
||||||
|
:value="item.uuid"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="prompt-container">
|
||||||
|
<el-input
|
||||||
|
v-model="form.foregroundEdge1Prompt"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入前景边缘图1提示词"
|
||||||
|
class="prompt-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右列:图片预览 -->
|
||||||
|
<div class="right-column">
|
||||||
|
<div v-if="selectedForegroundEdge1" class="image-preview">
|
||||||
|
<img
|
||||||
|
:src="selectedForegroundEdge1.materialTempUrl"
|
||||||
|
:alt="selectedForegroundEdge1.imageName"
|
||||||
|
class="preview-image"
|
||||||
|
@error="handleImageError"
|
||||||
|
>
|
||||||
|
<div class="image-details">
|
||||||
|
<p><strong>{{ selectedForegroundEdge1.imageName }}</strong></p>
|
||||||
|
<p>{{ selectedForegroundEdge1.ownerName }}</p>
|
||||||
|
<p>{{ getImageTypeText(selectedForegroundEdge1.imageType) }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 前景边缘图2选择区域 -->
|
||||||
|
<div class="form-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>前景边缘图2选择</h3>
|
||||||
|
</div>
|
||||||
|
<div class="section-content">
|
||||||
|
<div class="two-column-layout">
|
||||||
|
<!-- 左列:下拉框和提示词 -->
|
||||||
|
<div class="left-column">
|
||||||
|
<div class="selector-wrapper">
|
||||||
|
<el-select
|
||||||
|
v-model="form.foregroundEdge2Id"
|
||||||
|
placeholder="请选择前景边缘图2"
|
||||||
|
class="image-select"
|
||||||
|
:loading="imageListLoading"
|
||||||
|
@change="handleForegroundEdge2Change"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in imageList"
|
||||||
|
:key="item.uuid"
|
||||||
|
:label="item.imageName"
|
||||||
|
:value="item.uuid"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="prompt-container">
|
||||||
|
<el-input
|
||||||
|
v-model="form.foregroundEdge2Prompt"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入前景边缘图2提示词"
|
||||||
|
class="prompt-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右列:图片预览 -->
|
||||||
|
<div class="right-column">
|
||||||
|
<div v-if="selectedForegroundEdge2" class="image-preview">
|
||||||
|
<img
|
||||||
|
:src="selectedForegroundEdge2.materialTempUrl"
|
||||||
|
:alt="selectedForegroundEdge2.imageName"
|
||||||
|
class="preview-image"
|
||||||
|
@error="handleImageError"
|
||||||
|
>
|
||||||
|
<div class="image-details">
|
||||||
|
<p><strong>{{ selectedForegroundEdge2.imageName }}</strong></p>
|
||||||
|
<p>{{ selectedForegroundEdge2.ownerName }}</p>
|
||||||
|
<p>{{ getImageTypeText(selectedForegroundEdge2.imageType) }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 背景边缘图选择区域 -->
|
||||||
|
<div class="form-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>背景边缘图选择</h3>
|
||||||
|
</div>
|
||||||
|
<div class="section-content">
|
||||||
|
<div class="two-column-layout">
|
||||||
|
<!-- 左列:下拉框和提示词 -->
|
||||||
|
<div class="left-column">
|
||||||
|
<div class="selector-wrapper">
|
||||||
|
<el-select
|
||||||
|
v-model="form.backgroundEdgeId"
|
||||||
|
placeholder="请选择背景边缘图"
|
||||||
|
class="image-select"
|
||||||
|
:loading="imageListLoading"
|
||||||
|
@change="handleBackgroundEdgeChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in imageList"
|
||||||
|
:key="item.uuid"
|
||||||
|
:label="item.imageName"
|
||||||
|
:value="item.uuid"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="prompt-container">
|
||||||
|
<el-input
|
||||||
|
v-model="form.backgroundEdgePrompt"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入背景边缘图提示词"
|
||||||
|
class="prompt-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右列:图片预览 -->
|
||||||
|
<div class="right-column">
|
||||||
|
<div v-if="selectedBackgroundEdge" class="image-preview">
|
||||||
|
<img
|
||||||
|
:src="selectedBackgroundEdge.materialTempUrl"
|
||||||
|
:alt="selectedBackgroundEdge.imageName"
|
||||||
|
class="preview-image"
|
||||||
|
@error="handleImageError"
|
||||||
|
>
|
||||||
|
<div class="image-details">
|
||||||
|
<p><strong>{{ selectedBackgroundEdge.imageName }}</strong></p>
|
||||||
|
<p>{{ selectedBackgroundEdge.ownerName }}</p>
|
||||||
|
<p>{{ getImageTypeText(selectedBackgroundEdge.imageType) }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 生成参数区域 -->
|
||||||
|
<div class="form-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<h3>生成参数</h3>
|
||||||
|
</div>
|
||||||
|
<div class="section-content">
|
||||||
|
<div class="parameter-container">
|
||||||
|
<div class="parameter-row">
|
||||||
|
<div class="parameter-item">
|
||||||
|
<label class="parameter-label">张数 (n)</label>
|
||||||
|
<el-input-number
|
||||||
|
v-model="form.n"
|
||||||
|
:min="1"
|
||||||
|
:max="100"
|
||||||
|
placeholder="请输入张数"
|
||||||
|
class="parameter-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="parameter-item">
|
||||||
|
<label class="parameter-label">参考提示词权重</label>
|
||||||
|
<el-input-number
|
||||||
|
v-model="form.refPromptWeight"
|
||||||
|
:min="0"
|
||||||
|
:max="1"
|
||||||
|
:precision="2"
|
||||||
|
:step="0.1"
|
||||||
|
placeholder="请输入权重"
|
||||||
|
class="parameter-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="parameter-item">
|
||||||
|
<label class="parameter-label">模型版本</label>
|
||||||
|
<el-input
|
||||||
|
v-model="form.modelVersion"
|
||||||
|
placeholder="请输入模型版本"
|
||||||
|
class="parameter-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="parameter-row">
|
||||||
|
<div class="parameter-item">
|
||||||
|
<label class="parameter-label">所有人姓名</label>
|
||||||
|
<el-input
|
||||||
|
v-model="form.ownerName"
|
||||||
|
placeholder="请输入所有人姓名"
|
||||||
|
class="parameter-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="parameter-item">
|
||||||
|
<label class="parameter-label">所有人电话</label>
|
||||||
|
<el-input
|
||||||
|
v-model="form.ownerPhone"
|
||||||
|
placeholder="请输入所有人电话"
|
||||||
|
class="parameter-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="button-container">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="large"
|
||||||
|
:loading="generateLoading"
|
||||||
|
class="generate-button"
|
||||||
|
@click="handleGenerate"
|
||||||
|
>
|
||||||
|
<i class="el-icon-magic-stick" />
|
||||||
|
生成图像
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getImageList, imageProcessing } from '@/api/image-management'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'BackgroundModel'
|
name: 'BackgroundModel',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
// 主图选择
|
||||||
|
baseImageId: '',
|
||||||
|
// 参考图选择
|
||||||
|
refImageId: '',
|
||||||
|
refPrompt: '',
|
||||||
|
// 前景边缘图选择
|
||||||
|
foregroundEdge1Id: '',
|
||||||
|
foregroundEdge2Id: '',
|
||||||
|
foregroundEdge1Prompt: '',
|
||||||
|
foregroundEdge2Prompt: '',
|
||||||
|
// 背景边缘图选择
|
||||||
|
backgroundEdgeId: '',
|
||||||
|
backgroundEdgePrompt: '',
|
||||||
|
// 生成参数
|
||||||
|
n: 1,
|
||||||
|
refPromptWeight: 0.5,
|
||||||
|
modelVersion: 'v3',
|
||||||
|
// 所有人信息
|
||||||
|
ownerName: '',
|
||||||
|
ownerPhone: ''
|
||||||
|
},
|
||||||
|
imageList: [],
|
||||||
|
imageListLoading: false,
|
||||||
|
generateLoading: false,
|
||||||
|
selectedBaseImage: null,
|
||||||
|
selectedRefImage: null,
|
||||||
|
selectedForegroundEdge1: null,
|
||||||
|
selectedForegroundEdge2: null,
|
||||||
|
selectedBackgroundEdge: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['name', 'phone'])
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadImageList()
|
||||||
|
this.setDefaultUserInfo()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 设置默认用户信息
|
||||||
|
setDefaultUserInfo() {
|
||||||
|
if (this.name) {
|
||||||
|
this.form.ownerName = this.name
|
||||||
|
}
|
||||||
|
if (this.phone) {
|
||||||
|
this.form.ownerPhone = this.phone
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 加载图像列表
|
||||||
|
loadImageList() {
|
||||||
|
this.imageListLoading = true
|
||||||
|
const params = {
|
||||||
|
current: 1,
|
||||||
|
size: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
getImageList(params).then(response => {
|
||||||
|
console.log('图像列表响应:', response)
|
||||||
|
console.log('响应数据结构:', {
|
||||||
|
success: response.success,
|
||||||
|
data: response.data,
|
||||||
|
total: response.total,
|
||||||
|
message: response.message
|
||||||
|
})
|
||||||
|
|
||||||
|
// 检查响应是否成功 - 参考图像管理列表的处理方式
|
||||||
|
const isSuccess = response.success === true || (response.data && response.data.length >= 0)
|
||||||
|
console.log('判断是否成功:', {
|
||||||
|
'response.success': response.success,
|
||||||
|
'response.data存在': !!response.data,
|
||||||
|
'isSuccess': isSuccess
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isSuccess) {
|
||||||
|
// 根据后端返回的数据结构,数据在response.data中
|
||||||
|
console.log('原始数据:', response.data)
|
||||||
|
this.imageList = response.data || []
|
||||||
|
console.log('设置后的图像列表:', this.imageList)
|
||||||
|
} else {
|
||||||
|
console.error('获取图像列表失败:', response.message)
|
||||||
|
this.$message.error(response.message || '获取图像列表失败')
|
||||||
|
this.imageList = []
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('获取图像列表异常:', error)
|
||||||
|
this.$message.error('获取图像列表失败: ' + error.message)
|
||||||
|
this.imageList = []
|
||||||
|
}).finally(() => {
|
||||||
|
this.imageListLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理主图选择变化
|
||||||
|
handleBaseImageChange(imageId) {
|
||||||
|
console.log('选择的主图ID:', imageId)
|
||||||
|
if (imageId) {
|
||||||
|
this.selectedBaseImage = this.imageList.find(item => item.uuid === imageId)
|
||||||
|
console.log('选中的主图信息:', this.selectedBaseImage)
|
||||||
|
} else {
|
||||||
|
this.selectedBaseImage = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理参考图选择变化
|
||||||
|
handleRefImageChange(refImageId) {
|
||||||
|
console.log('选择的参考图ID:', refImageId)
|
||||||
|
if (refImageId) {
|
||||||
|
this.selectedRefImage = this.imageList.find(item => item.uuid === refImageId)
|
||||||
|
console.log('选中的参考图信息:', this.selectedRefImage)
|
||||||
|
} else {
|
||||||
|
this.selectedRefImage = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理前景边缘图1选择变化
|
||||||
|
handleForegroundEdge1Change(edge1Id) {
|
||||||
|
console.log('选择的前景边缘图1 ID:', edge1Id)
|
||||||
|
if (edge1Id) {
|
||||||
|
this.selectedForegroundEdge1 = this.imageList.find(item => item.uuid === edge1Id)
|
||||||
|
console.log('选中的前景边缘图1信息:', this.selectedForegroundEdge1)
|
||||||
|
} else {
|
||||||
|
this.selectedForegroundEdge1 = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理前景边缘图2选择变化
|
||||||
|
handleForegroundEdge2Change(edge2Id) {
|
||||||
|
console.log('选择的前景边缘图2 ID:', edge2Id)
|
||||||
|
if (edge2Id) {
|
||||||
|
this.selectedForegroundEdge2 = this.imageList.find(item => item.uuid === edge2Id)
|
||||||
|
console.log('选中的前景边缘图2信息:', this.selectedForegroundEdge2)
|
||||||
|
} else {
|
||||||
|
this.selectedForegroundEdge2 = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理背景边缘图选择变化
|
||||||
|
handleBackgroundEdgeChange(backgroundEdgeId) {
|
||||||
|
console.log('选择的背景边缘图ID:', backgroundEdgeId)
|
||||||
|
if (backgroundEdgeId) {
|
||||||
|
this.selectedBackgroundEdge = this.imageList.find(item => item.uuid === backgroundEdgeId)
|
||||||
|
console.log('选中的背景边缘图信息:', this.selectedBackgroundEdge)
|
||||||
|
} else {
|
||||||
|
this.selectedBackgroundEdge = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理图片加载错误
|
||||||
|
handleImageError(event) {
|
||||||
|
console.error('图片加载失败:', event)
|
||||||
|
this.$message.error('图片加载失败,请检查图片URL')
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取图片类型文本
|
||||||
|
getImageTypeText(type) {
|
||||||
|
const typeMap = {
|
||||||
|
background: '背景图',
|
||||||
|
person: '人物图',
|
||||||
|
product: '产品图',
|
||||||
|
material: '素材图',
|
||||||
|
other: '其他'
|
||||||
|
}
|
||||||
|
return typeMap[type] || '未知'
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理生成按钮点击
|
||||||
|
handleGenerate() {
|
||||||
|
// 验证必填项
|
||||||
|
if (!this.form.baseImageId) {
|
||||||
|
this.$message.warning('请选择主图')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.form.refImageId) {
|
||||||
|
this.$message.warning('请选择参考图')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.form.foregroundEdge1Id) {
|
||||||
|
this.$message.warning('请选择前景边缘图1')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.form.foregroundEdge2Id) {
|
||||||
|
this.$message.warning('请选择前景边缘图2')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.form.backgroundEdgeId) {
|
||||||
|
this.$message.warning('请选择背景边缘图')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始生成
|
||||||
|
this.generateLoading = true
|
||||||
|
|
||||||
|
// 构建后端参数结构
|
||||||
|
const requestData = {
|
||||||
|
base_image_url: this.selectedBaseImage.materialTempUrl,
|
||||||
|
ref_image_url: this.selectedRefImage.materialTempUrl,
|
||||||
|
ref_prompt: this.form.refPrompt,
|
||||||
|
reference_edge: {
|
||||||
|
foreground_edge: [
|
||||||
|
this.selectedForegroundEdge1.materialTempUrl,
|
||||||
|
this.selectedForegroundEdge2.materialTempUrl
|
||||||
|
],
|
||||||
|
background_edge: [
|
||||||
|
this.selectedBackgroundEdge.materialTempUrl
|
||||||
|
],
|
||||||
|
foreground_edge_prompt: [
|
||||||
|
this.form.foregroundEdge1Prompt,
|
||||||
|
this.form.foregroundEdge2Prompt
|
||||||
|
],
|
||||||
|
background_edge_prompt: [
|
||||||
|
this.form.backgroundEdgePrompt
|
||||||
|
]
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
n: this.form.n,
|
||||||
|
ref_prompt_weight: this.form.refPromptWeight,
|
||||||
|
model_version: this.form.modelVersion
|
||||||
|
},
|
||||||
|
owner_info: {
|
||||||
|
owner_name: this.form.ownerName,
|
||||||
|
owner_phone: this.form.ownerPhone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('开始生成图像,参数:', requestData)
|
||||||
|
|
||||||
|
// 调用后端接口
|
||||||
|
imageProcessing(requestData).then(response => {
|
||||||
|
this.generateLoading = false
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
this.$message.success(response.message || '图像处理完成')
|
||||||
|
console.log('图像处理成功,返回数据:', response)
|
||||||
|
|
||||||
|
// 处理返回的图片数据
|
||||||
|
if (response.processedImages && response.processedImages.length > 0) {
|
||||||
|
console.log('生成的图片:', response.processedImages)
|
||||||
|
this.$message.info(`成功生成 ${response.processedImages.length} 张图像`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示处理信息
|
||||||
|
if (response.processingTimeMs) {
|
||||||
|
console.log('处理时间:', response.processingTimeMs + 'ms')
|
||||||
|
}
|
||||||
|
if (response.requestId) {
|
||||||
|
console.log('请求ID:', response.requestId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$message.error(response.message || '图像处理失败')
|
||||||
|
console.error('图像处理失败:', response)
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
this.generateLoading = false
|
||||||
|
console.error('调用图像处理接口失败:', error)
|
||||||
|
this.$message.error('调用图像处理接口失败:' + (error.message || '未知错误'))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.app-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-section {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
padding: 15px 20px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.two-column-layout {
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-column {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-column {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-wrapper {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-preview {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
width: 100%;
|
||||||
|
height: 120px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 2px solid #dcdfe6;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-details {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-details p {
|
||||||
|
margin: 0 0 4px 0;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #606266;
|
||||||
|
line-height: 1.4;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-details p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-details strong {
|
||||||
|
color: #303133;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-container {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-input .el-textarea__inner {
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-input .el-textarea__inner:focus {
|
||||||
|
border-color: #409eff;
|
||||||
|
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 参数区域样式 */
|
||||||
|
.parameter-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameter-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameter-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameter-label {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameter-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.generate-button {
|
||||||
|
padding: 12px 40px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-button:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-button:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.app-container {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.two-column-layout {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-column,
|
||||||
|
.right-column {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-content {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parameter-row {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 15px 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user