query("SELECT COUNT(*) FROM movies"); $stats['total_movies'] = $stmt->fetchColumn(); $stmt = $db->query("SELECT COUNT(*) FROM cinemas"); $stats['total_cinemas'] = $stmt->fetchColumn(); $stmt = $db->query("SELECT COUNT(*) FROM persons"); $stats['total_persons'] = $stmt->fetchColumn(); $stmt = $db->query("SELECT COUNT(*) FROM viewers"); $stats['total_viewership'] = $stmt->fetchColumn(); $stmt = $db->query("SELECT MIN(watch_date) as first, MAX(watch_date) as last FROM movies WHERE watch_date IS NOT NULL"); $row = $stmt->fetch(); $stats['first_date'] = $row['first']; $stats['last_date'] = $row['last']; return $stats; } function statsByCinema() { $db = getDB(); $stmt = $db->query(" SELECT c.id, c.name, c.color, COUNT(m.id) as count FROM cinemas c LEFT JOIN movies m ON c.id = m.cinema_id GROUP BY c.id ORDER BY count DESC "); return $stmt->fetchAll(); } function statsByPerson() { $db = getDB(); $stmt = $db->query(" SELECT p.id, p.name, p.color, p.avatar, COUNT(v.movie_id) as count FROM persons p LEFT JOIN viewers v ON p.id = v.person_id GROUP BY p.id ORDER BY count DESC "); return $stmt->fetchAll(); } function statsByMonth($limit = 12) { $db = getDB(); $stmt = $db->prepare(" SELECT strftime('%Y-%m', watch_date) as month, COUNT(*) as count FROM movies WHERE watch_date IS NOT NULL GROUP BY month ORDER BY month DESC LIMIT ? "); $stmt->execute([$limit]); return $stmt->fetchAll(); } function statsByYear() { $db = getDB(); $stmt = $db->query(" SELECT strftime('%Y', watch_date) as year, COUNT(*) as count FROM movies WHERE watch_date IS NOT NULL GROUP BY year ORDER BY year DESC "); return $stmt->fetchAll(); } // ===== 年度报告 ===== function getAnnualStats($year) { $db = getDB(); $stats = []; // 获取当前管理员 $admin = getCurrentAdmin(); $self_person_id = $admin['person_id'] ?? null; $stats['self_person_name'] = $admin['person_name'] ?? null; $stats['self_person_avatar'] = $admin['person_avatar'] ?? null; if (!$self_person_id) { // 未关联观影人,返回空数据 $stats['total'] = 0; $stats['days'] = 0; $stats['top_cinema'] = '无'; $stats['top_cinema_count'] = 0; $stats['top_person'] = '无'; $stats['top_person_count'] = 0; $stats['first_date'] = null; $stats['last_date'] = null; $stats['most_viewers_movie'] = '无'; $stats['most_viewers_count'] = 0; $stats['month_distribution'] = array_fill(1, 12, 0); $stats['weekday_distribution'] = ['日'=>0,'一'=>0,'二'=>0,'三'=>0,'四'=>0,'五'=>0,'六'=>0]; $stats['avg_per_month'] = 0; $stats['avg_days_between'] = 0; $stats['keywords'] = []; $stats['recent_movies'] = []; $stats['my_movies'] = []; $stats['common_viewers'] = []; return $stats; } // 1. 总观影数(当前用户参与的电影) $stmt = $db->prepare(" SELECT COUNT(DISTINCT m.id) FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? "); $stmt->execute([$year, $self_person_id]); $stats['total'] = (int)$stmt->fetchColumn(); // 2. 观影天数 $stmt = $db->prepare(" SELECT COUNT(DISTINCT m.watch_date) FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? AND m.watch_date IS NOT NULL "); $stmt->execute([$year, $self_person_id]); $stats['days'] = (int)$stmt->fetchColumn(); // 3. 最常去的影院 $stmt = $db->prepare(" SELECT c.name, COUNT(m.id) as count FROM movies m JOIN viewers v ON m.id = v.movie_id LEFT JOIN cinemas c ON m.cinema_id = c.id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? AND m.cinema_id IS NOT NULL GROUP BY m.cinema_id ORDER BY count DESC LIMIT 1 "); $stmt->execute([$year, $self_person_id]); $top_cinema = $stmt->fetch(); $stats['top_cinema'] = $top_cinema ? $top_cinema['name'] : '无'; $stats['top_cinema_count'] = $top_cinema ? (int)$top_cinema['count'] : 0; // 4. 最常一起观影的人(与当前用户同场最多的人) // 先获取当前用户看过的所有电影ID $stmt = $db->prepare(" SELECT DISTINCT m.id FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? "); $stmt->execute([$year, $self_person_id]); $movie_ids = $stmt->fetchAll(PDO::FETCH_COLUMN); // 共同观影人统计 $common_viewers = []; if (!empty($movie_ids)) { $placeholders = implode(',', array_fill(0, count($movie_ids), '?')); $params = array_merge($movie_ids, [$self_person_id]); $stmt = $db->prepare(" SELECT p.id, p.name, p.avatar, COUNT(*) as count FROM viewers v JOIN persons p ON v.person_id = p.id WHERE v.movie_id IN ($placeholders) AND v.person_id != ? GROUP BY v.person_id ORDER BY count DESC "); $stmt->execute($params); $common_viewers = $stmt->fetchAll(); } $stats['common_viewers'] = $common_viewers; // 最常一起观影的人(取第一个) $stats['top_person'] = !empty($common_viewers) ? $common_viewers[0]['name'] : '无'; $stats['top_person_count'] = !empty($common_viewers) ? (int)$common_viewers[0]['count'] : 0; // 5. 最早和最晚日期 $stmt = $db->prepare(" SELECT MIN(m.watch_date) as first, MAX(m.watch_date) as last FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? AND m.watch_date IS NOT NULL "); $stmt->execute([$year, $self_person_id]); $row = $stmt->fetch(); $stats['first_date'] = $row['first']; $stats['last_date'] = $row['last']; // 6. 单次最多人的电影(当前用户参与的电影中) $stmt = $db->prepare(" SELECT m.id, m.title, COUNT(v.id) as viewer_count FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND m.id IN (SELECT movie_id FROM viewers WHERE person_id = ?) GROUP BY m.id ORDER BY viewer_count DESC LIMIT 1 "); $stmt->execute([$year, $self_person_id]); $most_viewers = $stmt->fetch(); $stats['most_viewers_movie'] = $most_viewers ? $most_viewers['title'] : '无'; $stats['most_viewers_count'] = $most_viewers ? (int)$most_viewers['viewer_count'] : 0; // 7. 月份分布 $stmt = $db->prepare(" SELECT strftime('%m', m.watch_date) as month, COUNT(*) as count FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? AND m.watch_date IS NOT NULL GROUP BY month ORDER BY month "); $stmt->execute([$year, $self_person_id]); $month_data = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); $stats['month_distribution'] = []; for ($m=1; $m<=12; $m++) { $key = str_pad($m, 2, '0', STR_PAD_LEFT); $stats['month_distribution'][$m] = isset($month_data[$key]) ? (int)$month_data[$key] : 0; } // 8. 星期分布 $stmt = $db->prepare(" SELECT strftime('%w', m.watch_date) as wday, COUNT(*) as count FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? AND m.watch_date IS NOT NULL GROUP BY wday ORDER BY wday "); $stmt->execute([$year, $self_person_id]); $wday_data = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); $weekdays = ['日','一','二','三','四','五','六']; $stats['weekday_distribution'] = []; foreach ($weekdays as $idx => $name) { $stats['weekday_distribution'][$name] = isset($wday_data[$idx]) ? (int)$wday_data[$idx] : 0; } // 9. 月均和频率 $stats['avg_per_month'] = $stats['total'] > 0 ? round($stats['total'] / 12, 1) : 0; $stats['avg_days_between'] = $stats['total'] > 0 ? round(365 / $stats['total'], 1) : 0; // 10. 关键词(基于当前用户电影的备注) $stmt = $db->prepare(" SELECT m.remark FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? AND m.remark IS NOT NULL AND m.remark != '' "); $stmt->execute([$year, $self_person_id]); $remarks = $stmt->fetchAll(PDO::FETCH_COLUMN); $word_count = []; foreach ($remarks as $text) { $words = preg_split('/[\s,,。.!!??、;;::]+/', $text, -1, PREG_SPLIT_NO_EMPTY); foreach ($words as $w) { $w = trim($w); if (mb_strlen($w) >= 2) { if (!isset($word_count[$w])) $word_count[$w] = 0; $word_count[$w]++; } } } arsort($word_count); $stats['keywords'] = array_slice(array_keys($word_count), 0, 5); // 11. 最近5部(当前用户参与的) $stmt = $db->prepare(" SELECT DISTINCT m.title FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? ORDER BY m.watch_date DESC LIMIT 5 "); $stmt->execute([$year, $self_person_id]); $stats['recent_movies'] = $stmt->fetchAll(PDO::FETCH_COLUMN); // 12. 我的观影记录(含海报) $stmt = $db->prepare(" SELECT m.id, m.title, m.watch_date, m.poster_path FROM movies m JOIN viewers v ON m.id = v.movie_id WHERE strftime('%Y', m.watch_date) = ? AND v.person_id = ? GROUP BY m.id ORDER BY m.watch_date DESC "); $stmt->execute([$year, $self_person_id]); $movie_list = $stmt->fetchAll(); // 对每个电影查询一起观影的人(含头像) foreach ($movie_list as &$movie) { $stmt2 = $db->prepare(" SELECT p.id, p.name, p.avatar FROM viewers v LEFT JOIN persons p ON v.person_id = p.id WHERE v.movie_id = ? AND v.person_id != ? "); $stmt2->execute([$movie['id'], $self_person_id]); $movie['viewers'] = $stmt2->fetchAll(); } $stats['my_movies'] = $movie_list; return $stats; } function getYearsWithData() { $db = getDB(); $stmt = $db->query("SELECT DISTINCT strftime('%Y', watch_date) as year FROM movies WHERE watch_date IS NOT NULL ORDER BY year DESC"); return $stmt->fetchAll(PDO::FETCH_COLUMN); }