Files

543 lines
11 KiB
Vue
Raw Permalink Normal View History

2026-01-27 23:01:47 +08:00
<template>
2026-01-31 22:37:24 +08:00
<view class="avatar-detail-page">
<NavBar title="专属头像" />
2026-01-27 23:01:47 +08:00
<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="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>
</view>
<!-- Recommended Frames -->
<view class="section recommended-section">
<view class="section-header">
<view class="left">
<view class="bar"></view>
2026-01-28 16:41:05 +08:00
<text class="title">热门新春头像</text>
2026-01-27 23:01:47 +08:00
</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">
2026-01-28 16:41:05 +08:00
<image :src="item.imageUrl" class="frame-img" mode="aspectFit" />
2026-01-27 23:01:47 +08:00
</view>
2026-01-28 16:41:05 +08:00
<text class="frame-name">{{
item.type === "decor"
? "新春饰品"
: item.type === "avatar"
? "新春头像"
: "新春相框"
}}</text>
2026-01-27 23:01:47 +08:00
</view>
</view>
</view>
<!-- Wallpaper Banner -->
2026-01-28 10:55:39 +08:00
<view class="wallpaper-banner" @tap="goToFortune">
2026-01-27 23:01:47 +08:00
<view class="banner-icon">
2026-01-28 10:55:39 +08:00
<text>🏮</text>
2026-01-27 23:01:47 +08:00
</view>
<view class="banner-content">
2026-01-28 10:55:39 +08:00
<text class="banner-title">去抽取新年运势</text>
<text class="banner-desc">每日一签开启你的新年好运</text>
2026-01-28 10:35:31 +08:00
</view>
<text class="banner-arrow"></text>
</view>
2026-01-28 10:55:39 +08:00
<view class="wallpaper-banner" @tap="goToGreeting">
2026-01-28 10:35:31 +08:00
<view class="banner-icon">
2026-01-28 10:55:39 +08:00
<text>🧧</text>
2026-01-28 10:35:31 +08:00
</view>
<view class="banner-content">
2026-01-28 10:55:39 +08:00
<text class="banner-title">去制作新年贺卡</text>
<text class="banner-desc">定制专属祝福传递浓浓年味</text>
2026-01-28 10:35:31 +08:00
</view>
<text class="banner-arrow"></text>
</view>
<view class="wallpaper-banner" @tap="goToWallpaper">
<view class="banner-icon">
<text>🖼</text>
</view>
<view class="banner-content">
<text class="banner-title">去挑选新年壁纸</text>
2026-01-28 10:55:39 +08:00
<text class="banner-desc">精选新年壁纸让手机也过年</text>
2026-01-27 23:01:47 +08:00
</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>
2026-02-28 09:45:26 +08:00
import { ref } from "vue";
2026-02-08 18:57:45 +08:00
import { onLoad, onShareAppMessage, onShareTimeline } from "@dcloudio/uni-app";
2026-02-28 23:22:35 +08:00
import { getPageDetail, getShareReward } from "@/api/system";
2026-01-28 16:41:05 +08:00
import { getAvatarRecommendList } from "@/api/avatar.js";
2026-02-09 22:31:01 +08:00
import { getShareToken, saveViewRequest } from "@/utils/common.js";
2026-01-31 22:37:24 +08:00
import NavBar from "@/components/NavBar/NavBar.vue";
2026-01-27 23:01:47 +08:00
const defaultAvatar =
"https://file.lihailezzc.com/resource/d9b329082b32f8305101f708593a4882.png";
const detailData = ref(null);
const frameList = ref([]);
const shareToken = ref("");
onLoad((options) => {
if (options.shareToken) {
shareToken.value = options.shareToken;
fetchDetail();
}
fetchFrames();
});
2026-02-09 22:31:01 +08:00
onShareAppMessage(async () => {
2026-02-12 00:42:36 +08:00
const token = await getShareToken("avatar_download", detailData.value?.id);
2026-02-28 23:22:35 +08:00
getShareReward({ scene: "avatar_download" });
2026-02-08 18:57:45 +08:00
return {
title: "快来看看我刚领到的新年专属头像 🎊",
2026-02-09 22:31:01 +08:00
path: `/pages/avatar/detail?shareToken=${token}`,
2026-02-08 18:57:45 +08:00
imageUrl:
detailData.value?.imageUrl ||
"https://file.lihailezzc.com/resource/8dd026d76ef7a63d123b7fd698fb989b.png",
};
});
2026-02-09 22:31:01 +08:00
onShareTimeline(async () => {
2026-02-12 01:47:53 +08:00
const token = await getShareToken("avatar_download", detailData.value?.id);
2026-02-08 18:57:45 +08:00
return {
title: "快来看看我刚领到的新年专属头像 🎊",
2026-02-09 22:31:01 +08:00
query: `shareToken=${token}`,
2026-02-08 18:57:45 +08:00
imageUrl:
detailData.value?.imageUrl ||
"https://file.lihailezzc.com/resource/8dd026d76ef7a63d123b7fd698fb989b.png",
};
});
2026-01-27 23:01:47 +08:00
const fetchDetail = async () => {
try {
// uni.showLoading({ title: "加载中..." });
const res = await getPageDetail(shareToken.value);
2026-02-09 22:31:01 +08:00
saveViewRequest(shareToken.value, "avatar_detail", res.id);
2026-01-27 23:01:47 +08:00
if (res) {
detailData.value = res;
}
} catch (e) {
console.error(e);
// uni.showToast({ title: "获取详情失败", icon: "none" });
} finally {
// uni.hideLoading();
}
};
const fetchFrames = async () => {
try {
2026-01-28 16:41:05 +08:00
const res = await getAvatarRecommendList();
frameList.value = res;
2026-01-27 23:01:47 +08:00
} catch (e) {
console.error(e);
}
};
const previewImage = () => {
if (detailData.value?.imageUrl) {
uni.previewImage({
urls: [detailData.value.imageUrl],
});
}
};
const goToMake = () => {
uni.navigateTo({
url: "/pages/avatar/index",
});
};
2026-01-28 10:55:39 +08:00
const goToFortune = () => {
uni.navigateTo({
url: "/pages/fortune/index",
});
};
const goToGreeting = () => {
uni.switchTab({ url: "/pages/make/index" });
};
2026-01-27 23:01:47 +08:00
const goToWallpaper = () => {
uni.navigateTo({
url: "/pages/wallpaper/index",
});
};
</script>
<style lang="scss" scoped>
.avatar-detail-page {
min-height: 100vh;
2026-01-28 08:55:59 +08:00
background: #ffffff;
2026-01-27 23:01:47 +08:00
box-sizing: border-box;
}
.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 {
2026-01-28 08:55:59 +08:00
background: #ffffff;
2026-01-27 23:01:47 +08:00
border-radius: 40rpx;
padding: 24rpx;
2026-01-28 08:55:59 +08:00
box-shadow: 0 10rpx 40rpx rgba(0, 0, 0, 0.06);
2026-01-27 23:01:47 +08:00
margin-bottom: 60rpx;
2026-01-28 08:55:59 +08:00
border: 2rpx solid #f5f5f5;
2026-01-27 23:01:47 +08:00
}
.card-inner {
position: relative;
2026-01-28 08:55:59 +08:00
background: #fff9f9;
2026-01-27 23:01:47 +08:00
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);
2026-01-28 08:55:59 +08:00
border: 8rpx solid #ff3b30;
2026-01-27 23:01:47 +08:00
}
.loading-box {
width: 400rpx;
height: 400rpx;
display: flex;
align-items: center;
justify-content: center;
color: #999;
2026-01-28 08:55:59 +08:00
background: #f0f0f0;
2026-01-27 23:01:47 +08:00
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;
2026-01-28 08:55:59 +08:00
color: #ff3b30;
2026-01-27 23:01:47 +08:00
font-weight: bold;
display: flex;
align-items: center;
background: #fff;
padding: 10rpx 30rpx;
border-radius: 99rpx;
2026-01-28 08:55:59 +08:00
box-shadow: 0 4rpx 10rpx rgba(255, 59, 48, 0.1);
2026-01-27 23:01:47 +08:00
}
.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 {
2026-01-28 08:55:59 +08:00
background: #f5f5f5;
color: #333;
2026-01-27 23:01:47 +08:00
}
.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;
2026-01-28 08:55:59 +08:00
background: #f8f8f8;
2026-01-27 23:01:47 +08:00
border-radius: 24rpx;
padding: 20rpx;
}
.frame-img-box {
width: 140rpx;
height: 140rpx;
margin-bottom: 16rpx;
border-radius: 50%;
overflow: hidden;
2026-01-28 08:55:59 +08:00
background: #fff;
2026-01-27 23:01:47 +08:00
}
.frame-img {
width: 100%;
height: 100%;
}
.frame-name {
font-size: 24rpx;
color: #333;
font-weight: 500;
}
/* Wallpaper Banner */
.wallpaper-banner {
2026-01-28 08:55:59 +08:00
background: #f8f8f8;
2026-01-27 23:01:47 +08:00
border-radius: 24rpx;
padding: 30rpx;
display: flex;
align-items: center;
margin-bottom: 60rpx;
}
.banner-icon {
width: 80rpx;
height: 80rpx;
2026-01-28 08:55:59 +08:00
background: #fff;
2026-01-27 23:01:47 +08:00
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;
2026-01-28 08:55:59 +08:00
background: #eee;
2026-01-27 23:01:47 +08:00
}
.footer-line .text {
font-size: 20rpx;
2026-01-28 08:55:59 +08:00
color: #ccc;
2026-01-27 23:01:47 +08:00
margin: 0 20rpx;
letter-spacing: 2rpx;
}
.footer-sub {
font-size: 20rpx;
2026-01-28 08:55:59 +08:00
color: #ddd;
2026-01-27 23:01:47 +08:00
}
</style>