Files
aida_front/src/component/home/batchGeneration/createCloud.vue
bighuixiang 88866d9ea4 refactor: Improve code formatting and structure in main.ts and Login.vue
- Standardized import statements in main.ts for better readability.
- Enhanced the structure of the Vue component in Login.vue for improved clarity.
- Updated event handling and state management in Login.vue.
- Adjusted CSS styles for consistency and better organization.
2025-06-18 21:47:27 +08:00

856 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="createCloud" ref="createCloud"></div>
<a-modal
class="createCloud_modal generalModel"
v-model:visible="operationsModal"
:footer="null"
:get-container="() => $refs.createCloud"
width="50%"
:height="'77rem'"
:maskClosable="false"
:centered="true"
:closable="false"
:mask="true"
wrapClassName="#app"
:keyboard="false"
>
<div class="generalModel_btn">
<div class="generalModel_closeIcon" @click.stop="cancelDsign()">
<svg
width="46"
height="46"
viewBox="0 0 46 46"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="23" cy="23" r="23" fill="white" fill-opacity="0.3" />
<rect
x="32.5063"
y="12"
width="3"
height="29"
rx="1.5"
transform="rotate(45 32.5063 12)"
fill="#000"
/>
<rect
x="34.6274"
y="32.5059"
width="3"
height="29"
rx="1.5"
transform="rotate(135 34.6274 32.5059)"
fill="#000"
/>
</svg>
</div>
</div>
<div class="modal_title_text">
<div>Create Batch Generation Tasks</div>
</div>
<div class="allUserPoeration_center admin_page">
<div class="admin_state_item">
<span>Task type <span>*</span></span>
<a-select
v-model:value="buildType"
allowClear
style="width: 200px"
placeholder="Please select"
:options="cloudList"
@change="changeBuildType"
></a-select>
</div>
<div class="admin_state_item">
<span
>Project
<span
v-show="
buildType == 'SERIES_DESIGN' || buildType == 'SINGLE_DESIGN'
"
>*</span
></span
>
<a-select
v-model:value="projectData"
show-search
allowClear
:show-arrow="false"
:default-active-first-option="false"
:not-found-content="null"
:filter-option="false"
style="width: 16rem"
placeholder="Please select"
:options="objectList"
@search="getHistoryProjectList"
@change="changeProject"
>
<template #option="{ value: val, label, icon, updateTime }">
<span :title="updateTime.replace('T', ' ')">{{ label }}</span>
</template>
</a-select>
</div>
<div class="admin_state_item">
<span>Name <span>*</span></span>
<input
v-model="porjectName"
:placeholder="placeholder"
@focus="focus"
@blur="blur"
type="text"
style="width: 200px"
/>
</div>
<div class="admin_state_item" v-show="buildType">
<span>Quantity <span>*</span></span>
<input
v-model="numberOfImages"
placeholder="Please enter number"
type="text"
style="width: 200px"
@input="changeNumberOfImages"
/>
</div>
<!-- toProductimg -->
<div v-show="buildType == 'TO_PRODUCT_IMAGE'" class="admin_state_item">
<span>{{ $t("ProductImg.Similarity") }}</span>
<div class="sliderAndImput" style="width: 200px">
<!-- <a-slider class="system_silder"
v-model:value="similarity"
range
:step="5"
>
</a-slider> -->
<div style="display: flex">
<input type="number" readonly v-model="similarity[0]" />
<div style="margin: 0 1rem">-</div>
<input type="number" readonly v-model="similarity[1]" />
</div>
</div>
</div>
<div v-show="buildType == 'RELIGHT'" class="admin_state_item">
<span>{{ $t("ProductImg.RelightDirection") }}</span>
<a-select
style="width: 200px"
v-model:value="relightDirection"
:options="relightDirectionList"
></a-select>
</div>
<div v-show="buildType == 'RELIGHT'" class="admin_state_item">
<span>{{ $t("ProductImg.Highlight") }}</span>
<div class="sliderAndImput" style="width: 200px">
<a-slider
class="system_silder"
v-model:value="brightenValue"
:tooltipVisible="false"
:max="3"
:min="1"
:step="0.1"
>
</a-slider>
<input type="number" readonly v-model="brightenValue" />
</div>
</div>
<div
v-show="buildType == 'TO_PRODUCT_IMAGE' || buildType == 'relight'"
class="admin_state_item"
>
<span>Keyword</span>
<input
v-model="generateText"
:placeholder="$t('Generate.inputContent1')"
type="text"
style="width: 200px"
/>
</div>
<!-- <div class="selectImgList generalScroll" v-mousewheel v-show="exhibitionImgList.length>0">
<div v-for="item in exhibitionImgList" class="item">
<img :src="item.designOutfitUrl||item.url" alt="">
</div>
</div> -->
<div
class="productImg_content_item_imgBox generalScroll upload_item"
v-if="
buildType &&
buildType != 'SERIES_DESIGN' &&
buildType != 'SINGLE_DESIGN'
"
v-mousewheel
>
<div
class="content_item_imgBox_itemImg"
v-for="item in uploadElement"
:key="item"
>
<div class="imgBox" @click="() => (item.isChecked = !item.isChecked)">
<img
:class="[item?.isChecked ? 'active' : '']"
:src="item?.url"
class="upload_img"
/>
<a-checkbox v-model:checked="item.isChecked"></a-checkbox>
</div>
</div>
<div
class="content_item_imgBox_itemImg"
v-for="(file, index) in fileList"
:key="file"
>
<div
class="upload_file_item_content"
v-show="file?.status === 'uploading'"
style="display: flex; align-items: center"
>
<a-spin size="large" />
</div>
<div
class="imgBox"
v-show="file?.status === 'done'"
@click="() => (file.isChecked = !file.isChecked)"
>
<img
:class="[file?.isChecked ? 'active' : '']"
:src="file?.imgUrl"
class="upload_img"
/>
<a-checkbox v-model:checked="file.isChecked"></a-checkbox>
</div>
</div>
<div class="upload_file_item upload_component">
<!-- :action="uploadUrl + '/api/history/toProductImageElementUpload'" -->
<a-upload
:action="
getUploadUrl() + '/api/history/toProductImageElementUpload'
"
list-type="picture-card"
:capture="null"
:headers="{ Authorization: getCookie('token') }"
:before-upload="beforeUpload"
:data="{
projectId: 2061,
}"
v-model:file-list="fileList"
:multiple="true"
:maxCount="8"
accept=".jpg,.png,.jpeg,.bmp"
@change="(file) => fileUploadChange(file)"
>
<div class="upload_tip_block">
<i class="fi fi-br-upload"></i>
<!-- <img class="upload_img_icon" src="@/assets/images/homePage/add_file.png"> -->
</div>
</a-upload>
</div>
</div>
<!-- <div class="admin_state_item" style="width: 100%;">
<span style="margin: 0;">Generation time19min</span>
</div> -->
<div v-show="buildType" class="admin_state_item" style="width: 100%">
<span style="margin: 0"
>Cost credit{{ credits * numberOfImages }}</span
>
</div>
</div>
<div class="allUserPoeration_btn admin_page">
<!-- <div class="admin_search_item" @click="cancelDsign">
Close
</div> -->
<div class="admin_search_item" @click="setOk">OK</div>
</div>
</a-modal>
<div class="mark_loading" v-show="loadingShow">
<a-spin size="large" />
</div>
</template>
<script>
import {
defineComponent,
computed,
reactive,
watch,
onMounted,
h,
nextTick,
toRefs,
} from "vue";
import { LoadingOutlined } from "@ant-design/icons-vue";
import { Https } from "@/tool/https";
import { Modal, message } from "ant-design-vue";
import { getCookie, setCookie } from "@/tool/cookie";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import { getUploadUrl, isMoible } from "@/tool/util";
import dayjs, { Dayjs } from "dayjs";
import { useStore } from "vuex";
import { useI18n } from "vue-i18n";
import { getMinioUrl } from "@/tool/util";
import md5 from "md5";
export default defineComponent({
components: {},
props: {
cloudList: {
type: Array,
default: [],
},
},
emits: ["getContentList"],
setup(props, { emit }) {
const store = useStore();
let operations = reactive({
operationsModal: false,
loadingShow: false,
});
let operationsData = reactive({
buildType: "",
numberOfImages: "",
credits: 0,
exhibitionImgList: [], //选择的图片
projectData: null, //批量id
objectList: [],
porjectName: "", //任务名字
//toProduct
generateText: "", //输入的内容
similarity: [20, 40],
brightenValue: 1, //亮度
relightDirection: "Right Light", //打光方向
relightDirectionList: [
{
value: "Right Light",
label: useI18n().t("ProductImg.RightLight"),
},
{
value: "Left Light",
label: useI18n().t("ProductImg.LeftLight"),
},
{
value: "Top Light",
label: useI18n().t("ProductImg.TopLight"),
},
{
value: "Bottom Light",
label: useI18n().t("ProductImg.BottomLight"),
},
],
fileList: [],
uploadElement: [],
placeholder: "",
});
const getUploadElement = () => {
operations.loadingShow = true;
let value = {
id: operationsData.projectData,
moduleList: ["uploadElement"],
};
operationsData.placeholder = "Batch_" + setPlaceholder();
Https.axiosPost(Https.httpUrls.getModuleContent, value)
.then(async (rv) => {
operationsData.uploadElement = rv.uploadElement;
operations.loadingShow = false;
})
.catch((err) => {
operations.loadingShow = false;
});
};
let init = (projectData, buildType) => {
operations.operationsModal = true;
clearData();
if (projectData?.id) {
operationsData.projectData = {
label: projectData.name,
value: projectData.id,
};
getUploadElement();
}
if (buildType.value) operationsData.buildType = buildType;
};
const clearData = () => {
operationsData.porjectName = "";
operationsData.generateText = "";
operationsData.similarity = [20, 40];
operationsData.brightenValue = 1;
operationsData.fileList = [];
operationsData.uploadElement = [];
};
const changeProject = () => {
getUploadElement();
};
const changeBuildType = () => {
// operationsData.exhibitionImgList = []
operationsData.projectData = null;
props.cloudList.forEach((item) => {
if (item.value == operationsData.buildType) {
operationsData.credits = item.consumption;
}
});
getHistoryProjectList();
};
const getGenerateCloudImgList = (type) => {
let list = [];
if (type == "SINGLE_DESIGN" || type == "SERIES_DESIGN") return list;
let selectList = [];
let fileList = operationsData.fileList.filter((item) => item.isChecked);
let uploadElement = operationsData.uploadElement.filter(
(item) => item.isChecked
);
if (fileList) selectList.push(...fileList);
if (uploadElement) selectList.push(...uploadElement);
selectList.forEach((item) => {
let obj = {};
if (type == "POSE_TRANSFER") {
obj = {
poseId: 1,
productImage: getMinioUrl(item.imgUrl),
};
} else {
obj = {
elementId: item.id,
elementType: item.type || "ProductElement",
};
}
list.push(obj);
});
return list;
};
let getPorductImg = () => {
let modularData = store.state.UploadFilesModule.modularData;
let list = [];
if (
operationsData.buildType == "toProductImage" ||
operationsData.buildType == "relight"
) {
let productOrRelight = [];
if (operationsData.buildType == "toProductImage")
productOrRelight = modularData.design.likeData;
if (operationsData.buildType == "relight")
productOrRelight = modularData.toProduct;
productOrRelight.forEach((item) => {
if (!item.id) return;
let obj = {
createTime: "",
elementId: 0,
elementType: "",
id: 0,
isLike: 0,
taskId: "",
toProductImageRecordId: 0,
url: "",
};
obj.elementId = item.designOutfitId;
obj.elementType = "DesignOutfit";
if (operationsData.buildType == "relight") {
obj.elementId = item.id;
obj.elementType = "ToProductImage";
}
list.push(obj);
});
}
return list;
};
const getImageStrength = (num) => {
let imageStrength = num == 100 ? 95 : num;
return imageStrength;
};
const getPoseTransformData = () => {
let list = [];
let toProduct = store.state.UploadFilesModule.modularData.toProduct;
toProduct.forEach((item) => {
let obj = {
poseId: 1,
productImage: getMinioUrl(item.url),
};
list.push(obj);
});
return list;
};
let setAddData = () => {
let buildTypeCorresponding = {
SINGLE_DESIGN: "design",
SERIES_DESIGN: "design",
TO_PRODUCT_IMAGE: "toProductImage",
RELIGHT: "relight",
POSE_TRANSFER: "poseTransfer",
};
return {
buildType: buildTypeCorresponding[operationsData.buildType],
nums: operationsData.numberOfImages,
projectId: operationsData.projectData,
name: operationsData.porjectName || operationsData.projectData,
//productimg
toProductImage: {
prompt: operationsData.generateText, //输入的内容
toProductImageVOList: getGenerateCloudImgList(
operationsData.buildType
), //选择的图片
// toProductImageVOList:getPorductImg(),//选择的图片
projectId: operationsData.projectData,
direction: operationsData.relightDirection, //打光方向
brightenValue: operationsData.brightenValue,
imageStrength: (100 - getImageStrength()) / 100,
imageStrengthMin:
(100 - getImageStrength(operationsData.similarity[1])) / 100,
imageStrengthMax:
(100 - getImageStrength(operationsData.similarity[0])) / 100,
},
//poseTransform
// poseTransform:getPoseTransformData(),
poseTransform:
operationsData.buildType == "POSE_TRANSFER"
? getGenerateCloudImgList("POSE_TRANSFER")
: [],
private: operationsData.projectData,
ToProductImageDTO: operationsData.projectData,
};
};
let cancelDsign = () => {
operationsData.buildType = "";
operationsData.numberOfImages = "";
operations.operationsModal = false;
};
let setOk = () => {
let data;
data = setAddData();
if (operationsData.buildType == "TO_PRODUCT_IMAGE") {
if (data.toProductImage.toProductImageVOList.length == 0)
return message.warning("Please upload the picture first.");
// if(data.toProductImage.toProductImageVOList.length == 0)return message.warning("You need to go to the Design module and generate a design result first before you can use the 'To Product Image' cloud generation feature.")
} else if (operationsData.buildType == "RELIGHT") {
if (data.toProductImage.toProductImageVOList.length == 0)
return message.warning("Please upload the picture first.");
// if(data.toProductImage.toProductImageVOList.length == 0)return message.warning("You need to go to the 'To Product Image' module and generate a result first before you can use the 'Relight' cloud generation feature.")
} else if (operationsData.buildType == "POSE_TRANSFER") {
if (data.poseTransform.length == 0)
return message.warning("Please upload the picture first.");
// if(data.poseTransform.length == 0)return message.warning("You must first generate results in the 'To Product Image' module before you can use the 'Transfer Pose' cloud generation feature.")
}
if (operationsData.buildType == "DESIGN" && !operationsData.projectData)
return message.warning("Please select a project");
if (
!data.buildType ||
!data.nums ||
!data.name ||
(operationsData.buildType == "DESIGN" && !operationsData.projectData)
)
return message.warning("Please check the input box marked with *");
operations.loadingShow = true;
Https.axiosPost(Https.httpUrls.designCloud, data)
.then((rv) => {
if (rv) {
operations.loadingShow = false;
cancelDsign();
let porjectData = operationsData.objectList.find(
(item) => item.id === operationsData.projectData
);
let project = {
value: porjectData?.id,
label: porjectData?.name,
};
emit("getContentList", project);
}
})
.catch((error) => {
operations.loadingShow = false;
});
};
const changeNumberOfImages = () => {
if (
operationsData.buildType == "relight" ||
operationsData.buildType == "poseTransfer"
) {
if (
operationsData.exhibitionImgList.length <
Number(operationsData.numberOfImages)
) {
operationsData.numberOfImages =
operationsData.exhibitionImgList.length;
}
}
};
let getHistoryTime = null;
const getHistoryProjectList = (event) => {
clearTimeout(getHistoryTime);
if (!event && !operationsData.buildType) {
operationsData.objectList = [];
return;
}
getHistoryTime = setTimeout(() => {
let value = {
projectName: event,
page: 1,
size: 9999,
asc: 0,
process: operationsData.buildType,
};
Https.axiosPost(Https.httpUrls.historyProject, value).then((rv) => {
rv.content.forEach((item) => {
item.value = item.id;
item.label = item.name;
});
operationsData.objectList = rv.content;
});
}, 1000);
};
let beforeUpload = async (file) => {
const isJpgOrPng =
file.type === "image/jpeg" ||
file.type === "image/png" ||
file.type === "image/jpg" ||
file.type === "image/bmp";
if (!isJpgOrPng) {
message.info(useI18n().t("MoodboardUpload.jsContent3"));
}
const isLt2M = file.size / 1024 / 1024 < 5;
if (!isLt2M) {
message.info(useI18n().t("MoodboardUpload.jsContent4"));
}
return (isJpgOrPng && isLt2M) || Upload.LIST_IGNORE;
};
let fileUploadChange = (data) => {
let file = data.file;
let bor = true;
if (file.status === "done") {
let res = JSON.parse(file.xhr.response);
if (res.errCode == 0) {
file.imgUrl = res.data.url;
file.id = res.data.id;
file.isChecked = true;
file.type = "ProductElement";
operationsData.fileList.filter((v) => v.status === "done");
} else {
bor = false;
}
// this.showFileList = productImgData.fileList
} else if (file.status === "error") {
bor = false;
}
};
const setPlaceholder = () => {
if (!operationsData.projectData) return "";
let index = operationsData.objectList.findIndex(
(item) => item.id === operationsData.projectData
);
return operationsData.objectList[index].name;
};
const focus = () => {
if (operationsData.porjectName) return;
operationsData.porjectName = operationsData.placeholder;
};
const blur = () => {
if (operationsData.porjectName != operationsData.placeholder) return;
operationsData.porjectName = "";
};
return {
...toRefs(operations),
...toRefs(operationsData),
cancelDsign,
init,
changeProject,
focus,
blur,
setOk,
changeBuildType,
changeNumberOfImages,
getHistoryProjectList,
beforeUpload,
fileUploadChange,
getUploadUrl,
getCookie,
};
},
data() {
return {
indicator: h(LoadingOutlined, {
style: {
fontSize: "2.4rem",
},
spin: true,
}),
};
},
mounted() {},
methods: {},
directives: {
mousewheel: {
mounted(el) {
el.addEventListener("mouseenter", (e) => {
if (el.scrollWidth > el.clientWidth) {
el.parentElement.style.overflowY = "hidden";
}
});
// 鼠标移出事件
el.addEventListener("mouseleave", () => {
el.parentElement.style.overflowY = "auto";
});
el.addEventListener(
"wheel",
(e) => {
let num = 0;
if (e.deltaY > 0) {
num = 25;
} else {
num = -25;
}
el.scrollBy(num, 0);
},
{ passive: true }
);
},
},
},
});
</script>
<style lang="less" scoped>
:deep(.ant-modal-mask) {
background: rgba(0, 0, 0, 0.2);
}
:deep(.createCloud_modal) {
.ant-modal-body {
display: flex;
flex-direction: column;
}
}
</style>
<style lang="less" scoped>
.createCloud_modal {
.closeIcon {
z-index: 2;
}
.productImg_content_item_imgBox {
display: flex;
overflow-x: auto;
width: auto;
margin-bottom: 2rem;
align-items: center;
flex-wrap: nowrap;
width: 100%;
.content_item_imgBox_itemImg {
display: flex;
margin-right: 1rem;
position: relative;
height: 20rem;
max-height: 100%;
position: relative;
flex-shrink: 0;
img {
height: 100%;
width: 100%;
cursor: pointer;
object-fit: contain;
opacity: 0.5;
&.active {
opacity: 1;
}
}
.ant-checkbox-wrapper {
position: absolute;
right: 0;
top: 0;
}
&.content_item_imgBox_itemImg:hover {
.content_item_imgBox_itemImg_delete {
display: block;
cursor: pointer;
}
}
.content_item_imgBox_itemImg_delete {
display: none;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.2);
position: absolute;
i {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: #fff;
}
}
}
:deep(.upload_file_item) {
flex-shrink: 0;
}
.content_item_imgBox_itemImg:last-child {
margin-right: 0;
}
}
.allUserPoeration_btn {
display: flex;
flex-direction: row;
height: auto;
justify-content: flex-end;
padding: 1rem 0;
.admin_search_item {
margin-bottom: 0;
}
}
.allUserPoeration_center {
flex: 1;
overflow-y: auto;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
padding: 0 2rem;
> .selectImgList {
width: 100%;
display: flex;
overflow-x: auto;
align-items: center;
flex-wrap: nowrap;
height: 20rem;
margin: 2rem 0;
> .item {
height: 100%;
margin-right: 1rem;
&:last-child {
margin-right: 0;
}
> img {
height: 100%;
}
}
//
}
> .admin_state_item {
width: auto;
// width: 100%;
display: flex;
flex-direction: column;
align-items: flex-start;
> span {
text-align: left;
margin: 0;
margin-bottom: 1.5rem;
font-weight: 600;
}
:deep(> .ant-select > .ant-select-selector) {
border-radius: 1.6rem;
}
> input {
border-radius: 1.6rem;
}
> .sliderAndImput {
display: flex;
align-items: center;
flex: 1;
:deep(> .ant-slider) {
// border-radius: 1.6rem;
flex: 1;
}
> div {
input {
border-radius: 1.6rem;
width: 5rem;
padding: 4px 11px 4px;
margin-left: 1rem;
height: 100%;
text-align: center;
}
}
}
}
}
}
</style>