20260601173222

This commit is contained in:
oneao committed 2026-06-01 17:32:22 +08:00
1 parent 8b08d18010
commit 44dce232f4
5 files changed
+416 -149

No files matched your search

@@ -0,0 +1,66 @@
# 书签导入与整理计划
## 需求分析
用户希望将浏览器书签文件 `D:\bookmarks_2026_5_26.html` 中的内容导入并整理到 `docs/resources.mdx` 文件中。
## 书签文件结构分析
从读取的书签文件中识别出以下主要分组:
### 第一层分组
1. **AI 智能助手** - 包含 ChatGPT、腾讯元宝、v0 等
2. **前端开发** - 包含多个子文件夹:
* 图标库 (expo icons, iconfont, icones, lucide)
* 前端模板库 (uiverse, codepen, htmlrev, lottiefiles, mockuphone)
* TinyMCE 相关
* Uniapp 相关
* 前端组件库 (Arco Design)
* React Native 第三方库
* 插画库 (undraw, storyset, manypixels)
* React Native 开发相关
3. **Python** - PaddlePaddle 相关
## 实现方案
### 步骤
1. 创建一个 Node.js 脚本来解析书签 HTML 文件
2. 将解析结果转换为资源导航所需的分组格式
3. 更新 `docs/resources.mdx` 文件
### 修改文件
* `docs/resources.mdx` - 更新为解析后的书签内容
## 输出格式
使用现有的 `SearchableLinkGrid` 组件格式,保持分组结构清晰。
## 过滤规则
1. 跳过重复链接
2. 清理过长的标题(超过50字符截断)
3. 提取有意义的描述信息
## 风险评估
* 文件较大(50KB+),需要处理大量数据
* 部分链接可能失效,建议用户后续验证
## 测试计划
1. 解析书签文件
2. 生成新的 resources.mdx
3. 启动开发服务器验证显示效果
+137 -82
View File
@@ -10,7 +10,7 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
<SearchableLinkGrid
groups={[
{
groupName: 'AI 助手',
groupName: 'AI助手',
items: [
{
title: 'ChatGPT',
@@ -30,33 +30,28 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
],
},
{
groupName: '大模型与AI',
groupName: '大模型',
items: [
{
title: 'Ollama',
description: '本地大模型运行工具',
href: 'https://ollama.com/',
},
{
title: 'OpenCompass',
description: '大模型评测榜单',
href: 'https://rank.opencompass.org.cn/leaderboard-multimodal/',
title: 'Qwen',
description: '阿里云通义千问',
href: 'https://mcp.csdn.net/683559a9606a8318e85a74e7.html',
},
{
title: 'InternVL',
description: '多模态大模型',
href: 'https://internvl.readthedocs.io/en/latest/internvl3.0/quick_start.html',
},
{
title: 'Qwen',
description: '阿里云通义千问',
href: 'https://mcp.csdn.net/683559a9606a8318e85a74e7.html',
},
{
title: '腾讯混元',
description: '腾讯大模型',
href: 'https://github.com/Tencent-Hunyuan/Tencent-Hunyuan-Large',
},
],
},
{
groupName: 'AI工具',
items: [
{
title: 'MinerU',
description: '文档解析工具',
@@ -67,16 +62,36 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
description: 'OCR 识别工具',
href: 'https://paddlepaddle.github.io/PaddleOCR/latest/version3.x/pipeline_usage/OCR.html',
},
],
},
{
groupName: 'AI部署与推理',
items: [
{
title: 'PaddleNLP',
description: '自然语言处理框架',
href: 'https://paddlenlp.readthedocs.io/zh/latest/advanced_guide/distributed_training.html',
title: 'Ollama',
description: '本地大模型运行工具',
href: 'https://ollama.com/',
},
{
title: 'PaddleServing',
description: '模型部署服务',
href: 'https://github.com/PaddlePaddle/Serving/blob/v0.9.0/examples/Pipeline/PaddleOCR/ocr/README_CN.md',
},
{
title: 'PaddleNLP',
description: '自然语言处理框架',
href: 'https://paddlenlp.readthedocs.io/zh/latest/advanced_guide/distributed_training.html',
},
],
},
{
groupName: 'AI评测与资源',
items: [
{
title: 'OpenCompass',
description: '大模型评测榜单',
href: 'https://rank.opencompass.org.cn/leaderboard-multimodal/',
},
{
title: '免费 AI 接口整理',
description: '4种免费 AI 接口',
@@ -90,18 +105,13 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
],
},
{
groupName: '计算机视觉',
groupName: '视觉与OCR',
items: [
{
title: 'YOLOv11',
description: '目标检测模型',
href: 'https://modelers.csdn.net/683fe614606a8318e85b0e13.html',
},
{
title: 'X-AnyLabeling',
description: '标注工具',
href: 'https://github.com/CVHub520/X-AnyLabeling',
},
{
title: 'GeoLayoutLM',
description: '文档智能模型',
@@ -117,21 +127,31 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
description: '文档布局数据集',
href: 'https://opendatalab.com/OpenDataLab/PubLayNet/tree/main',
},
{
title: 'X-AnyLabeling',
description: '标注工具',
href: 'https://github.com/CVHub520/X-AnyLabeling',
},
],
},
{
groupName: '前端开发',
items: [
{
title: 'Tauri',
description: '跨平台桌面应用框架',
href: 'https://v2.tauri.app/zh-cn/',
},
{
title: 'Arco Design Vue',
description: '字节跳动前端组件库',
href: 'https://arco.design/vue/docs/start',
},
{
title: 'Tauri',
description: '跨平台桌面应用框架',
href: 'https://v2.tauri.app/zh-cn/',
},
],
},
{
groupName: '移动端开发',
items: [
{
title: 'gluestack-ui',
description: 'React Native UI 套件',
@@ -180,33 +200,53 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
],
},
{
groupName: 'UI 资源',
groupName: 'UI资源',
items: [
{
title: 'Expo Vector Icons',
description: 'React Native 图标库',
href: 'https://icons.expo.fyi/Index',
},
{
title: 'IconFont',
description: '阿里巴巴矢量图标库',
href: 'https://www.iconfont.cn/',
},
{
title: 'Icônes',
description: '开源图标库集合',
href: 'https://icones.js.org/collection/all',
},
{
title: 'Lucide',
description: '精美的开源图标库',
href: 'https://lucide.dev/icons/',
},
{
title: 'Icônes',
description: '开源图标库集合',
href: 'https://icones.js.org/collection/all',
},
{
title: 'SVG Repo',
description: '免费 SVG 矢量图标',
href: 'https://www.svgrepo.com/',
},
{
title: 'Expo Vector Icons',
description: 'React Native 图标库',
href: 'https://icons.expo.fyi/Index',
},
{
title: 'unDraw',
description: '开源插画库',
href: 'https://undraw.co/',
},
{
title: 'Storyset',
description: '可自定义插画',
href: 'https://storyset.com/',
},
{
title: 'ManyPixels',
description: '免费插画素材',
href: 'https://www.manypixels.co/gallery',
},
{
title: 'LottieFiles',
description: '动画资源平台',
href: 'https://app.lottiefiles.com/search',
},
{
title: 'UIverse',
description: 'CSS & Tailwind UI 组件',
@@ -222,45 +262,30 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
description: '免费 HTML 网站模板',
href: 'https://htmlrev.com/',
},
{
title: 'LottieFiles',
description: '动画资源平台',
href: 'https://app.lottiefiles.com/search',
},
{
title: 'MockUPhone',
description: '设备样机展示',
href: 'https://mockuphone.com/model/iphone-15/',
},
{
title: 'unDraw',
description: '开源插画库',
href: 'https://undraw.co/',
},
{
title: 'Storyset',
description: '可自定义插画',
href: 'https://storyset.com/',
},
{
title: 'ManyPixels',
description: '免费插画素材',
href: 'https://www.manypixels.co/gallery',
},
],
},
{
groupName: '开发工具',
groupName: '后端开发',
items: [
{
title: 'NestJS',
description: 'Node.js 企业级框架',
href: 'https://nest.nodejs.cn/',
},
],
},
{
groupName: '开发环境',
items: [
{
title: 'JDK 8',
title: 'JDK',
description: 'Java 开发工具包',
href: 'https://adoptium.net/zh-CN/temurin/releases?version=8',
href: 'https://adoptium.net/zh-CN/temurin/releases',
},
{
title: 'Go',
@@ -270,42 +295,72 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
{
title: 'nvm-windows',
description: 'Node 版本管理',
href: 'https://github.com/coreybutler/nvm-windows/releases',
href: 'https://nvm.uihtm.com/doc/download-nvm.html',
},
],
},
{
groupName: 'IDE',
items: [
{
title: 'IntelliJ IDEA',
description: 'Java IDE',
href: 'https://www.jetbrains.com/zh-cn/idea/',
},
{
title: 'URL Encoder',
description: 'SVG URL 编码工具',
href: 'https://yoksel.github.io/url-encoder/zh-cn/',
title: 'GoLand',
description: 'Go 语言 IDE',
href: 'https://www.jetbrains.com/zh-cn/go/',
},
{
title: 'Dependency Walker',
description: '依赖分析工具',
href: 'https://www.dependencywalker.com/',
title: 'DataGrip',
description: '数据库管理工具',
href: 'https://www.jetbrains.com/zh-cn/datagrip/',
},
],
},
{
groupName: '地图服务',
items: [
{
title: '天地图 API',
title: '天地图',
description: '地理编码服务',
href: 'http://lbs.tianditu.gov.cn/server/geocoding.html',
},
{
title: '天地图示例',
description: 'JS API 示例',
href: 'http://lbs.tianditu.gov.cn/api/js4.0/examples.html',
href: 'http://lbs.tianditu.gov.cn/home.html',
},
{
title: '天地图 UniApp',
description: 'UniApp 插件',
href: 'https://ext.dcloud.net.cn/plugin?id=22630',
},
],
},
{
groupName: '开发资源',
items: [
{
title: 'Ollama 完整教程',
description: '本地 LLM 管理',
href: 'https://www.cnblogs.com/obullxl/p/18295202',
title: '清华镜像源',
description: '清华大学开源软件镜像站',
href: 'https://mirrors.tuna.tsinghua.edu.cn/',
},
{
title: 'URL Encoder',
description: 'SVG URL 编码工具',
href: 'https://yoksel.github.io/url-encoder/zh-cn/',
},
],
},
{
groupName: '效率工具',
groupName: '系统工具',
items: [
{
title: 'VMware Workstation',
description: 'VMware Pro 下载',
href: 'https://github.com/201853910/VMwareWorkstation',
},
],
},
{
groupName: '效率办公',
items: [
{
title: 'DeepL翻译',
@@ -330,4 +385,4 @@ import SearchableLinkGrid from '@site/src/components/Link/SearchableLinkGrid';
],
},
]}
/>
/>
+1 -1
View File
@@ -82,7 +82,7 @@ const config: Config = {
alt: 'oneao',
src: 'img/logo.png',
},
hideOnScroll: true,
hideOnScroll: false,
items: [
{
type: 'docSidebar',
@@ -1,5 +1,6 @@
import React, { useState, useMemo } from 'react'
import LinkCard, { LinkCardProps } from './LinkCard'
import type { LinkCardProps } from './LinkCard'
import React, { useEffect, useMemo, useRef, useState } from 'react'
import LinkCard from './LinkCard'
import styles from './styles.module.css'
export interface GroupedLinkCardProps {
@@ -13,17 +14,61 @@ interface SearchableLinkGridProps {
export default function SearchableLinkGrid({ groups }: SearchableLinkGridProps) {
const [searchTerm, setSearchTerm] = useState('')
const [activeSection, setActiveSection] = useState('')
const sidebarRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const navbar = document.querySelector('.navbar')
const navbarHeight = navbar ? navbar.offsetHeight : 64
const threshold = navbarHeight + 32
if (sidebarRef.current) {
sidebarRef.current.style.top = `${threshold}px`
}
}, [])
useEffect(() => {
const navbar = document.querySelector('.navbar')
const navbarHeight = navbar ? navbar.offsetHeight : 64
const threshold = navbarHeight + 20
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
setActiveSection(entry.target.id)
}
}
},
{
rootMargin: `-${threshold}px 0px -80% 0px`,
threshold: 0.1,
},
)
groups.forEach((_, index) => {
const element = document.getElementById(`group-${index}`)
if (element) {
observer.observe(element)
}
})
return () => {
observer.disconnect()
}
}, [groups])
const filteredGroups = useMemo(() => {
if (!searchTerm.trim()) return groups
if (!searchTerm.trim())
return groups
const lowerTerm = searchTerm.toLowerCase()
return groups.map(group => ({
...group,
items: group.items.filter(
item =>
item.title.toLowerCase().includes(lowerTerm) ||
item.description.toLowerCase().includes(lowerTerm),
item.title.toLowerCase().includes(lowerTerm)
|| item.description.toLowerCase().includes(lowerTerm),
),
})).filter(group => group.items.length > 0)
}, [searchTerm, groups])
@@ -31,68 +76,99 @@ export default function SearchableLinkGrid({ groups }: SearchableLinkGridProps)
const totalItems = groups.reduce((sum, group) => sum + group.items.length, 0)
const filteredTotalItems = filteredGroups.reduce((sum, group) => sum + group.items.length, 0)
const scrollToSection = (index: number) => {
const element = document.getElementById(`group-${index}`)
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' })
}
}
return (
<div>
<div className={styles.searchContainer}>
<div className={styles.searchWrapper}>
<svg
className={styles.searchIcon}
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<circle cx="11" cy="11" r="8" />
<path d="m21 21-4.35-4.35" />
</svg>
<input
type="text"
placeholder="搜索资源..."
value={searchTerm}
onChange={e => setSearchTerm(e.target.value)}
className={styles.searchInput}
/>
</div>
<span className={styles.searchCount}>
{filteredTotalItems} / {totalItems} 项
</span>
</div>
{filteredGroups.length > 0 ? (
filteredGroups.map((group, groupIndex) => (
<div key={groupIndex} className={styles.group}>
<h3 className={styles.groupTitle}>{group.groupName}</h3>
<div className={styles.grid}>
{group.items.map((item, itemIndex) => (
<LinkCard key={itemIndex} {...item} />
))}
</div>
<div className={styles.container}>
<div className={styles.mainContent}>
<div className={styles.searchContainer}>
<div className={styles.searchWrapper}>
<svg
className={styles.searchIcon}
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<circle cx="11" cy="11" r="8" />
<path d="m21 21-4.35-4.35" />
</svg>
<input
type="text"
placeholder="搜索资源..."
value={searchTerm}
onChange={e => setSearchTerm(e.target.value)}
className={styles.searchInput}
/>
</div>
))
) : (
<div className={styles.noResults}>
<svg
className={styles.noResultsIcon}
width="48"
height="48"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
>
<circle cx="11" cy="11" r="8" />
<path d="m21 21-4.35-4.35" />
<path d="M8 11s1.5-2 4-2 4 2 4 2" />
</svg>
<p>未找到匹配的资源</p>
<span className={styles.searchCount}>
{filteredTotalItems}
{' '}
/
{totalItems}
{' '}
项
</span>
</div>
)}
{filteredGroups.length > 0
? (
filteredGroups.map((group, groupIndex) => (
<div key={groupIndex} id={`group-${groupIndex}`} className={styles.group}>
<h3 className={styles.groupTitle}>{group.groupName}</h3>
<div className={styles.grid}>
{group.items.map((item, itemIndex) => (
<LinkCard key={itemIndex} {...item} />
))}
</div>
</div>
))
)
: (
<div className={styles.noResults}>
<svg
className={styles.noResultsIcon}
width="48"
height="48"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
>
<circle cx="11" cy="11" r="8" />
<path d="m21 21-4.35-4.35" />
<path d="M8 11s1.5-2 4-2 4 2 4 2" />
</svg>
<p>未找到匹配的资源</p>
</div>
)}
</div>
<nav className={styles.sidebar} ref={sidebarRef}>
<div className={styles.sidebarHeader}>快速导航</div>
<div className={styles.sidebarLinks}>
{groups.map((group, index) => (
<button
key={index}
onClick={() => scrollToSection(index)}
className={`${styles.sidebarLink} ${activeSection === `group-${index}` ? styles.active : ''}`}
>
{group.groupName}
</button>
))}
</div>
</nav>
</div>
)
}
}
@@ -1,3 +1,65 @@
/* 容器布局 */
.container {
display: flex;
gap: 24px;
}
.mainContent {
flex: 1;
}
/* 右侧导航 */
.sidebar {
width: 180px;
flex-shrink: 0;
position: sticky;
top: 2rem;
height: fit-content;
}
.sidebarHeader {
font-size: 14px;
font-weight: 600;
color: var(--ifm-color-emphasis-600);
margin-bottom: 12px;
padding-left: 8px;
}
.sidebarLinks {
display: flex;
flex-direction: column;
gap: 4px;
}
.sidebarLink {
display: block;
padding: 8px 12px;
font-size: 14px;
text-align: left;
border: none;
background: transparent;
color: var(--ifm-color-emphasis-700);
border-radius: 8px;
cursor: pointer;
transition:
background-color 0.2s ease,
color 0.2s ease;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sidebarLink:hover {
background-color: var(--ifm-color-emphasis-100);
color: var(--ifm-color-emphasis-900);
}
.sidebarLink.active {
background-color: var(--ifm-color-primary);
color: white;
}
/* 网格布局 */
.grid {
display: grid;
gap: 16px;
@@ -28,6 +90,13 @@
}
}
/* 响应式:隐藏右侧导航 */
@media (max-width: 1200px) {
.sidebar {
display: none;
}
}
/* 卡片 */
.card {
@@ -194,6 +263,7 @@
.group {
margin-bottom: 32px;
scroll-margin-top: calc(var(--ifm-navbar-height, 64px) + 1rem);
}
.group:last-child {