request->param('q', ''); $page = $this->request->param('page/d', 1); $limit = 20; if ($this->request->isAjax() || $this->request->param('ajax/d', 0)) { $data = LinksModel::search($q, $page, $limit); $this->result->setCount($data->total()); $this->result->success($data->items()); } $results = []; if ($q !== '') { $results = LinksModel::search($q, 1, 50)->items(); } $this->view->assign('q', $q); $this->view->assign('results', $results); $this->view->assign('config', $this->siteConfig()); $this->assignSeo(); return $this->view->fetch('search'); } /** * 搜索建议(自动补全) * 标题/关键词/网址/拼音(首字母+全拼)均可命中 */ public function suggest() { $q = trim((string)$this->request->param('q', '')); $list = []; if ($q !== '') { $isAlpha = (bool)preg_match('/^[a-zA-Z]+$/', $q); $list = LinksModel::where('status', 1) ->where(function ($query) use ($q, $isAlpha) { $query->where('title', 'like', "%{$q}%") ->whereOr('keywords', 'like', "%{$q}%") ->whereOr('url', 'like', "%{$q}%"); if ($isAlpha) { $query->whereOr('pinyin', 'like', '%' . strtolower($q) . '%'); } }) ->field('id,title,url') ->order('click_count', 'desc') ->limit(10) ->select(); } return $this->result->success($list); } /** * 网站评分(登录后 1-5 星,按用户去重可改分;聚合更新综合评分) * POST /haonav/rate {id, score} */ public function rate() { if (!$this->request->isPost()) { return $this->result->error('请求方式错误'); } $uid = $this->uid(); if (!$uid) { return $this->result->error('请先登录后再评分', 401); } $id = (int)$this->request->post('id/d', 0); $score = (int)$this->request->post('score/d', 0); if ($id <= 0 || $score < 1 || $score > 5) { return $this->result->error('参数错误'); } $link = LinksModel::find($id); if (!$link || $link->status != 1) { return $this->result->error('网站不存在或已下架'); } // 评分记录表由安装/升级流程(install.sql + Addon::upgrade 钩子)保证存在 $now = time(); $exists = Db::name('haonav_ratings')->where('user_id', $uid)->where('link_id', $id)->find(); if ($exists) { Db::name('haonav_ratings')->where('id', $exists['id'])->update([ 'score' => $score, 'update_at' => $now, ]); } else { Db::name('haonav_ratings')->insert([ 'user_id' => $uid, 'link_id' => $id, 'score' => $score, 'create_at' => $now, 'update_at' => $now, ]); } // 重新聚合该站评分,保证 rating / rating_count 精确 $agg = Db::name('haonav_ratings') ->where('link_id', $id) ->field('AVG(score) as avg_score, COUNT(*) as cnt') ->find(); $rating = ($agg && $agg['cnt']) ? round((float)$agg['avg_score'], 1) : 0.0; $count = $agg ? (int)$agg['cnt'] : 0; LinksModel::where('id', $id)->update([ 'rating' => $rating, 'rating_count' => $count, ]); return $this->result->success([ 'rating' => $rating, 'rating_count' => $count, 'my_score' => $score, ], '评分成功'); } }