248 lines
8.4 KiB
PHP
248 lines
8.4 KiB
PHP
<?php
|
|
|
|
namespace app\api\controller;
|
|
|
|
use app\common\service\ai\AiService;
|
|
use app\common\model\match\MatchEvent;
|
|
use app\common\model\match\MatchHistory;
|
|
use app\common\model\match\MatchRecent;
|
|
use app\common\model\article\Article;
|
|
use app\common\enum\YesNoEnum;
|
|
use app\common\model\ai\AiUnlock;
|
|
|
|
class AiController extends BaseApiController
|
|
{
|
|
public array $notNeedLogin = ['matchPredict', 'articleAnalysis'];
|
|
|
|
/**
|
|
* 赛事AI预测
|
|
*/
|
|
public function matchPredict()
|
|
{
|
|
$matchId = $this->request->get('match_id/d');
|
|
if (empty($matchId)) {
|
|
return $this->fail('参数缺失');
|
|
}
|
|
|
|
$cacheKey = 'ai_match_predict_' . $matchId;
|
|
$cached = cache($cacheKey);
|
|
if ($cached) {
|
|
$cached['from_cache'] = true;
|
|
return $this->data($cached);
|
|
}
|
|
|
|
$match = MatchEvent::where('id', $matchId)->where('is_show', 1)->findOrEmpty();
|
|
if ($match->isEmpty()) {
|
|
return $this->fail('赛事不存在');
|
|
}
|
|
$data = $match->toArray();
|
|
|
|
$homeTeam = $data['home_team'];
|
|
$awayTeam = $data['away_team'];
|
|
|
|
// 组装分析数据
|
|
$matchData = [
|
|
'match_info' => [
|
|
'home_team' => $homeTeam,
|
|
'away_team' => $awayTeam,
|
|
'league' => $data['league_name'] ?? '',
|
|
'match_time' => date('Y-m-d H:i', $data['match_time'] ?? time()),
|
|
'status' => $data['status'] ?? 0,
|
|
],
|
|
'head_to_head' => MatchHistory::where(function ($query) use ($homeTeam, $awayTeam) {
|
|
$query->where([['home_team', '=', $homeTeam], ['away_team', '=', $awayTeam]])
|
|
->whereOr([['home_team', '=', $awayTeam], ['away_team', '=', $homeTeam]]);
|
|
})->order('match_time desc')->limit(5)->select()->toArray(),
|
|
'home_recent' => MatchRecent::where('team_name', $homeTeam)
|
|
->order('match_time desc')->limit(5)->select()->toArray(),
|
|
'away_recent' => MatchRecent::where('team_name', $awayTeam)
|
|
->order('match_time desc')->limit(5)->select()->toArray(),
|
|
];
|
|
|
|
$result = AiService::predictMatch($matchId, $matchData, $this->userId);
|
|
if (!$result['success']) {
|
|
return $this->fail($result['error'] ?? 'AI分析失败');
|
|
}
|
|
|
|
$responseData = [
|
|
'analysis' => $result['data'],
|
|
'from_cache' => false,
|
|
'match_info' => $matchData['match_info'],
|
|
];
|
|
|
|
cache($cacheKey, $responseData, 6 * 3600);
|
|
|
|
return $this->data($responseData);
|
|
}
|
|
|
|
/**
|
|
* 赛事AI预测 - 分段请求
|
|
*/
|
|
public function matchPredictSection()
|
|
{
|
|
$matchId = $this->request->get('match_id/d');
|
|
$section = $this->request->get('section/s', '');
|
|
if (empty($matchId) || empty($section)) {
|
|
return $this->fail('参数缺失');
|
|
}
|
|
|
|
if (!$this->userId) {
|
|
return $this->fail('请先登录', [], 0, 401);
|
|
}
|
|
|
|
// 解锁检查:只有本人解锁过的才免费,其他人的缓存不算
|
|
$isUnlocked = AiUnlock::isUnlocked($this->userId, $matchId);
|
|
if (!$isUnlocked) {
|
|
if ($section === 'prediction') {
|
|
$unlockResult = AiUnlock::unlock($this->userId, $matchId);
|
|
if (!$unlockResult['ok']) {
|
|
return $this->fail($unlockResult['msg']);
|
|
}
|
|
} else {
|
|
return $this->fail('请先解锁该赛事分析');
|
|
}
|
|
}
|
|
|
|
$match = MatchEvent::where('id', $matchId)->where('is_show', 1)->findOrEmpty();
|
|
if ($match->isEmpty()) {
|
|
return $this->fail('赛事不存在');
|
|
}
|
|
$data = $match->toArray();
|
|
|
|
$homeTeam = $data['home_team'];
|
|
$awayTeam = $data['away_team'];
|
|
|
|
$matchData = [
|
|
'match_info' => [
|
|
'home_team' => $homeTeam,
|
|
'away_team' => $awayTeam,
|
|
'league' => $data['league_name'] ?? '',
|
|
'match_time' => date('Y-m-d H:i', $data['match_time'] ?? time()),
|
|
'status' => $data['status'] ?? 0,
|
|
'home_score' => $data['home_score'] ?? 0,
|
|
'away_score' => $data['away_score'] ?? 0,
|
|
'home_odds' => $data['home_odds'] ?? 0,
|
|
'draw_odds' => $data['draw_odds'] ?? 0,
|
|
'away_odds' => $data['away_odds'] ?? 0,
|
|
],
|
|
'head_to_head' => MatchHistory::where(function ($query) use ($homeTeam, $awayTeam) {
|
|
$query->where([['home_team', '=', $homeTeam], ['away_team', '=', $awayTeam]])
|
|
->whereOr([['home_team', '=', $awayTeam], ['away_team', '=', $homeTeam]]);
|
|
})->order('match_time desc')->limit(5)->select()->toArray(),
|
|
'home_recent' => MatchRecent::where('team_name', $homeTeam)
|
|
->order('match_time desc')->limit(5)->select()->toArray(),
|
|
'away_recent' => MatchRecent::where('team_name', $awayTeam)
|
|
->order('match_time desc')->limit(5)->select()->toArray(),
|
|
];
|
|
|
|
$result = AiService::predictMatchSection($matchId, $section, $matchData, $this->userId);
|
|
if (!$result['success']) {
|
|
return $this->fail($result['error'] ?? 'AI分析失败');
|
|
}
|
|
|
|
return $this->data([
|
|
'section' => $section,
|
|
'data' => $result['data'],
|
|
'from_cache' => $result['from_cache'] ?? false,
|
|
'match_info' => $matchData['match_info'],
|
|
'remain_count' => AiUnlock::getRemainCount($this->userId),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 资讯AI分析
|
|
*/
|
|
public function articleAnalysis()
|
|
{
|
|
$articleId = $this->request->get('article_id/d');
|
|
if (empty($articleId)) {
|
|
return $this->fail('参数缺失');
|
|
}
|
|
|
|
$article = Article::where(['id' => $articleId, 'is_show' => YesNoEnum::YES])->findOrEmpty();
|
|
if ($article->isEmpty()) {
|
|
return $this->fail('文章不存在');
|
|
}
|
|
|
|
$articleData = $article->toArray();
|
|
$result = AiService::analyzeArticle($articleId, $articleData, $this->userId);
|
|
if (!$result['success']) {
|
|
return $this->fail($result['error'] ?? 'AI分析失败');
|
|
}
|
|
return $this->data([
|
|
'analysis' => $result['data'],
|
|
'from_cache' => $result['from_cache'] ?? false,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 用户可信度分析
|
|
*/
|
|
public function userCredibility()
|
|
{
|
|
$targetUserId = $this->request->get('user_id/d');
|
|
if (empty($targetUserId)) {
|
|
return $this->fail('参数缺失');
|
|
}
|
|
|
|
// 组装用户数据(简化版,后续可扩展)
|
|
$userData = [
|
|
'user_id' => $targetUserId,
|
|
'register_days' => 30,
|
|
'post_count' => 0,
|
|
'comment_count' => 0,
|
|
'like_received' => 0,
|
|
];
|
|
|
|
$result = AiService::analyzeCredibility($targetUserId, $userData, $this->userId);
|
|
if (!$result['success']) {
|
|
return $this->fail($result['error'] ?? 'AI分析失败');
|
|
}
|
|
return $this->data([
|
|
'analysis' => $result['data'],
|
|
'from_cache' => $result['from_cache'] ?? false,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 彩票概率分析
|
|
*/
|
|
public function lotteryAnalysis()
|
|
{
|
|
$type = $this->request->get('type', 'ssq');
|
|
|
|
// 简化版彩票数据
|
|
$lotteryData = [
|
|
'lottery_type' => $type,
|
|
'recent_draws' => [],
|
|
'description' => $type === 'ssq' ? '双色球' : '大乐透',
|
|
];
|
|
|
|
$result = AiService::analyzeLottery($lotteryData, $this->userId);
|
|
if (!$result['success']) {
|
|
return $this->fail($result['error'] ?? 'AI分析失败');
|
|
}
|
|
return $this->data([
|
|
'analysis' => $result['data'],
|
|
'from_cache' => $result['from_cache'] ?? false,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 查询比赛解锁状态
|
|
*/
|
|
public function checkUnlock()
|
|
{
|
|
$matchId = $this->request->get('match_id/d');
|
|
if (empty($matchId)) {
|
|
return $this->fail('参数缺失');
|
|
}
|
|
$unlocked = $this->userId ? AiUnlock::isUnlocked($this->userId, $matchId) : false;
|
|
$remain = $this->userId ? AiUnlock::getRemainCount($this->userId) : 0;
|
|
return $this->data([
|
|
'unlocked' => $unlocked,
|
|
'remain_count' => $remain,
|
|
]);
|
|
}
|
|
}
|