一个简单的书影音记录应用

• 111 分钟阅读 • web · deepseek

以前记录书影音是在豆瓣app里记录,再用第三方应用mythsman/idouban导出,其中要用到mythsman/mouban后端,这个应用经常出问题。本文用php简单实现了书影音的记录,不使用数据库,记录在文本文件中。

代码

<?php
// =============================================================================
// 配置文件
// =============================================================================

// 开启错误显示(调试完成后可注释)
ini_set('display_errors', 1);
error_reporting(E_ALL);

// 会话处理
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

// 系统配置
$DATA_FILE = 'books_data.txt';
$DATE_FORMAT = 'Y-m-d';
$UPLOAD_DIR = 'uploads/';
$MAX_FILE_SIZE = 2 * 1024 * 1024; // 2MB
$ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];

// 🔐 密码配置 - 请修改这里的密码!
$ADMIN_PASSWORD = 'admin'; // 将这里的密码改成你想要的
$SESSION_TIMEOUT = 3600; // 会话超时时间(秒),1小时

date_default_timezone_set('Asia/Shanghai');

// 创建必要的目录
if (!file_exists($UPLOAD_DIR)) {
    mkdir($UPLOAD_DIR, 0755, true);
}

// =============================================================================
// 核心函数
// =============================================================================

/**
 * 检查用户是否已登录
 */
function isLoggedIn() {
    global $SESSION_TIMEOUT;
    
    if (isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true) {
        if (isset($_SESSION['login_time']) && (time() - $_SESSION['login_time']) < $SESSION_TIMEOUT) {
            return true;
        }
    }
    return false;
}

/**
 * 登录验证
 */
function login($password) {
    global $ADMIN_PASSWORD;
    if ($password === $ADMIN_PASSWORD) {
        $_SESSION['logged_in'] = true;
        $_SESSION['login_time'] = time();
        return true;
    }
    return false;
}

/**
 * 退出登录
 */
function logout() {
    $_SESSION = array();
    session_destroy();
}

/**
 * 处理图片上传
 */
function handleUpload($fileField) {
    global $UPLOAD_DIR, $MAX_FILE_SIZE, $ALLOWED_TYPES;
    
    if (!isset($_FILES[$fileField]) || $_FILES[$fileField]['error'] === UPLOAD_ERR_NO_FILE) {
        return '';
    }
    
    $file = $_FILES[$fileField];
    if ($file['error'] !== UPLOAD_ERR_OK) {
        return '';
    }
    
    // 检查文件大小
    if ($file['size'] > $MAX_FILE_SIZE) {
        return '';
    }
    
    // 检查文件类型
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);
    
    if (!in_array($mime, $ALLOWED_TYPES)) {
        return '';
    }
    
    // 生成安全文件名
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    $safeName = 'item_' . time() . '_' . bin2hex(random_bytes(4)) . '.' . $ext;
    $targetPath = $UPLOAD_DIR . $safeName;
    
    if (move_uploaded_file($file['tmp_name'], $targetPath)) {
        return $safeName;
    }
    
    return '';
}

/**
 * 加载所有记录并按月份分组
 */
function loadItemsGroupedByMonth($showAll = false) {
    global $DATA_FILE;
    
    $items = ['books' => [], 'movies' => []];
    if (file_exists($DATA_FILE)) {
        $lines = file($DATA_FILE, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        foreach ($lines as $line) {
            $parts = explode(' ||| ', $line, 8);
            if (count($parts) >= 7) {
                $item = [
                    'id' => $parts[0],
                    'type' => $parts[1],
                    'title' => $parts[2],
                    'cover_url' => $parts[3],
                    'uploaded_cover' => $parts[4],
                    'douban_url' => $parts[5],
                    'read_date' => $parts[6],
                    'created' => $parts[7] ?? date('Y-m-d H:i:s')
                ];
                
                // 添加月份字段
                $item['year_month'] = date('Y年m月', strtotime($item['read_date']));
                $item['year'] = date('Y', strtotime($item['read_date']));
                $item['month'] = date('m', strtotime($item['read_date']));
                
                if ($item['type'] === 'book') {
                    $items['books'][] = $item;
                } elseif ($item['type'] === 'movie') {
                    $items['movies'][] = $item;
                }
            }
        }
        
        // 按日期排序(最新的在前面)
        usort($items['books'], function($a, $b) {
            return strtotime($b['read_date']) - strtotime($a['read_date']);
        });
        
        usort($items['movies'], function($a, $b) {
            return strtotime($b['read_date']) - strtotime($a['read_date']);
        });
        
        // 如果不是显示全部,则限制条数
        if (!$showAll) {
            $items['books'] = array_slice($items['books'], 0, 10);
            $items['movies'] = array_slice($items['movies'], 0, 10);
        }
        
        // 按月份分组
        $groupedItems = [
            'books' => groupItemsByMonth($items['books']),
            'movies' => groupItemsByMonth($items['movies'])
        ];
        
        return $groupedItems;
    }
    return ['books' => [], 'movies' => []];
}

/**
 * 将项目按月份分组
 */
function groupItemsByMonth($items) {
    $grouped = [];
    foreach ($items as $item) {
        $yearMonth = $item['year_month'];
        if (!isset($grouped[$yearMonth])) {
            $grouped[$yearMonth] = [
                'month' => $yearMonth,
                'year' => $item['year'],
                'month_num' => $item['month'],
                'items' => []
            ];
        }
        $grouped[$yearMonth]['items'][] = $item;
    }
    
    // 按月份排序(最新的在前面)
    uasort($grouped, function($a, $b) {
        return ($b['year'] . $b['month_num']) <=> ($a['year'] . $a['month_num']);
    });
    
    return $grouped;
}

/**
 * 获取所有项目数量
 */
function getAllItemsCount() {
    global $DATA_FILE;
    
    $counts = ['books' => 0, 'movies' => 0];
    if (file_exists($DATA_FILE)) {
        $lines = file($DATA_FILE, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        foreach ($lines as $line) {
            $parts = explode(' ||| ', $line, 8);
            if (count($parts) >= 7) {
                $type = $parts[1];
                if ($type === 'book') {
                    $counts['books']++;
                } elseif ($type === 'movie') {
                    $counts['movies']++;
                }
            }
        }
    }
    return $counts;
}

/**
 * 保存记录(需要登录)
 */
function saveItem($type, $title, $cover_url, $uploaded_cover, $douban_url, $read_date) {
    if (!isLoggedIn()) {
        return false;
    }
    
    global $DATA_FILE;
    
    $items = loadItemsGroupedByMonth(true);
    $id = time() . '_' . rand(1000, 9999);
    
    $newItem = [
        'id' => $id,
        'type' => $type,
        'title' => trim(str_replace('|||', '︳', $title)),
        'cover_url' => trim($cover_url),
        'uploaded_cover' => trim($uploaded_cover),
        'douban_url' => trim($douban_url),
        'read_date' => $read_date,
        'created' => date('Y-m-d H:i:s')
    ];
    
    // 将所有项目保存回文件
    $allItems = [];
    foreach (['books', 'movies'] as $category) {
        foreach ($items[$category] as $monthGroup) {
            $allItems = array_merge($allItems, $monthGroup['items']);
        }
    }
    
    // 添加新项目
    $allItems[] = $newItem;
    
    // 重新排序
    usort($allItems, function($a, $b) {
        return strtotime($b['read_date']) - strtotime($a['read_date']);
    });
    
    // 保存到文件
    $lines = [];
    foreach ($allItems as $item) {
        $lines[] = implode(' ||| ', [
            $item['id'], $item['type'], $item['title'], $item['cover_url'],
            $item['uploaded_cover'], $item['douban_url'], $item['read_date'], $item['created']
        ]);
    }
    
    return file_put_contents($DATA_FILE, implode(PHP_EOL, $lines)) !== false;
}

/**
 * 删除记录(需要登录)
 */
function deleteItem($id) {
    if (!isLoggedIn()) {
        return false;
    }
    
    global $DATA_FILE, $UPLOAD_DIR;
    
    $items = loadItemsGroupedByMonth(true);
    $itemToDelete = null;
    $allItems = [];
    
    // 查找要删除的记录并重新构建所有项目数组
    foreach (['books', 'movies'] as $category) {
        foreach ($items[$category] as $monthGroup) {
            foreach ($monthGroup['items'] as $item) {
                if ($item['id'] === $id) {
                    $itemToDelete = $item;
                } else {
                    $allItems[] = $item;
                }
            }
        }
    }
    
    if (!$itemToDelete) return false;
    
    // 删除关联的图片
    if (!empty($itemToDelete['uploaded_cover'])) {
        $imagePath = $UPLOAD_DIR . $itemToDelete['uploaded_cover'];
        if (file_exists($imagePath)) {
            @unlink($imagePath);
        }
    }
    
    // 保存新列表
    $lines = [];
    foreach ($allItems as $item) {
        $lines[] = implode(' ||| ', [
            $item['id'], $item['type'], $item['title'], $item['cover_url'],
            $item['uploaded_cover'], $item['douban_url'], $item['read_date'], $item['created']
        ]);
    }
    
    return file_put_contents($DATA_FILE, implode(PHP_EOL, $lines)) !== false;
}

// =============================================================================
// 处理请求
// =============================================================================
$action = $_GET['action'] ?? '';
$message = '';

// 检查是否显示全部
$showAllBooks = isset($_GET['show_all_books']);
$showAllMovies = isset($_GET['show_all_movies']);
$showAll = $showAllBooks || $showAllMovies;

// 显示模式:cards(卡片)或 list(列表)
// 优先使用URL参数,其次使用cookie,最后默认cards
if (isset($_GET['view'])) {
    $viewMode = $_GET['view'];
    // 保存到cookie,30天有效期
    setcookie('view_mode', $viewMode, time() + 30*24*60*60, '/');
} elseif (isset($_COOKIE['view_mode']) && in_array($_COOKIE['view_mode'], ['cards', 'list'])) {
    $viewMode = $_COOKIE['view_mode'];
} else {
    $viewMode = 'cards';
}

// 登录/登出
if ($action === 'login' && isset($_POST['password'])) {
    if (login($_POST['password'])) {
        header('Location: ' . $_SERVER['PHP_SELF']);
        exit;
    } else {
        $message = '<div class="message error">❌ 密码错误</div>';
    }
} elseif ($action === 'logout') {
    logout();
    header('Location: ' . $_SERVER['PHP_SELF']);
    exit;
}

// 添加记录
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['title'])) {
    if (!isLoggedIn()) {
        $message = '<div class="message error">❌ 请先登录</div>';
    } else {
        $uploadedCover = '';
        if (isset($_FILES['cover_upload']) && $_FILES['cover_upload']['error'] !== UPLOAD_ERR_NO_FILE) {
            $uploadedCover = handleUpload('cover_upload');
        }
        
        $itemType = $_POST['item_type'] ?? 'book';
        $success = saveItem(
            $itemType,
            $_POST['title'],
            $_POST['cover_url'] ?? '',
            $uploadedCover,
            $_POST['douban_url'] ?? '',
            $_POST['read_date'] ?? date($DATE_FORMAT)
        );
        
        if ($success) {
            $message = '<div class="message success">✅ ' . ($itemType === 'book' ? '书籍' : '电影') . '添加成功!</div>';
        } else {
            $message = '<div class="message error">❌ 添加失败</div>';
        }
    }
}

// 删除记录
if ($action === 'delete' && isset($_GET['id'])) {
    if (!isLoggedIn()) {
        $message = '<div class="message error">❌ 请先登录</div>';
    } else {
        if (deleteItem($_GET['id'])) {
            $message = '<div class="message success">✅ 删除成功!</div>';
        }
    }
}

// 加载数据
$items = loadItemsGroupedByMonth($showAll);
$books = $items['books'];
$movies = $items['movies'];
$allCounts = getAllItemsCount();
$loggedIn = isLoggedIn();
$showLoginForm = ($action === 'login' || (empty($books) && empty($movies))) && !$loggedIn;

// =============================================================================
// HTML界面 - 优化响应式
// =============================================================================
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
    <title><?= $loggedIn ? '📚🎬 书影音管理后台' : '📚🎬 我的书影音' ?></title>
    <style>
        /* 基础设置 */
        * { 
            margin: 0; 
            padding: 0; 
            box-sizing: border-box; 
        }
        
        body { 
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', sans-serif; 
            line-height: 1.5; 
            background: #f8f9fa; 
            color: #333;
            padding: 12px;
            font-size: 16px;
        }
        
        .container { 
            max-width: 1400px; 
            margin: 0 auto; 
        }
        
        /* 头部导航 */
        header { 
            background: white; 
            border-radius: 12px; 
            padding: 20px; 
            margin-bottom: 25px; 
            box-shadow: 0 2px 10px rgba(0,0,0,0.06); 
            display: flex; 
            justify-content: space-between; 
            align-items: center;
        }
        
        .header-left h1 { 
            color: #2c3e50; 
            font-size: 1.8rem; 
            font-weight: 700;
        }
        
        .header-left .subtitle { 
            color: #7f8c8d; 
            font-size: 0.95rem; 
        }
        
        .header-right { 
            display: flex; 
            gap: 12px; 
            align-items: center; 
        }
        
        /* 消息提示 */
        .message { 
            padding: 12px; 
            margin: 15px 0; 
            border-radius: 8px; 
            font-size: 0.95rem;
        }
        
        .success { 
            background: #d4edda; 
            color: #155724; 
            border-left: 4px solid #28a745; 
        }
        
        .error { 
            background: #f8d7da; 
            color: #721c24; 
            border-left: 4px solid #dc3545; 
        }
        
        /* 按钮 */
        .btn { 
            padding: 10px 18px; 
            border: none; 
            border-radius: 8px; 
            font-size: 1rem; 
            font-weight: 600; 
            cursor: pointer; 
            transition: all 0.3s; 
            text-decoration: none; 
            display: inline-flex;
            align-items: center;
            justify-content: center;
            min-height: 44px;
        }
        
        .btn-primary { 
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 
            color: white; 
        }
        
        .btn-primary:hover { 
            transform: translateY(-2px); 
            box-shadow: 0 5px 15px rgba(102,126,234,0.4); 
        }
        
        .btn-small { 
            padding: 6px 12px; 
            font-size: 0.9rem; 
            border-radius: 6px; 
            min-height: 36px;
        }
        
        .btn-danger { 
            background: #dc3545; 
            color: white; 
        }
        
        .btn-outline { 
            background: transparent; 
            border: 2px solid #667eea; 
            color: #667eea; 
        }
        
        .btn-outline:hover { 
            background: #667eea; 
            color: white; 
        }
        
        .btn-secondary { 
            background: #6c757d; 
            color: white; 
        }
        
        .btn-secondary:hover { 
            background: #5a6268; 
        }
        
        /* 视图切换按钮 */
        .view-toggle {
            display: flex;
            border-radius: 8px;
            overflow: hidden;
            border: 2px solid #e0e0e0;
            background: white;
        }
        
        .view-toggle-btn {
            padding: 8px 16px;
            border: none;
            background: none;
            cursor: pointer;
            font-size: 1.2rem;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            min-width: 44px;
        }
        
        .view-toggle-btn:hover {
            background: #f8f9ff;
        }
        
        .view-toggle-btn.active {
            background: #667eea;
            color: white;
        }
        
        /* 双列布局 */
        .two-columns { 
            display: grid; 
            grid-template-columns: 1fr 1fr; 
            gap: 20px;
            margin-bottom: 30px;
        }
        
        .column { 
            background: white; 
            border-radius: 12px; 
            padding: 20px; 
            box-shadow: 0 3px 10px rgba(0,0,0,0.06);
        }
        
        .column-title { 
            font-size: 1.3rem; 
            margin-bottom: 20px; 
            color: #2c3e50; 
            display: flex; 
            align-items: center; 
            gap: 10px;
            font-weight: 600;
        }
        
        .column-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
        }
        
        /* 月份分组样式 */
        .month-group {
            margin-bottom: 25px;
        }
        
        .month-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 12px 20px;
            border-radius: 8px;
            font-size: 1.1rem;
            font-weight: 600;
            margin-bottom: 15px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        /* 书籍/电影卡片 */
        .items-grid { 
            display: grid; 
            grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); 
            gap: 18px; 
        }
        
        .item-card { 
            background: white; 
            border-radius: 12px; 
            overflow: hidden; 
            box-shadow: 0 3px 12px rgba(0,0,0,0.06); 
            transition: all 0.3s;
            display: flex;
            flex-direction: column;
            height: 100%;
        }
        
        .item-card:hover { 
            transform: translateY(-4px); 
            box-shadow: 0 8px 20px rgba(0,0,0,0.12); 
        }
        
        .item-cover { 
            height: 180px; 
            display: flex; 
            align-items: center; 
            justify-content: center; 
            overflow: hidden;
            position: relative;
        }
        
        .item-cover img { 
            width: 100%; 
            height: 100%; 
            object-fit: cover; 
            transition: transform 0.5s; 
        }
        
        .item-card:hover .item-cover img { 
            transform: scale(1.05); 
        }
        
        .book-cover { background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); }
        .movie-cover { background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); }
        
        .item-info { 
            padding: 18px; 
            flex-grow: 1;
            display: flex;
            flex-direction: column;
        }
        
        .item-title { 
            font-size: 1.05rem; 
            font-weight: 600; 
            margin-bottom: 10px; 
            color: #2c3e50; 
            line-height: 1.4;
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;
            overflow: hidden;
        }
        
        .item-meta { 
            display: flex; 
            justify-content: space-between; 
            align-items: center;
            margin-top: auto; 
            font-size: 0.9rem; 
            color: #666;
        }
        
        .item-actions { 
            display: flex; 
            gap: 8px; 
            margin-top: 15px;
        }
        
        .type-badge { 
            padding: 4px 10px; 
            border-radius: 20px; 
            font-size: 0.75rem; 
            font-weight: 600; 
            display: inline-block;
            margin-bottom: 8px;
        }
        
        .book-badge { background: #e3f2fd; color: #1976d2; }
        .movie-badge { background: #fce4ec; color: #c2185b; }
        
        /* 列表显示样式 - 优化移动端 */
        .items-list {
            display: flex;
            flex-direction: column;
            gap: 12px;
        }
        
        .list-item {
            display: flex;
            align-items: center;
            padding: 15px;
            background: white;
            border-radius: 10px;
            border-left: 4px solid #667eea;
            box-shadow: 0 2px 6px rgba(0,0,0,0.04);
            transition: all 0.3s;
        }
        
        .list-item:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(0,0,0,0.08);
        }
        
        .list-item.book-item {
            border-left-color: #1976d2;
        }
        
        .list-item.movie-item {
            border-left-color: #c2185b;
        }
        
        .list-item-cover {
            width: 80px;
            height: 80px;
            border-radius: 8px;
            overflow: hidden;
            margin-right: 15px;
            flex-shrink: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
        }
        
        .list-item-cover img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        .list-item-info {
            flex-grow: 1;
            min-width: 0; /* 防止文本溢出 */
        }
        
        .list-item-title {
            font-weight: 600;
            font-size: 1.05rem;
            margin-bottom: 5px;
            color: #2c3e50;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        
        .list-item-meta {
            display: flex;
            gap: 10px;
            font-size: 0.9rem;
            color: #666;
            flex-wrap: wrap;
            align-items: center;
        }
        
        .list-item-type {
            padding: 3px 8px;
            border-radius: 4px;
            font-size: 0.75rem;
            font-weight: 600;
            white-space: nowrap;
        }
        
        .list-item-type.book {
            background: #e3f2fd;
            color: #1976d2;
        }
        
        .list-item-type.movie {
            background: #fce4ec;
            color: #c2185b;
        }
        
        .list-item-actions {
            display: flex;
            gap: 8px;
            margin-left: 10px;
            flex-shrink: 0;
        }
        
        /* 表单 */
        .form-row { 
            display: grid; 
            grid-template-columns: 1fr 1fr; 
            gap: 18px;
            margin-bottom: 20px;
        }
        
        .form-group { 
            display: flex; 
            flex-direction: column; 
        }
        
        label { 
            margin-bottom: 8px; 
            font-weight: 600; 
            color: #2c3e50; 
            font-size: 0.95rem;
        }
        
        input, select, textarea { 
            padding: 12px; 
            border: 2px solid #e0e0e0; 
            border-radius: 8px; 
            font-size: 1rem;
            width: 100%;
            min-height: 48px;
        }
        
        input:focus, select:focus, textarea:focus { 
            outline: none; 
            border-color: #667eea; 
            box-shadow: 0 0 0 3px rgba(102,126,234,0.1); 
        }
        
        /* 类型选择器 */
        .type-selector { 
            display: flex; 
            gap: 15px; 
            margin-bottom: 25px;
        }
        
        .type-option { 
            flex: 1; 
            text-align: center; 
            padding: 15px; 
            border: 2px solid #e0e0e0; 
            border-radius: 10px; 
            cursor: pointer; 
            transition: all 0.3s;
        }
        
        .type-option:hover { 
            border-color: #667eea; 
            background: #f8f9ff; 
        }
        
        .type-option.selected { 
            border-color: #667eea; 
            background: #667eea; 
            color: white; 
        }
        
        /* 上传区域 */
        .upload-area { 
            border: 2px dashed #667eea; 
            border-radius: 10px; 
            padding: 20px; 
            text-align: center; 
            background: #f8f9ff; 
            cursor: pointer; 
            transition: all 0.3s; 
            margin: 15px 0; 
        }
        
        .upload-area:hover { 
            background: #eef1ff; 
        }
        
        .upload-preview { 
            max-width: 150px; 
            max-height: 150px; 
            margin: 15px auto; 
            border-radius: 8px; 
            display: none; 
        }
        
        /* 登录框 */
        .login-box { 
            max-width: 400px; 
            margin: 50px auto; 
            background: white; 
            padding: 30px; 
            border-radius: 15px; 
            box-shadow: 0 10px 30px rgba(0,0,0,0.1); 
            text-align: center; 
        }
        
        /* 空状态 */
        .empty-state { 
            text-align: center; 
            padding: 40px 20px; 
            color: #666; 
        }
        
        /* 显示全部按钮区域 */
        .show-all-section {
            text-align: center;
            margin: 20px 0;
            padding: 15px;
            background: #f8f9ff;
            border-radius: 10px;
            border: 2px dashed #667eea;
        }
        
        /* 页脚统计 */
        footer { 
            text-align: center; 
            padding: 20px; 
            color: #666; 
            font-size: 0.9rem; 
            margin-top: 40px; 
            border-top: 1px solid #eee; 
        }
        
        .stats { 
            display: grid; 
            grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); 
            gap: 15px; 
            margin-top: 15px;
        }
        
        .stat-item { 
            background: #f8f9fa; 
            padding: 15px; 
            border-radius: 10px; 
            text-align: center;
        }
        
        .stat-number { 
            font-size: 1.6rem; 
            font-weight: bold; 
            margin-bottom: 5px;
        }
        
        .book-stat { color: #1976d2; }
        .movie-stat { color: #c2185b; }
        
        /* 响应式设计 - 针对小屏优化列表显示 */
        @media (max-width: 768px) {
            body {
                padding: 10px;
                font-size: 15px;
            }
            
            header {
                padding: 15px;
                flex-direction: column;
                align-items: flex-start;
                gap: 15px;
            }
            
            .header-right {
                width: 100%;
                justify-content: flex-start;
                flex-wrap: wrap;
            }
            
            .items-grid {
                grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            }
            
            /* 小屏列表显示优化 */
            .list-item {
                flex-direction: row;
                align-items: flex-start;
                padding: 12px;
            }
            
            .list-item-cover {
                width: 70px;
                height: 70px;
                margin-right: 12px;
            }
            
            .list-item-info {
                flex: 1;
                min-width: 0;
            }
            
            .list-item-title {
                font-size: 1rem;
                margin-bottom: 4px;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
            }
            
            .list-item-meta {
                gap: 8px;
                font-size: 0.85rem;
                flex-wrap: wrap;
            }
            
            .list-item-type {
                padding: 2px 6px;
                font-size: 0.7rem;
            }
            
            .list-item-actions {
                margin-left: 8px;
                flex-direction: column;
                gap: 6px;
            }
            
            .list-item-actions .btn-small {
                padding: 5px 10px;
                font-size: 0.8rem;
                min-height: 32px;
            }
            
            .item-cover {
                height: 160px;
            }
            
            .form-row {
                grid-template-columns: 1fr;
            }
            
            .type-selector {
                flex-direction: column;
            }
            
            .column {
                padding: 15px;
            }
            
            .column-header {
                flex-direction: column;
                align-items: flex-start;
                gap: 10px;
            }
            
            .month-header {
                font-size: 1rem;
                padding: 10px 15px;
            }
        }
        
        @media (max-width: 480px) {
            .items-grid {
                grid-template-columns: 1fr;
            }
            
            .header-left h1 {
                font-size: 1.5rem;
            }
            
            /* 超小屏列表显示进一步优化 */
            .list-item {
                padding: 10px;
                gap: 10px;
            }
            
            .list-item-cover {
                width: 60px;
                height: 60px;
                margin-right: 10px;
            }
            
            .list-item-title {
                font-size: 0.95rem;
            }
            
            .list-item-meta {
                font-size: 0.8rem;
            }
            
            .list-item-type {
                font-size: 0.65rem;
                padding: 1px 5px;
            }
            
            .list-item-actions {
                flex-direction: column;
                gap: 5px;
            }
            
            .list-item-actions .btn-small {
                padding: 4px 8px;
                font-size: 0.75rem;
            }
            
            .stats {
                grid-template-columns: repeat(2, 1fr);
            }
            
            .item-title {
                font-size: 1rem;
            }
            
            .show-all-section {
                padding: 10px;
            }
        }
        
        @media (max-width: 992px) { 
            .two-columns { 
                grid-template-columns: 1fr; 
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- 头部导航 -->
        <header>
            <div class="header-left">
                <h1>📚🎬 我的书影音</h1>
                <p class="subtitle"><?= $loggedIn ? '管理员模式' : '公开浏览模式' ?></p>
            </div>
            <div class="header-right">
                <?php if ($loggedIn): ?>
                    <div class="view-toggle">
                        <a href="?view=cards<?= $showAllBooks ? '&show_all_books=1' : '' ?><?= $showAllMovies ? '&show_all_movies=1' : '' ?>" 
                           class="view-toggle-btn <?= $viewMode === 'cards' ? 'active' : '' ?>" 
                           title="卡片视图">
                            🗂️ 
                        </a>
                        <a href="?view=list<?= $showAllBooks ? '&show_all_books=1' : '' ?><?= $showAllMovies ? '&show_all_movies=1' : '' ?>" 
                           class="view-toggle-btn <?= $viewMode === 'list' ? 'active' : '' ?>" 
                           title="列表视图">
                            📋
                        </a>
                    </div>
                    <span style="color: #28a745; font-weight: 600;">✅ 已登录</span>
                    <a href="?action=logout" class="btn" style="background: #6c757d; color: white;">🚪 退出</a>
                <?php else: ?>
                    <?php if (!empty($books) || !empty($movies)): ?>
                        <div class="view-toggle">
                            <a href="?view=cards<?= $showAllBooks ? '&show_all_books=1' : '' ?><?= $showAllMovies ? '&show_all_movies=1' : '' ?>" 
                               class="view-toggle-btn <?= $viewMode === 'cards' ? 'active' : '' ?>" 
                               title="卡片视图">
                                🗂️ 
                            </a>
                            <a href="?view=list<?= $showAllBooks ? '&show_all_books=1' : '' ?><?= $showAllMovies ? '&show_all_movies=1' : '' ?>" 
                               class="view-toggle-btn <?= $viewMode === 'list' ? 'active' : '' ?>" 
                               title="列表视图">
                                📋
                            </a>
                        </div>
                        <a href="?action=login" class="btn btn-primary">🔑 登录</a>
                    <?php endif; ?>
                    <span style="color: #6c757d;">👤 访客</span>
                <?php endif; ?>
            </div>
        </header>
        
        <?php if ($message): echo $message; endif; ?>
        
        <!-- 登录表单 -->
        <?php if ($showLoginForm): ?>
            <div class="login-box">
                <h2>🔐 管理员登录</h2>
                <p>请输入密码进入管理后台</p>
                
                <form method="POST" action="?action=login" class="login-form">
                    <input type="password" name="password" placeholder="输入管理员密码" required 
                           style="width: 100%; padding: 12px; margin: 15px 0; border: 2px solid #e0e0e0; border-radius: 8px; font-size: 16px;">
                    <button type="submit" class="btn btn-primary" style="width: 100%;">
                        🔑 登录
                    </button>
                </form>
                
                <?php if (!empty($books) || !empty($movies)): ?>
                    <p style="margin-top: 20px; color: #666; font-size: 0.9rem;">
                        <a href="<?= $_SERVER['PHP_SELF'] ?>" style="color: #667eea; text-decoration: none;">
                            ← 返回浏览书影音
                        </a>
                    </p>
                <?php endif; ?>
            </div>
        <?php endif; ?>
        
        <!-- 书影音双列布局 -->
        <?php if ((!empty($books) || !empty($movies)) && !$showLoginForm): ?>
            <div class="two-columns">
                <!-- 书籍列 -->
                <div class="column">
                    <div class="column-header">
                        <h2 class="column-title">
                            <span style="background: #1976d2; color: white; width: 36px; height: 36px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;">📚</span>
                            书籍
                        </h2>
                        <div>
                            <span style="color: #666; font-size: 0.9rem;">
                                共 <?= $allCounts['books'] ?> 本
                                <?php if (!$showAllBooks && $allCounts['books'] > 10): ?>
                                    (显示最新 10 本)
                                <?php endif; ?>
                            </span>
                        </div>
                    </div>
                    
                    <?php if (empty($books)): ?>
                        <div class="empty-state">
                            <div style="font-size: 3rem; color: #ddd; margin-bottom: 15px;">📚</div>
                            <p>暂无书籍记录</p>
                            <?php if ($loggedIn): ?>
                                <p style="color: #666; font-size: 0.9rem; margin-top: 10px;">在下方添加你的第一本书</p>
                            <?php endif; ?>
                        </div>
                    <?php else: ?>
                        <?php foreach ($books as $monthGroup): ?>
                            <div class="month-group">
                                <div class="month-header">
                                    📅 <?= $monthGroup['month'] ?>
                                </div>
                                
                                <?php if ($viewMode === 'cards'): ?>
                                    <!-- 卡片视图 -->
                                    <div class="items-grid">
                                        <?php foreach ($monthGroup['items'] as $item): ?>
                                            <div class="item-card">
                                                <div class="item-cover book-cover">
                                                    <?php if (!empty($item['uploaded_cover']) || !empty($item['cover_url'])): ?>
                                                        <?php $imgSrc = !empty($item['uploaded_cover']) ? $UPLOAD_DIR . $item['uploaded_cover'] : $item['cover_url']; ?>
                                                        <img src="<?= htmlspecialchars($imgSrc) ?>" 
                                                             alt="<?= htmlspecialchars($item['title']) ?>" 
                                                             onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
                                                        <div style="display:none; color: white; font-size: 2rem; width:100%; height:100%; align-items:center; justify-content:center;">📚</div>
                                                    <?php else: ?>
                                                        <div style="color: white; font-size: 2rem;">📚</div>
                                                    <?php endif; ?>
                                                </div>
                                                
                                                <div class="item-info">
                                                    <span class="type-badge book-badge">书籍</span>
                                                    <h3 class="item-title"><?= htmlspecialchars($item['title']) ?></h3>
                                                    
                                                    <div class="item-meta">
                                                        <span>📅 <?= $item['read_date'] ?></span>
                                                        <?php if (!empty($item['uploaded_cover'])): ?>
                                                            <span title="本地上传的图片">📤</span>
                                                        <?php endif; ?>
                                                    </div>
                                                    
                                                    <div class="item-actions">
                                                        <?php if (!empty($item['douban_url'])): ?>
                                                            <a href="<?= htmlspecialchars($item['douban_url']) ?>" 
                                                               target="_blank" class="btn btn-primary btn-small">
                                                                🔗 豆瓣
                                                            </a>
                                                        <?php endif; ?>
                                                        
                                                        <?php if ($loggedIn): ?>
                                                            <button class="btn btn-danger btn-small" 
                                                                    onclick="if(confirm('确定删除这本书吗?')) location.href='?action=delete&id=<?= $item['id'] ?>'">
                                                                🗑️ 删除
                                                            </button>
                                                        <?php endif; ?>
                                                    </div>
                                                </div>
                                            </div>
                                        <?php endforeach; ?>
                                    </div>
                                <?php else: ?>
                                    <!-- 列表视图 -->
                                    <div class="items-list">
                                        <?php foreach ($monthGroup['items'] as $item): ?>
                                            <div class="list-item book-item">
                                                <div class="list-item-cover">
                                                    <?php if (!empty($item['uploaded_cover']) || !empty($item['cover_url'])): ?>
                                                        <?php $imgSrc = !empty($item['uploaded_cover']) ? $UPLOAD_DIR . $item['uploaded_cover'] : $item['cover_url']; ?>
                                                        <img src="<?= htmlspecialchars($imgSrc) ?>" 
                                                             alt="<?= htmlspecialchars($item['title']) ?>" 
                                                             onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
                                                        <div style="display:none; color: #666; font-size: 1.5rem;">📚</div>
                                                    <?php else: ?>
                                                        <div style="color: #666; font-size: 1.5rem;">📚</div>
                                                    <?php endif; ?>
                                                </div>
                                                
                                                <div class="list-item-info">
                                                    <div class="list-item-title" title="<?= htmlspecialchars($item['title']) ?>">
                                                        <?= htmlspecialchars($item['title']) ?>
                                                    </div>
                                                    <div class="list-item-meta">
                                                        <span class="list-item-type book">书籍</span>
                                                        <span>📅 <?= $item['read_date'] ?></span>
                                                        <?php if (!empty($item['uploaded_cover'])): ?>
                                                            <span title="本地上传的图片">📤</span>
                                                        <?php endif; ?>
                                                    </div>
                                                </div>
                                                
                                                <div class="list-item-actions">
                                                    <?php if (!empty($item['douban_url'])): ?>
                                                        <a href="<?= htmlspecialchars($item['douban_url']) ?>" 
                                                           target="_blank" class="btn btn-primary btn-small">
                                                            🔗 豆瓣
                                                        </a>
                                                    <?php endif; ?>
                                                    
                                                    <?php if ($loggedIn): ?>
                                                        <button class="btn btn-danger btn-small" 
                                                                onclick="if(confirm('确定删除这本书吗?')) location.href='?action=delete&id=<?= $item['id'] ?>'">
                                                            🗑️ 删除
                                                        </button>
                                                    <?php endif; ?>
                                                </div>
                                            </div>
                                        <?php endforeach; ?>
                                    </div>
                                <?php endif; ?>
                            </div>
                        <?php endforeach; ?>
                        
                        <?php if (!$showAllBooks && $allCounts['books'] > 10): ?>
                            <div class="show-all-section">
                                <p style="margin-bottom: 10px; color: #666;">
                                    已显示最新 10 本书,共 <?= $allCounts['books'] ?> 本
                                </p>
                                <a href="?view=<?= $viewMode ?>&show_all_books=1" class="btn btn-outline">
                                    📚 显示全部书籍
                                </a>
                            </div>
                        <?php elseif ($showAllBooks): ?>
                            <div class="show-all-section">
                                <p style="margin-bottom: 10px; color: #28a745; font-weight: 600;">
                                    ✅ 显示全部 <?= $allCounts['books'] ?> 本书
                                </p>
                                <a href="?view=<?= $viewMode ?>" class="btn btn-primary">
                                    ↩️ 返回首页(显示最新10条)
                                </a>
                            </div>
                        <?php endif; ?>
                    <?php endif; ?>
                </div>
                
                <!-- 电影列 -->
                <div class="column">
                    <div class="column-header">
                        <h2 class="column-title">
                            <span style="background: #c2185b; color: white; width: 36px; height: 36px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;">🎬</span>
                            电影
                        </h2>
                        <div>
                            <span style="color: #666; font-size: 0.9rem;">
                                共 <?= $allCounts['movies'] ?> 部
                                <?php if (!$showAllMovies && $allCounts['movies'] > 10): ?>
                                    (显示最新 10 部)
                                <?php endif; ?>
                            </span>
                        </div>
                    </div>
                    
                    <?php if (empty($movies)): ?>
                        <div class="empty-state">
                            <div style="font-size: 3rem; color: #ddd; margin-bottom: 15px;">🎬</div>
                            <p>暂无电影记录</p>
                            <?php if ($loggedIn): ?>
                                <p style="color: #666; font-size: 0.9rem; margin-top: 10px;">在下方添加你的第一部电影</p>
                            <?php endif; ?>
                        </div>
                    <?php else: ?>
                        <?php foreach ($movies as $monthGroup): ?>
                            <div class="month-group">
                                <div class="month-header">
                                    📅 <?= $monthGroup['month'] ?>
                                </div>
                                
                                <?php if ($viewMode === 'cards'): ?>
                                    <!-- 卡片视图 -->
                                    <div class="items-grid">
                                        <?php foreach ($monthGroup['items'] as $item): ?>
                                            <div class="item-card">
                                                <div class="item-cover movie-cover">
                                                    <?php if (!empty($item['uploaded_cover']) || !empty($item['cover_url'])): ?>
                                                        <?php $imgSrc = !empty($item['uploaded_cover']) ? $UPLOAD_DIR . $item['uploaded_cover'] : $item['cover_url']; ?>
                                                        <img src="<?= htmlspecialchars($imgSrc) ?>" 
                                                             alt="<?= htmlspecialchars($item['title']) ?>" 
                                                             onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
                                                        <div style="display:none; color: white; font-size: 2rem; width:100%; height:100%; align-items:center; justify-content:center;">🎬</div>
                                                    <?php else: ?>
                                                        <div style="color: white; font-size: 2rem;">🎬</div>
                                                    <?php endif; ?>
                                                </div>
                                                
                                                <div class="item-info">
                                                    <span class="type-badge movie-badge">电影</span>
                                                    <h3 class="item-title"><?= htmlspecialchars($item['title']) ?></h3>
                                                    
                                                    <div class="item-meta">
                                                        <span>📅 <?= $item['read_date'] ?></span>
                                                        <?php if (!empty($item['uploaded_cover'])): ?>
                                                            <span title="本地上传的图片">📤</span>
                                                        <?php endif; ?>
                                                    </div>
                                                    
                                                    <div class="item-actions">
                                                        <?php if (!empty($item['douban_url'])): ?>
                                                            <a href="<?= htmlspecialchars($item['douban_url']) ?>" 
                                                               target="_blank" class="btn btn-primary btn-small">
                                                                🔗 豆瓣
                                                            </a>
                                                        <?php endif; ?>
                                                        
                                                        <?php if ($loggedIn): ?>
                                                            <button class="btn btn-danger btn-small" 
                                                                    onclick="if(confirm('确定删除这部电影吗?')) location.href='?action=delete&id=<?= $item['id'] ?>'">
                                                                🗑️ 删除
                                                            </button>
                                                        <?php endif; ?>
                                                    </div>
                                                </div>
                                            </div>
                                        <?php endforeach; ?>
                                    </div>
                                <?php else: ?>
                                    <!-- 列表视图 -->
                                    <div class="items-list">
                                        <?php foreach ($monthGroup['items'] as $item): ?>
                                            <div class="list-item movie-item">
                                                <div class="list-item-cover">
                                                    <?php if (!empty($item['uploaded_cover']) || !empty($item['cover_url'])): ?>
                                                        <?php $imgSrc = !empty($item['uploaded_cover']) ? $UPLOAD_DIR . $item['uploaded_cover'] : $item['cover_url']; ?>
                                                        <img src="<?= htmlspecialchars($imgSrc) ?>" 
                                                             alt="<?= htmlspecialchars($item['title']) ?>" 
                                                             onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
                                                        <div style="display:none; color: #666; font-size: 1.5rem;">🎬</div>
                                                    <?php else: ?>
                                                        <div style="color: #666; font-size: 1.5rem;">🎬</div>
                                                    <?php endif; ?>
                                                </div>
                                                
                                                <div class="list-item-info">
                                                    <div class="list-item-title" title="<?= htmlspecialchars($item['title']) ?>">
                                                        <?= htmlspecialchars($item['title']) ?>
                                                    </div>
                                                    <div class="list-item-meta">
                                                        <span class="list-item-type movie">电影</span>
                                                        <span>📅 <?= $item['read_date'] ?></span>
                                                        <?php if (!empty($item['uploaded_cover'])): ?>
                                                            <span title="本地上传的图片">📤</span>
                                                        <?php endif; ?>
                                                    </div>
                                                </div>
                                                
                                                <div class="list-item-actions">
                                                    <?php if (!empty($item['douban_url'])): ?>
                                                        <a href="<?= htmlspecialchars($item['douban_url']) ?>" 
                                                           target="_blank" class="btn btn-primary btn-small">
                                                            🔗 豆瓣
                                                        </a>
                                                    <?php endif; ?>
                                                    
                                                    <?php if ($loggedIn): ?>
                                                        <button class="btn btn-danger btn-small" 
                                                                onclick="if(confirm('确定删除这部电影吗?')) location.href='?action=delete&id=<?= $item['id'] ?>'">
                                                            🗑️ 删除
                                                        </button>
                                                    <?php endif; ?>
                                                </div>
                                            </div>
                                        <?php endforeach; ?>
                                    </div>
                                <?php endif; ?>
                            </div>
                        <?php endforeach; ?>
                        
                        <?php if (!$showAllMovies && $allCounts['movies'] > 10): ?>
                            <div class="show-all-section">
                                <p style="margin-bottom: 10px; color: #666;">
                                    已显示最新 10 部电影,共 <?= $allCounts['movies'] ?> 部
                                </p>
                                <a href="?view=<?= $viewMode ?>&show_all_movies=1" class="btn btn-outline">
                                    🎬 显示全部电影
                                </a>
                            </div>
                        <?php elseif ($showAllMovies): ?>
                            <div class="show-all-section">
                                <p style="margin-bottom: 10px; color: #28a745; font-weight: 600;">
                                    ✅ 显示全部 <?= $allCounts['movies'] ?> 部电影
                                </p>
                                <a href="?view=<?= $viewMode ?>" class="btn btn-primary">
                                    ↩️ 返回首页(显示最新10条)
                                </a>
                            </div>
                        <?php endif; ?>
                    <?php endif; ?>
                </div>
            </div>
        <?php elseif ($loggedIn && !$showLoginForm): ?>
            <!-- 空状态 -->
            <div class="empty-state">
                <div style="font-size: 4rem; color: #ddd; margin-bottom: 20px;">📚🎬</div>
                <h3>书影音空空如也</h3>
                <p>开始添加你的第一本书或电影吧!</p>
            </div>
        <?php endif; ?>
        
        <!-- 添加记录表单(仅管理员可见) -->
        <?php if ($loggedIn && !$showLoginForm): ?>
            <div class="column" style="margin-top: 30px;">
                <h2 class="column-title">➕ 添加新记录</h2>
                
                <form method="POST" enctype="multipart/form-data">
                    <!-- 类型选择器 -->
                    <div class="type-selector" id="typeSelector">
                        <div class="type-option selected" data-type="book">
                            <div style="font-size: 2rem; margin-bottom: 10px;">📚</div>
                            <div>书籍</div>
                        </div>
                        <div class="type-option" data-type="movie">
                            <div style="font-size: 2rem; margin-bottom: 10px;">🎬</div>
                            <div>电影</div>
                        </div>
                    </div>
                    <input type="hidden" name="item_type" id="item_type" value="book">
                    
                    <div class="form-row">
                        <div class="form-group">
                            <label>📖 标题 *</label>
                            <input type="text" name="title" required placeholder="输入书名或电影名">
                        </div>
                        <div class="form-group">
                            <label>📅 日期</label>
                            <input type="date" name="read_date" value="<?= date($DATE_FORMAT) ?>">
                        </div>
                    </div>
                    
                    <div class="form-row">
                        <div class="form-group">
                            <label>🌐 豆瓣链接(可选)</label>
                            <input type="url" name="douban_url" placeholder="豆瓣链接">
                        </div>
                        <div class="form-group">
                            <label>🖼️ 封面图片URL(可选)</label>
                            <input type="url" name="cover_url" placeholder="图片URL链接">
                        </div>
                    </div>
                    
                    <!-- 图片上传 -->
                    <div class="form-group">
                        <label>📤 上传封面图片(可选,最大2MB)</label>
                        <div class="upload-area" id="uploadArea">
                            <input type="file" name="cover_upload" id="cover_upload" 
                                   accept="image/jpeg,image/png,image/gif,image/webp" 
                                   style="display: none;">
                            <div style="font-size: 4rem; color: #667eea; margin-bottom: 10px;">
                                📁
                            </div>
                            <p>点击或拖放图片到这里</p>
                            <p style="color: #666; font-size: 0.9rem; margin-top: 5px;">
                                支持 JPG, PNG, GIF, WebP 格式
                            </p>
                            <img id="uploadPreview" class="upload-preview" alt="预览">
                        </div>
                    </div>
                    
                    <button type="submit" class="btn btn-primary" style="width: 100%;">💾 保存记录</button>
                </form>
            </div>
        <?php endif; ?>
        
        <!-- 页脚统计 -->
        <footer>
            <div class="stats">
                <div class="stat-item">
                    <div class="stat-number book-stat"><?= $allCounts['books'] ?></div>
                    <div>📚 书籍总数</div>
                </div>
                <div class="stat-item">
                    <div class="stat-number movie-stat"><?= $allCounts['movies'] ?></div>
                    <div>🎬 电影总数</div>
                </div>
                <div class="stat-item">
                    <div class="stat-number" style="color: #667eea;"><?= $allCounts['books'] + $allCounts['movies'] ?></div>
                    <div>📊 总记录数</div>
                </div>
                <?php if ($loggedIn): ?>
                    <div class="stat-item">
                        <div class="stat-number" style="color: #28a745;"><?= round((time() - $_SESSION['login_time']) / 60) ?></div>
                        <div>🕒 登录时长(分钟)</div>
                    </div>
                <?php endif; ?>
            </div>
            <p style="margin-top: 15px; color: #999; font-size: 0.85rem;">
                <?= $loggedIn ? '🔐 管理员模式' : '👁️ 公开浏览模式' ?> | 系统版本 5.1 | <?= date('Y') ?> ©
            </p>
        </footer>
    </div>
    
    <!-- JavaScript -->
    <script>
        // 类型选择器
        const typeOptions = document.querySelectorAll('.type-option');
        const itemTypeInput = document.getElementById('item_type');
        
        typeOptions.forEach(option => {
            option.addEventListener('click', function() {
                typeOptions.forEach(opt => opt.classList.remove('selected'));
                this.classList.add('selected');
                itemTypeInput.value = this.dataset.type;
                updateFormPlaceholders();
            });
        });
        
        // 图片上传交互
        const uploadArea = document.getElementById('uploadArea');
        if (uploadArea) {
            uploadArea.addEventListener('click', function() {
                document.getElementById('cover_upload').click();
            });
            
            // 拖放上传
            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
                uploadArea.addEventListener(eventName, preventDefaults, false);
            });
            
            function preventDefaults(e) {
                e.preventDefault();
                e.stopPropagation();
            }
            
            ['dragenter', 'dragover'].forEach(eventName => {
                uploadArea.addEventListener(eventName, highlight, false);
            });
            
            ['dragleave', 'drop'].forEach(eventName => {
                uploadArea.addEventListener(eventName, unhighlight, false);
            });
            
            function highlight() {
                uploadArea.style.background = '#eef1ff';
                uploadArea.style.borderColor = '#764ba2';
            }
            
            function unhighlight() {
                uploadArea.style.background = '#f8f9ff';
                uploadArea.style.borderColor = '#667eea';
            }
            
            uploadArea.addEventListener('drop', handleDrop, false);
            
            function handleDrop(e) {
                const dt = e.dataTransfer;
                const files = dt.files;
                if (files.length > 0) {
                    document.getElementById('cover_upload').files = files;
                    previewImage(files[0]);
                }
            }
            
            // 文件选择预览
            document.getElementById('cover_upload').addEventListener('change', function(e) {
                if (this.files.length > 0) {
                    previewImage(this.files[0]);
                }
            });
            
            function previewImage(file) {
                const preview = document.getElementById('uploadPreview');
                if (file && file.type.startsWith('image/')) {
                    const reader = new FileReader();
                    reader.onload = function(e) {
                        preview.src = e.target.result;
                        preview.style.display = 'block';
                    };
                    reader.readAsDataURL(file);
                }
            }
        }
        
        // 设置今天为默认日期
        const dateInput = document.querySelector('input[name="read_date"]');
        if (dateInput) {
            dateInput.value = '<?= date($DATE_FORMAT) ?>';
        }
        
        // 根据类型修改表单占位符
        function updateFormPlaceholders() {
            const type = itemTypeInput.value;
            const titleInput = document.querySelector('input[name="title"]');
            const doubanInput = document.querySelector('input[name="douban_url"]');
            
            if (type === 'book') {
                titleInput.placeholder = '输入书名';
                doubanInput.placeholder = 'https://book.douban.com/subject/...';
            } else {
                titleInput.placeholder = '输入电影名';
                doubanInput.placeholder = 'https://movie.douban.com/subject/...';
            }
        }
        
        // 初始化
        updateFormPlaceholders();
    </script>
</body>
</html>

放在支持php的web服务上,登录密码admin。
书影音记录条目:名称,豆瓣链接,图片(可从豆瓣下载,不能直接引用,有防盗链)。

体验

卡片模式

列表模式

添加条目

我的书影音
代码由deepseek生成。对个人来说已经够用了。

文章标签: web, deepseek

上一篇 : 从valine迁移到waline及数据导入
下一篇 : 用旧苹果手机当nas监控副屏(二)
留言
阅读进度 0%