CheckInDialog.vue 4.58 KB
<template>
  <van-popup
    :show="show"
    @update:show="$emit('update:show', $event)"
    round
    position="bottom"
    :style="{ minHeight: '30%', maxHeight: '80%', width: '100%' }"
  >
    <div class="p-4">
      <div class="flex justify-between items-center mb-3">
        <h3 class="font-medium">今日打卡</h3>
        <van-icon name="cross" @click="handleClose" />
      </div>

      <div v-if="checkInSuccess" class="bg-green-50 border border-green-200 rounded-lg p-4 text-center">
        <svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-500 mx-auto mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
        </svg>
        <h4 class="text-green-700 font-medium mb-1">打卡成功!</h4>
        <p class="text-green-600 text-sm">+5 积分已添加到您的账户</p>
      </div>
      <template v-else>
        <div class="flex space-x-2 py-2">
          <button
            v-for="checkInType in checkInTypes"
            :key="checkInType.id"
            :class="[
              'flex-1 flex flex-col items-center p-2 rounded-lg transition-colors',
              selectedCheckIn?.id === checkInType.id
                ? 'bg-green-100 border border-green-200'
                : 'bg-white/70 border border-gray-100 hover:bg-white'
            ]"
            @click="handleCheckInSelect(checkInType)"
          >
            <div :class="[
              'w-12 h-12 rounded-full flex items-center justify-center mb-1 transition-colors',
              selectedCheckIn?.id === checkInType.id
                ? 'bg-green-500 text-white'
                : 'bg-gray-100 text-gray-500'
            ]">
              <van-icon v-if="checkInType.id === 'reflection'" name="coupon-o" size="1.5rem"/>
              <van-icon v-if="checkInType.id === 'reading'" name="edit" size="1.5rem" />
              <van-icon v-if="checkInType.id === 'exercise'" name="tosend" size="1.5rem" />
              <van-icon v-if="checkInType.id === 'mix'" name="send-gift-o" size="1.5rem" />
            </div>
            <span class="text-xs">{{ checkInType.name }}</span>
          </button>
        </div>

        <div v-if="selectedCheckIn" class="mt-3">
          <textarea
            :placeholder="`请输入${selectedCheckIn.name}内容...`"
            v-model="checkInContent"
            class="w-full p-3 border border-gray-200 rounded-lg text-sm resize-none h-24"
          />
          <button
            class="mt-2 w-full bg-gradient-to-r from-green-500 to-green-600 text-white py-2 rounded-lg flex items-center justify-center"
            @click="handleCheckInSubmit"
            :disabled="isCheckingIn"
          >
            <template v-if="isCheckingIn">
              <div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin mr-2"></div>
              提交中...
            </template>
            <template v-else>提交打卡</template>
          </button>
        </div>
      </template>
    </div>
  </van-popup>
</template>

<script setup>
import { ref } from 'vue'
import { showToast } from 'vant'
import { checkInTypes } from '@/utils/mockData'
import { useRoute, useRouter } from 'vue-router'

const route = useRoute()
const router = useRouter()

const props = defineProps({
  show: {
    type: Boolean,
    required: true,
    default: false
  }
})

const emit = defineEmits(['update:show', 'check-in-success'])

const selectedCheckIn = ref(null)
const checkInContent = ref('')
const isCheckingIn = ref(false)
const checkInSuccess = ref(false)

const handleCheckInSelect = (type) => {
  if (type.id === 'mix') {
    router.push({
      path: '/checkin/index',
    })
  }
  selectedCheckIn.value = type;
}

const handleCheckInSubmit = async () => {
  if (!selectedCheckIn.value) {
    showToast('请选择打卡项目')
    return
  }
  if (!checkInContent.value.trim()) {
    showToast('请输入打卡内容')
    return
  }

  isCheckingIn.value = true
  try {
    // 模拟API调用
    await new Promise(resolve => setTimeout(resolve, 1000))
    checkInSuccess.value = true
    emit('check-in-success')

    // 重置表单
    setTimeout(() => {
      checkInSuccess.value = false
      selectedCheckIn.value = null
      checkInContent.value = ''
      emit('update:show', false)
    }, 1500)
  } catch (error) {
    showToast('打卡失败,请重试')
  } finally {
    isCheckingIn.value = false
  }
}

const handleClose = () => {
  selectedCheckIn.value = null
  checkInContent.value = ''
  checkInSuccess.value = false
  emit('update:show', false)
}
</script>