index.vue 9.96 KB
<template>
  <view class="min-h-screen flex flex-col bg-white">
    <view class="flex-1 px-4 pt-3 pb-6 flex flex-col">
      <!-- Title -->
      <h2 class="text-xl font-bold text-center mb-2">
        输入助力码
      </h2>
      <!-- Description -->
      <view class="text-gray-600 text-center text-sm mb-6">
        请输入家人提供的助力码,参与助力榜排行
      </view>
      <!-- Input boxes -->
      <view class="motto-input-container">
        <view
          v-for="(char, index) in mottoChars"
          :key="index"
          class="motto-input-box"
          :style="{
            borderColor: focusedIndex === index ? THEME_COLORS.PRIMARY : '#d1d5db'
          }"
        >
          <input
            :ref="(el) => (inputRefs[index] = el)"
            type="text"
            v-model="mottoChars[index]"
            @input="(e) => handleInputChange(index, e.target.value)"
            @keydown="(e) => handleKeyDown(index, e)"
            @focus="focusedIndex = index"
            @blur="handleBlur(index)"
            class="motto-input"
            :cursorSpacing="100"
          />
        </view>
      </view>
      <!-- Help text -->
      <view class="text-gray-500 text-center text-sm mb-4">
        没有口令?请联系家里小辈,咨询单位学校是否参与了助力榜排行哦
      </view>

      <!-- 幼儿园信息显示 -->
      <view v-if="matchedKindergarten" class="mb-6">
        <view class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
          <view class="flex items-center space-x-3">
            <!-- 幼儿园Logo -->
            <view class="w-12 h-12 rounded-full bg-white flex items-center justify-center overflow-hidden border-gray-200 border">
              <image
                :src="matchedKindergarten.logo || defaultKindergartenLogo"
                class="w-full h-full object-cover"
              />
            </view>
            <!-- 幼儿园信息 -->
            <view class="flex-1">
              <view class="font-medium text-gray-900 mb-1">{{ matchedKindergarten.name }}</view>
              <view class="text-sm text-gray-600">{{ matchedKindergarten.address }}</view>
            </view>
          </view>
        </view>

        <!-- 确认提示 -->
        <view v-if="!isAlreadyJoined" class="text-center mb-4">
          <view class="text-gray-700 text-sm mb-2">这是您家小辈所在的单位/学校吗?</view>
          <view class="text-gray-600 text-xs">
            <view>确认后您的家庭步数将计入其中,参与助力榜的排行哦</view>
            <view>(不会影响家庭参与市、区榜)</view>
          </view>
        </view>

        <!-- 已参与提示 -->
        <view v-if="isAlreadyJoined" class="text-center mb-4">
          <view class="text-green-600 text-sm font-medium">您的家庭已经参与助力榜</view>
        </view>
      </view>
      <!-- Submit Button -->
      <view
        @tap="handleConfirmJoin"
        :disabled="!isComplete"
        :class="[
          'w-full py-3 text-white text-lg font-medium rounded-lg mt-auto text-center',
          isComplete ? 'bg-blue-500' : 'bg-gray-300'
        ]"
      >
        确认加入
      </view>
    </view>

  </view>
</template>

<script setup>
import { ref, computed, nextTick, onMounted, watch } from 'vue';
import Taro from '@tarojs/taro';
import { My, Check, IconFont } from '@nutui/icons-vue-taro';
// 获取接口信息
import { searchFamilyByPassphraseAPI, joinFamilyAPI } from '@/api/family';
// 导入主题颜色
import { THEME_COLORS } from '@/utils/config';
// 默认幼儿园Logo
const defaultKindergartenLogo = 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'

const mottoChars = ref(['', '', '', '']);
const inputRefs = ref([]);
const focusedIndex = ref(-1);

// 幼儿园相关数据
const matchedKindergarten = ref(null);
const isAlreadyJoined = ref(false);

// Mock 幼儿园数据
const mockKindergartenData = {
  '1234': {
    id: 1,
    name: '阳光幼儿园',
    address: '北京市朝阳区阳光街123号',
    logo: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
  },
  '5678': {
    id: 2,
    name: '彩虹幼儿园',
    address: '北京市海淀区彩虹路456号',
    logo: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
  }
};

// Mock 已参与助力榜的数据(模拟用户已经参与的幼儿园)
const mockJoinedKindergarten = {
  id: 1,
  name: '阳光幼儿园',
  address: '北京市朝阳区阳光街123号',
  logo: 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'
};

// 页面加载时检查是否已参与助力榜
onMounted(() => {
  checkExistingJoinStatus();
});

// 检查现有参与状态
const checkExistingJoinStatus = () => {
  // 模拟检查用户是否已经参与助力榜
  // 实际应该调用API检查
  const hasJoined = true; // 模拟已参与状态

  if (hasJoined && mockJoinedKindergarten) {
    matchedKindergarten.value = mockJoinedKindergarten;
    isAlreadyJoined.value = true;
    // 清空输入框,因为已经参与了
    mottoChars.value = ['', '', '', ''];
  }
};

// 检查并匹配幼儿园
const checkAndMatchKindergarten = () => {
  const motto = mottoChars.value.join('');

  if (motto.length === 4) {
    // 输入完成,查找匹配的幼儿园
    const kindergarten = mockKindergartenData[motto];
    if (kindergarten) {
      // 检查是否要更换幼儿园
      if (isAlreadyJoined.value && matchedKindergarten.value && kindergarten.id !== matchedKindergarten.value.id) {
        // 用户要更换幼儿园,显示确认提示
        showChangeConfirmation(kindergarten);
        return;
      }

      matchedKindergarten.value = kindergarten;
      // 如果之前已经参与,保持已参与状态;否则设为未参与
      if (!isAlreadyJoined.value) {
        isAlreadyJoined.value = false;
      }
    } else {
      matchedKindergarten.value = null;
      isAlreadyJoined.value = false;
    }
  } else {
    // 输入未完成,如果之前已参与,保持显示已参与的幼儿园
    if (!isAlreadyJoined.value) {
      matchedKindergarten.value = null;
    }
  }
};

// 显示更换幼儿园确认提示
const showChangeConfirmation = (newKindergarten) => {
  Taro.showModal({
    title: '更换单位/学校',
    content: `您要更换新的单位/学校,参与助力榜吗?\n\n新单位:${newKindergarten.name}`,
    confirmText: '确认更换',
    cancelText: '取消',
    success: (res) => {
      if (res.confirm) {
        // 用户确认更换,使用 nextTick 确保状态更新的顺序
        nextTick(() => {
          matchedKindergarten.value = newKindergarten;
          isAlreadyJoined.value = false; // 重置为未参与状态
        });
      } else {
        // 用户取消,清空输入
        nextTick(() => {
          mottoChars.value = ['', '', '', ''];
        });
      }
    }
  });
};

const handleInputChange = (index, value) => {
  // 允许输入多个字符,但只保留第一个有效字符(汉字、数字、大小写字母),兼容输入法
  if (value) {
    // 提取第一个有效字符(汉字、数字、大小写字母)
    const firstChar = value.match(/[\u4e00-\u9fa5a-zA-Z0-9]/)?.[0] || '';
    mottoChars.value[index] = firstChar;

    // 如果输入了有效字符且不是最后一个输入框,自动聚焦下一个
    if (firstChar && index < 3) {
      focusedIndex.value = index + 1;
      // 使用 nextTick 确保 DOM 更新后再聚焦
      nextTick(() => {
        if (inputRefs.value[index + 1]) {
          inputRefs.value[index + 1].focus();
        }
      });
    }
  } else {
    mottoChars.value[index] = '';
  }

  // 检查是否输入完成,如果完成则匹配幼儿园
  checkAndMatchKindergarten();
};

const handleKeyDown = (index, e) => {
  if (e.key === 'Backspace' && !mottoChars.value[index] && index > 0) {
    // 同样,在Taro中处理光标移动需要不同的方式
  }
};

/**
 * 处理输入框失焦事件
 * @param {number} index - 输入框索引
 */
const handleBlur = (index) => {
  // 重置焦点状态
  focusedIndex.value = -1;

  // 失焦时再次验证输入值,确保只保留有效字符(汉字、数字、大小写字母)
  const currentValue = mottoChars.value[index];
  if (currentValue) {
    const firstChar = currentValue.match(/[\u4e00-\u9fa5a-zA-Z0-9]/)?.[0] || '';
    mottoChars.value[index] = firstChar;
  }
};

const isComplete = computed(() => {
  return mottoChars.value.every((char) => char) && matchedKindergarten.value;
});
const handleConfirmJoin = async () => {
  if (!isComplete.value) return;

  // 如果已经参与助力榜,检查是否是更换操作
  if (isAlreadyJoined.value) {
    // 检查当前匹配的幼儿园是否与之前参与的不同
    const currentMotto = mottoChars.value.join('');
    const currentKindergarten = mockKindergartenData[currentMotto];

    if (currentKindergarten && mockJoinedKindergarten && currentKindergarten.id === mockJoinedKindergarten.id) {
      // 相同的幼儿园,提示已参与
      Taro.showToast({
        title: '您已经参与该助力榜',
        icon: 'none'
      });
      return;
    }
  }

  try {
    // 这里应该调用加入助力榜的API
    // 暂时使用模拟逻辑
    console.log('加入助力榜:', {
      kindergarten: matchedKindergarten.value,
      motto: mottoChars.value.join('')
    });

    // 模拟API调用成功
    isAlreadyJoined.value = true;
    // 更新已参与的幼儿园信息
    mockJoinedKindergarten.id = matchedKindergarten.value.id;
    mockJoinedKindergarten.name = matchedKindergarten.value.name;
    mockJoinedKindergarten.address = matchedKindergarten.value.address;
    mockJoinedKindergarten.logo = matchedKindergarten.value.logo;

    Taro.showToast({
      title: '加入成功',
      icon: 'success'
    });

    setTimeout(() => {
      // 返回上一页
      Taro.navigateBack({
        delta: 1
      });
    }, 1500);
  } catch (error) {
    console.error('加入助力榜失败:', error);
    Taro.showToast({
      title: '加入失败,请重试',
      icon: 'none'
    });
  }
};
</script>
<style lang="less">
@import './index.less';
</style>