guanghulab/modules/m-channel/channel-favorites.js
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

272 lines
9.1 KiB
JavaScript

// 频道收藏与拖拽排序管理
window.ChannelFavorites = {
// 当前正在拖拽的元素
draggingElement: null,
// 初始化
init: function() {
console.log('[favorites] 初始化');
this.bindEvents();
this.renderFavorites();
},
// 绑定事件
bindEvents: function() {
// 使用事件委托监听星星点击
document.addEventListener('click', (e) => {
const star = e.target.closest('.favorite-star');
if (star) {
e.preventDefault();
const card = star.closest('.module-card');
if (card) {
const moduleId = card.dataset.module;
if (moduleId) {
this.toggleFavorite(moduleId, star);
}
}
}
});
// 监听偏好变化,重新渲染收藏状态
if (window.EventBus) {
EventBus.on('preferences:changed', (data) => {
if (data.key === 'favorites' || data.full) {
this.updateAllStars();
}
});
}
},
// 切换收藏状态
toggleFavorite: function(moduleId, starElement) {
if (!window.ChannelPreferences) return;
const isNowFavorite = ChannelPreferences.toggleFavorite(moduleId);
// 更新星星样式
if (starElement) {
if (isNowFavorite) {
starElement.classList.add('active');
starElement.textContent = '★';
} else {
starElement.classList.remove('active');
starElement.textContent = '☆';
}
}
// 触发布局更新(收藏置顶)
this.updateFavoritesOrder();
// 发送事件
if (window.EventBus) {
EventBus.emit('favorite:toggled', {
module: moduleId,
favorite: isNowFavorite
});
}
},
// 更新所有星星的显示状态
updateAllStars: function() {
const favorites = window.ChannelPreferences ? ChannelPreferences.getFavorites() : [];
document.querySelectorAll('.favorite-star').forEach(star => {
const card = star.closest('.module-card');
if (card) {
const moduleId = card.dataset.module;
if (moduleId) {
if (favorites.includes(moduleId)) {
star.classList.add('active');
star.textContent = '★';
} else {
star.classList.remove('active');
star.textContent = '☆';
}
}
}
});
},
// 根据收藏状态重新排序(收藏置顶)
updateFavoritesOrder: function() {
const container = document.querySelector('.channel-content');
if (!container) return;
const cards = Array.from(container.querySelectorAll('.module-card'));
const favorites = window.ChannelPreferences ? ChannelPreferences.getFavorites() : [];
// 按收藏状态和原有顺序排序
cards.sort((a, b) => {
const aId = a.dataset.module;
const bId = b.dataset.module;
const aFav = favorites.includes(aId);
const bFav = favorites.includes(bId);
if (aFav && !bFav) return -1;
if (!aFav && bFav) return 1;
// 如果都是收藏或都不是收藏,保持原有顺序
const aOrder = cards.indexOf(a);
const bOrder = cards.indexOf(b);
return aOrder - bOrder;
});
// 重新插入到容器中
cards.forEach(card => container.appendChild(card));
// 保存排序到偏好设置
const moduleOrder = cards.map(card => card.dataset.module);
if (window.ChannelPreferences) {
ChannelPreferences.setModuleOrder(moduleOrder);
}
},
// 渲染收藏状态(初始化时调用)
renderFavorites: function() {
this.updateAllStars();
},
// ===== 拖拽排序相关 =====
// 初始化拖拽
initDragAndDrop: function() {
console.log('[favorites] 初始化拖拽排序');
const container = document.querySelector('.channel-content');
if (!container) return;
// 为每个卡片添加拖拽手柄
container.querySelectorAll('.module-card').forEach(card => {
// 检查是否已有拖拽手柄
if (!card.querySelector('.drag-handle')) {
const header = card.querySelector('.module-card-header');
if (header) {
const handle = document.createElement('span');
handle.className = 'drag-handle';
handle.innerHTML = '⋮⋮';
handle.setAttribute('draggable', 'false');
header.insertBefore(handle, header.firstChild);
}
}
// 设置 draggable
card.setAttribute('draggable', 'true');
// 移除旧监听器,添加新监听器
card.removeEventListener('dragstart', this.handleDragStart);
card.removeEventListener('dragend', this.handleDragEnd);
card.removeEventListener('dragover', this.handleDragOver);
card.removeEventListener('dragenter', this.handleDragEnter);
card.removeEventListener('dragleave', this.handleDragLeave);
card.removeEventListener('drop', this.handleDrop);
card.addEventListener('dragstart', this.handleDragStart.bind(this));
card.addEventListener('dragend', this.handleDragEnd.bind(this));
card.addEventListener('dragover', this.handleDragOver);
card.addEventListener('dragenter', this.handleDragEnter);
card.addEventListener('dragleave', this.handleDragLeave);
card.addEventListener('drop', this.handleDrop.bind(this));
});
},
// 拖拽开始
handleDragStart: function(e) {
this.draggingElement = e.target.closest('.module-card');
if (!this.draggingElement) return;
e.dataTransfer.setData('text/plain', this.draggingElement.dataset.module);
e.dataTransfer.effectAllowed = 'move';
// 添加拖拽中的样式
setTimeout(() => {
this.draggingElement.classList.add('dragging');
}, 0);
},
// 拖拽结束
handleDragEnd: function(e) {
const card = e.target.closest('.module-card');
if (card) {
card.classList.remove('dragging');
}
// 移除所有高亮
document.querySelectorAll('.module-card.drop-target').forEach(el => {
el.classList.remove('drop-target');
});
this.draggingElement = null;
},
// 拖拽经过(必须阻止默认事件才能成为放置目标)
handleDragOver: function(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
},
// 拖拽进入
handleDragEnter: function(e) {
const card = e.target.closest('.module-card');
if (card && card !== this.draggingElement) {
card.classList.add('drop-target');
}
},
// 拖拽离开
handleDragLeave: function(e) {
const card = e.target.closest('.module-card');
if (card) {
card.classList.remove('drop-target');
}
},
// 放置
handleDrop: function(e) {
e.preventDefault();
const targetCard = e.target.closest('.module-card');
if (!targetCard || !this.draggingElement || targetCard === this.draggingElement) {
return;
}
// 移除高亮
targetCard.classList.remove('drop-target');
// 获取所有卡片
const container = document.querySelector('.channel-content');
const cards = Array.from(container.querySelectorAll('.module-card'));
const fromIndex = cards.indexOf(this.draggingElement);
const toIndex = cards.indexOf(targetCard);
if (fromIndex === -1 || toIndex === -1) return;
// 重新排序
if (window.ChannelPreferences) {
ChannelPreferences.reorderModules(fromIndex, toIndex);
}
// 移动 DOM 元素
if (fromIndex < toIndex) {
targetCard.insertAdjacentElement('afterend', this.draggingElement);
} else {
targetCard.insertAdjacentElement('beforebegin', this.draggingElement);
}
// 触发事件
if (window.EventBus) {
EventBus.emit('favorites:reordered', {
from: fromIndex,
to: toIndex,
module: this.draggingElement.dataset.module
});
}
},
// 刷新拖拽功能(在布局变化后调用)
refreshDragAndDrop: function() {
this.initDragAndDrop();
}
};
console.log('[favorites] 已加载');