index.vue 10.5 KB
<!--
 * @Description: 积分攻略列表页面
-->
<template>
  <view class="points-list-page">
    <!-- 搜索框 -->
    <view class="search-section">
      <view class="search-box">
        <input
          v-model="searchKeyword"
          placeholder="搜索积分攻略"
          class="search-input"
          @input="handleSearch"
        />
      </view>
    </view>

    <!-- 攻略分类 -->
    <view class="category-section">
      <view class="category-title">攻略分类</view>
      <view class="category-grid">
        <view
          v-for="category in categories"
          :key="category.id"
          class="category-item"
          @click="filterByCategory(category.id)"
          :class="{ active: selectedCategory === category.id }"
        >
          <text class="category-name">{{ category.name }}</text>
        </view>
      </view>
    </view>

    <!-- 攻略列表 -->
    <view class="points-list-section">
      <scroll-view
        class="points-list"
        :scroll-y="true"
        :style="scrollStyle"
      >
        <view class="points-items">
          <view
            v-for="item in filteredPointsItems"
            :key="item.id"
            class="points-item"
            @click="showPointsDetail(item)"
          >
            <view class="points-item-left">
              <view class="points-content">
                <text class="points-title">{{ item.title }}</text>
                <text class="points-desc">{{ item.description }}</text>
                <view class="points-reward">
                  <text class="reward-text">可获得: {{ item.reward }}积分</text>
                </view>
              </view>
            </view>
            <view class="points-item-right">
              <text class="arrow-text"><RectRight /></text>
            </view>
          </view>
        </view>

        <!-- 空状态 -->
        <view
          v-if="filteredPointsItems.length === 0"
          class="empty-state"
        >
          <text class="empty-text">暂无相关积分攻略</text>
        </view>
      </scroll-view>
    </view>

    <!-- 右侧弹出详情 -->
    <nut-popup
      v-model:visible="showDetailPopup"
      position="right"
      :style="{ width: '85%', height: '100%' }"
      @close="closeDetail"
    >
      <view class="detail-popup">
        <!-- 详情头部 -->
        <view class="detail-header">
          <view class="detail-title">{{ currentPointsItem?.title }}</view>
          <view class="close-btn1" @click="closeDetail">
            <text class="close-text">关闭</text>
          </view>
        </view>

        <!-- 详情内容 -->
        <scroll-view class="detail-content" :scroll-y="true">
          <view class="detail-body">
            <!-- 攻略描述 -->
            <view class="detail-section">
              <view class="section-title">攻略描述</view>
              <text class="section-content">{{ currentPointsItem?.description }}</text>
            </view>

            <!-- 获取步骤 -->
            <view class="detail-section">
              <view class="section-title">获取步骤</view>
              <view class="solution-content">
                <view
                  v-for="(step, index) in currentPointsItem?.steps"
                  :key="index"
                  class="solution-step"
                >
                  <view class="step-number">{{ index + 1 }}</view>
                  <text class="step-content">{{ step }}</text>
                </view>
              </view>
            </view>

            <!-- 积分奖励 -->
            <view class="detail-section">
              <view class="section-title">积分奖励</view>
              <view class="reward-section">
                <view class="reward-item">
                  <text class="reward-label">基础积分:</text>
                  <text class="reward-value">{{ currentPointsItem?.reward }}分</text>
                </view>
                <view v-if="currentPointsItem?.bonusReward" class="reward-item">
                  <text class="reward-label">额外奖励:</text>
                  <text class="reward-value bonus">{{ currentPointsItem?.bonusReward }}分</text>
                </view>
              </view>
            </view>

            <!-- 注意事项 -->
            <view v-if="currentPointsItem?.notes?.length" class="detail-section">
              <view class="section-title">注意事项</view>
              <view class="notes-content">
                <view
                  v-for="(note, index) in currentPointsItem.notes"
                  :key="index"
                  class="note-item"
                >
                  <text class="note-text">• {{ note }}</text>
                </view>
              </view>
            </view>
          </view>
        </scroll-view>
      </view>
    </nut-popup>

    <!-- Toast提示 -->
    <nut-toast
      v-model:visible="toastVisible"
      :msg="toastMessage"
      :type="toastType"
    />
  </view>
</template>

<script setup>
// import '@tarojs/taro/html.css'
import { ref, computed, onMounted } from 'vue'
import Taro from '@tarojs/taro'
import { RectRight } from '@nutui/icons-vue-taro'
import './index.less'

/**
 * 积分攻略列表页面组件
 * 功能:展示各种积分获取攻略、搜索和分类筛选
 */

// ==================== 响应式数据 ====================
/**
 * 搜索关键词
 */
const searchKeyword = ref('')

/**
 * 选中的分类
 */
const selectedCategory = ref('all')

/**
 * 详情弹窗显示状态
 */
const showDetailPopup = ref(false)

/**
 * 当前查看的积分攻略项
 */
const currentPointsItem = ref(null)

/**
 * Toast提示
 */
const toastVisible = ref(false)
const toastMessage = ref('')
const toastType = ref('success')

/**
 * 攻略分类数据
 */
const categories = ref([
  { id: 'all', name: '全部' },
  { id: 'daily', name: '日常任务' },
  { id: 'activity', name: '活动参与' },
  { id: 'family', name: '家庭互动' },
  { id: 'special', name: '特殊奖励' }
])

/**
 * 积分攻略数据
 */
const pointsItems = ref([
  // 常规积分
  {
    id: 'p001',
    category: 'daily',
    title: '日常步数积分攻略',
    description: '通过日常走路获得积分,简单易行的积分获取方式',
    reward: '100步=1',
    steps: [
      '在微信里,我-设置-通用-辅助功能,启用“微信运功”功能',
      '每日保持运动,记录步数',
      '打开“老来赛”小程序,就可以同步微信步数',
    ],
    notes: [
      '家庭成员步数同样按此规则计算'
    ]
  },
  {
    id: 'p002',
    category: 'activity',
    title: '参与活动积分攻略',
    description: '参加线下活动打卡,获得丰厚积分奖励',
    reward: 1000,
    steps: [
      '关注活动页面的最新活动信息',
      '前往活动地点参与活动',
      '在任意一个商户卡点完成打卡',
      '系统确认后发放1000积分奖励'
    ],
    notes: [
      '只要打卡一个商户卡点即可',
      '每次参与活动都可获得积分',
      '需要实地参与才能获得积分'
    ]
  },
  {
    id: 'p003',
    category: 'activity',
    title: '完成活动积分攻略',
    description: '完成南京路商圈活动,获得超高积分奖励',
    reward: 5000,
    steps: [
      '参与南京路商圈活动',
      '了解活动设置的卡点位置',
      '逐一前往各个卡点完成打卡',
      '完成所有卡点的打卡任务',
      '系统确认后发放5000积分奖励'
    ],
    notes: [
      '南京路商圈设置多个卡点',
      '完成所有卡点的打卡任务即视为完成活动',
      '奖励积分高达5000分'
    ]
  },
  // 额外积分
  {
    id: 'p004',
    category: 'family',
    title: '家庭成员达标奖励',
    description: '家庭成员达到5人,获得奖励积分',
    reward: 500,
    steps: [
      '创建或加入家庭',
      '邀请家人加入家庭',
      '确保家庭成员达到5人',
      '系统自动检测家庭人数',
      '达到5人后自动发放500积分奖励'
    ],
    notes: [
      '家庭成员达5人获得500分',
      '一次性奖励积分',
      '鼓励家庭成员共同参与'
    ]
  },
  {
    id: 'p005',
    category: 'family',
    title: '家庭陪伴运动攻略',
    description: '家庭成员陪伴运动,获得额外积分奖励',
    reward: 100,
    steps: [
      '与家庭成员一起进行运动',
      '运动过程中拍摄照片',
      '在APP中上传陪伴运动照片',
      '系统确认照片有效性',
      '获得100积分陪伴运动奖励'
    ],
    notes: [
      '只要上传照片即视为有效陪伴',
      '每天上传陪伴运动最多可获得100积分',
      '鼓励家庭成员互相陪伴'
    ]
  },
  {
    id: 'p006',
    category: 'special',
    title: '轮椅陪伴运动攻略',
    description: '陪伴轮椅老人运动,获得额外补偿积分',
    reward: 100,
    steps: [
      '陪伴轮椅老人进行运动',
      '系统识别轮椅陪伴情况',
      '获得轮椅补偿100分'
    ],
    notes: [
      '一次性奖励积分',
      '额外获得轮椅补偿100分',
      '体现对特殊群体的关爱'
    ]
  }
])

/**
 * 滚动样式
 */
const scrollStyle = computed(() => {
  return {
    height: 'calc(100vh - 260rpx)' // 减去header、搜索框、分类的高度
  }
})

/**
 * 过滤后的积分攻略项
 */
const filteredPointsItems = computed(() => {
  let items = pointsItems.value

  // 按分类过滤
  if (selectedCategory.value !== 'all') {
    items = items.filter(item => item.category === selectedCategory.value)
  }

  // 按搜索关键词过滤
  if (searchKeyword.value.trim()) {
    const keyword = searchKeyword.value.toLowerCase()
    items = items.filter(item =>
      item.title.toLowerCase().includes(keyword) ||
      item.description.toLowerCase().includes(keyword)
    )
  }

  return items
})

// ==================== 方法 ====================
/**
 * 返回上一页
 */
const goBack = () => {
  Taro.navigateBack()
}

/**
 * 处理搜索
 */
const handleSearch = () => {
  // 搜索逻辑已在computed中处理
}

/**
 * 按分类过滤
 */
const filterByCategory = (categoryId) => {
  selectedCategory.value = categoryId
}

/**
 * 显示积分攻略详情
 */
const showPointsDetail = (item) => {
  currentPointsItem.value = item
  showDetailPopup.value = true
}

/**
 * 关闭详情
 */
const closeDetail = () => {
  showDetailPopup.value = false
  currentPointsItem.value = null
}

// ==================== 生命周期 ====================
onMounted(() => {
  // 页面初始化逻辑
})
</script>

<script>
export default {
  name: 'PointsListPage'
}
</script>