FOOD_PREFERENCES.md 4.5 KB

食物偏好选项实现说明

📋 概述

注册页面的食物偏好选项现在支持以下功能:

  • 国际化支持 - 所有食物名称支持 4 种语言(日语、英语、简体中文、繁体中文)
  • API 集成准备 - 预留了 API 接口,可轻松切换到后端数据
  • Fallback 机制 - API 失败时自动使用本地国际化数据

🔧 当前实现

1. 数据结构

interface FoodOption {
  id: string; // 食物唯一标识
  label: string; // 显示的本地化名称
}

2. 本地化配置

src/locale/*.json 中添加了 register.foods 部分:

{
  "register": {
    "foods": {
      "sushi": "寿司",
      "ramen": "ラーメン"
      // ...
    }
  }
}

3. 当前行为

  • 页面加载时调用 fetchFoodOptions()
  • 目前使用本地国际化数据作为 fallback
  • 用户选择的是 food.id,存储在 form.favoriteFoods 数组中

🚀 切换到 API 模式

步骤 1: 更新 register.vue

src/views/login/register.vue 中,找到 fetchFoodOptions 函数:

// 当前代码(第 255-267 行)
const fetchFoodOptions = async () => {
  try {
    // TODO: 取消注释以下代码以启用 API
    // const response = await getFoodPreferences(locale.value)
    // foodOptions.value = response.data

    // 暂时使用本地 fallback
    foodOptions.value = getFallbackFoodOptions();
  } catch (error) {
    console.error("Failed to fetch food options:", error);
    foodOptions.value = getFallbackFoodOptions();
  }
};

修改为:

import { getFoodPreferences } from "@/api/preferences";

const fetchFoodOptions = async () => {
  try {
    // 从 API 获取
    const response = await getFoodPreferences(locale.value);
    foodOptions.value = response.data || response;
  } catch (error) {
    console.error("Failed to fetch food options:", error);
    // API 失败时使用本地 fallback
    foodOptions.value = getFallbackFoodOptions();
  }
};

步骤 2: 后端 API 实现

后端需要实现以下接口:

GET /app-api/member/preferences/foods

Query Parameters:

  • locale (可选): 语言代码 (ja, en, zh-Hans, zh-Hant)

Response:

{
  "code": 0,
  "data": [
    {
      "id": "sushi",
      "label": "寿司",
      "category": "japanese",
      "icon": "🍣"
    },
    {
      "id": "ramen",
      "label": "ラーメン",
      "category": "japanese",
      "icon": "🍜"
    }
  ]
}

步骤 3: 保存用户偏好

handleRegister 函数中,可以调用保存 API:

import { saveFoodPreferences } from "@/api/preferences";

const handleRegister = async () => {
  if (!form.nickname || !form.contact) {
    showToast(t("register.fillRequired"));
    return;
  }

  loading.value = true;
  try {
    // 注册用户
    // const userRes = await registerUser(form)

    // 保存食物偏好
    if (form.favoriteFoods.length > 0) {
      await saveFoodPreferences(form.favoriteFoods);
    }

    showToast(t("register.success"));
    router.push("/index");
  } catch (error) {
    console.error(error);
    showToast(t("register.failed"));
  } finally {
    loading.value = false;
  }
};

🎯 优势

使用 API 的好处:

  1. 动态管理 - 可以在后台添加/删除食物选项,无需发布新版本
  2. 个性化 - 可以根据地区、餐厅类型返回不同选项
  3. 数据分析 - 收集用户偏好数据用于推荐算法
  4. 一致性 - 与后端数据库保持同步

保留 Fallback 的好处:

  1. 离线支持 - API 失败时仍能正常使用
  2. 快速加载 - 本地数据立即可用
  3. 降级方案 - 确保用户体验不受影响

📝 国际化翻译

已添加的翻译键:

register.foods.sushi
register.foods.ramen
register.foods.gyoza
register.foods.tempura
register.foods.udon
register.foods.sashimi
register.foods.yakitori

如需添加新的食物选项,在所有语言文件中添加对应的翻译即可。

🔄 语言切换

当用户切换语言时,食物选项会自动更新为对应语言的翻译:

// 监听语言变化(可选)
watch(locale, () => {
  fetchFoodOptions();
});

📚 相关文件

  • src/views/login/register.vue - 注册页面组件
  • src/api/preferences.ts - 偏好设置 API 接口
  • src/locale/ja.json - 日语翻译
  • src/locale/en.json - 英语翻译
  • src/locale/zh-Hans.json - 简体中文翻译
  • src/locale/zh-Hant.json - 繁体中文翻译