index.vue 4.82 KB
<template>
  <view class="min-h-screen flex flex-col bg-white">
    <!-- <AppHeader title="加入家庭" /> -->
    <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 ? '#3b82f6' : '#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"
          />
        </view>
      </view>
      <!-- Help text -->
      <view class="text-gray-500 text-center text-sm mb-4">
        没有口令?请联系您的大家长获取
      </view>
      <!-- Role selection -->
      <view class="mb-6">
        <h3 class="identity-title">
          选择您的身份
        </h3>
        <view class="flex gap-2 flex-wrap">
          <view
            v-for="role in familyRoles"
            :key="role.id"
            @click="selectedRole = role.id"
            :class="[
              'w-[calc(49%-4rpx)] py-3 rounded-lg border text-center flex flex-col items-center gap-1',
              selectedRole === role.id
                ? 'border-blue-500 bg-blue-50 text-blue-500'
                : 'border-gray-200 text-gray-700'
            ]"
          >
            <My size="20" />
            <span class="text-sm">{{ role.label }}</span>
          </view>
        </view>
      </view>
      <!-- Submit Button -->
      <view
        @click="handleJoinFamily"
        :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 } from 'vue';
import Taro from '@tarojs/taro';
import { My } from '@nutui/icons-vue-taro';
import AppHeader from '../../components/AppHeader.vue';

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

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] = '';
  }
};

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 familyRoles = [
  { id: 'husband', label: '丈夫' },
  { id: 'wife', label: '妻子' },
  { id: 'son', label: '儿子' },
  { id: 'daughter-in-law', label: '儿媳' },
  { id: 'son-in-law', label: '女婿' },
  { id: 'daughter', label: '女儿' },
  { id: 'grandson', label: '孙子' },
  { id: 'maternal-grandson', label: '外孙' },
  { id: 'granddaughter', label: '孙女' },
  { id: 'maternal-granddaughter', label: '外孙女' }
];

const isComplete = computed(() => {
  return mottoChars.value.every((char) => char) && selectedRole.value;
});

const handleJoinFamily = () => {
  if (isComplete.value) {
    Taro.reLaunch({
      url: '/pages/Dashboard/index'
    });
  }
};
</script>
<style lang="less">
@import './index.less';
</style>