如何实现本地视频图库单选按钮评分的持久化存储?
本地视频图库评分存储方案解决指南
项目背景
我正在开发一个本地运行的视频图库,包含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,字段如下:
执行SQL语句:字段名 类型 说明 id INT(11) 主键,自增 video_id VARCHAR(50) 对应视频的name(如m1,m2) rating TINYINT(1) 评分值1-5 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
相关产品推荐
相关产品推荐

