瀑布流
This commit is contained in:
248
docs/api/api.php
248
docs/api/api.php
@@ -168,17 +168,21 @@ switch ($act) {
|
||||
case 'unified_hot':
|
||||
$result = get_unified_hot($type);
|
||||
break;
|
||||
case 'mini':
|
||||
$result = recipe_mini();
|
||||
break;
|
||||
case 'index':
|
||||
default:
|
||||
$result = array(
|
||||
'code' => 200,
|
||||
'message' => '🍳 菜谱API服务正常运行',
|
||||
'data' => array(
|
||||
'version' => '1.26.0',
|
||||
'version' => '1.29.0',
|
||||
'endpoints' => array(
|
||||
'list' => '?act=list',
|
||||
'detail' => '?act=detail&id=1',
|
||||
'full' => '?act=full&id=1',
|
||||
'mini' => '?act=mini&id=1',
|
||||
'ingredients' => '?act=ingredients',
|
||||
'ingredient_detail' => '?act=ingredient_detail&id=1',
|
||||
'search' => '?act=search&keyword=苹果',
|
||||
@@ -225,52 +229,24 @@ function recipe_list() {
|
||||
$cateId = (int) ($_GET['cate_id'] ?? 0);
|
||||
$tagId = (int) ($_GET['tag_id'] ?? 0);
|
||||
$search = trim($_GET['search'] ?? '');
|
||||
$userId = trim($_GET['user_id'] ?? '');
|
||||
$usePreference = isset($_GET['use_preference']) && $_GET['use_preference'] === 'true';
|
||||
|
||||
if ($limit > 100) $limit = 100;
|
||||
if ($limit < 1) $limit = 20;
|
||||
if ($page < 1) $page = 1;
|
||||
|
||||
$preferredTags = array();
|
||||
$preferredCategories = array();
|
||||
$blockedAllergens = array();
|
||||
|
||||
if ($usePreference && !empty($userId)) {
|
||||
$preference = load_user_preference_data($userId);
|
||||
$preferredTags = $preference['preferred_tags'] ?? array();
|
||||
$preferredCategories = $preference['preferred_categories'] ?? array();
|
||||
$blockedAllergens = $preference['blocked_allergens'] ?? array();
|
||||
}
|
||||
|
||||
if (isset($_GET['preferred_tags'])) {
|
||||
$preferredTags = array_map('intval', explode(',', $_GET['preferred_tags']));
|
||||
}
|
||||
if (isset($_GET['preferred_categories'])) {
|
||||
$preferredCategories = array_map('intval', explode(',', $_GET['preferred_categories']));
|
||||
}
|
||||
|
||||
$tablePost = $zbp->db->dbpre . 'post';
|
||||
$tableCategory = $zbp->db->dbpre . 'category';
|
||||
$tablePostStat = $zbp->db->dbpre . 'post_stat';
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$whereSql = "WHERE p.log_Type = 0 AND p.log_Status = 0";
|
||||
|
||||
if ($cateId > 0) {
|
||||
$whereSql .= " AND p.log_CateID = $cateId";
|
||||
} elseif (!empty($preferredCategories)) {
|
||||
$cateList = implode(',', $preferredCategories);
|
||||
$whereSql .= " AND p.log_CateID IN ($cateList)";
|
||||
}
|
||||
|
||||
if ($tagId > 0) {
|
||||
$whereSql .= " AND p.log_Tag LIKE '%{$tagId}%'";
|
||||
} elseif (!empty($preferredTags)) {
|
||||
$tagConditions = array();
|
||||
foreach ($preferredTags as $pt) {
|
||||
$tagConditions[] = "p.log_Tag LIKE '%{$pt}%'";
|
||||
}
|
||||
$whereSql .= " AND (" . implode(' OR ', $tagConditions) . ")";
|
||||
}
|
||||
|
||||
if (!empty($search)) {
|
||||
@@ -282,8 +258,8 @@ function recipe_list() {
|
||||
$countResult = $zbp->db->Query($countSql);
|
||||
$total = (int) ($countResult[0]['total'] ?? 0);
|
||||
|
||||
$selectFields = "p.log_ID, p.log_Title, p.log_Intro, p.log_CateID, p.log_Tag, p.log_PostTime, p.log_ViewNums, p.log_CommNums, p.log_Meta, p.log_Content, c.cate_Name";
|
||||
$sql = "SELECT $selectFields FROM $tablePost p LEFT JOIN $tableCategory c ON p.log_CateID = c.cate_ID $whereSql ORDER BY p.log_PostTime DESC LIMIT $offset, $limit";
|
||||
$selectFields = "p.log_ID, p.log_Title, p.log_Intro, p.log_CateID, p.log_Tag, p.log_PostTime, p.log_ViewNums, p.log_CommNums, p.log_Meta, p.log_Content, c.cate_Name, COALESCE(s.rate_nums, 0) as rate_nums, COALESCE(s.rate_score, 0) as rate_score";
|
||||
$sql = "SELECT $selectFields 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 $whereSql ORDER BY p.log_PostTime DESC LIMIT $offset, $limit";
|
||||
$results = $zbp->db->Query($sql);
|
||||
|
||||
$list = array();
|
||||
@@ -302,7 +278,11 @@ function recipe_list() {
|
||||
'comment_count' => (int) ($row['log_CommNums'] ?? 0),
|
||||
'meta' => $meta,
|
||||
'url' => '?id=' . $row['log_ID'],
|
||||
'cover' => extract_cover_from_content($row['log_Content'] ?? '')
|
||||
'cover' => extract_cover_from_content($row['log_Content'] ?? ''),
|
||||
'rating' => ApiResponse::getRatingSummary(
|
||||
(float) ($row['rate_score'] ?? 0),
|
||||
(int) ($row['rate_nums'] ?? 0)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -313,35 +293,11 @@ function recipe_list() {
|
||||
'list' => $list,
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
'total' => $total,
|
||||
'filter' => array(
|
||||
'preferred_tags' => $preferredTags,
|
||||
'preferred_categories' => $preferredCategories
|
||||
)
|
||||
'total' => $total
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function load_user_preference_data($userId) {
|
||||
$cacheDir = dirname(__FILE__) . '/cache/preference/';
|
||||
$file = $cacheDir . 'pref_' . md5($userId) . '.json';
|
||||
|
||||
if (file_exists($file)) {
|
||||
$content = file_get_contents($file);
|
||||
$data = json_decode($content, true);
|
||||
return is_array($data) ? $data : array(
|
||||
'preferred_tags' => array(),
|
||||
'preferred_categories' => array(),
|
||||
'blocked_allergens' => array()
|
||||
);
|
||||
}
|
||||
return array(
|
||||
'preferred_tags' => array(),
|
||||
'preferred_categories' => array(),
|
||||
'blocked_allergens' => array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜谱详情
|
||||
*/
|
||||
@@ -358,13 +314,27 @@ function recipe_detail() {
|
||||
return array('code' => 404, 'message' => '❌ 菜谱不存在');
|
||||
}
|
||||
|
||||
// 增加浏览量
|
||||
if (isset($_GET['viewnums']) && $_GET['viewnums'] === 'true') {
|
||||
$post->ViewNums += 1;
|
||||
$sql = $zbp->db->sql->Update($zbp->table['Post'], array('log_ViewNums' => $post->ViewNums), array(array('=', 'log_ID', $post->ID)));
|
||||
$zbp->db->Update($sql);
|
||||
}
|
||||
|
||||
$tableRecipeIdMap = $zbp->db->dbpre . 'recipe_id_map';
|
||||
$tablePostStat = $zbp->db->dbpre . 'post_stat';
|
||||
$idMapSql = "SELECT old_id FROM $tableRecipeIdMap WHERE new_log_id = $id LIMIT 1";
|
||||
$idMapResult = $zbp->db->Query($idMapSql);
|
||||
$picId = !empty($idMapResult) ? (int) $idMapResult[0]['old_id'] : null;
|
||||
|
||||
$statSql = "SELECT rate_nums, rate_score FROM $tablePostStat WHERE log_id = $id LIMIT 1";
|
||||
$statResult = $zbp->db->Query($statSql);
|
||||
$rateNums = 0;
|
||||
$rateScore = 0.00;
|
||||
if (!empty($statResult)) {
|
||||
$rateNums = (int) ($statResult[0]['rate_nums'] ?? 0);
|
||||
$rateScore = (float) ($statResult[0]['rate_score'] ?? 0);
|
||||
}
|
||||
|
||||
$meta = json_decode($post->Meta, true) ?: array();
|
||||
$ingredients = get_recipe_ingredients($id);
|
||||
|
||||
@@ -373,6 +343,7 @@ function recipe_detail() {
|
||||
'message' => 'success',
|
||||
'data' => array(
|
||||
'id' => $post->ID,
|
||||
'pic_id' => $picId,
|
||||
'title' => $post->Title,
|
||||
'content' => $post->Content,
|
||||
'intro' => $post->Intro,
|
||||
@@ -391,7 +362,123 @@ function recipe_detail() {
|
||||
'id' => $post->Author->ID,
|
||||
'name' => $post->Author->Name,
|
||||
'avatar' => $post->Author->Avatar
|
||||
) : null
|
||||
) : null,
|
||||
'rating' => ApiResponse::formatRating($rateScore, $rateNums)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜谱迷你信息
|
||||
* 返回简化的核心信息:code, pic_id, title, intro, category, allergens, nutrition
|
||||
* 适用于列表页、卡片展示等需要快速加载的场景
|
||||
* @return array 迷你版菜谱信息
|
||||
*/
|
||||
function recipe_mini() {
|
||||
global $zbp;
|
||||
|
||||
$id = (int) ($_GET['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
return array('code' => 400, 'message' => '缺少菜谱ID参数');
|
||||
}
|
||||
|
||||
$tablePost = $zbp->db->dbpre . 'post';
|
||||
$tableCategory = $zbp->db->dbpre . 'category';
|
||||
$tableRecipeIdMap = $zbp->db->dbpre . 'recipe_id_map';
|
||||
$tableRecipeIngredient = $zbp->db->dbpre . 'recipe_ingredient';
|
||||
$tableIngredientDetail = $zbp->db->dbpre . 'ingredient_detail';
|
||||
$tableRecipeNutrition = $zbp->db->dbpre . 'recipe_nutrition';
|
||||
$tablePostStat = $zbp->db->dbpre . 'post_stat';
|
||||
|
||||
$sql = "SELECT p.log_ID, p.log_Title, p.log_Intro, p.log_CateID,
|
||||
c.cate_Name as cate_name, c.cate_ParentID as cate_parent_id,
|
||||
COALESCE(s.rate_nums, 0) as rate_nums, COALESCE(s.rate_score, 0) as rate_score
|
||||
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 = $id AND p.log_Type = 0 AND p.log_Status = 0";
|
||||
|
||||
$result = $zbp->db->Query($sql);
|
||||
|
||||
if (empty($result)) {
|
||||
return array('code' => 404, 'message' => '菜谱不存在');
|
||||
}
|
||||
|
||||
$row = $result[0];
|
||||
|
||||
$picId = null;
|
||||
$idMapSql = "SELECT old_id FROM $tableRecipeIdMap WHERE new_log_id = $id LIMIT 1";
|
||||
$idMapResult = $zbp->db->Query($idMapSql);
|
||||
if (!empty($idMapResult)) {
|
||||
$picId = (int) $idMapResult[0]['old_id'];
|
||||
}
|
||||
|
||||
$allergenSql = "SELECT DISTINCT id.allergen
|
||||
FROM $tableRecipeIngredient ri
|
||||
INNER JOIN $tableIngredientDetail id ON ri.detail_id = id.ingredient_id
|
||||
WHERE ri.log_id = $id AND id.allergen IS NOT NULL AND id.allergen != '' AND id.allergen != '[]'";
|
||||
$allergenResults = $zbp->db->Query($allergenSql);
|
||||
$allergens = array();
|
||||
foreach ($allergenResults as $aRow) {
|
||||
$aList = json_decode($aRow['allergen'] ?? '[]', true);
|
||||
if (is_array($aList)) {
|
||||
$allergens = array_merge($allergens, $aList);
|
||||
}
|
||||
}
|
||||
$allergens = array_values(array_unique($allergens));
|
||||
|
||||
$nutritionSql = "SELECT name, value, unit FROM $tableRecipeNutrition WHERE log_id = $id";
|
||||
$nutritionResults = $zbp->db->Query($nutritionSql);
|
||||
$nutrition = array();
|
||||
foreach ($nutritionResults as $nRow) {
|
||||
$nutrition[] = array(
|
||||
'name' => $nRow['name'],
|
||||
'value' => (float) $nRow['value'],
|
||||
'unit' => $nRow['unit']
|
||||
);
|
||||
}
|
||||
|
||||
$categoryHierarchy = array();
|
||||
$currentCateId = (int) $row['cate_parent_id'];
|
||||
while ($currentCateId > 0) {
|
||||
$cateSql = "SELECT cate_ID, cate_Name, cate_ParentID FROM $tableCategory WHERE cate_ID = $currentCateId LIMIT 1";
|
||||
$cateResult = $zbp->db->Query($cateSql);
|
||||
if (!empty($cateResult)) {
|
||||
$cateRow = $cateResult[0];
|
||||
array_unshift($categoryHierarchy, array(
|
||||
'id' => (int) $cateRow['cate_ID'],
|
||||
'name' => $cateRow['cate_Name']
|
||||
));
|
||||
$currentCateId = (int) $cateRow['cate_ParentID'];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$categoryHierarchy[] = array(
|
||||
'id' => (int) $row['log_CateID'],
|
||||
'name' => $row['cate_name']
|
||||
);
|
||||
|
||||
return array(
|
||||
'code' => 200,
|
||||
'message' => 'success',
|
||||
'data' => array(
|
||||
'id' => (int) $row['log_ID'],
|
||||
'code' => 'CP' . str_pad($row['log_ID'], 5, '0', STR_PAD_LEFT),
|
||||
'pic_id' => $picId,
|
||||
'title' => $row['log_Title'],
|
||||
'intro' => $row['log_Intro'],
|
||||
'category' => array(
|
||||
'id' => (int) $row['log_CateID'],
|
||||
'name' => $row['cate_name'],
|
||||
'hierarchy' => $categoryHierarchy
|
||||
),
|
||||
'allergens' => $allergens,
|
||||
'nutrition' => $nutrition,
|
||||
'rating' => ApiResponse::getRatingSummary(
|
||||
(float) ($row['rate_score'] ?? 0),
|
||||
(int) ($row['rate_nums'] ?? 0)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -428,8 +515,8 @@ function recipe_full() {
|
||||
m.mem_ID as author_id, m.mem_Name as author_name, m.mem_Alias as author_alias,
|
||||
m.mem_Email as author_email, m.mem_HomePage as author_homepage,
|
||||
COALESCE(s.like_nums, 0) as like_nums,
|
||||
COALESCE(s.recommend_nums, 0) as recommend_nums,
|
||||
COALESCE(s.recommend_score, 0) as recommend_score
|
||||
COALESCE(s.rate_nums, 0) as rate_nums,
|
||||
COALESCE(s.rate_score, 0) as rate_score
|
||||
FROM $tablePost p
|
||||
LEFT JOIN $tableCategory c ON p.log_CateID = c.cate_ID
|
||||
LEFT JOIN $tableMember m ON p.log_AuthorID = m.mem_ID
|
||||
@@ -626,8 +713,12 @@ function recipe_full() {
|
||||
'view_count' => (int) ($row['log_ViewNums'] ?? 0),
|
||||
'comment_count' => (int) ($row['log_CommNums'] ?? 0),
|
||||
'like_count' => (int) ($row['like_nums'] ?? 0),
|
||||
'recommend_count' => (int) ($row['recommend_nums'] ?? 0),
|
||||
'recommend_score' => (float) ($row['recommend_score'] ?? 0)
|
||||
'rate_count' => (int) ($row['rate_nums'] ?? 0),
|
||||
'rate_score' => (float) ($row['rate_score'] ?? 0)
|
||||
),
|
||||
'rating' => ApiResponse::formatRating(
|
||||
(float) ($row['rate_score'] ?? 0),
|
||||
(int) ($row['rate_nums'] ?? 0)
|
||||
),
|
||||
'meta' => array(
|
||||
'indices' => $meta['indices'] ?? array(),
|
||||
@@ -650,21 +741,11 @@ function ingredient_list() {
|
||||
$cateId = (int) ($_GET['cate_id'] ?? 0);
|
||||
$search = trim($_GET['search'] ?? '');
|
||||
$author = trim($_GET['author'] ?? '');
|
||||
$userId = trim($_GET['user_id'] ?? '');
|
||||
$usePreference = isset($_GET['use_preference']) && $_GET['use_preference'] === 'true';
|
||||
|
||||
if ($limit > 100) $limit = 100;
|
||||
if ($limit < 1) $limit = 20;
|
||||
if ($page < 1) $page = 1;
|
||||
|
||||
$blockedAllergens = array();
|
||||
if (isset($_GET['blocked_allergens'])) {
|
||||
$blockedAllergens = array_filter(explode(',', $_GET['blocked_allergens']));
|
||||
} elseif ($usePreference && !empty($userId)) {
|
||||
$preference = load_user_preference_data($userId);
|
||||
$blockedAllergens = $preference['blocked_allergens'] ?? array();
|
||||
}
|
||||
|
||||
$table = $zbp->db->dbpre . 'ingredient_detail';
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
@@ -691,24 +772,9 @@ function ingredient_list() {
|
||||
$results = $zbp->db->Query($sql);
|
||||
|
||||
$list = array();
|
||||
$filtered = 0;
|
||||
foreach ($results as $row) {
|
||||
$allergenType = json_decode($row['allergen_type'] ?? '[]', true);
|
||||
|
||||
if (!empty($blockedAllergens) && !empty($allergenType)) {
|
||||
$hasBlocked = false;
|
||||
foreach ($allergenType as $type) {
|
||||
if (in_array($type, $blockedAllergens)) {
|
||||
$hasBlocked = true;
|
||||
$filtered++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($hasBlocked) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$item = array(
|
||||
'id' => (int) $row['ingredient_id'],
|
||||
'name' => $row['name'],
|
||||
@@ -732,9 +798,7 @@ function ingredient_list() {
|
||||
'list' => $list,
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
'total' => $total,
|
||||
'filtered' => $filtered,
|
||||
'blocked_allergens' => $blockedAllergens
|
||||
'total' => $total
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user