gate / static /js /user-data-sync.js
harii66's picture
Upload 23 files
b4edbc0 verified
(function() {
'use strict';
class UserDataSync {
constructor() {
this.username = null;
this.data = {
favorite_channels: [],
download_concurrency: 16,
batch_download_concurrency: 3,
fab_position: { bottom: 30, right: 30 },
playback_history: [],
program_reminders: []
};
this.isInitialized = false;
this.pendingUpdates = {};
this.saveTimer = null;
}
/**
* 初始化用户数据
*/
init(username) {
if (!username) {
console.warn('⚠️ UserDataSync: 未提供用户名');
return false;
}
this.username = username;
// ✅ 从 sessionStorage 加载(登录时后端已写入)
const userDataKey = `user_data_${username}`;
const savedData = sessionStorage.getItem(userDataKey);
if (savedData) {
try {
const parsed = JSON.parse(savedData);
this.data = { ...this.data, ...parsed };
console.log('✅ 用户数据已加载:', Object.keys(this.data));
} catch (e) {
console.error('❌ 解析用户数据失败:', e);
}
}
this.isInitialized = true;
return true;
}
/**
* 标记数据已修改(防抖保存)
*/
markChanged(key) {
if (!this.isInitialized) return;
this.pendingUpdates[key] = this.data[key];
// 防抖:1秒后保存
if (this.saveTimer) {
clearTimeout(this.saveTimer);
}
this.saveTimer = setTimeout(() => {
this.save();
}, 1000);
}
/**
* 立即保存到后端
*/
async save(force = false) {
if (!this.isInitialized || !this.username) return false;
if (!force && Object.keys(this.pendingUpdates).length === 0) return true;
const updates = force ? this.data : this.pendingUpdates;
try {
// ✅ 保存到 sessionStorage(同步)
const userDataKey = `user_data_${this.username}`;
sessionStorage.setItem(userDataKey, JSON.stringify(this.data));
// ✅ 通过后端保存到 Redis
const response = await fetch('/api/user/data/sync', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: this.username,
data: updates
})
});
if (response.ok) {
console.log('✅ 用户数据已同步到 Redis:', Object.keys(updates));
this.pendingUpdates = {};
return true;
} else {
console.warn('⚠️ 同步失败,数据已保存到本地');
return false;
}
} catch (error) {
console.error('❌ 同步失败:', error);
return false;
}
}
// ==================== 便捷方法 ====================
getFavorites() {
return this.data.favorite_channels || [];
}
setFavorites(favorites) {
this.data.favorite_channels = Array.isArray(favorites) ? favorites : [];
this.markChanged('favorite_channels');
}
getDownloadConcurrency() {
return this.data.download_concurrency || 16;
}
setDownloadConcurrency(concurrency) {
const value = parseInt(concurrency);
if (value >= 1 && value <= 32) {
this.data.download_concurrency = value;
this.markChanged('download_concurrency');
}
}
getBatchConcurrency() {
return this.data.batch_download_concurrency || 3;
}
setBatchConcurrency(concurrency) {
const value = parseInt(concurrency);
if (value >= 1 && value <= 10) {
this.data.batch_download_concurrency = value;
this.markChanged('batch_download_concurrency');
}
}
getFabPosition() {
return this.data.fab_position || { bottom: 30, right: 30 };
}
setFabPosition(position) {
if (position && typeof position === 'object') {
this.data.fab_position = position;
this.markChanged('fab_position');
}
}
getPlaybackHistory() {
return this.data.playback_history || [];
}
addPlaybackHistory(item) {
if (!Array.isArray(this.data.playback_history)) {
this.data.playback_history = [];
}
// 去重
this.data.playback_history = this.data.playback_history.filter(
h => h.path !== item.path
);
// 添加到开头
this.data.playback_history.unshift(item);
// 最多保留 50 条
if (this.data.playback_history.length > 50) {
this.data.playback_history = this.data.playback_history.slice(0, 50);
}
this.markChanged('playback_history');
}
getProgramReminders() {
return this.data.program_reminders || [];
}
addProgramReminder(reminder) {
if (!Array.isArray(this.data.program_reminders)) {
this.data.program_reminders = [];
}
const exists = this.data.program_reminders.some(
r => r.title === reminder.title && r.startTime === reminder.startTime
);
if (!exists) {
this.data.program_reminders.push(reminder);
this.markChanged('program_reminders');
}
}
removeProgramReminder(reminderId) {
if (Array.isArray(this.data.program_reminders)) {
this.data.program_reminders = this.data.program_reminders.filter(
r => r.id !== reminderId
);
this.markChanged('program_reminders');
}
}
}
// 创建全局单例
window.userDataSync = new UserDataSync();
// 页面卸载时保存
window.addEventListener('beforeunload', () => {
if (window.userDataSync && window.userDataSync.isInitialized) {
window.userDataSync.save(true);
}
});
console.log('✅ UserDataSync 已加载(无需 API)');
})();