wewe / templates /index.html
mistpe's picture
Update templates/index.html
251d559 verified
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>电影信息管理系统</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
<h1 class="text-4xl font-bold mb-8 text-center text-blue-600">电影信息管理系统</h1>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow duration-300">
<h2 class="text-xl font-semibold mb-4 text-blue-500">评分最高的电影</h2>
<div id="highest-rated-movie" class="text-gray-700"></div>
</div>
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow duration-300">
<h2 class="text-xl font-semibold mb-4 text-blue-500">票房最高的电影</h2>
<div id="highest-grossing-movie" class="text-gray-700"></div>
</div>
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow duration-300">
<h2 class="text-xl font-semibold mb-4 text-blue-500">电影年份分布</h2>
<canvas id="movies-by-year-chart"></canvas>
</div>
</div>
<div class="bg-white rounded-lg shadow-md p-6 mb-8 hover:shadow-lg transition-shadow duration-300">
<h2 class="text-2xl font-semibold mb-4 text-blue-500">电影数据分析</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="flex flex-col items-center">
<h3 class="text-lg font-semibold mb-2 text-gray-700">类型分布</h3>
<div style="width: 300px; height: 300px;">
<canvas id="genre-distribution-chart"></canvas>
</div>
</div>
<div class="flex flex-col items-center">
<h3 class="text-lg font-semibold mb-2 text-gray-700">评分与票房关系</h3>
<div style="width: 100%; height: 300px;">
<canvas id="rating-boxoffice-chart"></canvas>
</div>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow-md p-6 mb-8 hover:shadow-lg transition-shadow duration-300">
<h2 class="text-2xl font-semibold mb-4 text-blue-500">电影搜索和筛选</h2>
<div class="flex flex-wrap gap-4 mb-4">
<input id="search-input" type="text" placeholder="搜索电影..." class="p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-400">
<select id="genre-filter" class="p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-400">
<option value="">所有类型</option>
</select>
<select id="year-filter" class="p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-400">
<option value="">所有年份</option>
</select>
<select id="language-filter" class="p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-400">
<option value="">所有语言</option>
</select>
<select id="sort-by" class="p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-400">
<option value="year">年份</option>
<option value="rating">评分</option>
<option value="box_office">票房</option>
</select>
<select id="sort-order" class="p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-400">
<option value="desc">降序</option>
<option value="asc">升序</option>
</select>
<button id="apply-filters" class="bg-blue-500 text-white p-2 rounded hover:bg-blue-600 transition-colors duration-300">应用筛选</button>
</div>
</div>
<div class="mt-8">
<h2 class="text-2xl font-semibold mb-4 text-blue-500">电影列表</h2>
<div id="movie-list" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"></div>
</div>
</div>
<script>
let allMovies = [];
async function fetchData() {
try {
const [movies, highestRated, highestGrossing, genres, languages] = await Promise.all([
axios.get('/api/movies'),
axios.get('/api/highest-rated'),
axios.get('/api/highest-grossing'),
axios.get('/api/genres'),
axios.get('/api/languages')
]);
allMovies = movies.data;
displayHighestRated(highestRated.data);
displayHighestGrossing(highestGrossing.data);
displayMoviesByYearChart(allMovies);
displayGenreDistributionChart(allMovies);
displayRatingBoxOfficeChart(allMovies);
populateFilters(genres.data, languages.data);
displayAllMovies(allMovies);
} catch (error) {
console.error('Error fetching data:', error);
alert('加载数据时出错,请刷新页面重试。');
}
}
function displayHighestRated(movie) {
document.getElementById('highest-rated-movie').innerHTML = `
<p class="font-semibold">${movie.title} (${movie.year}年)</p>
<p>评分: ${movie.rating}</p>
<p>导演: ${movie.director}</p>
`;
}
function displayHighestGrossing(movie) {
document.getElementById('highest-grossing-movie').innerHTML = `
<p class="font-semibold">${movie.title} (${movie.year}年)</p>
<p>票房: ${movie.box_office}百万美元</p>
<p>导演: ${movie.director}</p>
`;
}
function displayMoviesByYearChart(movies) {
const years = movies.map(movie => movie.year);
const counts = {};
years.forEach(year => counts[year] = (counts[year] || 0) + 1);
const ctx = document.getElementById('movies-by-year-chart').getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: Object.keys(counts).sort(),
datasets: [{
label: '电影数量',
data: Object.keys(counts).sort().map(year => counts[year]),
backgroundColor: 'rgba(59, 130, 246, 0.6)'
}]
},
options: {
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 1
}
}
}
}
});
}
function displayGenreDistributionChart(movies) {
const genres = movies.map(movie => movie.genre);
const counts = {};
genres.forEach(genre => counts[genre] = (counts[genre] || 0) + 1);
const ctx = document.getElementById('genre-distribution-chart').getContext('2d');
new Chart(ctx, {
type: 'pie',
data: {
labels: Object.keys(counts),
datasets: [{
data: Object.values(counts),
backgroundColor: [
'#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF',
'#FF9F40', '#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0'
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
labels: {
boxWidth: 12
}
}
}
}
});
}
function displayRatingBoxOfficeChart(movies) {
const ctx = document.getElementById('rating-boxoffice-chart').getContext('2d');
new Chart(ctx, {
type: 'scatter',
data: {
datasets: [{
label: '评分 vs 票房',
data: movies.map(movie => ({
x: movie.rating,
y: movie.box_office
})),
backgroundColor: 'rgba(59, 130, 246, 0.6)'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
title: {
display: true,
text: '评分'
},
min: 5,
max: 10
},
y: {
title: {
display: true,
text: '票房 (百万美元)'
},
min: 0
}
}
}
});
}
function populateFilters(genres, languages) {
const yearFilter = document.getElementById('year-filter');
const genreFilter = document.getElementById('genre-filter');
const languageFilter = document.getElementById('language-filter');
const years = [...new Set(allMovies.map(movie => movie.year))].sort((a, b) => b - a);
years.forEach(year => {
const option = document.createElement('option');
option.value = year;
option.textContent = year;
yearFilter.appendChild(option);
});
genres.forEach(genre => {
const option = document.createElement('option');
option.value = genre;
option.textContent = genre;
genreFilter.appendChild(option);
});
languages.forEach(language => {
const option = document.createElement('option');
option.value = language;
option.textContent = language;
languageFilter.appendChild(option);
});
}
function displayAllMovies(movies) {
const movieList = document.getElementById('movie-list');
movieList.innerHTML = movies.map(movie => `
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow duration-300">
<h3 class="text-lg font-semibold mb-2 text-blue-500">${movie.title} (${movie.year}年)</h3>
<p><span class="font-semibold">导演:</span> ${movie.director}</p>
<p><span class="font-semibold">类型:</span> ${movie.genre}</p>
<p><span class="font-semibold">评分:</span> ${movie.rating}</p>
<p><span class="font-semibold">时长:</span> ${movie.duration}分钟</p>
<p><span class="font-semibold">票房:</span> ${movie.box_office}百万美元</p>
<p><span class="font-semibold">语言:</span> ${movie.language}</p>
</div>
`).join('');
}
async function applyFilters() {
const searchQuery = document.getElementById('search-input').value;
const genre = document.getElementById('genre-filter').value;
const year = document.getElementById('year-filter').value;
const language = document.getElementById('language-filter').value;
const sortBy = document.getElementById('sort-by').value;
const sortOrder = document.getElementById('sort-order').value;
try {
const response = await axios.get('/api/movies/filter', {
params: { genre, year, language }
});
let filteredMovies = response.data;
if (searchQuery) {
filteredMovies = filteredMovies.filter(movie =>
movie.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
movie.director.toLowerCase().includes(searchQuery.toLowerCase())
);
}
filteredMovies.sort((a, b) => {
const valueA = a[sortBy];
const valueB = b[sortBy];
if (sortOrder === 'asc') {
return valueA > valueB ? 1 : -1;
} else {
return valueA < valueB ? 1 : -1;
}
});
displayAllMovies(filteredMovies);
} catch (error) {
console.error('Error applying filters:', error);
alert('应用筛选时出错,请重试。');
}
}
document.getElementById('apply-filters').addEventListener('click', applyFilters);
fetchData();
</script>
</body>
</html>