index.vue 9.59 KB
<!--
 * @Date: 2025-08-27 17:47:26
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-09-05 10:39:16
 * @FilePath: /lls_program/src/pages/Rewards/index.vue
 * @Description: 文件描述
-->
<template>
  <view class="min-h-screen flex flex-col bg-white">
    <!-- Blue header background -->
    <view v-if="isCreator" class="bg-blue-500 h-48 absolute w-full top-0 left-0 z-0"></view>
    <!-- <AppHeader title="兑换中心" :showBack="false" /> -->
    <!-- Content -->
    <view class="relative z-10 flex-1 pb-20">
      <!-- Points display -->
      <view v-if="isCreator" class="pt-8 pb-8 flex flex-col items-center">
        <h2 class="text-4xl font-bold text-white mb-1">{{ totalPoints }}分</h2>
        <p class="text-white text-opacity-80">我的积分</p>
      </view>
      <!-- Main content -->
      <view class="bg-white rounded-t-3xl px-4 pt-5">
<!--        <!~~ Points strategy section ~~>
        <view v-if="!isCreator" class="mb-8 bg-gradient-to-br from-blue-50 to-indigo-50 rounded-2xl p-5 shadow-sm border border-blue-100">
          <view class="flex justify-between items-center mb-4">
            <h3 class="text-lg font-medium text-gray-800">积分攻略</h3>
            <view @tap="handleViewAll" class="text-blue-500 text-sm flex items-center hover:text-blue-600">
              查看全部
              <!~~ <Right size="16" /> ~~>
            </view>
          </view>
          <!~~ Strategy cards ~~>
          <view v-if="isStrategyExpanded" class="space-y-3 mb-4 transition-all duration-300">
            <view class="bg-white border border-gray-100 p-4 rounded-lg flex items-start shadow-sm">
              <view class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center mr-3">
                <My size="20" class="text-blue-500" />
              </view>
              <view>
                <h4 class="font-medium">每日同步步数可获得积分</h4>
                <p class="text-sm text-gray-600">
                  每100步可兑换1积分,每日上限200积分
                </p>
              </view>
            </view>
            <view class="bg-white border border-gray-100 p-4 rounded-lg flex items-start shadow-sm">
              <view class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center mr-3">
                <My size="20" class="text-blue-500" />
              </view>
              <view>
                <h4 class="font-medium">家人陪伴健步有奖励积分</h4>
                <p class="text-sm text-gray-600">
                  一起健步晒合影每天可获得额外100积分
                </p>
              </view>
            </view>
            <view class="bg-white border border-gray-100 p-4 rounded-lg flex items-start shadow-sm">
              <view class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center mr-3">
                <My size="20" class="text-blue-500" />
              </view>
              <view>
                <h4 class="font-medium">邀请家人加入家庭,人数达标奖励</h4>
                <p class="text-sm text-gray-600">
                  邀请的家人达到5位,获得500奖励积分
                </p>
              </view>
            </view>
          </view>
          <!~~ Expand/Collapse button at bottom ~~>
          <view @tap="toggleStrategyExpand" class="flex justify-center items-center py-2 cursor-pointer hover:bg-blue-100 rounded-lg transition-colors">
            <ArrowUp v-if="isStrategyExpanded" size="16" class="text-gray-500" />
            <ArrowDown v-else size="16" class="text-gray-500" />
          </view>
        </view>-->
        <!-- Quick exchange options -->
        <!-- Search bar -->
        <view class="mb-6">
          <view class="relative">
            <input type="text" v-model="searchQuery" placeholder="搜索商户名称"
              class=" bg-gray-100 rounded-lg py-3 pl-10 pr-4 border border-transparent focus:bg-white focus:border-blue-500 focus:outline-none" />
            <view class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
              <Search2 size="20" class="text-gray-400" />
            </view>
          </view>
        </view>

        <view class="flex gap-3 mb-6">
          <view v-for="option in quickExchangeOptions" :key="option.points" @click="selectedPoints = option.points"
            :class="[
              'flex-1 py-3 rounded-lg border text-center',
              selectedPoints === option.points
                ? 'border-blue-500 bg-blue-50 text-blue-500'
                : 'border-gray-200 text-gray-700'
            ]">
            <view class="text-center">
              <view>{{ option.label }}</view>
              <view>可兑</view>
            </view>
          </view>
        </view>
        <view class="flex justify-between items-center mb-4">
          <h3 class="text-lg font-medium">可兑换列表</h3>
          <view class="flex items-center text-gray-500 text-sm" @click="toggleSortOrder">
            <span class="mr-1">{{ sortOrder === 'desc' ? '从高到低排列' : '从低到高排列' }}</span>
            <ScreenLittle />
          </view>
        </view>
        <!-- Rewards list -->
        <view class="space-y-4">
          <view v-for="reward in sortedRewardItems" :key="reward.id"
            class="bg-white rounded-xl p-4 flex items-center shadow-[0_2px_8px_rgba(0,0,0,0.08)]">
            <image :src="reward.logo" class="w-16 h-16 rounded-lg mr-4 flex-shrink-0" mode="aspectFill" />
            <view class="flex-1 min-w-0">
              <view class="font-medium text-base">{{ reward.title }}</view>
              <view class="text-gray-500 text-sm mt-1">{{ reward.merchant }}</view>
            </view>
            <view class="ml-4 px-4 py-2 bg-blue-500 text-white rounded-lg text-sm flex-shrink-0"
              @click="goToRewardDetail(reward)">
              {{ isCreator ? reward.points + '分兑换' : '查看' }}
            </view>
          </view>
        </view>
      </view>
    </view>
    <!-- <BottomNav /> -->
  </view>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';
import Taro, { useDidShow } from '@tarojs/taro';
import { ScreenLittle, Search2, My, ArrowUp, ArrowDown } from '@nutui/icons-vue-taro';
import { getUserProfileAPI } from '@/api/user';
import { getFamilyDashboardAPI } from '@/api/family';

const searchQuery = ref('');
const selectedPoints = ref(null);
const sortOrder = ref('desc'); // 'asc' or 'desc'

const totalPoints = ref(0);
const isCreator = ref(false);
const isStrategyExpanded = ref(false); // 积分攻略展开状态,默认收起

const sortedRewardItems = computed(() => {
  let items = [...rewardItems.value];

  // Filter by search query
  if (searchQuery.value) {
    items = items.filter(item =>
      item.merchant.toLowerCase().includes(searchQuery.value.toLowerCase())
    );
  }

  // Sort items
  return items.sort((a, b) => {
    if (sortOrder.value === 'asc') {
      return a.points - b.points;
    } else {
      return b.points - a.points;
    }
  });
});

const toggleSortOrder = () => {
  sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc';
};

const rewardItems = ref([
  {
    id: 1,
    logo: 'https://placehold.co/400x400/e2f3ff/0369a1?text=LFX&font=roboto',
    title: '杏花楼集团85折券',
    merchant: '杏花楼集团',
    points: 10
  },
  {
    id: 2,
    logo: 'https://placehold.co/400x400/e2f3ff/0369a1?text=LFX&font=roboto',
    title: '吴良材眼镜店85折券',
    merchant: '吴良材眼镜店',
    points: 10
  },
  {
    id: 3,
    logo: 'https://placehold.co/400x400/e2f3ff/0369a1?text=LFX&font=roboto',
    title: '老凤祥银楼20元抵用券',
    merchant: '老凤祥银楼',
    points: 1000
  },
  {
    id: 4,
    logo: 'https://placehold.co/400x400/e2f3ff/0369a1?text=LFX&font=roboto',
    title: '沈大成双酿团2元抵用券',
    merchant: '沈大成双酿团',
    points: 100
  },
  {
    id: 5,
    logo: 'https://placehold.co/400x400/e2f3ff/0369a1?text=LFX&font=roboto',
    title: '这是一个非常非常非常非常非常长的标题用于测试换行效果',
    merchant: '一个名字很长的商家',
    points: 500
  }
]);

const quickExchangeOptions = ref([
  { points: 3000, label: '1000-3000分' },
  { points: 1000, label: '100-1000分' },
  { points: 100, label: '1-100分' }
]);

const goToRewardDetail = (reward) => {
  Taro.navigateTo({
    url: `/pages/RewardDetail/index?id=${reward.id}`
  });
};

/**
 * 处理查看全部积分攻略
 */
const handleViewAll = () => {
  Taro.navigateTo({
    url: '/pages/PointsList/index'
  });
};

/**
 * 切换积分攻略展开收起状态
 */
const toggleStrategyExpand = () => {
  isStrategyExpanded.value = !isStrategyExpanded.value;
};

const initData = async () => {
  // 获取用户信息,判断是否为创建者
  try {
    const { code, data } = await getUserProfileAPI();
    if (code) {
      isCreator.value = data?.user?.is_creator || false;
      // 只有创建者才显示积分并获取家庭数据
      if (isCreator.value) {
        // 获取家庭首页数据,从中提取总积分
        const familyData = await getFamilyDashboardAPI();
        if (familyData.code) {
          totalPoints.value = familyData.data.family.total_points || 0;
        } else {
          totalPoints.value = 0;
        }
      }
    }
  } catch (error) {
    console.error('获取用户信息失败:', error);
    isCreator.value = false;
  }
  console.warn('初始化数据')
}

useDidShow(() => {
  initData();
})
</script>

<style scoped>
/* 过渡动画 */
.transition-all {
  transition: all 0.3s ease-in-out;
}

.duration-300 {
  transition-duration: 300ms;
}

.cursor-pointer {
  cursor: pointer;
}

.gap-3 {
  gap: 0.75rem;
}
</style>