Files
YGChatCS/src/pages-aigc/detail/detail.vue
duanshuwen 1ebdf92159 refactor: remove unused CustomEmpty and related code
clean up dead code by removing all CustomEmpty component imports, template usages and the associated detailEmptyText state variable
2026-07-13 22:48:27 +08:00

297 lines
7.2 KiB
Vue

<template>
<view class="aigc-detail-page">
<AigcTopBar :points="pointBalance" @back="handleBack" @history="handleOpenRecords" @recharge="handleRecharge" />
<view class="aigc-detail-content">
<template v-if="taskDetail">
<ResultPreview v-if="result.cover" :result="result" />
<ResultMeta :items="metaItems" />
<ResultActions :saving="isSaving" @save="handleSave" />
<view class="aigc-detail-text-actions">
<view class="aigc-detail-text-action" @tap="handleRegenerate">再生成一版</view>
<view class="aigc-detail-text-action" @tap="handleChangeTemplate">换个模板</view>
<view class="aigc-detail-text-action" @tap="handleOpenRecords">历史记录</view>
</view>
</template>
</view>
</view>
</template>
<script setup>
import { computed, ref } from "vue";
import { onLoad, onShareAppMessage, onShow } from "@dcloudio/uni-app";
import AigcTopBar from "@/pages-aigc/components/AigcTopBar/index.vue";
import { useCurrentCredit } from "@/pages-aigc/hooks/useCurrentCredit.js";
import { getAigcGeneratorTaskDetail } from "@/request/api/AigcApi.js";
import ResultActions from "./components/ResultActions/index.vue";
import ResultMeta from "./components/ResultMeta/index.vue";
import ResultPreview from "./components/ResultPreview/index.vue";
const { pointBalance, fetchCurrentCredit } = useCurrentCredit();
const taskId = ref("");
const taskDetail = ref(null);
const isSaving = ref(false);
const GENERATOR_TYPE_TEXT = {
0: "图片版",
1: "视频版",
};
const TASK_STATUS_TEXT = {
0: "排队中",
1: "生成中",
2: "已完成",
3: "生成失败",
4: "视频生成中",
};
const getMappedText = (mapping, value, prefix) => {
if (Object.prototype.hasOwnProperty.call(mapping, value)) {
return mapping[value];
}
return value === undefined || value === null || value === "" ? "-" : `${prefix}${value}`;
};
const result = computed(() => {
const record = taskDetail.value || {};
const imageUrl = record.imageResultUrl || "";
const videoUrl = record.videoResultUrl || "";
const isVideo = Boolean(videoUrl) && (record.generatorType === 1 || !imageUrl);
const typeText = getMappedText(GENERATOR_TYPE_TEXT, record.generatorType, "类型");
const statusText = getMappedText(TASK_STATUS_TEXT, record.taskStatus, "状态");
const consumedText =
record.generatorCost === undefined || record.generatorCost === null || record.generatorCost === ""
? "-"
: `${record.generatorCost}积分`;
return {
id: record.taskId,
title: record.itemTitle || record.taskId || "生成结果",
cover: isVideo ? videoUrl : imageUrl || videoUrl,
mediaType: isVideo ? "video" : "image",
accent: "#0a4d46",
variantLabel: typeText,
resultLabel: statusText,
consumedText,
desc: record.itemSubTitle || statusText,
};
});
const metaItems = computed(() => {
const record = taskDetail.value;
if (!record) return [];
const completeTime =
record.videoGeneratorCompleteTime || record.imageGeneratorCompleteTime || record.createTime || "-";
return [
{
label: "状态",
value: result.value.resultLabel,
},
{
label: "已消耗",
value: result.value.consumedText,
},
{
label: "完成时间",
value: completeTime,
},
];
});
const showPlaceholderToast = (title) => {
uni.showToast({
title,
icon: "none",
});
};
const fetchTaskDetail = async () => {
uni.showLoading({
title: "加载中",
mask: true,
});
try {
const res = await getAigcGeneratorTaskDetail({ taskId: taskId.value });
if (res?.code === 0 && res.data && typeof res.data === "object" && !Array.isArray(res.data)) {
taskDetail.value = res.data;
return;
}
taskDetail.value = null;
showPlaceholderToast("获取任务详情失败");
} catch (error) {
console.error("获取AIGC生成任务详情失败", error);
taskDetail.value = null;
showPlaceholderToast("获取任务详情失败");
} finally {
uni.hideLoading();
}
};
onLoad((query = {}) => {
taskId.value = String(query.taskId || "").trim();
if (!taskId.value) {
showPlaceholderToast("缺少任务ID");
return;
}
fetchTaskDetail();
});
onShow(() => {
fetchCurrentCredit();
});
onShareAppMessage(() => {
const shareInfo = {
title: taskDetail.value?.itemTitle,
path: taskId.value
? `/pages-aigc/detail/detail?taskId=${encodeURIComponent(taskId.value)}`
: "/pages-aigc/home/home",
};
const imageUrl = taskDetail.value?.imageResultUrl || "";
if (imageUrl) {
shareInfo.imageUrl = imageUrl;
}
return shareInfo;
});
const handleBack = () => {
const pages = getCurrentPages();
if (pages.length > 1) {
uni.navigateBack();
}
};
const handleRecharge = () => {
showPlaceholderToast("积分充值");
};
const downloadImage = (url) =>
new Promise((resolve, reject) => {
if (!/^https?:\/\//i.test(url)) {
resolve(url);
return;
}
uni.downloadFile({
url,
success: (res) => {
if (res.statusCode === 200 && res.tempFilePath) {
resolve(res.tempFilePath);
return;
}
reject(res);
},
fail: reject,
});
});
const saveImageToAlbum = (filePath) =>
new Promise((resolve, reject) => {
uni.saveImageToPhotosAlbum({
filePath,
success: resolve,
fail: reject,
});
});
const isAlbumPermissionDenied = (error) => {
const errorMessage = String(error?.errMsg || "").toLowerCase();
return (
errorMessage.includes("auth deny") ||
errorMessage.includes("authorize:no response") ||
errorMessage.includes("permission denied")
);
};
const promptAlbumPermission = () => {
uni.showModal({
title: "需要相册权限",
content: "请在设置中允许保存图片到相册。",
confirmText: "去设置",
success: ({ confirm }) => {
if (confirm) {
uni.openSetting();
}
},
});
};
const handleSave = async () => {
if (isSaving.value) return;
if (result.value.mediaType !== "image") {
showPlaceholderToast("当前结果不是图片");
return;
}
if (!result.value.cover) {
showPlaceholderToast("暂无可保存的图片");
return;
}
isSaving.value = true;
uni.showLoading({
title: "保存中",
mask: true,
});
let saveError = null;
try {
const filePath = await downloadImage(result.value.cover);
await saveImageToAlbum(filePath);
} catch (error) {
saveError = error;
} finally {
uni.hideLoading();
isSaving.value = false;
}
if (!saveError) {
uni.showToast({
title: "已保存到相册",
icon: "success",
});
return;
}
if (isAlbumPermissionDenied(saveError)) {
promptAlbumPermission();
} else {
showPlaceholderToast("保存图片失败");
}
};
const handleRegenerate = () => {
showPlaceholderToast("再生成一版");
};
const handleChangeTemplate = () => {
uni.navigateTo({
url: "/pages-aigc/home/home",
fail: () => showPlaceholderToast("换个模板"),
});
};
const handleOpenRecords = () => {
uni.navigateTo({
url: "/pages-aigc/record/record",
fail: () => showPlaceholderToast("历史记录"),
});
};
</script>
<style scoped lang="scss">
@import "./styles/index.scss";
</style>