Files
kitchen/docs/api/api_what_to_eat.php
Developer 8d27c67d3a api实现
2026-04-09 08:54:36 +08:00

948 lines
32 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 🎯 "今天吃什么"智能选择接口
*
* @file api_what_to_eat.php
* @author AI Assistant
* @date 2025-04-08
* @version 1.24.0
* @desc 提供随机选择和智能推荐功能,支持点赞、推荐、浏览量
* @lastUpdate 2026-04-08 增加 POST 请求支持
*/
$startTime = microtime(true);
require '../zb_system/function/c_system_base.php';
$zbp->Load();
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Content-Type: application/json; charset=utf-8');
// 处理 OPTIONS 预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
try {
// 支持 GET 和 POST 请求
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'GET') {
$act = strtolower(trim($_GET['act'] ?? 'random'));
$params = $_GET;
} elseif ($method === 'POST') {
// 尝试解析 JSON 或表单数据
$input = file_get_contents('php://input');
$jsonData = json_decode($input, true);
if (is_array($jsonData)) {
$params = $jsonData;
} else {
$params = $_POST;
}
$act = strtolower(trim($params['act'] ?? 'random'));
} else {
$act = 'random';
$params = array();
}
$result = array();
switch ($act) {
case 'random':
$result = get_random_recipe();
break;
case 'smart':
$result = get_smart_recipe();
break;
case 'config':
$result = get_config();
break;
case 'subcategories':
$result = get_subcategories();
break;
case 'available_filters':
$result = get_available_filters();
break;
case 'like':
$result = do_like();
break;
case 'recommend':
$result = do_recommend();
break;
case 'view':
$result = do_view();
break;
default:
$result = array(
'code' => 200,
'message' => 'success',
'data' => array(
'description' => '今天吃什么智能选择器',
'version' => '1.24.0',
'methods' => array('GET', 'POST'),
'endpoints' => array(
'random' => '?act=random',
'smart' => '?act=smart',
'config' => '?act=config',
'subcategories' => '?act=subcategories&parent_id=12',
'available_filters' => '?act=available_filters&selected_categories=12,13',
'like' => '?act=like&id=1&action=like',
'recommend' => '?act=recommend&id=1&action=recommend',
'view' => '?act=view&id=1'
),
'post_examples' => array(
'random' => array('act' => 'random'),
'smart' => array('act' => 'smart', 'include_categories' => array(12, 13), 'include_tags' => array(1, 4)),
'like' => array('act' => 'like', 'id' => 123, 'action' => 'like'),
'recommend' => array('act' => 'recommend', 'id' => 123, 'action' => 'recommend')
)
)
);
}
} catch (Exception $e) {
$result = array(
'code' => 500,
'message' => '服务器错误: ' . $e->getMessage(),
'data' => null
);
}
$result['_query_time'] = round((microtime(true) - $startTime) * 1000, 2) . 'ms';
echo json_encode($result, JSON_UNESCAPED_UNICODE);
exit;
/**
* 获取配置选项
* @return array
*/
function get_config() {
global $zbp;
$tableCategory = $zbp->db->dbpre . 'category';
$tableTag = $zbp->db->dbpre . 'tag';
$categories = array();
$cateSql = "SELECT c.cate_ID, c.cate_Name, c.cate_Count as count, c.cate_ParentID
FROM $tableCategory c
WHERE c.cate_ParentID IN (11, 1000)
ORDER BY c.cate_ParentID, c.cate_Order ASC";
$cateResults = $zbp->db->Query($cateSql);
foreach ($cateResults as $row) {
$parentName = '';
if ($row['cate_ParentID'] == 11) {
$parentName = '菜谱';
} elseif ($row['cate_ParentID'] == 1000) {
$parentName = '食材';
}
$categories[] = array(
'id' => (int) $row['cate_ID'],
'name' => $row['cate_Name'],
'count' => (int) ($row['count'] ?? 0),
'parent_id' => (int) $row['cate_ParentID'],
'parent_name' => $parentName
);
}
$tags = array(
'taste' => array(),
'craft' => array()
);
$tagSql = "SELECT tag_ID, tag_Name, tag_Alias FROM $tableTag WHERE tag_Alias IN ('口味', '做法') ORDER BY tag_Alias, tag_ID ASC";
$tagResults = $zbp->db->Query($tagSql);
foreach ($tagResults as $row) {
$tagItem = array(
'id' => (int) $row['tag_ID'],
'name' => $row['tag_Name']
);
if ($row['tag_Alias'] === '口味') {
$tags['taste'][] = $tagItem;
} elseif ($row['tag_Alias'] === '做法') {
$tags['craft'][] = $tagItem;
}
}
$allergenTypes = array(
array('type' => 'seafood', 'name' => '海鲜', 'icon' => '🦐'),
array('type' => 'nuts', 'name' => '坚果', 'icon' => '🥜'),
array('type' => 'dairy', 'name' => '乳制品', 'icon' => '🥛'),
array('type' => 'egg', 'name' => '蛋类', 'icon' => '🥚'),
array('type' => 'gluten', 'name' => '麸质', 'icon' => '🌾'),
array('type' => 'soy', 'name' => '大豆', 'icon' => '🫘'),
array('type' => 'peanut', 'name' => '花生', 'icon' => '🥜')
);
$nutritionOptions = array(
'calories' => array('min' => 50, 'max' => 1000, 'unit' => 'kcal', 'name' => '热量'),
'protein' => array('levels' => array('low', 'medium', 'high'), 'unit' => 'g', 'name' => '蛋白质'),
'fat' => array('levels' => array('low', 'medium', 'high'), 'unit' => 'g', 'name' => '脂肪'),
'carbs' => array('levels' => array('low', 'medium', 'high'), 'unit' => 'g', 'name' => '碳水'),
'fiber' => array('levels' => array('low', 'medium', 'high'), 'unit' => 'g', 'name' => '纤维'),
'vitamins' => array('options' => array('A', 'B', 'C', 'D', 'E'), 'name' => '维生素'),
'minerals' => array('options' => array('钙', '铁', '锌', '镁', '钾'), 'name' => '矿物质')
);
return array(
'code' => 200,
'message' => 'success',
'data' => array(
'categories' => $categories,
'tags' => $tags,
'allergen_types' => $allergenTypes,
'nutrition_options' => $nutritionOptions
)
);
}
/**
* 获取子分类
* @return array
*/
function get_subcategories() {
global $zbp, $params;
$parentId = isset($params['parent_id']) ? (int) $params['parent_id'] : 0;
if ($parentId <= 0) {
return array(
'code' => 400,
'message' => '缺少 parent_id 参数',
'data' => null
);
}
$tableCategory = $zbp->db->dbpre . 'category';
$subcategories = array();
$sql = "SELECT cate_ID, cate_Name, cate_Count as count
FROM $tableCategory
WHERE cate_ParentID = $parentId
ORDER BY RAND()
LIMIT 20";
$results = $zbp->db->Query($sql);
foreach ($results as $row) {
$subcategories[] = array(
'id' => (int) $row['cate_ID'],
'name' => $row['cate_Name'],
'count' => (int) ($row['count'] ?? 0)
);
}
return array(
'code' => 200,
'message' => 'success',
'data' => array(
'parent_id' => $parentId,
'subcategories' => $subcategories,
'total' => count($subcategories)
)
);
}
/**
* 获取可用的筛选选项(动态筛选)
* @return array
*/
function get_available_filters() {
global $zbp, $params;
$selectedCategories = isset($params['selected_categories']) ? array_map('intval', explode(',', $params['selected_categories'])) : array();
$selectedTags = isset($params['selected_tags']) ? array_map('intval', explode(',', $params['selected_tags'])) : array();
$parentCategoryId = isset($params['parent_category_id']) ? (int) $params['parent_category_id'] : 0;
$tablePost = $zbp->db->dbpre . 'post';
$tableCategory = $zbp->db->dbpre . 'category';
$tableTag = $zbp->db->dbpre . 'tag';
$whereClauses = array("p.log_Type = 0", "p.log_Status = 0");
if (!empty($selectedCategories)) {
$cateList = implode(',', $selectedCategories);
$whereClauses[] = "p.log_CateID IN ($cateList)";
}
if (!empty($selectedTags)) {
$tagConditions = array();
foreach ($selectedTags as $tagId) {
$tagConditions[] = "p.log_Tag LIKE '%{$tagId}%'";
}
if (!empty($tagConditions)) {
$whereClauses[] = "(" . implode(' OR ', $tagConditions) . ")";
}
}
$whereSql = implode(' AND ', $whereClauses);
$countSql = "SELECT COUNT(*) as cnt FROM $tablePost p WHERE $whereSql";
$countResult = $zbp->db->Query($countSql);
$totalRecipes = (int) ($countResult[0]['cnt'] ?? 0);
$availableSubcategories = array();
if ($parentCategoryId > 0) {
$subcateSql = "SELECT DISTINCT c.cate_ID, c.cate_Name, COUNT(p.log_ID) as recipe_count
FROM $tableCategory c
LEFT JOIN $tablePost p ON p.log_CateID = c.cate_ID AND p.log_Type = 0 AND p.log_Status = 0";
if (!empty($selectedTags)) {
$tagConditions = array();
foreach ($selectedTags as $tagId) {
$tagConditions[] = "p.log_Tag LIKE '%{$tagId}%'";
}
if (!empty($tagConditions)) {
$subcateSql .= " AND (" . implode(' OR ', $tagConditions) . ")";
}
}
$subcateSql .= " WHERE c.cate_ParentID = $parentCategoryId
GROUP BY c.cate_ID, c.cate_Name
HAVING recipe_count > 0
ORDER BY recipe_count DESC
LIMIT 20";
$subcateResults = $zbp->db->Query($subcateSql);
foreach ($subcateResults as $row) {
$availableSubcategories[] = array(
'id' => (int) $row['cate_ID'],
'name' => $row['cate_Name'],
'count' => (int) $row['recipe_count']
);
}
}
$availableTags = array(
'taste' => array(),
'craft' => array()
);
if (!empty($selectedCategories)) {
$cateList = implode(',', $selectedCategories);
$tagSql = "SELECT DISTINCT t.tag_ID, t.tag_Name, t.tag_Alias, COUNT(p.log_ID) as recipe_count
FROM $tableTag t
LEFT JOIN $tablePost p ON p.log_Tag LIKE CONCAT('%', t.tag_ID, '%')
AND p.log_Type = 0 AND p.log_Status = 0 AND p.log_CateID IN ($cateList)
WHERE t.tag_Alias IN ('口味', '做法')
GROUP BY t.tag_ID, t.tag_Name, t.tag_Alias
HAVING recipe_count > 0
ORDER BY recipe_count DESC";
$tagResults = $zbp->db->Query($tagSql);
foreach ($tagResults as $row) {
$tagItem = array(
'id' => (int) $row['tag_ID'],
'name' => $row['tag_Name'],
'count' => (int) $row['recipe_count']
);
if ($row['tag_Alias'] === '口味') {
$availableTags['taste'][] = $tagItem;
} elseif ($row['tag_Alias'] === '做法') {
$availableTags['craft'][] = $tagItem;
}
}
}
return array(
'code' => 200,
'message' => 'success',
'data' => array(
'available_subcategories' => $availableSubcategories,
'available_tags' => $availableTags,
'total_recipes' => $totalRecipes
)
);
}
/**
* 随机选择菜谱
* @return array
*/
function get_random_recipe() {
global $zbp;
$tablePost = $zbp->db->dbpre . 'post';
$sql = "SELECT p.log_ID FROM $tablePost p
WHERE p.log_Type = 0 AND p.log_Status = 0
ORDER BY RAND()
LIMIT 5";
$results = $zbp->db->Query($sql);
if (empty($results)) {
return array(
'code' => 404,
'message' => '没有找到菜谱',
'data' => array(
'candidates' => array(),
'candidates_count' => 0,
'best_match_count' => 0
)
);
}
$candidates = array();
foreach ($results as $row) {
$recipeId = (int) $row['log_ID'];
$recipeDetail = get_recipe_detail($recipeId);
if (isset($recipeDetail['data']['recipe'])) {
$candidates[] = $recipeDetail['data']['recipe'];
}
}
return array(
'code' => 200,
'message' => 'success',
'data' => array(
'candidates' => $candidates,
'candidates_count' => count($candidates),
'best_match_count' => count($candidates),
'total_shown' => count($candidates)
)
);
}
/**
* 智能推荐菜谱
* @return array
*/
function get_smart_recipe() {
global $zbp, $params;
$excludeAllergens = isset($params['exclude_allergens']) ? explode(',', $params['exclude_allergens']) : array();
$excludeCategories = isset($params['exclude_categories']) ? array_map('intval', explode(',', $params['exclude_categories'])) : array();
$excludeTags = isset($params['exclude_tags']) ? array_map('intval', explode(',', $params['exclude_tags'])) : array();
$includeCategories = isset($params['include_categories']) ? array_map('intval', explode(',', $params['include_categories'])) : array();
$includeTags = isset($params['include_tags']) ? array_map('intval', explode(',', $params['include_tags'])) : array();
$tablePost = $zbp->db->dbpre . 'post';
$whereClauses = array("p.log_Type = 0", "p.log_Status = 0");
$bestMatchClauses = array("p.log_Type = 0", "p.log_Status = 0");
if (!empty($excludeCategories)) {
$excludeCateList = implode(',', $excludeCategories);
$whereClauses[] = "p.log_CateID NOT IN ($excludeCateList)";
$bestMatchClauses[] = "p.log_CateID NOT IN ($excludeCateList)";
}
if (!empty($includeCategories)) {
$includeCateList = implode(',', $includeCategories);
$whereClauses[] = "p.log_CateID IN ($includeCateList)";
$bestMatchClauses[] = "p.log_CateID IN ($includeCateList)";
}
if (!empty($excludeTags)) {
foreach ($excludeTags as $tagId) {
$whereClauses[] = "p.log_Tag NOT LIKE '%{$tagId}%'";
$bestMatchClauses[] = "p.log_Tag NOT LIKE '%{$tagId}%'";
}
}
$bestMatchCount = 0;
if (!empty($includeTags)) {
$tagConditions = array();
foreach ($includeTags as $tagId) {
$tagConditions[] = "p.log_Tag LIKE '%{$tagId}%'";
}
if (!empty($tagConditions)) {
$whereClauses[] = "(" . implode(' OR ', $tagConditions) . ")";
$bestMatchClauses[] = implode(' AND ', $tagConditions);
}
$bestMatchWhereSql = implode(' AND ', $bestMatchClauses);
$bestMatchSql = "SELECT COUNT(*) as cnt FROM $tablePost p WHERE $bestMatchWhereSql";
$bestMatchResult = $zbp->db->Query($bestMatchSql);
$bestMatchCount = (int) ($bestMatchResult[0]['cnt'] ?? 0);
}
$whereSql = implode(' AND ', $whereClauses);
$countSql = "SELECT COUNT(*) as cnt FROM $tablePost p WHERE $whereSql";
$countResult = $zbp->db->Query($countSql);
$candidatesCount = (int) ($countResult[0]['cnt'] ?? 0);
if ($candidatesCount === 0) {
return array(
'code' => 404,
'message' => '没有找到符合条件的菜谱,请调整筛选条件',
'data' => array(
'candidates_count' => 0,
'best_match_count' => 0,
'suggestions' => array(
'尝试减少筛选条件',
'更换营养要求'
)
)
);
}
if ($bestMatchCount === 0) {
$bestMatchCount = $candidatesCount;
}
$sql = "SELECT p.log_ID FROM $tablePost p WHERE $whereSql ORDER BY RAND() LIMIT 1";
$results = $zbp->db->Query($sql);
if (empty($results)) {
return array(
'code' => 404,
'message' => '没有找到符合条件的菜谱,请调整筛选条件',
'data' => array(
'candidates_count' => 0,
'best_match_count' => 0,
'suggestions' => array(
'尝试减少筛选条件',
'更换营养要求'
)
)
);
}
$sql = "SELECT p.log_ID FROM $tablePost p WHERE $whereSql ORDER BY RAND() LIMIT 5";
$results = $zbp->db->Query($sql);
if (empty($results)) {
return array(
'code' => 404,
'message' => '没有找到符合条件的菜谱,请调整筛选条件',
'data' => array(
'candidates_count' => 0,
'best_match_count' => 0,
'suggestions' => array(
'尝试减少筛选条件',
'更换营养要求'
)
)
);
}
$candidates = array();
foreach ($results as $row) {
$recipeId = (int) $row['log_ID'];
if (!empty($excludeAllergens)) {
$allergenFiltered = filter_by_allergen($recipeId, $excludeAllergens);
if (!$allergenFiltered) {
continue;
}
}
$recipeDetail = get_recipe_detail($recipeId);
if (isset($recipeDetail['data']['recipe'])) {
$candidates[] = $recipeDetail['data']['recipe'];
}
}
if (empty($candidates)) {
return array(
'code' => 404,
'message' => '没有找到符合条件的菜谱,请调整筛选条件',
'data' => array(
'candidates_count' => 0,
'best_match_count' => 0,
'suggestions' => array(
'尝试减少筛选条件',
'更换营养要求'
)
)
);
}
return array(
'code' => 200,
'message' => 'success',
'data' => array(
'candidates' => $candidates,
'candidates_count' => $candidatesCount,
'best_match_count' => $bestMatchCount,
'total_shown' => count($candidates)
)
);
}
/**
* 过滤过敏原
* @param int $recipeId
* @param array $excludeAllergens
* @return bool
*/
function filter_by_allergen($recipeId, $excludeAllergens) {
global $zbp;
$tableRecipeIngredient = $zbp->db->dbpre . 'recipe_ingredient';
$tableIngredientDetail = $zbp->db->dbpre . 'ingredient_detail';
$sql = "SELECT id.allergen_type
FROM $tableRecipeIngredient ri
LEFT JOIN $tableIngredientDetail id ON ri.ingredient_name = id.name
WHERE ri.log_id = $recipeId AND id.allergen_type IS NOT NULL";
$results = $zbp->db->Query($sql);
foreach ($results as $row) {
$allergenTypes = json_decode($row['allergen_type'] ?? '[]', true);
if (!empty($allergenTypes)) {
foreach ($allergenTypes as $type) {
if (in_array($type, $excludeAllergens)) {
return false;
}
}
}
}
return true;
}
/**
* 获取菜谱详情
* @param int $recipeId
* @return array
*/
function get_recipe_detail($recipeId) {
global $zbp;
$tablePost = $zbp->db->dbpre . 'post';
$tableCategory = $zbp->db->dbpre . 'category';
$tablePostStat = $zbp->db->dbpre . 'post_stat';
$tableRecipeIngredient = $zbp->db->dbpre . 'recipe_ingredient';
$tableIngredientDetail = $zbp->db->dbpre . 'ingredient_detail';
$tableRecipeNutrition = $zbp->db->dbpre . 'recipe_nutrition';
$tableTag = $zbp->db->dbpre . 'tag';
$sql = "SELECT p.log_ID, p.log_Title, p.log_Content, p.log_Intro, p.log_CateID,
p.log_PostTime, p.log_ViewNums, p.log_Tag, c.cate_Name,
COALESCE(s.like_nums, 0) as like_nums,
COALESCE(s.recommend_nums, 0) as recommend_nums
FROM $tablePost p
LEFT JOIN $tableCategory c ON p.log_CateID = c.cate_ID
LEFT JOIN $tablePostStat s ON p.log_ID = s.log_id
WHERE p.log_ID = $recipeId
LIMIT 1";
$results = $zbp->db->Query($sql);
if (empty($results)) {
return array(
'code' => 404,
'message' => '菜谱不存在',
'data' => null
);
}
$viewUpdateSql = "UPDATE $tablePost SET log_ViewNums = log_ViewNums + 1 WHERE log_ID = $recipeId";
$zbp->db->Query($viewUpdateSql);
$row = $results[0];
$tagIds = array_filter(array_map('intval', explode(',', $row['log_Tag'] ?? '')));
$tags = array();
if (!empty($tagIds)) {
$tagIdList = implode(',', $tagIds);
$tagSql = "SELECT tag_ID, tag_Name FROM $tableTag WHERE tag_ID IN ($tagIdList)";
$tagResults = $zbp->db->Query($tagSql);
foreach ($tagResults as $tagRow) {
$tags[] = array(
'id' => (int) $tagRow['tag_ID'],
'name' => $tagRow['tag_Name']
);
}
}
$ingredientSql = "SELECT ri.name as ingredient_name, ri.amount, ri.type,
id.ingredient_id, id.alias, id.suitable_crowd, id.unsuitable_crowd,
id.intro as ingredient_intro, id.efficacy, id.cooking_tips,
id.nutrition as ingredient_nutrition, id.allergen_type,
id.category_names
FROM $tableRecipeIngredient ri
LEFT JOIN $tableIngredientDetail id ON ri.name = id.name
WHERE ri.log_id = $recipeId
ORDER BY ri.sort ASC";
$ingredientResults = $zbp->db->Query($ingredientSql);
$ingredients = array(
'main' => array(),
'auxiliary' => array(),
'seasoning' => array()
);
foreach ($ingredientResults as $ingRow) {
$type = $ingRow['type'] ?? 'main';
$ingredientDetail = array(
'name' => $ingRow['ingredient_name'],
'amount' => $ingRow['amount'] ?? '',
'detail' => null
);
if (!empty($ingRow['ingredient_id'])) {
$ingredientDetail['detail'] = array(
'id' => (int) $ingRow['ingredient_id'],
'alias' => json_decode($ingRow['alias'] ?? '[]', true),
'suitable_crowd' => json_decode($ingRow['suitable_crowd'] ?? '[]', true),
'unsuitable_crowd' => json_decode($ingRow['unsuitable_crowd'] ?? '[]', true),
'intro' => $ingRow['ingredient_intro'] ?? '',
'efficacy' => $ingRow['efficacy'] ?? '',
'cooking_tips' => $ingRow['cooking_tips'] ?? '',
'nutrition' => json_decode($ingRow['ingredient_nutrition'] ?? '[]', true),
'allergen_type' => json_decode($ingRow['allergen_type'] ?? '[]', true),
'category_names' => json_decode($ingRow['category_names'] ?? '[]', true)
);
}
$ingredients[$type][] = $ingredientDetail;
}
$nutrition = get_nutrition_from_db($recipeId);
$cover = '';
if (preg_match('/<img[^>]+src=["\']([^"\']+)["\']/i', $row['log_Content'] ?? '', $matches)) {
$cover = $matches[1];
}
return array(
'code' => 200,
'message' => 'success',
'data' => array(
'recipe' => array(
'id' => (int) $row['log_ID'],
'title' => $row['log_Title'],
'cover' => $cover,
'intro' => mb_substr(strip_tags($row['log_Intro'] ?? ''), 0, 100),
'category' => array(
'id' => (int) ($row['log_CateID'] ?? 0),
'name' => $row['cate_Name'] ?? ''
),
'tags' => $tags,
'ingredients' => $ingredients,
'nutrition' => $nutrition,
'statistics' => array(
'view_count' => (int) ($row['log_ViewNums'] ?? 0) + 1,
'like_count' => (int) ($row['like_nums'] ?? 0),
'recommend_count' => (int) ($row['recommend_nums'] ?? 0)
),
'publish_time' => strtotime($row['log_PostTime']),
'url' => '?act=detail&id=' . $row['log_ID']
),
'candidates_count' => 1,
'filter_applied' => new stdClass()
)
);
}
/**
* 从数据库获取营养成分
* @param int $recipeId
* @return array
*/
function get_nutrition_from_db($recipeId) {
global $zbp;
$tableRecipeNutrition = $zbp->db->dbpre . 'recipe_nutrition';
$nutrition = array(
'calories' => null,
'protein' => null,
'fat' => null,
'carbs' => null,
'fiber' => null,
'sodium' => null,
'cholesterol' => null,
'all' => array()
);
$sql = "SELECT name, value, unit FROM $tableRecipeNutrition WHERE log_id = $recipeId";
$results = $zbp->db->Query($sql);
foreach ($results as $row) {
$name = $row['name'];
$value = (float) $row['value'];
$unit = $row['unit'];
$nutrition['all'][] = array(
'name' => $name,
'value' => $value,
'unit' => $unit
);
if (strpos($name, '能量') !== false || strpos($name, '热量') !== false) {
$nutrition['calories'] = round($value) . ($unit ?? 'kcal');
} elseif (strpos($name, '蛋白质') !== false) {
$nutrition['protein'] = round($value, 1) . ($unit ?? 'g');
} elseif (strpos($name, '脂肪') !== false) {
$nutrition['fat'] = round($value, 1) . ($unit ?? 'g');
} elseif (strpos($name, '碳水') !== false || strpos($name, '糖') !== false) {
$nutrition['carbs'] = round($value, 1) . ($unit ?? 'g');
} elseif (strpos($name, '纤维') !== false) {
$nutrition['fiber'] = round($value, 1) . ($unit ?? 'g');
} elseif (strpos($name, '钠') !== false) {
$nutrition['sodium'] = round($value, 1) . ($unit ?? 'mg');
} elseif (strpos($name, '胆固醇') !== false) {
$nutrition['cholesterol'] = round($value, 1) . ($unit ?? 'mg');
}
}
return $nutrition;
}
/**
* 从内容解析营养成分
* @param string $content
* @return array
*/
function parse_nutrition_from_content($content) {
$nutrition = array(
'calories' => null,
'protein' => null,
'fat' => null,
'carbs' => null,
'fiber' => null,
'vitamins' => array(),
'minerals' => array()
);
if (preg_match('/热量[:]\s*(\d+)/u', $content, $matches)) {
$nutrition['calories'] = (int) $matches[1];
}
if (preg_match('/蛋白质[:]\s*([\d.]+)/u', $content, $matches)) {
$nutrition['protein'] = $matches[1] . 'g';
}
if (preg_match('/脂肪[:]\s*([\d.]+)/u', $content, $matches)) {
$nutrition['fat'] = $matches[1] . 'g';
}
if (preg_match('/碳水[:]\s*([\d.]+)/u', $content, $matches)) {
$nutrition['carbs'] = $matches[1] . 'g';
}
return $nutrition;
}
/**
* 点赞/取消点赞
* @return array
*/
function do_like() {
global $zbp, $params;
$id = (int) ($params['id'] ?? 0);
$action = trim($params['action'] ?? 'like');
if ($id <= 0) {
return array('code' => 400, 'message' => '缺少 ID 参数');
}
$tablePostStat = $zbp->db->dbpre . 'post_stat';
$checkSql = "SELECT * FROM $tablePostStat WHERE log_id = $id LIMIT 1";
$exists = $zbp->db->Query($checkSql);
if (empty($exists)) {
$insertSql = "INSERT INTO $tablePostStat (log_id, like_nums, recommend_nums) VALUES ($id, 1, 0)";
$zbp->db->Query($insertSql);
$likeNums = 1;
} else {
if ($action === 'like') {
$updateSql = "UPDATE $tablePostStat SET like_nums = like_nums + 1 WHERE log_id = $id";
} else {
$updateSql = "UPDATE $tablePostStat SET like_nums = GREATEST(0, like_nums - 1) WHERE log_id = $id";
}
$zbp->db->Query($updateSql);
$resultSql = "SELECT like_nums FROM $tablePostStat WHERE log_id = $id LIMIT 1";
$result = $zbp->db->Query($resultSql);
$likeNums = (int) ($result[0]['like_nums'] ?? 0);
}
return array(
'code' => 200,
'message' => $action === 'like' ? '点赞成功' : '取消点赞成功',
'data' => array(
'id' => $id,
'like_count' => $likeNums,
'action' => $action
)
);
}
/**
* 推荐/取消推荐
* @return array
*/
function do_recommend() {
global $zbp, $params;
$id = (int) ($params['id'] ?? 0);
$action = trim($params['action'] ?? 'recommend');
$score = (int) ($params['score'] ?? 5);
if ($id <= 0) {
return array('code' => 400, 'message' => '缺少 ID 参数');
}
$tablePostStat = $zbp->db->dbpre . 'post_stat';
$checkSql = "SELECT * FROM $tablePostStat WHERE log_id = $id LIMIT 1";
$exists = $zbp->db->Query($checkSql);
if (empty($exists)) {
$insertSql = "INSERT INTO $tablePostStat (log_id, like_nums, recommend_nums) VALUES ($id, 0, 1)";
$zbp->db->Query($insertSql);
$recommendNums = 1;
} else {
if ($action === 'recommend') {
$updateSql = "UPDATE $tablePostStat SET recommend_nums = recommend_nums + 1 WHERE log_id = $id";
} else {
$updateSql = "UPDATE $tablePostStat SET recommend_nums = GREATEST(0, recommend_nums - 1) WHERE log_id = $id";
}
$zbp->db->Query($updateSql);
$resultSql = "SELECT recommend_nums FROM $tablePostStat WHERE log_id = $id LIMIT 1";
$result = $zbp->db->Query($resultSql);
$recommendNums = (int) ($result[0]['recommend_nums'] ?? 0);
}
return array(
'code' => 200,
'message' => $action === 'recommend' ? '推荐成功' : '取消推荐成功',
'data' => array(
'id' => $id,
'recommend_count' => $recommendNums,
'action' => $action,
'score' => $score
)
);
}
/**
* 增加浏览量
* @return array
*/
function do_view() {
global $zbp, $params;
$id = (int) ($params['id'] ?? 0);
if ($id <= 0) {
return array('code' => 400, 'message' => '缺少 ID 参数');
}
$tablePost = $zbp->db->dbpre . 'post';
$updateSql = "UPDATE $tablePost SET log_ViewNums = log_ViewNums + 1 WHERE log_ID = $id";
$zbp->db->Query($updateSql);
$resultSql = "SELECT log_ViewNums FROM $tablePost WHERE log_ID = $id LIMIT 1";
$result = $zbp->db->Query($resultSql);
$viewNums = (int) ($result[0]['log_ViewNums'] ?? 0);
return array(
'code' => 200,
'message' => '浏览量已更新',
'data' => array(
'id' => $id,
'view_count' => $viewNums
)
);
}