feat(aigc): add shared work page and AIGC sharing

- add new shared work page to view shared AIGC generated images and videos
- add createAigcGeneratorTaskShare and getAigcGeneratorTaskShareDetail APIs
- update ResultActions component to add share preparation state and native share support
- remove deprecated SharePreviewPopup component and its associated styles
- update AIGC detail page to generate share keys and adjust native share metadata
- register the new shared work page in pages.json
This commit is contained in:
duanshuwen
2026-07-16 13:28:46 +08:00
parent dcf67dedfc
commit 67b1b78f1f
8 changed files with 313 additions and 314 deletions

View File

@@ -6,7 +6,8 @@
<template v-if="taskDetail">
<ResultPreview v-if="result.cover" :result="result" />
<ResultMeta :items="metaItems" />
<ResultActions :saving="isSaving" @save="handleSave" @share="handleOpenSharePreview" />
<ResultActions :saving="isSaving" :share-ready="Boolean(shareKey)" :share-preparing="isPreparingShare"
@save="handleSave" @prepare-share="handlePrepareShare" />
<view class="aigc-detail-text-actions">
<view class="aigc-detail-text-action" @tap="handleRegenerate">再生成一版</view>
@@ -16,29 +17,28 @@
</template>
</view>
<SharePreviewPopup ref="sharePreviewPopup" :app-name="currentClientName" :title="result.title"
:variant-label="result.variantLabel" :image-url="sharePreviewImage" />
</view>
</template>
<script setup>
import { computed, ref } from "vue";
import { onLoad, onShareAppMessage, onShow } from "@dcloudio/uni-app";
import { getCurrentConfig } from "@/constant/base.js";
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 {
createAigcGeneratorTaskShare,
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";
import SharePreviewPopup from "./components/SharePreviewPopup/index.vue";
const { pointBalance, fetchCurrentCredit } = useCurrentCredit();
const taskId = ref("");
const taskDetail = ref(null);
const isSaving = ref(false);
const sharePreviewPopup = ref(null);
const currentClientName = String(getCurrentConfig()?.name || "").trim() || "微信小程序";
const isPreparingShare = ref(false);
const shareKey = ref("");
const GENERATOR_TYPE_TEXT = {
0: "图片版",
@@ -128,6 +128,7 @@ const fetchTaskDetail = async () => {
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;
prepareShareKey();
return;
}
@@ -159,9 +160,9 @@ onShow(() => {
onShareAppMessage(() => {
const shareInfo = {
title: taskDetail.value?.itemTitle || "分享旅行作品",
path: taskId.value
? `/pages-aigc/detail/detail?taskId=${encodeURIComponent(taskId.value)}`
: "/pages-aigc/home/home",
path: shareKey.value
? `/pages-aigc/sharedWork/sharedWork?shareKey=${encodeURIComponent(shareKey.value)}`
: "/pages/index/index",
};
const imageUrl = sharePreviewImage.value;
@@ -172,8 +173,38 @@ onShareAppMessage(() => {
return shareInfo;
});
const handleOpenSharePreview = () => {
sharePreviewPopup.value?.open();
const prepareShareKey = async (showFeedback = false) => {
if (isPreparingShare.value || !taskId.value) return;
if (shareKey.value) return;
isPreparingShare.value = true;
try {
const res = await createAigcGeneratorTaskShare({ taskId: taskId.value });
const nextShareKey = String(res?.data?.shareKey || "").trim();
if (res?.code === 0 && nextShareKey) {
shareKey.value = nextShareKey;
if (showFeedback) {
showPlaceholderToast("分享已准备,请再次点击");
}
return;
}
if (showFeedback) {
showPlaceholderToast(res?.msg || "创建分享失败");
}
} catch (error) {
console.error("创建AIGC任务分享失败", error);
if (showFeedback) {
showPlaceholderToast("创建分享失败");
}
} finally {
isPreparingShare.value = false;
}
};
const handlePrepareShare = () => {
prepareShareKey(true);
};
const handleBack = () => {