request->param('type', ''); $phase = $this->request->param('phase', ''); $categoryId = (int)$this->request->param('category_id', 0); $page = max(1, (int)$this->request->param('page', 1)); $limit = min(50, max(1, (int)$this->request->param('limit', 10))); // 未显式传阶段时,按当前周期阶段智能匹配 if (!$phase) { $current = CycleService::current($this->auth->id); $phase = $current['phase'] ?: ''; } $query = Db::name('content') ->where('status', 'normal') ->where('verify', 'passed'); if ($type) { $query->where('type', $type); } if ($categoryId) { $query->where('category_id', $categoryId); } $all = $query->order('weigh', 'desc')->select(); // 阶段匹配优先:先取命中当前阶段(含 all)的内容,过少时回退全量, // 避免某些阶段(如排卵期)内容过少导致列表空置 if ($phase) { $matched = array_values(array_filter($all, function ($item) use ($phase) { $phases = array_filter(explode(',', $item['phase'])); return in_array('all', $phases) || in_array($phase, $phases); })); if (count($matched) >= 3 || count($matched) === count($all)) { $all = $matched; } else { $rest = array_values(array_filter($all, function ($item) use ($matched) { return !in_array($item['id'], array_column($matched, 'id')); })); $all = array_merge($matched, $rest); } } $total = count($all); $list = array_slice($all, ($page - 1) * $limit, $limit); $member = MemberService::status($this->auth->id); $list = array_map(function ($item) use ($member) { return [ 'id' => (int)$item['id'], 'type' => $item['type'], 'title' => $item['title'], 'summary' => $item['summary'], 'emoji' => $item['cover_emoji'], 'media_type' => $item['media_type'], 'duration' => (int)$item['duration'], 'duration_text' => $item['duration'] ? floor($item['duration'] / 60) . ' 分钟' : '', 'access' => $item['access'], 'locked' => $item['access'] === 'member' && !$member['is_member'], ]; }, $list); $this->success('', [ 'list' => $list, 'total' => $total, 'page' => $page, 'limit' => $limit, 'has_more' => $page * $limit < $total, 'phase' => $phase, 'category' => $this->categoryList($type), ]); } /** * 内容详情 * GET id=1 */ public function detail() { $id = (int)$this->request->param('id', 0); $item = Db::name('content')->where('id', $id)->where('status', 'normal')->find(); if (!$item) { $this->error('内容不存在'); } $member = MemberService::status($this->auth->id); $locked = $item['access'] === 'member' && !$member['is_member']; $this->success('', [ 'id' => (int)$item['id'], 'type' => $item['type'], 'title' => $item['title'], 'summary' => $item['summary'], 'body' => $locked ? mb_substr($item['body'], 0, 80) . '…' : $item['body'], 'emoji' => $item['cover_emoji'], 'media_type' => $item['media_type'], 'duration' => (int)$item['duration'], 'access' => $item['access'], 'locked' => $locked, 'lock_tip' => $locked ? '该内容为会员专享,开通会员即可查看' : '', 'disclaimer' => $item['type'] === 'advice' || $item['type'] === 'knowledge' ? '以上内容仅供参考,不能替代医疗诊断。' : '', ]); } /** * 分类 */ public function categories() { $type = $this->request->param('type', ''); $query = Db::name('content_category')->where('status', 'normal'); if ($type) { $query->where('type', $type); } $list = $query->order('weigh', 'desc')->select(); $this->success('', ['list' => $list]); } protected function categoryList($type) { if (!$type) { return []; } $list = Db::name('content_category') ->where('type', $type) ->where('status', 'normal') ->order('weigh', 'desc') ->field('id,name') ->select(); return $list; } }