Skip to content

Commit

Permalink
v1 projects
Browse files Browse the repository at this point in the history
Signed-off-by: samzong <samzong.lu@gmail.com>
  • Loading branch information
samzong committed Dec 28, 2024
1 parent 08faa34 commit a2829f8
Show file tree
Hide file tree
Showing 10 changed files with 378 additions and 433 deletions.
168 changes: 100 additions & 68 deletions .vitepress/theme/components/ProjectCard.vue
Original file line number Diff line number Diff line change
@@ -1,72 +1,74 @@
<script setup lang="ts">
import { type Project } from '../../types/project'
import { computed } from 'vue'
import { useRouter } from 'vitepress'
import { type Project } from "../../types/project";
import { computed } from "vue";
import { useRouter } from "vitepress";
const router = useRouter()
const router = useRouter();
const props = defineProps<{
project: Project
}>()
project: Project;
}>();
const navigateToDoc = () => {
router.go(props.project.docPath)
}
router.go(props.project.docPath);
};
// 判断项目是否是新项目, 如果项目创建时间超过1个月, 则不显示新项目标签
const isNew = computed(() => {
const oneYearAgo = new Date()
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1)
return new Date(props.project.createdAt) > oneYearAgo
})
const oneYearAgo = new Date();
oneYearAgo.setMonth(oneYearAgo.getMonth() - 1);
return new Date(props.project.createdAt) > oneYearAgo;
});
const truncatedDescription = computed(() => {
const maxLength = 80
const maxLength = 80;
return props.project.description.length > maxLength
? props.project.description.slice(0, maxLength) + '...'
: props.project.description
})
? props.project.description.slice(0, maxLength) + "..."
: props.project.description;
});
const MAX_VISIBLE_TAGS = 3
const MAX_VISIBLE_TAGS = 3;
const visibleTags = computed(() => {
return props.project.tags.slice(0, MAX_VISIBLE_TAGS)
})
return props.project.tags.slice(0, MAX_VISIBLE_TAGS);
});
const remainingTagsCount = computed(() => {
return Math.max(0, props.project.tags.length - MAX_VISIBLE_TAGS)
})
return Math.max(0, props.project.tags.length - MAX_VISIBLE_TAGS);
});
// 为不同类型的标签设置不同的颜色
const getTagColor = (tag: string) => {
const tagColors: { [key: string]: string } = {
'Vue3': '#42b883',
'Vue': '#42b883',
'React': '#61dafb',
'TypeScript': '#3178c6',
'JavaScript': '#f7df1e',
'Node.js': '#339933',
'Python': '#3776ab',
'Go': '#00add8',
'Rust': '#dea584',
'Docker': '#2496ed',
'Kubernetes': '#326ce5',
'AWS': '#ff9900',
'VitePress': '#646cff',
'Blog': '#ff5722',
'Web': '#1e88e5',
'API': '#4caf50',
'CLI': '#607d8b',
}
return tagColors[tag] || '#8e44ad' // 默认紫色
}
Vue3: "#42b883",
Vue: "#42b883",
React: "#61dafb",
TypeScript: "#3178c6",
JavaScript: "#f7df1e",
"Node.js": "#339933",
Python: "#3776ab",
Go: "#00add8",
Rust: "#dea584",
Docker: "#2496ed",
Kubernetes: "#326ce5",
AWS: "#ff9900",
VitePress: "#646cff",
Blog: "#ff5722",
Web: "#1e88e5",
API: "#4caf50",
CLI: "#607d8b",
};
return tagColors[tag] || "#8e44ad"; // 默认紫色
};
// 生成默认 logo 文本
const defaultLogoText = computed(() => {
return props.project.name.split(' ')
.map(word => word[0])
.join('')
return props.project.name
.split(" ")
.map((word) => word[0])
.join("")
.toUpperCase()
.slice(0, 2)
})
.slice(0, 2);
});
</script>

<template>
Expand All @@ -75,22 +77,22 @@ const defaultLogoText = computed(() => {
<div class="card-content">
<div class="card-header">
<div class="logo-container">
<img
<img
v-if="project.logo"
:src="project.logo"
:src="project.logo"
:alt="project.name"
class="project-logo"
>
/>
<div v-else class="default-logo">
{{ defaultLogoText }}
</div>
</div>
<div class="header-content">
<h3 class="project-title">{{ project.name }}</h3>
<div class="project-tags">
<span
v-for="tag in visibleTags"
:key="tag"
<span
v-for="tag in visibleTags"
:key="tag"
class="project-tag"
:style="{ backgroundColor: getTagColor(tag) }"
>
Expand All @@ -105,14 +107,40 @@ const defaultLogoText = computed(() => {
<p class="project-description">{{ truncatedDescription }}</p>
<div class="project-actions" @click.stop>
<div class="flex-spacer"></div>
<a v-if="project.github" :href="project.github" target="_blank" class="action-button github" title="View on GitHub">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
<a
v-if="project.github"
:href="project.github"
target="_blank"
class="action-button github"
title="View on GitHub"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"
/>
</svg>
</a>
<a v-if="project.website" :href="project.website" target="_blank" class="action-button website" title="Visit Website">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm7.931 9h-2.764a14.67 14.67 0 0 0-1.792-6.243A8.013 8.013 0 0 1 19.931 11zM12.53 4.027c1.035 1.364 2.427 3.78 2.627 6.973H9.03c.139-2.596.994-5.028 2.451-6.974.172-.01.344-.026.519-.026.179 0 .354.016.53.027zm-3.842.7C7.704 6.618 7.136 8.762 7.03 11H4.069a8.013 8.013 0 0 1 4.619-6.273zM4.069 13h2.974c.136 2.379.665 4.478 1.556 6.23A8.01 8.01 0 0 1 4.069 13zm7.381 6.973C10.049 18.275 9.222 15.896 9.041 13h6.113c-.208 2.773-1.117 5.196-2.603 6.972-.182.012-.364.028-.551.028-.186 0-.367-.016-.55-.027zm4.011-.772c.955-1.794 1.538-3.901 1.691-6.201h2.778a8.005 8.005 0 0 1-4.469 6.201z"/>
<a
v-if="project.website"
:href="project.website"
target="_blank"
class="action-button website"
title="Visit Website"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path
d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm7.931 9h-2.764a14.67 14.67 0 0 0-1.792-6.243A8.013 8.013 0 0 1 19.931 11zM12.53 4.027c1.035 1.364 2.427 3.78 2.627 6.973H9.03c.139-2.596.994-5.028 2.451-6.974.172-.01.344-.026.519-.026.179 0 .354.016.53.027zm-3.842.7C7.704 6.618 7.136 8.762 7.03 11H4.069a8.013 8.013 0 0 1 4.619-6.273zM4.069 13h2.974c.136 2.379.665 4.478 1.556 6.23A8.01 8.01 0 0 1 4.069 13zm7.381 6.973C10.049 18.275 9.222 15.896 9.041 13h6.113c-.208 2.773-1.117 5.196-2.603 6.972-.182.012-.364.028-.551.028-.186 0-.367-.016-.55-.027zm4.011-.772c.955-1.794 1.538-3.901 1.691-6.201h2.778a8.005 8.005 0 0 1-4.469 6.201z"
/>
</svg>
</a>
</div>
Expand Down Expand Up @@ -145,9 +173,7 @@ const defaultLogoText = computed(() => {
.project-card:hover {
transform: translateY(-6px);
box-shadow:
0 8px 24px rgba(0, 0, 0, 0.12),
0 2px 4px var(--vp-c-brand-light);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 4px var(--vp-c-brand-light);
}
.dark .project-card {
Expand All @@ -159,9 +185,7 @@ const defaultLogoText = computed(() => {
.dark .project-card:hover {
background: rgba(36, 36, 36, 0.9);
border-color: var(--vp-c-brand);
box-shadow:
0 8px 24px rgba(0, 0, 0, 0.3),
0 2px 4px var(--vp-c-brand);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3), 0 2px 4px var(--vp-c-brand);
}
.new-badge {
Expand All @@ -183,7 +207,7 @@ const defaultLogoText = computed(() => {
.new-badge::before,
.new-badge::after {
content: '';
content: "";
position: absolute;
top: 0;
width: 100%;
Expand Down Expand Up @@ -232,7 +256,11 @@ const defaultLogoText = computed(() => {
width: 100%;
height: 100%;
border-radius: 12px;
background: linear-gradient(135deg, var(--vp-c-brand) 0%, var(--vp-c-brand-light) 100%);
background: linear-gradient(
135deg,
var(--vp-c-brand) 0%,
var(--vp-c-brand-light) 100%
);
color: white;
display: flex;
align-items: center;
Expand All @@ -256,7 +284,11 @@ const defaultLogoText = computed(() => {
.project-title {
font-size: 1.4em;
margin: 0;
background: linear-gradient(120deg, var(--vp-c-brand) 0%, var(--vp-c-brand-light) 100%);
background: linear-gradient(
120deg,
var(--vp-c-brand) 0%,
var(--vp-c-brand-light) 100%
);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
Expand Down Expand Up @@ -394,4 +426,4 @@ const defaultLogoText = computed(() => {
.action-button:hover svg {
transform: scale(1.1);
}
</style>
</style>
76 changes: 39 additions & 37 deletions .vitepress/types/project.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,50 @@
export interface Project {
name: string
description: string
github: string
website?: string
logo?: string
tags: string[]
createdAt: string // ISO 格式的日期字符串,如:'2024-01-01'
docPath: string // 项目文档路径,如:'/projects/samzong-blog'
name: string;
description: string;
github: string;
website?: string;
logo?: string;
tags: string[];
createdAt: string; // ISO 格式的日期字符串,如:'2024-01-01'
docPath: string; // 项目文档路径,如:'/projects/samzong-blog'
}

export const projects: Project[] = [
{
name: 'samzong.github.io',
description: '个人博客网站,基于 VitePress 构建,支持暗黑模式、全文搜索、标签分类等功能。',
github: 'https://github.com/samzong/samzong.github.io',
website: 'https://samzong.me',
logo: '/logo.png',
tags: ['Vue3', 'VitePress', 'Blog'],
createdAt: '2024-01-01',
docPath: '/projects/samzong-blog'
name: "SD Chat",
description:
"基于 Stable Diffusion 的聊天机器人,支持文本到图像、视频生成等功能。",
github: "https://github.com/samzong/sd-chat",
logo: "/logo.png",
tags: ["Stable Diffusion", "Python"],
createdAt: "2024-12-25",
docPath: "/projects/sd-chat",
},
{
name: 'OpenAI Translator',
description: '基于 OpenAI API 的智能翻译工具,支持多语言互译、文本润色、语法纠正等功能。',
github: 'https://github.com/samzong/openai-translator',
website: 'https://translator.samzong.me',
tags: ['TypeScript', 'OpenAI', 'React', 'API'],
createdAt: '2023-12-01',
docPath: '/projects/openai-translator'
name: "Chrome tabboost",
description:
"基于 Arc 浏览器的标签增强工具,支持快捷键、标签管理、自定义快捷键等功能。",
github: "https://github.com/samzong/chrome-tabboost",
tags: ["Chrome", "Arc", "Typescript"],
createdAt: "2024-12-18",
docPath: "/projects/chrome-tabboost",
},
{
name: 'Docker Compose Hub',
description: '收集和维护常用服务的 Docker Compose 配置,包含数据库、缓存、消息队列等基础服务。',
github: 'https://github.com/samzong/docker-compose-hub',
tags: ['Docker', 'DevOps', 'Infrastructure'],
createdAt: '2023-06-15',
docPath: '/projects/docker-compose-hub'
name: "MacMusicPlayer",
description:
"一个简洁、轻量级的 macOS 音乐播放器,设计为菜单栏应用程序,让您可以轻松控制音乐播放而不打断工作流程。",
github: "https://github.com/samzong/MacMusicPlayer",
tags: ["macOS", "SwiftUI", "Music"],
createdAt: "2024-09-18",
docPath: "/projects/macmusicplayer",
},
{
name: 'Kubernetes Tools',
description: '一组用于简化 Kubernetes 日常运维工作的工具集,包含日志收集、监控报警、配置管理等功能。',
github: 'https://github.com/samzong/k8s-tools',
tags: ['Kubernetes', 'Go', 'CLI', 'DevOps'],
createdAt: '2023-09-20',
docPath: '/projects/kubernetes-tools'
}
]
name: "Samzong Blog",
description: "一个简洁、轻量级的博客,收集了我的一些技术文章和项目文档。",
github: "https://github.com/samzong/samzong.github.io",
website: "https://samzong.me",
tags: ["VitePress", "Typescript"],
createdAt: "2024-12-28",
docPath: "/",
},
];
41 changes: 41 additions & 0 deletions projects/chrome-tabboost.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# TabBoost

TabBoost 是一个 Chrome 扩展程序,旨在复制 Arc 浏览器中常用的功能,以增强 Chrome 用户的体验。

## 功能

- **标签增强**: 改进了标签页的管理和导航功能,使用户可以更高效地处理多个标签页。
- **快捷键支持**: 支持多种快捷键操作,提升浏览效率。
- **用户界面优化**: 提供更简洁、直观的用户界面,改善浏览体验。

## 安装

1. 打开 Chrome 浏览器,并访问 [Chrome Web Store](https://chrome.google.com/webstore/category/extensions)
2. 搜索 `TabBoost` 并点击安装按钮。
3. 安装完成后,点击浏览器右上角的 TabBoost 图标,即可开始使用。

## 使用

### 标签管理

- 使用快捷键 `Ctrl + T` 打开新标签页。
- 使用 `Ctrl + W` 关闭当前标签页。
- 使用 `Ctrl + Tab` 切换到下一个标签页。

### 自定义快捷键

1. 点击浏览器右上角的 TabBoost 图标。
2. 选择 `设置`
3.`快捷键` 部分,设置你想要的快捷键组合。

## 反馈与贡献

如果你有任何问题或建议,请在 [GitHub 仓库](https://github.com/samzong/chrome-tabboost) 提交问题或创建拉取请求。

## 许可证

该项目采用 [MIT 许可证](https://opensource.org/licenses/MIT)

---

TabBoost 是一个开源项目,欢迎大家贡献代码和提交反馈。希望这个扩展能提升你在 Chrome 浏览器中的使用体验!
Loading

0 comments on commit a2829f8

Please sign in to comment.