You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现本地视频图库单选按钮评分的持久化存储?

本地视频图库评分存储方案解决指南

项目背景

我正在开发一个本地运行的视频图库,包含15个页面,每页有200-300个视频缩略图。点击缩略图会打开模态框查看视频详情和播放视频。目前使用StarRate模块的单选按钮实现五星评分功能,需要完成两个核心需求:

  • 页面加载时从本地存储读取评分并恢复单选按钮状态
  • 评分变更时自动保存所有评分到本地,确保下次打开加载最新数据

之前考虑过localStorage但担心数据丢失,倾向于保存到本地文件(JSON/TXT均可),同时也在评估用本地MySQL存储的方案。

当前文件保存代码的问题及改进

找到的保存代码存在两个问题:每次保存生成新文件(如Text.txt、Text(1).txt)而非覆盖;未绑定评分变更的触发事件。

关于文件覆盖的说明

浏览器出于安全限制,前端JavaScript无法直接覆盖本地已存在的文件,只能触发下载提示,由用户手动替换原有文件。如果需要自动覆盖本地文件,需要用桌面应用框架(如Electron),但纯前端可以优化以下两点:

1. 修复保存代码的BUG并优化格式

原代码中存在单选按钮判断的逻辑错误(=赋值而非===判断),同时将保存格式改为JSON,更便于后续读取解析:

<script>
// 用JSON格式存储评分,结构为 { "m1": 3, "m2": 5 }
function saveRatings() {
    const ratings = {};
    // 遍历所有单选按钮,收集选中的评分
    document.querySelectorAll('input[type="radio"]:checked').forEach(radio => {
        ratings[radio.name] = parseInt(radio.value);
    });
    // 转为JSON字符串
    const textToSave = JSON.stringify(ratings, null, 2);
    const blob = new Blob([textToSave], { type: "application/json" });
    const url = window.URL.createObjectURL(blob);
    const downloadLink = document.createElement("a");
    downloadLink.download = "ratings.json";
    downloadLink.href = url;
    downloadLink.onclick = (e) => {
        setTimeout(() => window.URL.revokeObjectURL(url), 100);
        document.body.removeChild(e.target);
    };
    document.body.appendChild(downloadLink);
    downloadLink.click();
}

// 绑定评分变更事件:所有单选按钮改变时触发保存
document.querySelectorAll('input[type="radio"]').forEach(radio => {
    radio.addEventListener('change', saveRatings);
});
</script>

2. 实现从本地文件加载评分

添加文件选择控件,让用户选择之前保存的ratings.json,读取后恢复单选按钮状态:

<!-- 在页面添加文件选择按钮 -->
<input type="file" id="loadRatingsFile" accept=".json" style="margin: 10px;">

<script>
document.getElementById('loadRatingsFile').addEventListener('change', function(e) {
    const file = e.target.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = function(event) {
        try {
            const ratings = JSON.parse(event.target.result);
            // 遍历评分数据,设置对应单选按钮为选中状态
            Object.keys(ratings).forEach(videoId => {
                const ratingValue = ratings[videoId];
                const radio = document.querySelector(`input[name="${videoId}"][value="${ratingValue}"]`);
                if (radio) radio.checked = true;
            });
            alert('评分加载成功');
        } catch (err) {
            alert('文件格式错误,请选择正确的ratings.json文件');
        }
    };
    reader.readAsText(file);
});
</script>

XAMPP + MySQL + PHP 存储方案指导

如果选择用数据库存储评分,这是更可靠的持久化方案,以下是完整步骤:

1. 安装并配置XAMPP

  • 下载安装XAMPP,启动Apache和MySQL服务
  • 访问http://localhost/phpmyadmin进入数据库管理界面

2. 创建数据库和表

在phpMyAdmin中:

  • 创建数据库:video_gallery
  • 创建评分表ratings,字段如下:
    字段名类型说明
    idINT(11)主键,自增
    video_idVARCHAR(50)对应视频的name(如m1,m2)
    ratingTINYINT(1)评分值1-5
    执行SQL语句:
    CREATE DATABASE video_gallery;
    USE video_gallery;
    CREATE TABLE ratings (
        id INT(11) AUTO_INCREMENT PRIMARY KEY,
        video_id VARCHAR(50) NOT NULL UNIQUE,
        rating TINYINT(1) NOT NULL CHECK (rating BETWEEN 1 AND 5)
    );
    

3. 编写PHP接口

在XAMPP的htdocs目录下创建以下两个PHP文件:

save_rating.php(保存/更新评分)

<?php
header('Content-Type: application/json');
$conn = new mysqli('localhost', 'root', '', 'video_gallery');
if ($conn->connect_error) {
    die(json_encode(['success' => false, 'msg' => '数据库连接失败']));
}

$video_id = $_POST['video_id'] ?? '';
$rating = $_POST['rating'] ?? 0;

if (empty($video_id) || !in_array($rating, [1,2,3,4,5])) {
    echo json_encode(['success' => false, 'msg' => '参数错误']);
    exit;
}

// 存在则更新,不存在则插入
$sql = "INSERT INTO ratings (video_id, rating) VALUES (?, ?) ON DUPLICATE KEY UPDATE rating = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('sii', $video_id, $rating, $rating);

if ($stmt->execute()) {
    echo json_encode(['success' => true]);
} else {
    echo json_encode(['success' => false, 'msg' => $stmt->error]);
}

$stmt->close();
$conn->close();
?>

load_ratings.php(加载所有评分)

<?php
header('Content-Type: application/json');
$conn = new mysqli('localhost', 'root', '', 'video_gallery');
if ($conn->connect_error) {
    die(json_encode([]));
}

$sql = "SELECT video_id, rating FROM ratings";
$result = $conn->query($sql);
$ratings = [];
while ($row = $result->fetch_assoc()) {
    $ratings[$row['video_id']] = $row['rating'];
}

echo json_encode($ratings);
$conn->close();
?>

4. 修改前端代码对接接口

<script>
// 页面加载时加载评分
$(document).ready(function() {
    $.get('http://localhost/load_ratings.php', function(ratings) {
        Object.keys(ratings).forEach(videoId => {
            const ratingValue = ratings[videoId];
            $(`input[name="${videoId}"][value="${ratingValue}"]`).prop('checked', true);
        });
    });

    // 评分变更时保存到数据库
    $('input[type="radio"]').on('change', function() {
        const videoId = $(this).attr('name');
        const rating = $(this).val();
        $.post('http://localhost/save_rating.php', {
            video_id: videoId,
            rating: rating
        }, function(response) {
            if (!response.success) {
                alert('保存失败:' + response.msg);
            }
        }, 'json');
    });
});
</script>

注意事项

  • 确保XAMPP的Apache和MySQL服务处于运行状态
  • 前端页面需放在XAMPP的htdocs目录下,通过http://localhost/xxx.html访问,不能直接打开本地HTML文件
  • 首次使用MySQL时,记得设置root密码或保持默认(空密码)

内容的提问来源于stack exchange,提问作者Tim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:57:01