diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 000000000..892a6fef8 --- /dev/null +++ b/assets/css/style.css @@ -0,0 +1,446 @@ +/* WebStack.cc 简洁样式 */ + +/* 基础重置 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #333; + background-color: #f8f9fa; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 20px; +} + +/* 头部样式 */ +.header { + background: #fff; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + position: sticky; + top: 0; + z-index: 100; +} + +.header .container { + display: flex; + align-items: center; + justify-content: space-between; + padding: 15px 20px; +} + +.logo { + display: flex; + align-items: center; + gap: 15px; +} + +.logo img { + width: 48px; + height: 48px; + object-fit: contain; +} + +.logo h1 { + font-size: 24px; + font-weight: 700; + color: #2c3e50; + margin: 0; +} + +.logo p { + font-size: 14px; + color: #666; + margin: 0; + margin-left: 10px; +} + +/* 导航样式 */ +.nav { + flex: 1; + margin: 0 30px; +} + +.nav-list { + display: flex; + list-style: none; + gap: 25px; + justify-content: center; + margin: 0; + padding: 0; +} + +.nav-list a { + text-decoration: none; + color: #555; + font-weight: 500; + padding: 10px 0; + position: relative; + transition: color 0.3s ease; +} + +.nav-list a:hover { + color: #007bff; +} + +.nav-list a::after { + content: ''; + position: absolute; + width: 0; + height: 2px; + bottom: 0; + left: 50%; + background-color: #007bff; + transition: all 0.3s ease; +} + +.nav-list a:hover::after, +.nav-list a.active::after { + width: 100%; + left: 0; +} + +/* 语言切换 */ +.lang-switch { + display: flex; + gap: 5px; +} + +.lang-btn { + padding: 8px 12px; + text-decoration: none; + color: #666; + border: 1px solid #ddd; + border-radius: 5px; + font-size: 12px; + transition: all 0.3s ease; +} + +.lang-btn:hover, +.lang-btn.active { + background-color: #007bff; + color: white; + border-color: #007bff; +} + +/* 主要内容区域 */ +.main { + min-height: calc(100vh - 200px); + padding: 40px 0; +} + +.content { + padding: 20px 0; +} + +/* 分类标题 */ +.category-title { + display: flex; + align-items: center; + margin: 40px 0 25px 0; + padding-bottom: 15px; + border-bottom: 2px solid #e9ecef; +} + +.category-title h2 { + font-size: 28px; + font-weight: 700; + color: #2c3e50; + margin: 0; +} + +.category-title .icon { + font-size: 24px; + margin-right: 15px; + color: #007bff; +} + +/* 子分类样式 */ +.subcategory { + margin: 30px 0; +} + +.subcategory-title { + display: flex; + align-items: center; + margin: 25px 0 20px 0; +} + +.subcategory-title h3 { + font-size: 22px; + font-weight: 600; + color: #495057; + margin: 0; +} + +.subcategory-title .label { + background: #007bff; + color: white; + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; + margin-left: 10px; +} + +/* 网站网格 */ +.websites-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 20px; + margin-bottom: 40px; +} + +/* 网站卡片 */ +.website-card { + background: #fff; + border: 1px solid #e9ecef; + border-radius: 8px; + padding: 20px; + text-decoration: none; + color: inherit; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 15px; + position: relative; +} + +.website-card:hover { + transform: translateY(-2px); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + border-color: #007bff; +} + +.website-logo { + width: 48px; + height: 48px; + border-radius: 8px; + object-fit: contain; + flex-shrink: 0; +} + +.website-info { + flex: 1; + min-width: 0; +} + +.website-name { + font-size: 16px; + font-weight: 600; + color: #2c3e50; + margin: 0 0 5px 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.website-description { + font-size: 14px; + color: #666; + margin: 0; + line-height: 1.4; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.website-card::after { + content: '↗'; + position: absolute; + top: 15px; + right: 15px; + font-size: 16px; + color: #bbb; + transition: color 0.3s ease; +} + +.website-card:hover::after { + color: #007bff; +} + +/* 空状态 */ +.empty-state { + text-align: center; + padding: 60px 20px; + color: #6c757d; +} + +.empty-state h3 { + font-size: 18px; + margin-bottom: 10px; +} + +.empty-state p { + font-size: 14px; + margin: 0; +} + +/* 加载状态 */ +.loading { + text-align: center; + padding: 40px 20px; + color: #6c757d; +} + +.loading::before { + content: '⏳'; + font-size: 24px; + margin-right: 10px; +} + +/* 错误状态 */ +.error { + text-align: center; + padding: 40px 20px; + color: #dc3545; +} + +.error::before { + content: '⚠️'; + font-size: 24px; + margin-right: 10px; +} + +/* 底部样式 */ +.footer { + background: #fff; + border-top: 1px solid #e9ecef; + padding: 20px 0; + text-align: center; + color: #666; + font-size: 14px; +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .header .container { + flex-direction: column; + gap: 15px; + padding: 15px 20px; + } + + .nav { + margin: 0; + } + + .nav-list { + flex-wrap: wrap; + justify-content: center; + gap: 15px; + } + + .nav-list a { + font-size: 14px; + padding: 8px 0; + } + + .logo { + order: -1; + justify-content: center; + } + + .logo h1 { + font-size: 20px; + } + + .logo p { + display: none; + } + + .websites-grid { + grid-template-columns: 1fr; + gap: 15px; + } + + .website-card { + padding: 15px; + } + + .website-logo { + width: 40px; + height: 40px; + } + + .website-name { + font-size: 15px; + } + + .website-description { + font-size: 13px; + } + + .category-title h2 { + font-size: 24px; + } + + .subcategory-title h3 { + font-size: 20px; + } +} + +@media (max-width: 480px) { + .container { + padding: 0 15px; + } + + .nav-list { + gap: 10px; + } + + .nav-list a { + font-size: 13px; + padding: 6px 0; + } + + .website-card { + padding: 12px; + gap: 12px; + } + + .website-logo { + width: 36px; + height: 36px; + } +} + +/* 平滑滚动 */ +html { + scroll-behavior: smooth; +} + +/* 焦点样式 */ +.website-card:focus { + outline: 2px solid #007bff; + outline-offset: 2px; +} + +/* 过渡动画 */ +.category-title, +.subcategory-title, +.website-card { + opacity: 0; + transform: translateY(20px); + animation: fadeInUp 0.6s ease forwards; +} + +.website-card:nth-child(1) { animation-delay: 0.1s; } +.website-card:nth-child(2) { animation-delay: 0.2s; } +.website-card:nth-child(3) { animation-delay: 0.3s; } +.website-card:nth-child(4) { animation-delay: 0.4s; } +.website-card:nth-child(5) { animation-delay: 0.5s; } +.website-card:nth-child(6) { animation-delay: 0.6s; } + +@keyframes fadeInUp { + to { + opacity: 1; + transform: translateY(0); + } +} \ No newline at end of file diff --git a/assets/js/app.js b/assets/js/app.js new file mode 100644 index 000000000..0fd0d31f3 --- /dev/null +++ b/assets/js/app.js @@ -0,0 +1,261 @@ +// WebStack.cc 应用脚本 + +class WebStackApp { + constructor() { + this.data = null; + this.init(); + } + + async init() { + try { + await this.loadData(); + this.renderContent(); + this.bindEvents(); + } catch (error) { + this.showError('加载数据失败,请刷新页面重试'); + console.error('Error loading data:', error); + } + } + + async loadData() { + const response = await fetch('./websites.json'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + this.data = await response.json(); + } + + renderContent() { + const content = document.getElementById('content'); + if (!content) return; + + if (!this.data || !this.data.categories) { + this.showError('数据格式错误'); + return; + } + + content.innerHTML = ''; + + this.data.categories.forEach(category => { + const categoryElement = this.createCategoryElement(category); + content.appendChild(categoryElement); + }); + } + + createCategoryElement(category) { + const categoryDiv = document.createElement('section'); + categoryDiv.className = 'category'; + categoryDiv.id = category.id; + + // 分类标题 + const titleDiv = document.createElement('div'); + titleDiv.className = 'category-title'; + + const icon = this.getIcon(category.icon); + const titleHTML = ` + ${icon} +

${category.name}

+ `; + titleDiv.innerHTML = titleHTML; + + categoryDiv.appendChild(titleDiv); + + // 子分类或网站列表 + if (category.subcategories && category.subcategories.length > 0) { + // 有子分类的情况 + category.subcategories.forEach(subcategory => { + const subcategoryDiv = this.createSubcategoryElement(subcategory); + categoryDiv.appendChild(subcategoryDiv); + }); + } else if (category.websites && category.websites.length > 0) { + // 直接是网站列表 + const gridDiv = this.createWebsitesGrid(category.websites); + categoryDiv.appendChild(gridDiv); + } + + return categoryDiv; + } + + createSubcategoryElement(subcategory) { + const subcategoryDiv = document.createElement('div'); + subcategoryDiv.className = 'subcategory'; + subcategoryDiv.id = subcategory.id; + + // 子分类标题 + const titleDiv = document.createElement('div'); + titleDiv.className = 'subcategory-title'; + const titleHTML = ` +

${subcategory.name}

+ ${subcategory.websites ? subcategory.websites.length : 0} + `; + titleDiv.innerHTML = titleHTML; + + subcategoryDiv.appendChild(titleDiv); + + // 网站网格 + if (subcategory.websites && subcategory.websites.length > 0) { + const gridDiv = this.createWebsitesGrid(subcategory.websites); + subcategoryDiv.appendChild(gridDiv); + } + + return subcategoryDiv; + } + + createWebsitesGrid(websites) { + const gridDiv = document.createElement('div'); + gridDiv.className = 'websites-grid'; + + websites.forEach(website => { + const card = this.createWebsiteCard(website); + gridDiv.appendChild(card); + }); + + return gridDiv; + } + + createWebsiteCard(website) { + const card = document.createElement('a'); + card.className = 'website-card'; + card.href = website.url; + card.target = '_blank'; + card.rel = 'noopener noreferrer'; + card.title = website.description; + + // 处理logo图片 + let logoSrc = `../assets/images/logos/${website.logo}`; + if (window.location.pathname.includes('/index.html') || window.location.pathname === '/') { + logoSrc = `./assets/images/logos/${website.logo}`; + } + + const cardHTML = ` + +
+

${website.name}

+

${website.description}

+
+ `; + + card.innerHTML = cardHTML; + + // 添加点击事件 + card.addEventListener('click', (e) => { + // 可以在这里添加统计代码 + this.trackClick(website.name); + }); + + return card; + } + + getIcon(iconName) { + const icons = { + 'star': '⭐', + 'doc': '📄', + 'lightbulb': '💡', + 'thumbs-up': '👍', + 'diamond': '💎', + 'pencil': '✏️', + 'user': '👥', + 'recommended': '⭐', + 'community': '📄', + 'inspiration': '💡', + 'resources': '👍', + 'tools': '💎', + 'learning': '✏️', + 'teams': '👥' + }; + return icons[iconName] || '🔗'; + } + + bindEvents() { + // 平滑滚动 + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', (e) => { + e.preventDefault(); + const target = document.querySelector(anchor.getAttribute('href')); + if (target) { + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + + // 更新导航状态 + document.querySelectorAll('.nav-list a').forEach(link => { + link.classList.remove('active'); + }); + anchor.classList.add('active'); + } + }); + }); + + // 滚动时更新导航状态 + window.addEventListener('scroll', () => { + this.updateActiveNavigation(); + }); + } + + updateActiveNavigation() { + const sections = document.querySelectorAll('.category'); + const navLinks = document.querySelectorAll('.nav-list a'); + + let current = ''; + sections.forEach(section => { + const sectionTop = section.offsetTop - 100; + if (window.pageYOffset >= sectionTop) { + current = section.getAttribute('id'); + } + }); + + navLinks.forEach(link => { + link.classList.remove('active'); + if (link.getAttribute('href') === `#${current}`) { + link.classList.add('active'); + } + }); + } + + showLoading() { + const content = document.getElementById('content'); + if (content) { + content.innerHTML = '
正在加载...
'; + } + } + + showError(message) { + const content = document.getElementById('content'); + if (content) { + content.innerHTML = `
${message}
`; + } + } + + showEmpty(message = '暂无数据') { + const content = document.getElementById('content'); + if (content) { + content.innerHTML = ` +
+

${message}

+

请稍后再试或联系管理员

+
+ `; + } + } + + trackClick(websiteName) { + // 可以在这里添加统计分析代码 + console.log('Clicked:', websiteName); + + // 例如:发送到Google Analytics + // gtag('event', 'click', { + // event_category: 'website', + // event_label: websiteName + // }); + } +} + +// 当页面加载完成后初始化应用 +document.addEventListener('DOMContentLoaded', () => { + const app = new WebStackApp(); +}); + +// 导出供其他脚本使用 +window.WebStackApp = WebStackApp; \ No newline at end of file diff --git a/cn/index.html b/cn/index.html index 7172f7df3..1cf056828 100644 --- a/cn/index.html +++ b/cn/index.html @@ -1,4293 +1,54 @@ - - - - - - - - + + WebStack.cc - 设计师网址导航 - - + + - - - - - - - - - - - - - - - - - - - - - - - + - - - -
-