feat: 新增平台

This commit is contained in:
2025-11-30 19:49:25 +08:00
parent c3e56a954d
commit fbd2c491b2
41 changed files with 4293 additions and 76 deletions

View File

@@ -1,5 +1,107 @@
// 现代化UI组件库
const UI = {
// 初始化所有自定义下拉框
initSelects() {
document.querySelectorAll('select.ui-input, select.ui-select').forEach(select => {
if (select.dataset.uiInit) return; // 已初始化
this.createCustomSelect(select);
});
},
// 创建自定义下拉框
createCustomSelect(select) {
select.dataset.uiInit = 'true';
// 创建包装器
const wrapper = document.createElement('div');
wrapper.className = 'ui-select-wrapper';
select.parentNode.insertBefore(wrapper, select);
// 隐藏原生 select
select.classList.add('ui-select-native');
wrapper.appendChild(select);
// 创建触发器
const trigger = document.createElement('div');
trigger.className = 'ui-select-trigger';
trigger.tabIndex = 0;
wrapper.appendChild(trigger);
// 创建下拉菜单
const dropdown = document.createElement('div');
dropdown.className = 'ui-select-dropdown';
wrapper.appendChild(dropdown);
// 更新选项
const updateOptions = () => {
dropdown.innerHTML = '';
const selectedValue = select.value;
let selectedText = '';
Array.from(select.options).forEach(option => {
const optionEl = document.createElement('div');
optionEl.className = 'ui-select-option';
optionEl.dataset.value = option.value;
optionEl.textContent = option.textContent;
if (option.value === selectedValue) {
optionEl.classList.add('selected');
selectedText = option.textContent;
}
optionEl.addEventListener('click', () => {
select.value = option.value;
select.dispatchEvent(new Event('change', { bubbles: true }));
wrapper.classList.remove('open');
updateTrigger();
});
dropdown.appendChild(optionEl);
});
return selectedText;
};
// 更新触发器显示
const updateTrigger = () => {
const selectedText = updateOptions();
if (selectedText) {
trigger.innerHTML = `<span>${selectedText}</span>`;
} else {
trigger.innerHTML = `<span class="placeholder">${select.options[0]?.textContent || '请选择'}</span>`;
}
};
// 初始化
updateTrigger();
// 点击触发器
trigger.addEventListener('click', (e) => {
e.stopPropagation();
// 关闭其他下拉框
document.querySelectorAll('.ui-select-wrapper.open').forEach(w => {
if (w !== wrapper) w.classList.remove('open');
});
wrapper.classList.toggle('open');
});
// 键盘支持
trigger.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
wrapper.classList.toggle('open');
} else if (e.key === 'Escape') {
wrapper.classList.remove('open');
}
});
// 监听原生 select 变化
select.addEventListener('change', updateTrigger);
// 监听选项变化(用于动态更新)
const observer = new MutationObserver(updateTrigger);
observer.observe(select, { childList: true, subtree: true });
},
// 显示通知消息
notify(message, type = 'info', duration = 3000) {
const container = document.getElementById('notification-container') || this.createNotificationContainer();
@@ -118,3 +220,20 @@ const UI = {
return icons[type] || icons.info;
}
};
// 点击外部关闭下拉框
document.addEventListener('click', (e) => {
if (!e.target.closest('.ui-select-wrapper')) {
document.querySelectorAll('.ui-select-wrapper.open').forEach(w => {
w.classList.remove('open');
});
}
});
// 页面加载完成后自动初始化下拉框
document.addEventListener('DOMContentLoaded', () => {
UI.initSelects();
});
// 提供手动刷新方法(用于动态加载的内容)
UI.refreshSelects = UI.initSelects;