index.vue 5.73 KB
<template>
  <view class="feedback-list">
    <!-- Loading State -->
    <view v-if="loading" class="flex justify-center items-center py-20">
      <view class="text-gray-500">加载中...</view>
    </view>

    <!-- Content -->
    <view v-else>
      <!-- Feedback List -->
      <view v-if="feedbackList.length > 0">
        <view
          v-for="feedback in feedbackList"
          :key="feedback.id"
          class="feedback-item"
        >
          <!-- Header -->
          <view class="feedback-header">
            <view class="feedback-id">反馈 #{{ feedback.id }}</view>
            <view
              class="feedback-status"
              :class="{
                'pending': feedback.status === 'PENDING',
                'processed': feedback.status === 'PROCESSED'
              }"
            >
              {{ feedback.status === 'PENDING' ? '待处理' : '已处理' }}
            </view>
          </view>

          <!-- Content -->
          <view class="feedback-content">
            <view class="feedback-note">{{ feedback.note }}</view>

            <view class="feedback-meta" v-if="feedback.name || feedback.contact">
              <view class="meta-item" v-if="feedback.name">
                <text>👤 {{ feedback.name }}</text>
              </view>
              <view class="meta-item" v-if="feedback.contact">
                <text>📞 {{ feedback.contact }}</text>
              </view>
            </view>
          </view>

          <!-- Images -->
          <view v-if="feedback.images && feedback.images.length > 0" class="feedback-images">
            <image
              v-for="(image, index) in feedback.images"
              :key="index"
              :src="image"
              class="feedback-image"
              mode="aspectFill"
              @tap="previewImage(image, feedback.images)"
            />
          </view>

          <!-- Reply -->
          <view v-if="feedback.reply" class="feedback-reply">
            <view class="reply-label">官方回复:</view>
            <view class="reply-content">{{ feedback.reply }}</view>
            <view v-if="feedback.reply_time" class="reply-time">
              回复时间:{{ formatDate(feedback.reply_time) }}
            </view>
          </view>
        </view>
      </view>

      <!-- Empty State -->
      <view v-else class="empty-state">
        <view class="empty-icon">💬</view>
        <view class="empty-title">暂无反馈记录</view>
        <view class="empty-desc">您还没有提交过任何意见反馈</view>
      </view>

      <!-- Load More -->
      <view v-if="hasMore && feedbackList.length > 0" class="load-more" @click="loadMore">
        {{ loadingMore ? '加载中...' : '加载更多' }}
      </view>

      <!-- No More Data -->
      <view v-if="!hasMore && feedbackList.length > 0" class="no-more">
        没有更多数据了
      </view>
    </view>

    <!-- Fixed Button -->
    <view class="fixed-button" @click="goToFeedback">
      新增反馈
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import Taro from '@tarojs/taro';
import { useDidShow } from '@tarojs/taro';
import { getFeedbackListAPI } from '@/api/feedback';

// 响应式数据
const loading = ref(false);
const loadingMore = ref(false);
const feedbackList = ref([]);
const hasMore = ref(true);
const currentPage = ref(0);
const pageSize = ref(10);

/**
 * @description: 加载反馈列表
 * @param {boolean} isLoadMore - 是否为加载更多
 */
const loadFeedbackList = async (isLoadMore = false) => {
  try {
    if (isLoadMore) {
      loadingMore.value = true;
    } else {
      loading.value = true;
      currentPage.value = 0;
      feedbackList.value = [];
    }

    const params = {
      page: currentPage.value,
      limit: pageSize.value
    };

    const response = await getFeedbackListAPI(params);

    if (response.code === 1 && response.data && response.data.list) {
      const newList = response.data.list.map(item => ({
        ...item,
      }));

      if (isLoadMore) {
        feedbackList.value = [...feedbackList.value, ...newList];
      } else {
        feedbackList.value = newList;
      }

      // 判断是否还有更多数据
      hasMore.value = newList.length === pageSize.value;

      if (hasMore.value) {
        currentPage.value++;
      }
    } else {
      hasMore.value = false;
      if (!isLoadMore) {
        feedbackList.value = [];
      }
    }
  } catch (error) {
    console.error('加载反馈列表失败:', error);
    Taro.showToast({
      title: '加载失败,请重试',
      icon: 'none'
    });
    hasMore.value = false;
  } finally {
    loading.value = false;
    loadingMore.value = false;
  }
};

/**
 * @description: 加载更多
 */
const loadMore = () => {
  if (!loadingMore.value && hasMore.value) {
    loadFeedbackList(true);
  }
};

/**
 * @description: 格式化日期
 * @param {string} dateString - 日期字符串
 * @returns {string} 格式化后的日期
 */
const formatDate = (dateString) => {
  if (!dateString) return '';
  const date = new Date(dateString);
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit'
  });
};

/**
 * @description: 预览图片
 * @param {string} current - 当前图片
 * @param {Array} images - 图片列表
 */
const previewImage = (current, images) => {
  Taro.previewImage({
    current,
    urls: images
  });
};

/**
 * @description: 跳转到新增反馈页面
 */
const goToFeedback = () => {
  Taro.navigateTo({
    url: '/pages/Feedback/index'
  });
};

// 页面显示时刷新数据
useDidShow(() => {
  loadFeedbackList();
});

// 页面加载时获取数据
onMounted(() => {
  loadFeedbackList();
});
</script>

<style lang="less">
@import './index.less';
</style>