404 lines
16 KiB
PHP
404 lines
16 KiB
PHP
|
|
<?php
|
||
|
|
require_once 'config.php';
|
||
|
|
|
||
|
|
$image_id = $_GET['id'] ?? 0;
|
||
|
|
$feedback_success = '';
|
||
|
|
$feedback_error = '';
|
||
|
|
|
||
|
|
if (!$image_id) {
|
||
|
|
die('图片ID不能为空');
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
$stmt = $pdo->prepare("
|
||
|
|
SELECT i.*, u.username,
|
||
|
|
GROUP_CONCAT(t.name) as tag_names,
|
||
|
|
GROUP_CONCAT(t.color) as tag_colors,
|
||
|
|
GROUP_CONCAT(t.id) as tag_ids,
|
||
|
|
(SELECT COUNT(*) FROM image_feedbacks WHERE image_id = i.id AND type = 'like') as like_count,
|
||
|
|
(SELECT COUNT(*) FROM image_feedbacks WHERE image_id = i.id AND type = 'report') as report_count,
|
||
|
|
(SELECT COUNT(*) FROM image_feedbacks WHERE image_id = i.id AND user_id = ? AND type = 'like') as user_liked
|
||
|
|
FROM images i
|
||
|
|
LEFT JOIN users u ON i.user_id = u.id
|
||
|
|
LEFT JOIN image_tags it ON i.id = it.image_id
|
||
|
|
LEFT JOIN tags t ON it.tag_id = t.id
|
||
|
|
WHERE i.id = ?
|
||
|
|
GROUP BY i.id
|
||
|
|
");
|
||
|
|
$stmt->execute([$_SESSION['user_id'] ?? 0, $image_id]);
|
||
|
|
$image = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
|
|
|
||
|
|
if (!$image) {
|
||
|
|
die('图片不存在或已被删除');
|
||
|
|
}
|
||
|
|
|
||
|
|
$tags = [];
|
||
|
|
if ($image['tag_names']) {
|
||
|
|
$tagNames = explode(',', $image['tag_names']);
|
||
|
|
$tagColors = explode(',', $image['tag_colors']);
|
||
|
|
$tagIds = explode(',', $image['tag_ids']);
|
||
|
|
|
||
|
|
for ($i = 0; $i < count($tagNames); $i++) {
|
||
|
|
if (!empty($tagNames[$i])) {
|
||
|
|
$tags[] = [
|
||
|
|
'id' => $tagIds[$i],
|
||
|
|
'name' => $tagNames[$i],
|
||
|
|
'color' => $tagColors[$i]
|
||
|
|
];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!isset($_SESSION['viewed_images'])) {
|
||
|
|
$_SESSION['viewed_images'] = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!in_array($image_id, $_SESSION['viewed_images'])) {
|
||
|
|
$pdo->prepare("UPDATE images SET views = views + 1 WHERE id = ?")->execute([$image_id]);
|
||
|
|
$_SESSION['viewed_images'][] = $image_id;
|
||
|
|
}
|
||
|
|
|
||
|
|
} catch(PDOException $e) {
|
||
|
|
die('数据库错误: ' . $e->getMessage());
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SESSION['user_id'])) {
|
||
|
|
$type = $_POST['type'];
|
||
|
|
$comment = trim($_POST['comment'] ?? '');
|
||
|
|
|
||
|
|
try {
|
||
|
|
$stmt = $pdo->prepare("SELECT id FROM image_feedbacks WHERE image_id = ? AND user_id = ? AND type = ?");
|
||
|
|
$stmt->execute([$image_id, $_SESSION['user_id'], $type]);
|
||
|
|
|
||
|
|
if ($stmt->rowCount() > 0) {
|
||
|
|
$feedback_error = '您已经对此图片进行过此操作';
|
||
|
|
} else {
|
||
|
|
$stmt = $pdo->prepare("INSERT INTO image_feedbacks (image_id, user_id, type, comment) VALUES (?, ?, ?, ?)");
|
||
|
|
if ($stmt->execute([$image_id, $_SESSION['user_id'], $type, $comment])) {
|
||
|
|
$feedback_success = $type === 'like' ? '感谢您的喜欢!' : '举报已提交,我们会尽快处理。';
|
||
|
|
|
||
|
|
if ($type === 'like' && $image['user_id'] != $_SESSION['user_id']) {
|
||
|
|
sendNotification(
|
||
|
|
$image['user_id'],
|
||
|
|
'image_feedback',
|
||
|
|
'您的图片被喜欢了!',
|
||
|
|
"用户 {$_SESSION['username']} 喜欢了您的图片「{$image['title']}」",
|
||
|
|
"view-image.php?id={$image_id}"
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
header("Location: view-image.php?id={$image_id}");
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch(PDOException $e) {
|
||
|
|
$feedback_error = '操作失败:' . $e->getMessage();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
?>
|
||
|
|
|
||
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="<?php echo $lang; ?>" data-theme="<?php echo $currentUserSettings['dark_mode'] ? 'dark' : 'light'; ?>">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<title><?php echo htmlspecialchars($image['title'] ?: '图片详情'); ?> - <?php echo SITE_NAME; ?></title>
|
||
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||
|
|
<link rel="stylesheet" href="css/style.css">
|
||
|
|
<style>
|
||
|
|
.image-preview {
|
||
|
|
text-align: center;
|
||
|
|
margin-bottom: 30px;
|
||
|
|
background: var(--card-bg);
|
||
|
|
padding: 20px;
|
||
|
|
border-radius: var(--radius-lg);
|
||
|
|
box-shadow: var(--shadow);
|
||
|
|
}
|
||
|
|
.image-preview img {
|
||
|
|
max-width: 90%;
|
||
|
|
max-height: 70vh;
|
||
|
|
width: auto;
|
||
|
|
height: auto;
|
||
|
|
border-radius: var(--radius);
|
||
|
|
transition: var(--transition);
|
||
|
|
cursor: zoom-in;
|
||
|
|
}
|
||
|
|
.image-preview img.zoomed {
|
||
|
|
max-width: 100%;
|
||
|
|
max-height: 90vh;
|
||
|
|
cursor: zoom-out;
|
||
|
|
}
|
||
|
|
.image-info {
|
||
|
|
background: var(--card-bg);
|
||
|
|
padding: 30px;
|
||
|
|
border-radius: var(--radius-lg);
|
||
|
|
box-shadow: var(--shadow);
|
||
|
|
}
|
||
|
|
.info-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||
|
|
gap: 15px;
|
||
|
|
margin: 20px 0;
|
||
|
|
}
|
||
|
|
.info-item {
|
||
|
|
padding: 15px;
|
||
|
|
background: var(--bg-color);
|
||
|
|
border-radius: var(--radius);
|
||
|
|
border-left: 4px solid var(--primary-color);
|
||
|
|
}
|
||
|
|
.info-label {
|
||
|
|
font-weight: bold;
|
||
|
|
color: #666;
|
||
|
|
font-size: 0.9em;
|
||
|
|
margin-bottom: 5px;
|
||
|
|
}
|
||
|
|
.copy-buttons {
|
||
|
|
display: flex;
|
||
|
|
gap: 10px;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
margin: 20px 0;
|
||
|
|
}
|
||
|
|
.copy-btn {
|
||
|
|
flex: 1;
|
||
|
|
min-width: 120px;
|
||
|
|
}
|
||
|
|
.feedback-buttons {
|
||
|
|
display: flex;
|
||
|
|
gap: 10px;
|
||
|
|
margin: 15px 0;
|
||
|
|
}
|
||
|
|
.like-btn, .report-btn {
|
||
|
|
padding: 10px 20px;
|
||
|
|
border: none;
|
||
|
|
border-radius: var(--radius);
|
||
|
|
cursor: pointer;
|
||
|
|
font-size: 0.9rem;
|
||
|
|
transition: var(--transition);
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
}
|
||
|
|
.like-btn {
|
||
|
|
background: #e8f5e9;
|
||
|
|
color: #27ae60;
|
||
|
|
border: 2px solid #27ae60;
|
||
|
|
}
|
||
|
|
.like-btn:hover {
|
||
|
|
background: #27ae60;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
.like-btn.liked {
|
||
|
|
background: #27ae60;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
.report-btn {
|
||
|
|
background: #ffeaea;
|
||
|
|
color: #e74c3c;
|
||
|
|
border: 2px solid #e74c3c;
|
||
|
|
}
|
||
|
|
.report-btn:hover {
|
||
|
|
background: #e74c3c;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
[data-theme="dark"] .like-btn {
|
||
|
|
background: #1e3a2e;
|
||
|
|
color: #4ade80;
|
||
|
|
border-color: #4ade80;
|
||
|
|
}
|
||
|
|
[data-theme="dark"] .report-btn {
|
||
|
|
background: #3a1e1e;
|
||
|
|
color: #f87171;
|
||
|
|
border-color: #f87171;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<?php include 'components/navbar.php'; ?>
|
||
|
|
|
||
|
|
<div class="container">
|
||
|
|
<div class="image-detail">
|
||
|
|
<div class="image-preview">
|
||
|
|
<img src="uploads/<?php echo $image['filename']; ?>"
|
||
|
|
alt="<?php echo htmlspecialchars($image['title']); ?>"
|
||
|
|
id="previewImage">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="image-info">
|
||
|
|
<h1><?php echo htmlspecialchars($image['title'] ?: '未命名图片'); ?></h1>
|
||
|
|
|
||
|
|
<?php if($image['description']): ?>
|
||
|
|
<p class="image-description"><?php echo nl2br(htmlspecialchars($image['description'])); ?></p>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<?php if(!empty($tags)): ?>
|
||
|
|
<div class="tags-container">
|
||
|
|
<?php foreach($tags as $tag): ?>
|
||
|
|
<span class="tag" style="background: <?php echo $tag['color']; ?>">
|
||
|
|
<i class="fas fa-tag"></i> <?php echo htmlspecialchars($tag['name']); ?>
|
||
|
|
</span>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<div class="info-grid">
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label"><i class="fas fa-user"></i> 上传者</div>
|
||
|
|
<div><?php echo htmlspecialchars($image['username']); ?></div>
|
||
|
|
</div>
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label"><i class="fas fa-calendar"></i> 上传时间</div>
|
||
|
|
<div><?php echo date('Y-m-d H:i', strtotime($image['uploaded_at'])); ?></div>
|
||
|
|
</div>
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label"><i class="fas fa-eye"></i> 浏览量</div>
|
||
|
|
<div><?php echo $image['views']; ?></div>
|
||
|
|
</div>
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label"><i class="fas fa-heart"></i> 喜欢数</div>
|
||
|
|
<div><?php echo $image['like_count']; ?></div>
|
||
|
|
</div>
|
||
|
|
<div class="info-item">
|
||
|
|
<div class="info-label"><i class="fas fa-globe"></i> 状态</div>
|
||
|
|
<div>
|
||
|
|
<span class="status-badge <?php echo $image['is_public'] ? 'status-public' : 'status-private'; ?>">
|
||
|
|
<?php echo $image['is_public'] ? '公开' : '私有'; ?>
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<?php if(isset($_SESSION['user_id'])): ?>
|
||
|
|
<div class="image-feedback">
|
||
|
|
<h3><i class="fas fa-comment-dots"></i> 图片反馈</h3>
|
||
|
|
|
||
|
|
<?php if($feedback_success): ?>
|
||
|
|
<div class="alert alert-success">
|
||
|
|
<i class="fas fa-check-circle"></i> <?php echo $feedback_success; ?>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<?php if($feedback_error): ?>
|
||
|
|
<div class="alert alert-error">
|
||
|
|
<i class="fas fa-exclamation-triangle"></i> <?php echo $feedback_error; ?>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<div class="feedback-buttons">
|
||
|
|
<form method="POST" style="display: inline;">
|
||
|
|
<input type="hidden" name="type" value="like">
|
||
|
|
<button type="submit" class="like-btn <?php echo $image['user_liked'] ? 'liked' : ''; ?>">
|
||
|
|
<?php if($image['user_liked']): ?>
|
||
|
|
<i class="fas fa-heart"></i> 已喜欢
|
||
|
|
<?php else: ?>
|
||
|
|
<i class="far fa-heart"></i> 喜欢
|
||
|
|
<?php endif; ?>
|
||
|
|
</button>
|
||
|
|
</form>
|
||
|
|
|
||
|
|
<button type="button" class="report-btn" onclick="showReportForm()">
|
||
|
|
<i class="fas fa-flag"></i> 举报
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div id="reportForm" style="display: none; margin-top: 15px;">
|
||
|
|
<form method="POST">
|
||
|
|
<input type="hidden" name="type" value="report">
|
||
|
|
<div class="form-group">
|
||
|
|
<label>举报原因(可选)</label>
|
||
|
|
<textarea name="comment" rows="3" placeholder="请描述举报原因..."></textarea>
|
||
|
|
</div>
|
||
|
|
<button type="submit" class="btn btn-danger">
|
||
|
|
<i class="fas fa-paper-plane"></i> 提交举报
|
||
|
|
</button>
|
||
|
|
<button type="button" class="btn btn-secondary" onclick="hideReportForm()">
|
||
|
|
<i class="fas fa-times"></i> 取消
|
||
|
|
</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<h3><i class="fas fa-share-alt"></i> 分享链接</h3>
|
||
|
|
<div class="copy-buttons">
|
||
|
|
<?php
|
||
|
|
$image_url = SITE_URL . '/view-image.php?id=' . $image_id;
|
||
|
|
$direct_url = SITE_URL . '/uploads/' . $image['filename'];
|
||
|
|
$bbcode = "[img]{$direct_url}[/img]";
|
||
|
|
$markdown = "![{$image['title']}]({$direct_url})";
|
||
|
|
$html = "<img src=\"{$direct_url}\" alt=\"{$image['title']}\">";
|
||
|
|
?>
|
||
|
|
|
||
|
|
<button class="btn copy-btn" data-text="<?php echo $image_url; ?>">
|
||
|
|
<i class="fas fa-link"></i> 页面链接
|
||
|
|
</button>
|
||
|
|
<button class="btn copy-btn" data-text="<?php echo $direct_url; ?>">
|
||
|
|
<i class="fas fa-image"></i> 图片直链
|
||
|
|
</button>
|
||
|
|
<button class="btn copy-btn" data-text="<?php echo htmlspecialchars($bbcode); ?>">
|
||
|
|
<i class="fas fa-code"></i> BBCode
|
||
|
|
</button>
|
||
|
|
<button class="btn copy-btn" data-text="<?php echo htmlspecialchars($markdown); ?>">
|
||
|
|
<i class="fab fa-markdown"></i> Markdown
|
||
|
|
</button>
|
||
|
|
<button class="btn copy-btn" data-text="<?php echo htmlspecialchars($html); ?>">
|
||
|
|
<i class="fab fa-html5"></i> HTML
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<?php if(isset($_SESSION['user_id']) && $_SESSION['user_id'] == $image['user_id']): ?>
|
||
|
|
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--border-color);">
|
||
|
|
<a href="delete-image.php?id=<?php echo $image['id']; ?>"
|
||
|
|
class="btn btn-danger"
|
||
|
|
onclick="return confirm('确定要删除这张图片吗?此操作不可恢复!')">
|
||
|
|
<i class="fas fa-trash"></i> 删除图片
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
function showReportForm() {
|
||
|
|
document.getElementById('reportForm').style.display = 'block';
|
||
|
|
}
|
||
|
|
|
||
|
|
function hideReportForm() {
|
||
|
|
document.getElementById('reportForm').style.display = 'none';
|
||
|
|
}
|
||
|
|
|
||
|
|
document.getElementById('previewImage').addEventListener('click', function() {
|
||
|
|
this.classList.toggle('zoomed');
|
||
|
|
});
|
||
|
|
|
||
|
|
document.querySelectorAll('.copy-btn').forEach(button => {
|
||
|
|
button.addEventListener('click', function() {
|
||
|
|
const text = this.getAttribute('data-text');
|
||
|
|
copyToClipboard(text);
|
||
|
|
|
||
|
|
const originalText = this.innerHTML;
|
||
|
|
this.innerHTML = '<i class="fas fa-check"></i> 已复制!';
|
||
|
|
this.style.background = 'var(--success-color)';
|
||
|
|
|
||
|
|
setTimeout(() => {
|
||
|
|
this.innerHTML = originalText;
|
||
|
|
this.style.background = '';
|
||
|
|
}, 2000);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
function copyToClipboard(text) {
|
||
|
|
if (navigator.clipboard) {
|
||
|
|
navigator.clipboard.writeText(text);
|
||
|
|
} else {
|
||
|
|
const textArea = document.createElement('textarea');
|
||
|
|
textArea.value = text;
|
||
|
|
document.body.appendChild(textArea);
|
||
|
|
textArea.select();
|
||
|
|
document.execCommand('copy');
|
||
|
|
document.body.removeChild(textArea);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|