feat: add gift points toast and refactor useTemplate layout
Add a new gift points notification toast to the AIGC home page for new user signup rewards. Restructure the useTemplate page's layout and SCSS, split the content container and add dedicated popup host for modal steps. Remove the unused UploadTemplatePreview component and all related references from the codebase.
This commit is contained in:
37
src/pages-aigc/home/components/GiftPointsToast/index.vue
Normal file
37
src/pages-aigc/home/components/GiftPointsToast/index.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<view v-if="visible" class="gift-points-toast" role="status">
|
||||
<text class="gift-points-badge">{{ title }}</text>
|
||||
<text class="gift-points-message">{{ message }}</text>
|
||||
<view class="gift-points-close" @tap="handleClose">
|
||||
<uni-icons type="closeempty" size="20" color="#ffffff" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "300积分已到账",
|
||||
},
|
||||
message: {
|
||||
type: String,
|
||||
default: "新用户权益已发放,可用于图片版或动效视频版内容升级。",
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["close", "update:visible"]);
|
||||
|
||||
const handleClose = () => {
|
||||
emit("update:visible", false);
|
||||
emit("close");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/index.scss";
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
.gift-points-toast {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
top: 4px;
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
overflow: hidden;
|
||||
padding: 7px 7px 7px 10px;
|
||||
border: 1px solid rgba(94, 171, 255, 0.56);
|
||||
border-radius: 18px;
|
||||
background: #172951f0;
|
||||
box-shadow: 0 10px 22px rgba(15, 68, 120, 0.18);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.gift-points-badge {
|
||||
flex: 0 0 111px;
|
||||
width: 111px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
border-radius: 999px;
|
||||
background: #20cf75;
|
||||
color: #ffffff;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
font-weight: 900;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.gift-points-message {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
max-height: 32px;
|
||||
overflow: hidden;
|
||||
color: rgba(239, 250, 255, 0.94);
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
font-weight: 800;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.gift-points-close {
|
||||
flex: 0 0 28px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -3,6 +3,11 @@
|
||||
<AigcTopBar :points="pointBalance" @back="handleBack" @history="handleHistory" @recharge="handleRecharge" />
|
||||
|
||||
<view class="aigc-home-browser">
|
||||
<GiftPointsToast
|
||||
:visible="giftToastVisible"
|
||||
@close="handleCloseGiftToast"
|
||||
/>
|
||||
|
||||
<TemplateCarousel v-model="activeIndex" :templates="templates" @select="handleSelectTemplate" />
|
||||
|
||||
<FlowSteps :steps="steps" />
|
||||
@@ -13,12 +18,14 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import AigcTopBar from "@/pages-aigc/components/AigcTopBar/index.vue";
|
||||
import GiftPointsToast from "./components/GiftPointsToast/index.vue";
|
||||
import TemplateCarousel from "./components/TemplateCarousel/index.vue";
|
||||
import FlowSteps from "./components/FlowSteps/index.vue";
|
||||
import { aigcFlowSteps, aigcTemplates } from "./data/templates.js";
|
||||
|
||||
const pointBalance = ref(300);
|
||||
const activeIndex = ref(0);
|
||||
const giftToastVisible = ref(true);
|
||||
const templates = aigcTemplates;
|
||||
const steps = aigcFlowSteps;
|
||||
|
||||
@@ -44,6 +51,10 @@ const handleRecharge = () => {
|
||||
showPlaceholderToast("积分充值");
|
||||
};
|
||||
|
||||
const handleCloseGiftToast = () => {
|
||||
giftToastVisible.value = false;
|
||||
};
|
||||
|
||||
const handleSelectTemplate = (template) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages-aigc/useTemplate/useTemplate?templateId=${encodeURIComponent(template.id || "")}`,
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
class="upload-template-preview"
|
||||
:style="{ '--upload-accent': template.accent || '#0a4d46' }"
|
||||
>
|
||||
<image class="upload-template-image" :src="template.cover" mode="aspectFill" />
|
||||
<view class="upload-template-shade" />
|
||||
|
||||
<view class="upload-template-copy">
|
||||
<text class="upload-template-badge">{{ version.label || "图片版" }}</text>
|
||||
<text class="upload-template-title">{{ template.title }}</text>
|
||||
<text class="upload-template-desc">{{ previewDesc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
template: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
version: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const previewDesc = computed(() => {
|
||||
if (props.template.desc) {
|
||||
return props.template.desc;
|
||||
}
|
||||
|
||||
return "上传一张清晰半身照,生成旅行内容";
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/index.scss";
|
||||
</style>
|
||||
@@ -1,85 +0,0 @@
|
||||
.upload-template-preview {
|
||||
position: relative;
|
||||
height: 286px;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 26px 26px;
|
||||
background: var(--upload-accent, #0a4d46);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.upload-template-image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.upload-template-shade {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(8, 22, 28, 0.04) 0%,
|
||||
rgba(8, 22, 28, 0.16) 46%,
|
||||
rgba(8, 22, 28, 0.72) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.upload-template-copy {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
right: 16px;
|
||||
bottom: 92px;
|
||||
left: 16px;
|
||||
min-width: 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.upload-template-badge {
|
||||
height: 20px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
max-width: 130px;
|
||||
overflow: hidden;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
color: #172033;
|
||||
font-size: 9px;
|
||||
line-height: 20px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.7px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.upload-template-title,
|
||||
.upload-template-desc {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.upload-template-title {
|
||||
margin-top: 10px;
|
||||
color: #ffffff;
|
||||
font-size: 24px;
|
||||
line-height: 30px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.upload-template-desc {
|
||||
margin-top: 6px;
|
||||
color: rgba(255, 255, 255, 0.78);
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
font-weight: 800;
|
||||
}
|
||||
@@ -17,16 +17,31 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.aigc-use-template-content {
|
||||
.aigc-use-template-body {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aigc-use-template-content {
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
padding: 24px 18px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.aigc-use-template-content.is-upload-guide {
|
||||
padding: 0 12px;
|
||||
.aigc-use-template-popup-host {
|
||||
position: fixed;
|
||||
z-index: 30;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aigc-use-template-note {
|
||||
|
||||
@@ -8,11 +8,8 @@
|
||||
@recharge="handleRecharge"
|
||||
/>
|
||||
|
||||
<view
|
||||
class="aigc-use-template-content"
|
||||
:class="{ 'is-upload-guide': currentStep !== 'version' }"
|
||||
>
|
||||
<template v-if="currentStep === 'version'">
|
||||
<view class="aigc-use-template-body">
|
||||
<view class="aigc-use-template-content">
|
||||
<TemplateVersionHero :template="currentTemplate" />
|
||||
|
||||
<VersionOptionList
|
||||
@@ -24,28 +21,24 @@
|
||||
<text class="aigc-use-template-note">
|
||||
动效视频版会先生成图片底图,再升级为 5秒内动效视频。
|
||||
</text>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template v-else>
|
||||
<UploadTemplatePreview
|
||||
:template="currentTemplate"
|
||||
:version="currentVersion"
|
||||
/>
|
||||
<view v-if="currentStep === 'uploadGuide'" class="aigc-use-template-popup-host">
|
||||
<PhotoGuidePanel
|
||||
v-if="currentStep === 'uploadGuide'"
|
||||
:avatar-src="guideAvatar"
|
||||
:positive-examples="positiveExamples"
|
||||
:negative-examples="negativeExamples"
|
||||
@close="handleCloseGuide"
|
||||
@confirm="handleConfirmGuide"
|
||||
/>
|
||||
</view>
|
||||
<view v-if="currentStep === 'photoPick'" class="aigc-use-template-popup-host">
|
||||
<PhotoPickDrawer
|
||||
v-else
|
||||
@close="handleCloseGuide"
|
||||
@camera="handlePickCamera"
|
||||
@album="handlePickAlbum"
|
||||
/>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -59,7 +52,6 @@ import guideAvatar from "./assets/xiaoqi-avatar.png";
|
||||
import PhotoGuidePanel from "./components/PhotoGuidePanel/index.vue";
|
||||
import PhotoPickDrawer from "./components/PhotoPickDrawer/index.vue";
|
||||
import TemplateVersionHero from "./components/TemplateVersionHero/index.vue";
|
||||
import UploadTemplatePreview from "./components/UploadTemplatePreview/index.vue";
|
||||
import VersionOptionList from "./components/VersionOptionList/index.vue";
|
||||
import { negativeExamples, positiveExamples } from "./data/photoGuideExamples.js";
|
||||
import { versionOptions } from "./data/versionOptions.js";
|
||||
@@ -73,10 +65,6 @@ const currentTemplate = computed(() => {
|
||||
return aigcTemplates.find((item) => item.id === templateId.value) || aigcTemplates[0] || {};
|
||||
});
|
||||
|
||||
const currentVersion = computed(() => {
|
||||
return versionOptions.find((item) => item.value === selectedVersion.value) || versionOptions[0] || {};
|
||||
});
|
||||
|
||||
onLoad((query = {}) => {
|
||||
templateId.value = query.templateId || "";
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user