optimize: fortune page share reward

This commit is contained in:
zzc
2026-01-27 23:01:47 +08:00
parent eb72b5556b
commit aee386da51
4 changed files with 595 additions and 2 deletions

View File

@@ -21,7 +21,6 @@ export const getAvatarFrameList = async (page = 1) => {
});
};
export const avatarDownloadRecord = async (data) => {
return request({
url: "/api/blessing/avatar/download",

View File

@@ -33,6 +33,14 @@
"navigationStyle": "custom"
}
},
{
"path": "pages/avatar/detail",
"style": {
"navigationBarTitleText": "头像详情",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/detail/index",
"style": {

586
pages/avatar/detail.vue Normal file
View File

@@ -0,0 +1,586 @@
<template>
<view class="avatar-detail-page" :style="{ paddingTop: navBarHeight + 'px' }">
<!-- Custom Navbar -->
<view
class="nav-bar"
:style="{
height: navBarHeight + 'px',
paddingTop: statusBarHeight + 'px',
}"
>
<view class="nav-content">
<view class="back" @tap="goBack"></view>
<text class="nav-title">新春头像详情</text>
</view>
</view>
<view class="content-wrap">
<!-- User Info -->
<view class="user-info-section" v-if="detailData">
<image
:src="detailData.from?.avatar || defaultAvatar"
class="user-avatar"
mode="aspectFill"
/>
<view class="user-text">
<view class="name-row">
<text class="nickname">{{
detailData.from?.nickname || "神秘用户"
}}</text>
<view class="tag">马年专属</view>
</view>
<text class="action-text">换上了新春头像</text>
</view>
</view>
<!-- Main Image Card -->
<view class="main-card">
<view class="card-inner">
<image
v-if="detailData?.imageUrl"
:src="detailData.imageUrl"
class="generated-avatar"
mode="aspectFill"
@tap="previewImage"
/>
<view class="loading-box" v-else>
<text>加载中...</text>
</view>
<!-- Decorative Elements -->
<view class="decor-tag">🐰</view>
<view class="card-footer-text">
<text class="icon">🌸</text> 2026 丙午马年限定
</view>
</view>
</view>
<!-- Action Buttons -->
<view class="action-group">
<button class="btn primary-btn" @tap="goToMake">
<text class="icon">🎨</text> 我也要领同款制作
</button>
<button class="btn secondary-btn" @tap="saveImage">
<text class="icon">📥</text> 保存到相册
</button>
</view>
<!-- Recommended Frames -->
<view class="section recommended-section">
<view class="section-header">
<view class="left">
<view class="bar"></view>
<text class="title">热门新春头像框</text>
</view>
<text class="more" @tap="goToMake">查看全部</text>
</view>
<view class="frame-grid">
<view
class="frame-item"
v-for="(item, index) in frameList"
:key="index"
@tap="goToMake"
>
<view class="frame-img-box">
<image :src="item.url" class="frame-img" mode="aspectFit" />
</view>
<text class="frame-name">{{ item.name || "新春相框" }}</text>
</view>
</view>
</view>
<!-- Wallpaper Banner -->
<view class="wallpaper-banner" @tap="goToWallpaper">
<view class="banner-icon">
<text>🖼</text>
</view>
<view class="banner-content">
<text class="banner-title">去挑选更多壁纸</text>
<text class="banner-desc">新年新气象全套皮肤限时领</text>
</view>
<text class="banner-arrow"></text>
</view>
<!-- Footer -->
<view class="page-footer">
<view class="footer-line">
<text class="line"></text>
<text class="text">2026 HAPPY NEW YEAR</text>
<text class="line"></text>
</view>
<text class="footer-sub">新春祝福 · 传递温情</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { getBavBarHeight } from "@/utils/system";
import { getAvatarFrameList, getPageDetail } from "@/api/avatar.js";
const defaultAvatar =
"https://file.lihailezzc.com/resource/d9b329082b32f8305101f708593a4882.png";
const detailData = ref(null);
const frameList = ref([]);
const shareToken = ref("");
const navBarHeight = ref(64);
const statusBarHeight = ref(20);
onLoad((options) => {
if (options.shareToken) {
shareToken.value = options.shareToken;
fetchDetail();
}
fetchFrames();
});
onMounted(() => {
const sysInfo = uni.getSystemInfoSync();
statusBarHeight.value = sysInfo.statusBarHeight;
navBarHeight.value = getBavBarHeight();
});
const goBack = () => {
// Check if can go back, otherwise go home
const pages = getCurrentPages();
if (pages.length > 1) {
uni.navigateBack();
} else {
uni.switchTab({ url: "/pages/index/index" });
}
};
const fetchDetail = async () => {
try {
// uni.showLoading({ title: "加载中..." });
const res = await getPageDetail(shareToken.value);
if (res) {
detailData.value = res;
}
} catch (e) {
console.error(e);
// uni.showToast({ title: "获取详情失败", icon: "none" });
} finally {
// uni.hideLoading();
}
};
const fetchFrames = async () => {
try {
const res = await getAvatarFrameList(1);
if (res) {
const list = Array.isArray(res) ? res : res.list || [];
frameList.value = list.slice(0, 3); // Take first 3
}
} catch (e) {
console.error(e);
}
};
const previewImage = () => {
if (detailData.value?.imageUrl) {
uni.previewImage({
urls: [detailData.value.imageUrl],
});
}
};
const saveImage = () => {
if (!detailData.value?.imageUrl) return;
uni.showLoading({ title: "保存中..." });
uni.downloadFile({
url: detailData.value.imageUrl,
success: (res) => {
if (res.statusCode === 200) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
// uni.hideLoading();
uni.showToast({ title: "保存成功", icon: "success" });
},
fail: () => {
// uni.hideLoading();
uni.showToast({ title: "保存失败", icon: "none" });
},
});
} else {
// uni.hideLoading();
uni.showToast({ title: "下载失败", icon: "none" });
}
},
fail: () => {
// uni.hideLoading();
uni.showToast({ title: "下载失败", icon: "none" });
},
});
};
const goToMake = () => {
uni.navigateTo({
url: "/pages/avatar/index",
});
};
const goToWallpaper = () => {
uni.navigateTo({
url: "/pages/wallpaper/index",
});
};
</script>
<style lang="scss" scoped>
.avatar-detail-page {
min-height: 100vh;
background: #fff0f5; /* Light Pink Background */
box-sizing: border-box;
}
.nav-bar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
box-sizing: border-box;
background: #fff0f5;
}
.nav-content {
display: flex;
align-items: center;
height: 100%;
padding: 0 24rpx;
}
.back {
font-size: 50rpx;
margin-right: 24rpx;
line-height: 1;
color: #333;
}
.nav-title {
font-size: 34rpx;
font-weight: bold;
color: #333;
flex: 1;
text-align: center;
margin-right: 50rpx; /* Balance back button */
}
.content-scroll {
}
.content-wrap {
padding: 30rpx 40rpx 60rpx;
}
/* User Info */
.user-info-section {
display: flex;
align-items: center;
margin-bottom: 40rpx;
}
.user-avatar {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
border: 4rpx solid #fff;
margin-right: 24rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.user-text {
flex: 1;
}
.name-row {
display: flex;
align-items: center;
margin-bottom: 8rpx;
}
.nickname {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-right: 16rpx;
}
.tag {
background: #ff3b30;
color: #fff;
font-size: 20rpx;
padding: 4rpx 12rpx;
border-radius: 99rpx;
}
.action-text {
font-size: 24rpx;
color: #999;
}
/* Main Card */
.main-card {
background: linear-gradient(180deg, #ffffff 0%, #fff5f5 100%);
border-radius: 40rpx;
padding: 24rpx;
box-shadow: 0 20rpx 60rpx rgba(255, 59, 48, 0.15);
margin-bottom: 60rpx;
}
.card-inner {
position: relative;
background: #fffaf0;
border-radius: 30rpx;
padding: 60rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.generated-avatar {
width: 400rpx;
height: 400rpx;
border-radius: 20rpx;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
border: 8rpx solid #d63333;
}
.loading-box {
width: 400rpx;
height: 400rpx;
display: flex;
align-items: center;
justify-content: center;
color: #999;
background: #eee;
border-radius: 20rpx;
}
.decor-tag {
position: absolute;
top: 30rpx;
right: 30rpx;
background: #fff;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
color: #ff3b30;
}
.card-footer-text {
margin-top: 40rpx;
font-size: 28rpx;
color: #d63333;
font-weight: bold;
display: flex;
align-items: center;
background: #fff;
padding: 10rpx 30rpx;
border-radius: 99rpx;
box-shadow: 0 4rpx 10rpx rgba(214, 51, 51, 0.1);
}
.card-footer-text .icon {
margin-right: 10rpx;
}
/* Buttons */
.action-group {
margin-bottom: 60rpx;
}
.btn {
height: 100rpx;
border-radius: 99rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
font-weight: 600;
margin-bottom: 30rpx;
border: none;
}
.btn::after {
border: none;
}
.primary-btn {
background: #ff3b30;
color: #fff;
box-shadow: 0 10rpx 20rpx rgba(255, 59, 48, 0.3);
}
.secondary-btn {
background: #eaeaea;
color: #666;
}
.btn .icon {
margin-right: 16rpx;
font-size: 36rpx;
}
/* Recommended Section */
.section {
margin-bottom: 40rpx;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
}
.section-header .left {
display: flex;
align-items: center;
}
.section-header .bar {
width: 8rpx;
height: 32rpx;
background: #ff3b30;
border-radius: 4rpx;
margin-right: 16rpx;
}
.section-header .title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.section-header .more {
font-size: 24rpx;
color: #999;
}
.frame-grid {
display: flex;
justify-content: space-between;
}
.frame-item {
width: 200rpx;
display: flex;
flex-direction: column;
align-items: center;
background: #fff;
border-radius: 24rpx;
padding: 20rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.03);
}
.frame-img-box {
width: 140rpx;
height: 140rpx;
margin-bottom: 16rpx;
border-radius: 50%;
overflow: hidden;
background: #f9f9f9;
}
.frame-img {
width: 100%;
height: 100%;
}
.frame-name {
font-size: 24rpx;
color: #333;
font-weight: 500;
}
/* Wallpaper Banner */
.wallpaper-banner {
background: #fff;
border-radius: 24rpx;
padding: 30rpx;
display: flex;
align-items: center;
margin-bottom: 60rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.03);
}
.banner-icon {
width: 80rpx;
height: 80rpx;
background: #fff0f5;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 24rpx;
}
.banner-icon text {
font-size: 40rpx;
color: #ff3b30;
}
.banner-content {
flex: 1;
}
.banner-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
display: block;
margin-bottom: 8rpx;
}
.banner-desc {
font-size: 22rpx;
color: #999;
}
.banner-arrow {
font-size: 36rpx;
color: #ccc;
}
/* Footer */
.page-footer {
text-align: center;
padding-bottom: 40rpx;
}
.footer-line {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
}
.footer-line .line {
width: 60rpx;
height: 2rpx;
background: #ccc;
}
.footer-line .text {
font-size: 20rpx;
color: #999;
margin: 0 20rpx;
letter-spacing: 2rpx;
}
.footer-sub {
font-size: 20rpx;
color: #ccc;
}
</style>

View File

@@ -497,7 +497,7 @@ onShareAppMessage(async () => {
return {
title: "制作我的新春头像",
path: `/pages/avatar/index?shareToken=${shareTokenRes.shareToken}`,
path: `/pages/avatar/detail?shareToken=${shareTokenRes.shareToken}`,
imageUrl:
"https://file.lihailezzc.com/resource/b48c41054c2633c478463ac1b1f1ca23.png", // 使用默认封面或 popularCards 的封面
};