api实现

This commit is contained in:
Developer
2026-04-09 08:54:36 +08:00
parent 2eaf317705
commit 8d27c67d3a
319 changed files with 70169 additions and 4677 deletions

View File

@@ -0,0 +1,947 @@
<?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
)
);
}