diff --git a/pages/index/index.vue b/pages/index/index.vue
index a8c9842..48b6092 100644
--- a/pages/index/index.vue
+++ b/pages/index/index.vue
@@ -18,6 +18,10 @@
{{ userInfo.nickName || "点击登录" }}
+
+ 积分
+ {{ userPoints }}
+
@@ -205,14 +209,17 @@
{{ item.usageCount }} 人在用
-
+
{{ item.likes }}
+
+
+
+
+
-
-
@@ -227,6 +234,7 @@
+
@@ -235,18 +243,28 @@ import { ref, onMounted, computed } from "vue";
import { getStatusBarHeight } from "@/utils/system";
import { onShareAppMessage, onShareTimeline, onShow } from "@dcloudio/uni-app";
import { useUserStore } from "@/stores/user";
-import { getRecommendList, getRankList } from "@/api/system";
+import {
+ getRecommendList,
+ getRankList,
+ abilityCheck,
+ watchAdReward,
+} from "@/api/system";
+import { saveRemoteImageToLocal, saveRecordRequest } from "@/utils/common";
import { getUserSignInfo, userSignIn } from "@/api/user";
+import { avatarDownloadRecord } from "@/api/avatar";
import LoginPopup from "@/components/LoginPopup/LoginPopup.vue";
import LuckyPopup from "@/components/LuckyPopup/LuckyPopup.vue";
+import RewardAd from "@/components/RewardAd/RewardAd.vue";
const userStore = useUserStore();
const statusBarHeight = ref(getStatusBarHeight());
const loginPopupRef = ref(null);
const luckyPopupRef = ref(null);
+const rewardAdRef = ref(null);
const userInfo = computed(() => userStore?.userInfo || {});
const isLoggedIn = computed(() => !!userStore.userInfo.nickName);
+const userPoints = computed(() => userStore.userInfo.points || 0);
const signInfo = ref({}); // 用户签到信息
const weekDays = computed(() => {
@@ -430,6 +448,90 @@ const navTo = (url) => {
uni.navigateTo({ url });
};
+const handleDownload = async (item) => {
+ if (!isLoggedIn.value) {
+ uni.$emit("show-login-popup");
+ return;
+ }
+
+ const type =
+ item.type === "wallpaper" ? "wallpaper_download" : "avatar_download";
+ const abilityRes = await abilityCheck(type);
+
+ if (!abilityRes.canUse) {
+ if (
+ abilityRes?.blockType === "need_share" &&
+ abilityRes?.message === "分享可继续"
+ ) {
+ uni.showToast({
+ title: "分享给好友即可下载",
+ icon: "none",
+ });
+ return;
+ }
+ if (
+ abilityRes?.blockType === "need_ad" &&
+ abilityRes?.message === "观看广告可继续"
+ ) {
+ uni.showModal({
+ title: "积分不足",
+ content: "观看广告可获得50积分,继续下载",
+ success: (res) => {
+ if (res.confirm) {
+ rewardAdRef.value.show();
+ }
+ },
+ });
+ return;
+ }
+ uni.showToast({
+ title: "您今日下载次数已用完,明日再试",
+ icon: "none",
+ });
+ return;
+ }
+
+ uni.showLoading({ title: "下载中..." });
+ try {
+ const promises = [
+ saveRemoteImageToLocal(item.resourceInfo.url),
+ saveRecordRequest("", item.id, type, item.resourceInfo.url),
+ ];
+
+ if (item.type === "avatar") {
+ promises.push(
+ avatarDownloadRecord({ id: item.id, url: item.resourceInfo.url }),
+ );
+ }
+
+ await Promise.all(promises);
+
+ await userStore.fetchUserAssets();
+ uni.showToast({ title: "保存成功 消耗 20 积分" });
+ } catch (e) {
+ console.error("Download failed", e);
+ uni.showToast({ title: "下载失败", icon: "none" });
+ } finally {
+ uni.hideLoading();
+ }
+};
+
+const handleAdReward = async (token) => {
+ try {
+ const res = await watchAdReward(token);
+ if (res) {
+ uni.showToast({
+ title: "获得50积分",
+ icon: "success",
+ });
+ await userStore.fetchUserAssets();
+ }
+ } catch (e) {
+ console.error("Reward claim failed", e);
+ uni.showToast({ title: "奖励发放失败", icon: "none" });
+ }
+};
+
const onRankItemTap = (item) => {
if (item.type === "avatar") {
uni.navigateTo({ url: `/pages/avatar/index?id=${item.id}` });
@@ -499,6 +601,27 @@ onShareTimeline(() => {
font-weight: bold;
color: #333;
}
+ .user-points {
+ display: flex;
+ align-items: center;
+ background: rgba(255, 255, 255, 0.2);
+ border: 1rpx solid rgba(255, 255, 255, 0.4);
+ border-radius: 20rpx;
+ padding: 2rpx 12rpx;
+ margin-top: 4rpx;
+
+ .points-label {
+ font-size: 18rpx;
+ color: #666;
+ margin-right: 4rpx;
+ }
+
+ .points-value {
+ font-size: 22rpx;
+ color: #d81e06;
+ font-weight: bold;
+ }
+ }
}
}
}
@@ -951,15 +1074,21 @@ onShareTimeline(() => {
}
}
- .rank-likes {
- display: flex;
- align-items: center;
+ .rank-action {
+ .download-btn {
+ width: 56rpx;
+ height: 56rpx;
+ border-radius: 50%;
+ background: linear-gradient(135deg, #ff9800, #ff5722);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 4rpx 12rpx rgba(255, 87, 34, 0.3);
- .likes-num {
- font-size: 24rpx;
- color: #a85a5a;
- margin-left: 8rpx;
- font-weight: 500;
+ &:active {
+ opacity: 0.9;
+ transform: scale(0.95);
+ }
}
}
}