本文目录导读:

- 项目结构
- 数据库结构 (database.sql)
- 配置文件 (config.php)
- 主页面 (index.php)
- 添加数据处理 (add_defense.php)
- 样式文件 (style.css)
- JavaScript (js/script.js)
- 使用方法
我可以帮你设计一个显示人盯人防守成功率的PHP项目,让我创建一个完整的示例:
项目结构
basketball-defense/
├── index.php # 主页面
├── config.php # 数据库配置
├── style.css # 样式文件
├── js/script.js # JavaScript文件
└── database.sql # 数据库结构
数据库结构 (database.sql)
CREATE DATABASE IF NOT EXISTS basketball_stats;
USE basketball_stats;
-- 球员表
CREATE TABLE players (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
position VARCHAR(20),
team VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 防守数据表
CREATE TABLE defense_stats (
id INT PRIMARY KEY AUTO_INCREMENT,
player_id INT,
match_date DATE,
opponent_player VARCHAR(50),
defensive_attempts INT DEFAULT 0, -- 防守次数
successful_defenses INT DEFAULT 0, -- 成功防守次数
blocks INT DEFAULT 0, -- 盖帽数
steals INT DEFAULT 0, -- 抢断数
fouls INT DEFAULT 0, -- 犯规数
FOREIGN KEY (player_id) REFERENCES players(id)
);
-- 示例数据
INSERT INTO players (name, position, team) VALUES
('张三', '后卫', '雷霆队'),
('李四', '前锋', '雷霆队'),
('王五', '中锋', '雷霆队'),
('赵六', '后卫', '勇士队');
INSERT INTO defense_stats (player_id, match_date, opponent_player, defensive_attempts, successful_defenses, blocks, steals, fouls) VALUES
(1, '2024-01-15', '库里', 12, 8, 1, 2, 3),
(1, '2024-01-20', '詹姆斯', 15, 10, 2, 1, 2),
(2, '2024-01-15', '杜兰特', 10, 6, 1, 1, 4),
(2, '2024-01-20', '字母哥', 14, 9, 3, 0, 2),
(3, '2024-01-15', '约基奇', 18, 12, 4, 1, 3),
(3, '2024-01-20', '恩比德', 16, 11, 3, 0, 2);
配置文件 (config.php)
<?php
session_start();
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'basketball_stats');
// 连接数据库
function dbConnect() {
try {
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) {
throw new Exception("连接失败: " . $conn->connect_error);
}
$conn->set_charset("utf8mb4");
return $conn;
} catch (Exception $e) {
die("数据库连接错误: " . $e->getMessage());
}
}
// 计算防守成功率
function calculateDefenseRate($successful, $attempts) {
if ($attempts <= 0) return 0;
return round(($successful / $attempts) * 100, 2);
}
// 获取球员防守统计数据
function getPlayerDefenseStats($playerId = null) {
$conn = dbConnect();
$where = $playerId ? "WHERE p.id = $playerId" : "";
$sql = "SELECT
p.id,
p.name,
p.position,
p.team,
COUNT(ds.id) as matches_played,
SUM(ds.defensive_attempts) as total_attempts,
SUM(ds.successful_defenses) as total_successful,
SUM(ds.blocks) as total_blocks,
SUM(ds.steals) as total_steals,
SUM(ds.fouls) as total_fouls,
AVG(ds.defensive_attempts) as avg_attempts_per_match,
AVG(ds.successful_defenses) as avg_successful_per_match
FROM players p
LEFT JOIN defense_stats ds ON p.id = ds.player_id
$where
GROUP BY p.id
ORDER BY (SUM(ds.successful_defenses)/NULLIF(SUM(ds.defensive_attempts),0)) DESC";
$result = $conn->query($sql);
$stats = [];
if ($result) {
while ($row = $result->fetch_assoc()) {
// 计算防守成功率
$row['defense_rate'] = calculateDefenseRate(
$row['total_successful'],
$row['total_attempts']
);
// 计算场均防守效率评分
$row['defense_rating'] = calculateDefenseRating($row);
$stats[] = $row;
}
}
$conn->close();
return $stats;
}
// 计算防守效率评分 (综合评分)
function calculateDefenseRating($stats) {
$rate = $stats['defense_rate'];
$blocks_effect = ($stats['total_blocks'] ?? 0) * 2;
$steals_effect = ($stats['total_steals'] ?? 0) * 1.5;
$fouls_penalty = ($stats['total_fouls'] ?? 0) * -0.5;
return round($rate + $blocks_effect + $steals_effect + $fouls_penalty, 2);
}
?>
主页面 (index.php)
<?php
require_once 'config.php';
// 获取筛选参数
$selectedPlayer = isset($_GET['player_id']) ? $_GET['player_id'] : null;
$dateFrom = isset($_GET['date_from']) ? $_GET['date_from'] : '';
$dateTo = isset($_GET['date_to']) ? $_GET['date_to'] : '';
// 获取统计数据
$stats = getPlayerDefenseStats($selectedPlayer);
// 获取所有球员用于筛选
$conn = dbConnect();
$players = $conn->query("SELECT id, name FROM players ORDER BY name");
$conn->close();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">人盯人防守成功率分析系统</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<header>
<h1>🏀 人盯人防守成功率分析</h1>
<p class="subtitle">实时监控球队防守表现</p>
</header>
<nav class="filter-section">
<form method="GET" action="index.php" class="filter-form">
<div class="filter-group">
<label>球员筛选:</label>
<select name="player_id">
<option value="">全部球员</option>
<?php while($player = $players->fetch_assoc()): ?>
<option value="<?php echo $player['id']; ?>"
<?php echo $selectedPlayer == $player['id'] ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($player['name']); ?>
</option>
<?php endwhile; ?>
</select>
</div>
<div class="filter-group">
<label>开始日期:</label>
<input type="date" name="date_from" value="<?php echo $dateFrom; ?>">
</div>
<div class="filter-group">
<label>结束日期:</label>
<input type="date" name="date_to" value="<?php echo $dateTo; ?>">
</div>
<button type="submit" class="btn-filter">筛选数据</button>
<a href="index.php" class="btn-reset">重置</a>
</form>
</nav>
<!-- 数据总览卡片 -->
<div class="summary-cards">
<?php
$avgRate = count($stats) > 0 ? array_sum(array_column($stats, 'defense_rate')) / count($stats) : 0;
$totalBlocks = array_sum(array_column($stats, 'total_blocks'));
$totalSteals = array_sum(array_column($stats, 'total_steals'));
?>
<div class="card">
<div class="card-icon">📊</div>
<div class="card-value"><?php echo round($avgRate, 1); ?>%</div>
<div class="card-label">平均防守成功率</div>
</div>
<div class="card">
<div class="card-icon">🛡️</div>
<div class="card-value"><?php echo $totalBlocks; ?></div>
<div class="card-label">总盖帽数</div>
</div>
<div class="card">
<div class="card-icon">✋</div>
<div class="card-value"><?php echo $totalSteals; ?></div>
<div class="card-label">总抢断数</div>
</div>
<div class="card">
<div class="card-icon">🎯</div>
<div class="card-value"><?php echo count($stats); ?></div>
<div class="card-label">球员数量</div>
</div>
</div>
<!-- 主要数据表格 -->
<div class="table-container">
<h2>球员防守统计排名</h2>
<table>
<thead>
<tr>
<th>排名</th>
<th>球员</th>
<th>位置</th>
<th>球队</th>
<th>场次</th>
<th>防守次数</th>
<th>成功防守</th>
<th>成功率</th>
<th>盖帽</th>
<th>抢断</th>
<th>犯规</th>
<th>防守评分</th>
<th>表现</th>
</tr>
</thead>
<tbody>
<?php $rank = 1; foreach($stats as $stat): ?>
<tr>
<td>
<span class="rank <?php echo $rank <= 3 ? 'top-3' : ''; ?>">
<?php echo $rank; ?>
</span>
</td>
<td><?php echo htmlspecialchars($stat['name']); ?></td>
<td><?php echo htmlspecialchars($stat['position']); ?></td>
<td><?php echo htmlspecialchars($stat['team']); ?></td>
<td><?php echo $stat['matches_played']; ?></td>
<td><?php echo $stat['total_attempts']; ?></td>
<td><?php echo $stat['total_successful']; ?></td>
<td class="rate-cell">
<div class="progress-wrapper">
<div class="progress-bar" style="width: <?php echo $stat['defense_rate']; ?>%;"></div>
<span><?php echo $stat['defense_rate']; ?>%</span>
</div>
</td>
<td><?php echo $stat['total_blocks']; ?></td>
<td><?php echo $stat['total_steals']; ?></td>
<td><?php echo $stat['total_fouls']; ?></td>
<td class="rating-cell">
<?php echo $stat['defense_rating']; ?>
<?php
$ratingClass = $stat['defense_rating'] > 70 ? 'excellent' : ($stat['defense_rating'] > 50 ? 'good' : 'needs-improvement');
?>
<div class="rating-dot <?php echo $ratingClass; ?>"></div>
</td>
<td>
<?php
$performance = $stat['defense_rating'] > 70 ? '🎖️' : ($stat['defense_rating'] > 50 ? '💪' : '📝');
echo $performance;
?>
</td>
</tr>
<?php $rank++; endforeach; ?>
</tbody>
</table>
</div>
<!-- 添加新数据的表单 -->
<div class="data-entry-section">
<h2>添加防守数据</h2>
<form method="POST" action="add_defense.php" class="data-form">
<div class="form-grid">
<div class="form-group">
<label>球员</label>
<select name="player_id" required>
<option value="">选择球员...</option>
<?php
$conn = dbConnect();
$playersList = $conn->query("SELECT id, name FROM players ORDER BY name");
while($p = $playersList->fetch_assoc()):
?>
<option value="<?php echo $p['id']; ?>"><?php echo $p['name']; ?></option>
<?php endwhile; ?>
</select>
</div>
<div class="form-group">
<label>对手球员</label>
<input type="text" name="opponent_player" required>
</div>
<div class="form-group">
<label>比赛日期</label>
<input type="date" name="match_date" required>
</div>
<div class="form-group">
<label>防守次数</label>
<input type="number" name="defensive_attempts" min="0" required>
</div>
<div class="form-group">
<label>成功防守次数</label>
<input type="number" name="successful_defenses" min="0" required>
</div>
<div class="form-group">
<label>盖帽数</label>
<input type="number" name="blocks" min="0" value="0">
</div>
<div class="form-group">
<label>抢断数</label>
<input type="number" name="steals" min="0" value="0">
</div>
<div class="form-group">
<label>犯规数</label>
<input type="number" name="fouls" min="0" value="0">
</div>
</div>
<button type="submit" class="btn-submit">提交数据</button>
</form>
</div>
</div>
<script src="js/script.js"></script>
</body>
</html>
添加数据处理 (add_defense.php)
<?php
require_once 'config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$player_id = $_POST['player_id'];
$opponent_player = $_POST['opponent_player'];
$match_date = $_POST['match_date'];
$defensive_attempts = $_POST['defensive_attempts'];
$successful_defenses = $_POST['successful_defenses'];
$blocks = $_POST['blocks'];
$steals = $_POST['steals'];
$fouls = $_POST['fouls'];
// 验证数据
if ($successful_defenses > $defensive_attempts) {
header('Location: index.php?error=successful_defenses_exceed');
exit;
}
$conn = dbConnect();
$sql = "INSERT INTO defense_stats
(player_id, opponent_player, match_date, defensive_attempts, successful_defenses, blocks, steals, fouls)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("issiiiii", $player_id, $opponent_player, $match_date, $defensive_attempts, $successful_defenses, $blocks, $steals, $fouls);
if ($stmt->execute()) {
header('Location: index.php?success=1');
} else {
header('Location: index.php?error=db_error');
}
$stmt->close();
$conn->close();
}
?>
样式文件 (style.css)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
background: #fff;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
overflow: hidden;
}
header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 30px;
text-align: center;
}
header h1 {
font-size: 2.5em;
margin-bottom: 10px;
}
{
opacity: 0.9;
font-size: 1.2em;
}
/* 筛选区域 */
.filter-section {
background: #f8f9fa;
padding: 20px;
border-bottom: 1px solid #dee2e6;
}
.filter-form {
display: flex;
flex-wrap: wrap;
gap: 15px;
align-items: flex-end;
}
.filter-group {
display: flex;
flex-direction: column;
gap: 5px;
}
.filter-group label {
font-weight: bold;
color: #495057;
font-size: 14px;
}
.filter-group select,
.filter-group input {
padding: 8px 12px;
border: 1px solid #ced4da;
border-radius: 5px;
font-size: 14px;
}
/* 统计卡片 */
.summary-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
padding: 30px;
background: #f8f9fa;
}
.card {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
text-align: center;
transition: transform 0.3s;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 12px rgba(0,0,0,0.15);
}
.card-icon {
font-size: 2.5em;
margin-bottom: 10px;
}
.card-value {
font-size: 2em;
font-weight: bold;
color: #667eea;
}
.card-label {
color: #6c757d;
font-size: 14px;
margin-top: 5px;
}
/* 表格样式 */
.table-container {
padding: 30px;
}
.table-container h2 {
margin-bottom: 20px;
color: #343a40;
}
table {
width: 100%;
border-collapse: collapse;
background: white;
}
th {
background: #667eea;
color: white;
padding: 12px;
text-align: left;
font-size: 14px;
white-space: nowrap;
}
td {
padding: 10px;
border-bottom: 1px solid #dee2e6;
font-size: 14px;
}
tr:hover {
background-color: #f8f9fa;
}
.rank {
display: inline-block;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
border-radius: 50%;
background: #e9ecef;
color: #343a40;
font-weight: bold;
}
.rank.top-3 {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
color: white;
}
/* 进度条 */
.progress-wrapper {
width: 150px;
height: 20px;
background: #e9ecef;
border-radius: 10px;
position: relative;
overflow: hidden;
}
.progress-bar {
height: 100%;
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
border-radius: 10px;
transition: width 0.3s;
}
.progress-wrapper span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 12px;
font-weight: bold;
color: white;
text-shadow: 1px 1px 2px rgba(0,0,0,0.3);
}
/* 评分 */
.rating-cell {
position: relative;
}
.rating-dot {
position: absolute;
top: 5px;
right: 5px;
width: 10px;
height: 10px;
border-radius: 50%;
}
.rating-dot.excellent {
background: #28a745;
animation: pulse 1s infinite;
}
.rating-dot.good {
background: #ffc107;
}
.rating-dot.needs-improvement {
background: #dc3545;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.3); }
100% { transform: scale(1); }
}
/* 添加数据表单 */
.data-entry-section {
padding: 30px;
background: #f8f9fa;
border-top: 1px solid #dee2e6;
}
.data-entry-section h2 {
margin-bottom: 20px;
color: #343a40;
}
.data-form {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 5px;
}
.form-group label {
font-weight: bold;
color: #495057;
}
.form-group input,
.form-group select {
padding: 8px 12px;
border: 1px solid #ced4da;
border-radius: 5px;
}
.btn-submit,
.btn-filter {
background: #667eea;
color: white;
padding: 12px 24px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
transition: background 0.3s;
}
.btn-submit:hover,
.btn-filter:hover {
background: #5a67d8;
}
.btn-reset {
background: #6c757d;
color: white;
padding: 12px 24px;
border: none;
border-radius: 5px;
text-decoration: none;
}
/* 响应式设计 */
@media (max-width: 768px) {
.filter-form {
flex-direction: column;
}
.summary-cards {
grid-template-columns: repeat(2, 1fr);
padding: 15px;
}
.table-container {
padding: 15px;
overflow-x: auto;
}
.data-entry-section {
padding: 15px;
}
.form-grid {
grid-template-columns: 1fr;
}
}
JavaScript (js/script.js)
// 数据过滤和交互逻辑
document.addEventListener('DOMContentLoaded', function() {
// 添加表单验证
const dataForm = document.querySelector('.data-form');
if (dataForm) {
dataForm.addEventListener('submit', function(e) {
const attempts = parseInt(document.querySelector('input[name="defensive_attempts"]').value);
const successful = parseInt(document.querySelector('input[name="successful_defenses"]').value);
if (successful > attempts) {
e.preventDefault();
alert('错误:成功防守次数不能大于防守总次数!');
}
});
}
// 显示提示信息
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('success')) {
showNotification('数据添加成功!', 'success');
}
if (urlParams.get('error')) {
const errors = {
'successful_defenses_exceed': '成功防守次数不能大于总防守次数',
'db_error': '数据库错误,请稍后重试'
};
const errorMsg = errors[urlParams.get('error')] || '发生错误';
showNotification(errorMsg, 'error');
}
// 排名动画
animateRanks();
// 进度条动画
animateProgressBars();
});
function showNotification(message, type) {
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.innerHTML = `
<span>${message}</span>
<button onclick="this.parentElement.remove()">×</button>
`;
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 3000);
}
function animateRanks() {
const ranks = document.querySelectorAll('.rank');
ranks.forEach((rank, index) => {
setTimeout(() => {
rank.classList.add('animated');
}, index * 100);
});
}
function animateProgressBars() {
const bars = document.querySelectorAll('.progress-bar');
bars.forEach(bar => {
const targetWidth = bar.style.width;
bar.style.width = '0%';
setTimeout(() => {
bar.style.width = targetWidth;
}, 300);
});
}
// 添加CSS动画样式
const style = document.createElement('style');
style.textContent = `
.rank.animated {
animation: spinIn 0.5s ease-out;
}
@keyframes spinIn {
from { transform: rotate(0deg) scale(0); }
to { transform: rotate(360deg) scale(1); }
}
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 15px 25px;
border-radius: 8px;
color: white;
font-weight: bold;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
z-index: 1000;
animation: slideIn 0.3s ease-out;
}
.notification.success {
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
}
.notification.error {
background: linear-gradient(135deg, #dc3545 0%, #f5576c 100%);
}
@keyframes slideIn {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
`;
document.head.appendChild(style);
使用方法
-
环境要求:PHP 7.0+、MySQL 5.7+
-
安装步骤:
# 导入数据库 mysql -u root -p < database.sql # 将文件部署到PHP服务器 # 访问 http://localhost/basketball-defense/index.php
-
功能特点:
- 📊 实时计算防守成功率
- 🏆 球员防守排名
- 📈 可视化数据展示
- 🎯 综合防守评分
- 📝 数据录入和管理
- 🔍 按球员和日期筛选
这个项目提供了完整的人盯人防守成功率分析系统,包含数据录入、统计计算、可视化展示等功能,你可以根据实际需求进行修改和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播