439 lines
14 KiB
HTML
439 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>S.A. - 我的作品</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
line-height: 1.6;
|
|
color: #333;
|
|
background: linear-gradient(135deg, #e1f5fe, #f3e5f5);
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 0 20px;
|
|
}
|
|
|
|
/* 导航栏样式 */
|
|
header {
|
|
background-color: #009688; /* 青色主色调 */
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 1000;
|
|
}
|
|
|
|
nav {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 1rem 2rem;
|
|
}
|
|
|
|
.logo {
|
|
font-size: 1.5rem;
|
|
font-weight: bold;
|
|
color: white;
|
|
}
|
|
|
|
.nav-links {
|
|
display: flex;
|
|
list-style: none;
|
|
}
|
|
|
|
.nav-links li {
|
|
margin-left: 2rem;
|
|
}
|
|
|
|
.nav-links a {
|
|
text-decoration: none;
|
|
color: rgba(255, 255, 255, 0.9);
|
|
font-weight: 500;
|
|
transition: color 0.3s;
|
|
}
|
|
|
|
.nav-links a:hover {
|
|
color: white;
|
|
}
|
|
|
|
/* 主要内容区域 */
|
|
main {
|
|
padding: 2rem 0;
|
|
}
|
|
|
|
/* 英雄区域 */
|
|
.hero {
|
|
background: linear-gradient(135deg, #009688, #2196F3); /* 青蓝渐变 */
|
|
color: white;
|
|
padding: 4rem 0;
|
|
text-align: center;
|
|
margin-bottom: 3rem;
|
|
}
|
|
|
|
.hero h1 {
|
|
font-size: 2.5rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.hero p {
|
|
font-size: 1.2rem;
|
|
max-width: 600px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* 项目区域 */
|
|
.projects {
|
|
padding: 2rem 0;
|
|
}
|
|
|
|
.projects h2 {
|
|
text-align: center;
|
|
font-size: 2.5rem;
|
|
margin-bottom: 3rem;
|
|
color: #009688; /* 青色标题 */
|
|
}
|
|
|
|
.project-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
gap: 2rem;
|
|
margin-top: 2rem;
|
|
}
|
|
|
|
.project-card {
|
|
background-color: #E0F7FA; /* 青色透明背景 */
|
|
padding: 2rem;
|
|
border-radius: 10px;
|
|
text-align: center;
|
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
|
|
transition: transform 0.3s;
|
|
border: 1px solid rgba(0, 150, 136, 0.2); /* 青色边框 */
|
|
}
|
|
|
|
.project-card:hover {
|
|
transform: translateY(-10px);
|
|
box-shadow: 0 15px 30px rgba(0, 150, 136, 0.2); /* 青色阴影 */
|
|
}
|
|
|
|
.project-card h3 {
|
|
color: #009688; /* 青色标题 */
|
|
margin-bottom: 1rem;
|
|
font-size: 1.3rem;
|
|
}
|
|
|
|
.project-card h3 a {
|
|
color: inherit;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.project-card h3 a:hover {
|
|
color: #2196F3; /* 蓝色悬停效果 */
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.project-card .description {
|
|
margin-bottom: 1rem;
|
|
color: #666;
|
|
}
|
|
|
|
.project-card .tags {
|
|
margin: 1rem 0;
|
|
}
|
|
|
|
.tag {
|
|
display: inline-block;
|
|
background-color: #009688; /* 青色标签 */
|
|
color: white;
|
|
padding: 0.3rem 0.8rem;
|
|
border-radius: 20px;
|
|
font-size: 0.8rem;
|
|
margin: 0.2rem;
|
|
}
|
|
|
|
.project-card .links {
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.project-card .links a {
|
|
display: inline-block;
|
|
margin: 0 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
background-color: #009688; /* 青色按钮 */
|
|
color: white;
|
|
text-decoration: none;
|
|
border-radius: 5px;
|
|
transition: background-color 0.3s;
|
|
}
|
|
|
|
.project-card .links a:hover {
|
|
background-color: #2196F3; /* 蓝色悬停 */
|
|
}
|
|
|
|
/* 关于区域 */
|
|
.about {
|
|
padding: 5rem 0;
|
|
background-color: #E1F5FE; /* 淡青背景 */
|
|
}
|
|
|
|
.about h2 {
|
|
text-align: center;
|
|
font-size: 2.5rem;
|
|
margin-bottom: 2rem;
|
|
color: #009688; /* 青色标题 */
|
|
}
|
|
|
|
.about p {
|
|
margin-bottom: 1rem;
|
|
font-size: 1.1rem;
|
|
text-align: center;
|
|
}
|
|
|
|
/* 页脚 */
|
|
footer {
|
|
background-color: #009688; /* 青色页脚 */
|
|
color: white;
|
|
padding: 3rem 0;
|
|
text-align: center;
|
|
}
|
|
|
|
footer p {
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
/* 响应式设计 */
|
|
@media (max-width: 768px) {
|
|
.nav-links {
|
|
display: none;
|
|
}
|
|
|
|
.hero h1 {
|
|
font-size: 2rem;
|
|
}
|
|
|
|
.hero {
|
|
padding: 3rem 0;
|
|
}
|
|
|
|
.project-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
nav {
|
|
flex-direction: column;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.logo {
|
|
margin-bottom: 1rem;
|
|
}
|
|
}
|
|
</style>
|
|
<link rel="icon" href="../favicon.ico" type="image/x-icon">
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<nav>
|
|
<div class="logo">S.A. - 我的作品</div>
|
|
<ul class="nav-links">
|
|
<li><a href="/">首页</a></li>
|
|
<li><a href="#projects">项目</a></li>
|
|
<li><a href="#about">关于</a></li>
|
|
</ul>
|
|
</nav>
|
|
</header>
|
|
|
|
<main>
|
|
<section id="home" class="hero">
|
|
<div class="container">
|
|
<h1>S.A. - 我的作品</h1>
|
|
<p>欢迎来到 S.A. 的开源项目展示页面</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="projects" class="projects">
|
|
<div class="container">
|
|
<h2>我的作品</h2>
|
|
<div id="projects-container" class="project-grid">
|
|
<!-- 项目将通过JavaScript动态加载 -->
|
|
</div>
|
|
</div>
|
|
</section>-->
|
|
|
|
<section id="about" class="about">
|
|
<div class="container">
|
|
<h2>关于</h2>
|
|
<p>这里展示了 S.A. (@snoware) 的个人作品集。所有项目都采用了现代化的技术栈。</p>
|
|
<p>欢迎访问我的 <a href="https://gitee.com/Ironbayberry/" target="_blank" style="color: #009688; text-decoration: underline;">Gitee 个人主页</a> 查看更多项目。</p>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<footer>
|
|
<div class="container">
|
|
<p>© 2026 S.A. (@snoware). All rights reserved.</p>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
// 用于存储项目数据
|
|
let projectsData = [];
|
|
|
|
// 加载 TOML 文件并渲染项目
|
|
async function loadProjects() {
|
|
try {
|
|
// 从同目录下的 projects.txt 文件加载数据
|
|
const response = await fetch('projects.txt');
|
|
if (!response.ok) {
|
|
throw new Error(`无法加载项目数据: ${response.status} ${response.statusText}`);
|
|
}
|
|
|
|
const tomlText = await response.text();
|
|
|
|
// 简单的 TOML 解析器(由于不能引入外部库,我们使用简化的解析方法)
|
|
parseToml(tomlText);
|
|
renderProjects();
|
|
} catch (error) {
|
|
console.error('加载项目数据时出错:', error);
|
|
const container = document.getElementById('projects-container');
|
|
container.innerHTML = `<p class="error">加载项目失败: ${error.message}</p>`;
|
|
}
|
|
}
|
|
|
|
// 简化的 TOML 解析器
|
|
function parseToml(tomlText) {
|
|
// 将 TOML 文本转换为 JavaScript 对象
|
|
const lines = tomlText.split('\n');
|
|
let currentProject = null;
|
|
projectsData = [];
|
|
|
|
for (const line of lines) {
|
|
const trimmedLine = line.trim();
|
|
|
|
// 检测项目开始 [[projects]]
|
|
if (trimmedLine.startsWith('[[projects]]')) {
|
|
currentProject = {};
|
|
projectsData.push(currentProject);
|
|
} else if (currentProject && trimmedLine.includes('=')) {
|
|
const [key, value] = trimmedLine.split('=');
|
|
const cleanKey = key.trim();
|
|
let cleanValue = value.trim();
|
|
|
|
// 处理字符串值(去除引号)
|
|
if (cleanValue.startsWith('"') && cleanValue.endsWith('"')) {
|
|
cleanValue = cleanValue.substring(1, cleanValue.length - 1);
|
|
}
|
|
// 处理数组值
|
|
else if (cleanValue.startsWith('[') && cleanValue.endsWith(']')) {
|
|
cleanValue = cleanValue.substring(1, cleanValue.length - 1)
|
|
.split(',')
|
|
.map(item => item.trim().replace(/"/g, ''));
|
|
}
|
|
|
|
currentProject[cleanKey] = cleanValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 渲染项目到页面
|
|
function renderProjects() {
|
|
const container = document.getElementById('projects-container');
|
|
|
|
if (!projectsData || projectsData.length === 0) {
|
|
container.innerHTML = '<p>暂无项目数据</p>';
|
|
return;
|
|
}
|
|
|
|
// 生成项目卡片HTML
|
|
const projectsHTML = projectsData.map(project => {
|
|
// 处理URL中的模板变量
|
|
const processedDemoUrl = project.demo_url ? project.demo_url.replace(/\{\$rthSuffix\}/g, '') : null;
|
|
const processedRepoUrl = project.repo_url ? project.repo_url.replace(/\{\$rthSuffix\}/g, '') : null;
|
|
const processedDocUrl = project.doc_url ? project.doc_url.replace(/\{\$rthSuffix\}/g, '') : null;
|
|
|
|
return `
|
|
<div class="project-card">
|
|
<h3><a href="${processedDemoUrl || processedRepoUrl || '#'}" target="_blank">${project.name || '未知项目'}</a></h3>
|
|
<p class="description">${project.description || '暂无描述'}</p>
|
|
<div class="tags">
|
|
${(project.tags || []).map(tag => `<span class="tag">${tag}</span>`).join('')}
|
|
</div>
|
|
<div class="links">
|
|
${processedRepoUrl ? `<a href="${processedRepoUrl}" target="_blank">代码仓库</a>` : ''}
|
|
${processedDemoUrl ? `<a href="${processedDemoUrl}" target="_blank">演示</a>` : ''}
|
|
${processedDocUrl ? `<a href="${processedDocUrl}" target="_blank">文档</a>` : ''}
|
|
</div>
|
|
</div>
|
|
`}).join('');
|
|
|
|
container.innerHTML = projectsHTML;
|
|
}
|
|
|
|
// 平滑滚动效果
|
|
function setupSmoothScrolling() {
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
anchor.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
|
|
const targetId = this.getAttribute('href');
|
|
if (targetId === '#') return;
|
|
|
|
const targetElement = document.querySelector(targetId);
|
|
if (targetElement) {
|
|
window.scrollTo({
|
|
top: targetElement.offsetTop - 80, // 减去导航栏高度
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// 导航栏高亮当前部分
|
|
function setupActiveNavigation() {
|
|
window.addEventListener('scroll', () => {
|
|
const sections = document.querySelectorAll('section');
|
|
const navLinks = document.querySelectorAll('.nav-links a');
|
|
|
|
let current = '';
|
|
|
|
sections.forEach(section => {
|
|
const sectionTop = section.offsetTop;
|
|
const sectionHeight = section.clientHeight;
|
|
|
|
if (pageYOffset >= (sectionTop - 100)) {
|
|
current = section.getAttribute('id');
|
|
}
|
|
});
|
|
|
|
navLinks.forEach(link => {
|
|
link.classList.remove('active');
|
|
if (link.getAttribute('href') === `#${current}`) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// 页面加载完成后执行
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
loadProjects(); // 加载项目数据
|
|
setupSmoothScrolling(); // 设置平滑滚动
|
|
setupActiveNavigation(); // 设置导航高亮
|
|
|
|
console.log('S.A. 作品集页面已加载');
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|