feat(aigc): 新增图片生成动效视频的升级功能
- 新增图片转视频相关的API接口 - 调整AIGC详情页英雄区块高度至380px - 添加结果详情页升级动效视频入口 - 完善升级流程的逻辑与费用计算 - 适配多类型生成任务的判断规则
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
.template-version-hero {
|
||||
position: relative;
|
||||
height: 360px;
|
||||
height: 380px;
|
||||
overflow: hidden;
|
||||
border-radius: 24px;
|
||||
background: var(--template-accent, #0a4d46);
|
||||
|
||||
@@ -46,11 +46,14 @@ import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import Privacy from "@/components/Privacy/index.vue";
|
||||
import AigcTopBar from "@/pages-aigc/components/AigcTopBar/index.vue";
|
||||
import { useCurrentCredit } from "@/pages-aigc/hooks/useCurrentCredit.js";
|
||||
import { getWechatLoginCode } from "@/pages-aigc/services/wechatLogin.js";
|
||||
import {
|
||||
createAigcGeneratorTask,
|
||||
getAigcTemplateItemList,
|
||||
getAigcTemplateList,
|
||||
import { getWechatLoginCode } from "@/pages-aigc/services/wechatLogin.js";
|
||||
import {
|
||||
createAigcImageToVideoTask,
|
||||
createAigcGeneratorTask,
|
||||
getAigcImageToVideoItemDetail,
|
||||
getAigcGeneratorTaskDetail,
|
||||
getAigcTemplateItemList,
|
||||
getAigcTemplateList,
|
||||
} from "@/pages-aigc/request/AigcApi.js";
|
||||
import { updateImageFile } from "@/request/api/UpdateFile.js";
|
||||
import GenerateConfirmPanel from "./components/GenerateConfirmPanel/index.vue";
|
||||
@@ -72,14 +75,27 @@ const uploadedImageUrl = ref("");
|
||||
const currentStep = ref("version");
|
||||
const pointDialogVisible = ref(false);
|
||||
const isUploading = ref(false);
|
||||
const isCreatingTask = ref(false);
|
||||
const privacyVisible = ref(false);
|
||||
const privacyContractName = ref("隐私保护指引");
|
||||
const pendingImageSourceType = ref("");
|
||||
const isCreatingTask = ref(false);
|
||||
const privacyVisible = ref(false);
|
||||
const privacyContractName = ref("隐私保护指引");
|
||||
const pendingImageSourceType = ref("");
|
||||
const upgradeTaskId = ref("");
|
||||
const upgradeTemplateItemId = ref("");
|
||||
const imageToVideoItemDetail = ref(null);
|
||||
const upgradeSourceTaskDetail = ref(null);
|
||||
|
||||
const isImageToVideoUpgrade = computed(() => Boolean(upgradeTaskId.value));
|
||||
const IMAGE_GENERATION_COST = 350;
|
||||
const VIDEO_GENERATION_COST = 1000;
|
||||
|
||||
const currentTemplate = computed(() => {
|
||||
return templates.value.find((item) => item.templateId === templateId.value) || templates.value[0] || {};
|
||||
});
|
||||
const currentTemplate = computed(() => {
|
||||
const template =
|
||||
templates.value.find((item) => item.templateId === templateId.value) || templates.value[0] || {};
|
||||
const imageResultUrl = String(upgradeSourceTaskDetail.value?.imageResultUrl || "").trim();
|
||||
|
||||
if (!isImageToVideoUpgrade.value || !imageResultUrl) return template;
|
||||
return { ...template, templateContentUrl: imageResultUrl };
|
||||
});
|
||||
|
||||
const currentTemplateItem = computed(() => {
|
||||
return (
|
||||
@@ -89,16 +105,54 @@ const currentTemplateItem = computed(() => {
|
||||
);
|
||||
});
|
||||
|
||||
const currentCost = computed(() => {
|
||||
return Number(currentTemplateItem.value.generatorCost) || 0;
|
||||
});
|
||||
const currentCost = computed(() => {
|
||||
return isImageToVideoUpgrade.value
|
||||
? Number(imageToVideoItemDetail.value?.generatorCost) || 0
|
||||
: Number(currentTemplateItem.value.generatorType) === 1
|
||||
? VIDEO_GENERATION_COST
|
||||
: IMAGE_GENERATION_COST;
|
||||
});
|
||||
|
||||
const showPlaceholderToast = (title) => {
|
||||
const showPlaceholderToast = (title) => {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const fetchImageToVideoItemDetail = async () => {
|
||||
if (!isImageToVideoUpgrade.value) return;
|
||||
|
||||
try {
|
||||
const res = await getAigcImageToVideoItemDetail({ taskId: upgradeTaskId.value });
|
||||
if (res?.code === 0 && res.data && typeof res.data === "object" && !Array.isArray(res.data)) {
|
||||
imageToVideoItemDetail.value = res.data;
|
||||
return;
|
||||
}
|
||||
|
||||
showPlaceholderToast(res?.msg || "获取升级视频费用失败");
|
||||
} catch (error) {
|
||||
console.warn("获取AIGC图片升级视频生成项详情失败", error);
|
||||
showPlaceholderToast("获取升级视频费用失败");
|
||||
}
|
||||
};
|
||||
|
||||
const fetchUpgradeSourceTaskDetail = async () => {
|
||||
if (!isImageToVideoUpgrade.value) return;
|
||||
|
||||
try {
|
||||
const res = await getAigcGeneratorTaskDetail({ taskId: upgradeTaskId.value });
|
||||
if (res?.code === 0 && res.data && typeof res.data === "object" && !Array.isArray(res.data)) {
|
||||
upgradeSourceTaskDetail.value = res.data;
|
||||
return;
|
||||
}
|
||||
|
||||
showPlaceholderToast("获取原图片失败");
|
||||
} catch (error) {
|
||||
console.warn("获取AIGC原图片任务详情失败", error);
|
||||
showPlaceholderToast("获取原图片失败");
|
||||
}
|
||||
};
|
||||
|
||||
const resetSelectedPhoto = () => {
|
||||
selectedImageLocalPath.value = "";
|
||||
@@ -127,25 +181,39 @@ const fetchTemplateItemList = async () => {
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await getAigcTemplateItemList({ templateId: templateId.value });
|
||||
if (res?.code === 0 && Array.isArray(res.data)) {
|
||||
templateItems.value = res.data;
|
||||
selectedTemplateItemId.value = res.data[0]?.templateItemId || "";
|
||||
}
|
||||
const res = await getAigcTemplateItemList({ templateId: templateId.value });
|
||||
if (res?.code === 0 && Array.isArray(res.data)) {
|
||||
templateItems.value = res.data;
|
||||
const selectedUpgradeItem = res.data.find(
|
||||
(item) =>
|
||||
String(item.templateItemId || "") === upgradeTemplateItemId.value &&
|
||||
Number(item.generatorType) === 0,
|
||||
);
|
||||
const firstImageItem = res.data.find((item) => Number(item.generatorType) === 0);
|
||||
selectedTemplateItemId.value =
|
||||
(isImageToVideoUpgrade.value ? selectedUpgradeItem || firstImageItem : res.data[0])?.templateItemId || "";
|
||||
if (isImageToVideoUpgrade.value) {
|
||||
currentStep.value = "generateConfirm";
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("获取AIGC模板生成项失败", error);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchPageData = async () => {
|
||||
await fetchTemplateList();
|
||||
await fetchTemplateItemList();
|
||||
};
|
||||
const fetchPageData = async () => {
|
||||
await fetchTemplateList();
|
||||
await fetchImageToVideoItemDetail();
|
||||
await fetchUpgradeSourceTaskDetail();
|
||||
await fetchTemplateItemList();
|
||||
};
|
||||
|
||||
onLoad((query = {}) => {
|
||||
templateId.value = query.templateId || "";
|
||||
fetchPageData();
|
||||
});
|
||||
onLoad((query = {}) => {
|
||||
templateId.value = String(query.templateId || "").trim();
|
||||
upgradeTaskId.value = String(query.upgradeTaskId || "").trim();
|
||||
upgradeTemplateItemId.value = String(query.upgradeTemplateItemId || "").trim();
|
||||
fetchPageData();
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
fetchCurrentCredit();
|
||||
@@ -317,26 +385,31 @@ const handleClosePhotoConfirm = () => {
|
||||
currentStep.value = "photoPick";
|
||||
};
|
||||
|
||||
const handleConfirmPhoto = () => {
|
||||
if (!uploadedImageUrl.value) {
|
||||
showPlaceholderToast("请先上传图片");
|
||||
currentStep.value = "photoPick";
|
||||
const handleConfirmPhoto = () => {
|
||||
if (!uploadedImageUrl.value) {
|
||||
showPlaceholderToast("请先上传图片");
|
||||
currentStep.value = "photoPick";
|
||||
return;
|
||||
}
|
||||
|
||||
currentStep.value = "generateConfirm";
|
||||
};
|
||||
|
||||
const handleGenerate = async () => {
|
||||
if (isCreatingTask.value) return;
|
||||
const handleGenerate = async () => {
|
||||
if (isCreatingTask.value) return;
|
||||
|
||||
const templateItemId = currentTemplateItem.value.templateItemId;
|
||||
if (!templateItemId) {
|
||||
showPlaceholderToast("请选择生成类型");
|
||||
return;
|
||||
}
|
||||
if (!templateItemId) {
|
||||
showPlaceholderToast("请选择生成类型");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isImageToVideoUpgrade.value && !imageToVideoItemDetail.value) {
|
||||
showPlaceholderToast("升级视频费用加载失败,请稍后重试");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uploadedImageUrl.value) {
|
||||
if (!isImageToVideoUpgrade.value && !uploadedImageUrl.value) {
|
||||
showPlaceholderToast("请先上传图片");
|
||||
currentStep.value = "photoPick";
|
||||
return;
|
||||
@@ -354,17 +427,33 @@ const handleGenerate = async () => {
|
||||
uni.showLoading({
|
||||
title: "创建中",
|
||||
mask: true,
|
||||
});
|
||||
|
||||
try {
|
||||
const wxLoginCode = await getWechatLoginCode();
|
||||
const res = await createAigcGeneratorTask({
|
||||
templateItemId,
|
||||
imageUrlList: [uploadedImageUrl.value],
|
||||
wxLoginCode,
|
||||
});
|
||||
|
||||
const taskId = String(res?.data || "").trim();
|
||||
});
|
||||
|
||||
try {
|
||||
let res;
|
||||
if (isImageToVideoUpgrade.value) {
|
||||
const wxLoginCode = await getWechatLoginCode();
|
||||
res = await createAigcImageToVideoTask({
|
||||
taskId: upgradeTaskId.value,
|
||||
wxLoginCode,
|
||||
});
|
||||
} else {
|
||||
const wxLoginCode = await getWechatLoginCode();
|
||||
res = await createAigcGeneratorTask({
|
||||
templateItemId,
|
||||
imageUrlList: [uploadedImageUrl.value],
|
||||
wxLoginCode,
|
||||
});
|
||||
}
|
||||
|
||||
if (isImageToVideoUpgrade.value && String(res?.msg || "").includes("积分余额不足")) {
|
||||
pointDialogVisible.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const taskId = String(
|
||||
typeof res?.data === "object" && res.data !== null ? res.data.taskId : res?.data || "",
|
||||
).trim();
|
||||
if (res?.code === 0 && taskId) {
|
||||
fetchCurrentCredit();
|
||||
uni.redirectTo({
|
||||
|
||||
Reference in New Issue
Block a user