From 8dc6a046fa6858f8e229f900337ab557388c81c5 Mon Sep 17 00:00:00 2001
From: weizwz <1124725517@qq.com>
Date: Wed, 19 Nov 2025 22:03:31 +0800
Subject: [PATCH 1/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=A7=BB=E5=8A=A8?=
=?UTF-8?q?=E7=AB=AF=E7=9A=84=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/layout/Header.tsx | 40 ++++++---------------
components/layout/ThemeToggle.tsx | 6 +---
components/modals/EditLinkModal.tsx | 56 ++++++++++++++---------------
3 files changed, 39 insertions(+), 63 deletions(-)
diff --git a/components/layout/Header.tsx b/components/layout/Header.tsx
index c82b8d1..2f45f67 100644
--- a/components/layout/Header.tsx
+++ b/components/layout/Header.tsx
@@ -3,7 +3,7 @@
import React, { memo, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import { Button, Tooltip } from 'antd';
-import { EditOutlined, MenuOutlined, GithubOutlined } from '@ant-design/icons';
+import { MenuOutlined, GithubOutlined, SettingOutlined } from '@ant-design/icons';
import SearchBar from './SearchBar';
import ThemeToggle from './ThemeToggle';
@@ -58,36 +58,28 @@ const Header = memo(function Header({ onMenuClick }: HeaderProps) {
{/* 右侧工具栏 */}
-
+
}
+ icon={}
+ size='large'
onClick={handleManageClick}
aria-label="打开数据管理页面"
title="数据管理"
className="flex items-center justify-center"
- style={{
- fontSize: '18px',
- width: '40px',
- height: '40px',
- }}
/>
}
+ size='large'
onClick={() => window.open('https://github.com/weizwz/weiz-nav', '_blank', 'noopener,noreferrer')}
aria-label="访问 GitHub 项目地址"
title="GitHub"
className="flex items-center justify-center"
- style={{
- fontSize: '18px',
- width: '40px',
- height: '40px',
- }}
/>
@@ -107,21 +99,17 @@ const Header = memo(function Header({ onMenuClick }: HeaderProps) {
唯知导航
-
+
{onMenuClick && (
}
+ size='large'
onClick={onMenuClick}
aria-label="打开分类菜单"
title="分类菜单"
className="flex items-center justify-center lg:hidden"
- style={{
- fontSize: '18px',
- width: '40px',
- height: '40px',
- }}
/>
)}
@@ -129,31 +117,23 @@ const Header = memo(function Header({ onMenuClick }: HeaderProps) {
}
+ icon={}
+ size='large'
onClick={handleManageClick}
aria-label="打开数据管理页面"
title="数据管理"
className="flex items-center justify-center"
- style={{
- fontSize: '18px',
- width: '40px',
- height: '40px',
- }}
/>
}
+ size='large'
onClick={() => window.open('https://github.com/weizwz/weiz-nav', '_blank', 'noopener,noreferrer')}
aria-label="访问 GitHub 项目地址"
title="GitHub"
className="flex items-center justify-center"
- style={{
- fontSize: '18px',
- width: '40px',
- height: '40px',
- }}
/>
diff --git a/components/layout/ThemeToggle.tsx b/components/layout/ThemeToggle.tsx
index d3988e9..fb29e0b 100644
--- a/components/layout/ThemeToggle.tsx
+++ b/components/layout/ThemeToggle.tsx
@@ -76,16 +76,12 @@ export default function ThemeToggle() {
:
}
+ size='large'
onClick={toggleTheme}
className="transition-theme flex items-center justify-center"
aria-label={getTooltipTitle()}
role="switch"
aria-checked={isDark}
- style={{
- fontSize: '18px',
- width: '40px',
- height: '40px',
- }}
/>
);
diff --git a/components/modals/EditLinkModal.tsx b/components/modals/EditLinkModal.tsx
index 1825319..3066bf1 100644
--- a/components/modals/EditLinkModal.tsx
+++ b/components/modals/EditLinkModal.tsx
@@ -367,7 +367,34 @@ export const EditLinkModal: React.FC
= ({
-
+
+
+
+
+
+
+ {supportsEyeDropper && (
+ }
+ onClick={handleEyeDropper}
+ title="使用吸管工具选择颜色"
+ />
+ )}
+
+
+
+
+
{/* 预览卡片 */}
@@ -426,33 +453,6 @@ export const EditLinkModal: React.FC = ({
-
-
-
-
-
-
-
- {supportsEyeDropper && (
- }
- onClick={handleEyeDropper}
- title="使用吸管工具选择颜色"
- />
- )}
-
-
-
From 61bf5bfe2447b75a71c4f144296dc692fcfba6f7 Mon Sep 17 00:00:00 2001
From: weizwz <1124725517@qq.com>
Date: Wed, 19 Nov 2025 22:19:50 +0800
Subject: [PATCH 2/8] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8D=A1=E7=89=87?=
=?UTF-8?q?=E9=97=B4=E8=B7=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/navigation/LinkGrid.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/navigation/LinkGrid.tsx b/components/navigation/LinkGrid.tsx
index 39a69e7..c461297 100644
--- a/components/navigation/LinkGrid.tsx
+++ b/components/navigation/LinkGrid.tsx
@@ -160,7 +160,7 @@ const LinkGridBase: React.FC = ({
disabled={!isDraggingEnabled}
>
Date: Wed, 19 Nov 2025 23:08:37 +0800
Subject: [PATCH 3/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=20header=20=E6=A0=B7?=
=?UTF-8?q?=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/manage/page.tsx | 8 ++++----
app/page.tsx | 2 +-
components/layout/Header.tsx | 14 +++++++-------
components/layout/SearchBar.tsx | 10 +++-------
4 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/app/manage/page.tsx b/app/manage/page.tsx
index 56c9c50..bb67d94 100644
--- a/app/manage/page.tsx
+++ b/app/manage/page.tsx
@@ -282,9 +282,9 @@ export default function ManagePage() {
return (
-
+
{/* 页头 */}
-
+
{/* Logo/标题 */}
@@ -292,9 +292,9 @@ export default function ManagePage() {

-
+
数据管理
diff --git a/app/page.tsx b/app/page.tsx
index 6a7d883..872d65e 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -146,7 +146,7 @@ export default function Home() {
);
return (
-
+
{/* 固定顶部 Header */}
setDrawerOpen(true)} />
diff --git a/components/layout/Header.tsx b/components/layout/Header.tsx
index 2f45f67..1d233d6 100644
--- a/components/layout/Header.tsx
+++ b/components/layout/Header.tsx
@@ -37,7 +37,7 @@ const Header = memo(function Header({ onMenuClick }: HeaderProps) {
className="w-full bg-(--background-main) border-b border-gray-200 dark:border-neutral-700 transition-theme"
role="banner"
>
-
+
{/* Desktop 布局 */}
{/* Logo/标题 */}
@@ -45,9 +45,9 @@ const Header = memo(function Header({ onMenuClick }: HeaderProps) {

-
+
唯知导航
@@ -86,16 +86,16 @@ const Header = memo(function Header({ onMenuClick }: HeaderProps) {
{/* Mobile 布局 */}
-
+
{/* 顶部行:标题和工具栏 */}

-
+
唯知导航
@@ -140,7 +140,7 @@ const Header = memo(function Header({ onMenuClick }: HeaderProps) {
{/* 搜索栏 - 全宽 */}
-
diff --git a/components/layout/SearchBar.tsx b/components/layout/SearchBar.tsx
index ab4df92..8e453a9 100644
--- a/components/layout/SearchBar.tsx
+++ b/components/layout/SearchBar.tsx
@@ -157,8 +157,8 @@ export default function SearchBar() {
return (
}
- className="search-bar-modern"
- style={{
- borderRadius: '24px',
- paddingLeft: '12px',
- }}
+ className="search-bar-modern bg-(--background)! pl-3! shadow-none!"
aria-label="搜索输入框"
role="searchbox"
aria-describedby="search-description"
From 835984418182466393941bb030d46dbdafccb477 Mon Sep 17 00:00:00 2001
From: weizwz <1124725517@qq.com>
Date: Wed, 19 Nov 2025 23:35:30 +0800
Subject: [PATCH 4/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=95=B0=E6=8D=AE?=
=?UTF-8?q?=E7=AE=A1=E7=90=86=E7=95=8C=E9=9D=A2=E9=A3=8E=E6=A0=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/manage/page.tsx | 240 ++++++++++++++++++++++----------------------
1 file changed, 121 insertions(+), 119 deletions(-)
diff --git a/app/manage/page.tsx b/app/manage/page.tsx
index bb67d94..2fbe708 100644
--- a/app/manage/page.tsx
+++ b/app/manage/page.tsx
@@ -281,134 +281,136 @@ export default function ManagePage() {
}
return (
-
-
- {/* 页头 */}
-
-
-
- {/* Logo/标题 */}
-
-

-
- 数据管理
-
-
-
}
- onClick={handleBack}
- type="text"
- aria-label="返回主页"
- >
- 返回主页
-
-
-
-
-
- {/* 导入导出工具栏 */}
-
-
-
-
-
- 已选择 {selectedRowKeys.length} 项
-
+
+ {/* 页头 */}
+
+
+
+ {/* Logo/标题 */}
+
+

+
+ 数据管理
+
-
-
}
- onClick={handleResetClick}
- aria-label="重置数据"
- >
-
重置数据
-
-
- }
+ onClick={handleBack}
+ type="text"
+ aria-label="返回主页"
+ >
+ 返回主页
+
+
+
+
+ {/* 数据表格 */}
+
+
+ {/* 导入导出工具栏 */}
+
+
+
+
+
+ 已选择 {selectedRowKeys.length} 项
+
+
+
+
}
- onClick={handleBatchDeleteClick}
- aria-label={selectedRowKeys.length > 0 ? `批量删除选中的 ${selectedRowKeys.length} 个链接` : '批量删除'}
+ icon={
}
+ onClick={handleResetClick}
+ aria-label="重置数据"
>
-
批量删除
+
重置数据
-
-
}
- onClick={handleBatchCategoryClick}
- aria-label={selectedRowKeys.length > 0 ? `批量分类选中的 ${selectedRowKeys.length} 个链接` : '批量分类'}
- >
-
批量分类
-
-
}
- onClick={handleAddNew}
- aria-label="添加新链接"
- >
-
添加链接
-
+
+ }
+ onClick={handleBatchDeleteClick}
+ aria-label={selectedRowKeys.length > 0 ? `批量删除选中的 ${selectedRowKeys.length} 个链接` : '批量删除'}
+ >
+ 批量删除
+
+
+
}
+ onClick={handleBatchCategoryClick}
+ aria-label={selectedRowKeys.length > 0 ? `批量分类选中的 ${selectedRowKeys.length} 个链接` : '批量分类'}
+ >
+
批量分类
+
+
}
+ onClick={handleAddNew}
+ aria-label="添加新链接"
+ >
+
添加链接
+
+
-
- {/* 数据表格 */}
-
-
+
+
+
+ {/* 编辑链接弹窗 */}
+
+
+ {/* 编辑分类弹窗 */}
+
{
+ setCategoryEditModalOpen(false);
+ setCurrentCategory(null);
+ }}
+ onSubmit={handleCategorySubmit}
+ />
+
+ {/* 重置数据确认对话框 */}
+
-
- {/* 编辑链接弹窗 */}
-
-
- {/* 编辑分类弹窗 */}
-
{
- setCategoryEditModalOpen(false);
- setCurrentCategory(null);
- }}
- onSubmit={handleCategorySubmit}
- />
-
- {/* 重置数据确认对话框 */}
-
-
- {/* 批量分类弹窗 */}
- setBatchCategoryModalOpen(false)}
- onSubmit={handleBatchCategorySubmit}
- />
+ {/* 批量分类弹窗 */}
+ setBatchCategoryModalOpen(false)}
+ onSubmit={handleBatchCategorySubmit}
+ />
+
);
From c4dda42f541fe02381a3019f7104c55f6280a01c Mon Sep 17 00:00:00 2001
From: weizwz <1124725517@qq.com>
Date: Thu, 20 Nov 2025 10:22:14 +0800
Subject: [PATCH 5/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A1=A8=E6=A0=BC?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=B1=95=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/globals.css | 17 -----
components/management/DataTable.tsx | 111 +++++++++++++++-------------
2 files changed, 59 insertions(+), 69 deletions(-)
diff --git a/app/globals.css b/app/globals.css
index 00b37cc..d13c46d 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -322,23 +322,6 @@ select:focus-visible {
transition: none;
}
-/* DataTable 分类行样式 */
-.category-row > td {
- background-color: #eff6ff !important;
-}
-
-.dark .category-row > td {
- background-color: rgba(30, 58, 138, 0.3) !important;
-}
-
-.category-row:hover > td {
- background-color: #dbeafe !important;
-}
-
-.dark .category-row:hover > td {
- background-color: rgba(30, 64, 175, 0.4) !important;
-}
-
/* PWA 安装提示动画 */
@keyframes slide-up {
from {
diff --git a/components/management/DataTable.tsx b/components/management/DataTable.tsx
index cc92a15..bc0d1dc 100644
--- a/components/management/DataTable.tsx
+++ b/components/management/DataTable.tsx
@@ -2,7 +2,7 @@
import React, { useState, useMemo, useEffect } from 'react';
import { Table, Button, Space, Popconfirm } from 'antd';
-import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
+import { EditOutlined, DeleteOutlined, RightOutlined, DownOutlined } from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import { Link } from '@/types/link';
import { Category } from '@/types/category';
@@ -59,18 +59,19 @@ export const DataTable: React.FC
= ({
const categories = useAppSelector((state) => state.categories.items);
// 使用外部传入的 selectedRowKeys 或内部状态
- const selectedRowKeys = externalSelectedRowKeys !== undefined ? externalSelectedRowKeys : internalSelectedRowKeys;
+ const selectedRowKeys =
+ externalSelectedRowKeys !== undefined ? externalSelectedRowKeys : internalSelectedRowKeys;
// 构建树形数据结构
const treeData = useMemo(() => {
const tree: TreeNode[] = [];
// 按分类组织链接
- categories.forEach(category => {
+ categories.forEach((category) => {
const categoryLinks = links
- .filter(link => link.category === category.name)
+ .filter((link) => link.category === category.name)
.sort((a, b) => a.order - b.order)
- .map(link => ({
+ .map((link) => ({
key: link.id,
id: link.id,
name: link.name,
@@ -101,9 +102,9 @@ export const DataTable: React.FC = ({
// 添加未分类节点(如果有未分类的链接)
const uncategorizedLinks = links
- .filter(link => !link.category || link.category === '')
+ .filter((link) => !link.category || link.category === '')
.sort((a, b) => a.order - b.order)
- .map(link => ({
+ .map((link) => ({
key: link.id,
id: link.id,
name: link.name,
@@ -136,16 +137,13 @@ export const DataTable: React.FC = ({
return tree.sort((a, b) => a.order - b.order);
}, [links, categories]);
- // 默认展开所有分类(包括未分类)
+ // 默认展开第一个分类
useEffect(() => {
- const allCategoryKeys = categories.map(cat => `category-${cat.id}`);
- // 如果有未分类链接,也展开未分类节点
- const hasUncategorized = links.some(link => !link.category || link.category === '');
- if (hasUncategorized) {
- allCategoryKeys.push('category-uncategorized');
+ if (categories.length > 0) {
+ const firstCategoryKey = `category-${categories[0].id}`;
+ setExpandedRowKeys([firstCategoryKey]);
}
- setExpandedRowKeys(allCategoryKeys);
- }, [categories, links]);
+ }, [categories]);
// 表格列定义
const columns: ColumnsType = [
@@ -153,25 +151,48 @@ export const DataTable: React.FC = ({
title: '名称',
dataIndex: 'name',
key: 'name',
- width: 160,
+ width: 120,
ellipsis: true,
- render: (name: string, record: TreeNode) => (
-
- {name}
-
- ),
+ render: (name: string, record: TreeNode) =>
+ record.isCategory ? (
+ {name}
+ ) : record.icon ? (
+
+
+

{
+ e.currentTarget.style.display = 'none';
+ }}
+ />
+
+
{name}
+
+ ) : (
+ {name}
+ ),
},
{
title: '地址',
dataIndex: 'url',
key: 'url',
- width: 200,
+ width: 180,
ellipsis: true,
- render: (url: string, record: TreeNode) =>
+ render: (url: string, record: TreeNode) =>
record.isCategory ? (
-
) : url ? (
-
+
{url}
) : null,
@@ -180,9 +201,9 @@ export const DataTable: React.FC = ({
title: '描述',
dataIndex: 'description',
key: 'description',
- width: 300,
+ width: 240,
ellipsis: true,
- render: (description: string, record: TreeNode) =>
+ render: (description: string, record: TreeNode) =>
record.isCategory ? (
共 {record.children?.length || 0} 条链接
) : (
@@ -190,11 +211,11 @@ export const DataTable: React.FC = ({
),
},
{
- title: '背景颜色',
+ title: '背景',
dataIndex: 'backgroundColor',
key: 'backgroundColor',
width: 100,
- render: (color: string, record: TreeNode) =>
+ render: (color: string, record: TreeNode) =>
record.isCategory ? (
-
) : (
@@ -210,7 +231,7 @@ export const DataTable: React.FC = ({
{
title: '操作',
key: 'action',
- width: 150,
+ width: 120,
fixed: 'right',
render: (_, record: TreeNode) => {
if (record.isCategory) {
@@ -218,7 +239,7 @@ export const DataTable: React.FC = ({
if (record.id === 'uncategorized') {
return -;
}
-
+
// 分类节点的操作
const category: Category = {
id: record.id,
@@ -228,7 +249,7 @@ export const DataTable: React.FC = ({
createdAt: record.createdAt,
updatedAt: record.updatedAt,
};
-
+
return (
);
}
-
+
// 链接节点的操作
return (
@@ -280,12 +296,7 @@ export const DataTable: React.FC = ({
okText="确定"
cancelText="取消"
>
- }
- size="small"
- >
+ } size="small">
删除
@@ -300,7 +311,7 @@ export const DataTable: React.FC = ({
selectedRowKeys,
onChange: (newSelectedRowKeys: React.Key[]) => {
// 过滤掉分类节点
- const linkKeys = newSelectedRowKeys.filter(key => !String(key).startsWith('category-'));
+ const linkKeys = newSelectedRowKeys.filter((key) => !String(key).startsWith('category-'));
if (onSelectionChange) {
onSelectionChange(linkKeys);
} else {
@@ -321,15 +332,12 @@ export const DataTable: React.FC = ({
rowKey="key"
size="middle"
rowSelection={rowSelection}
- rowClassName={(record) =>
- record.isCategory
- ? 'category-row'
- : ''
- }
+ rowClassName={(record) => (record.isCategory ? 'category-row' : '')}
expandable={{
expandedRowKeys,
+ indentSize: 0,
onExpandedRowsChange: (keys) => setExpandedRowKeys([...keys]),
- defaultExpandAllRows: true,
+ // defaultExpandAllRows: true,
}}
pagination={{
current: currentPage,
@@ -347,7 +355,6 @@ export const DataTable: React.FC = ({
pageSizeOptions: ['10', '20', '50', '100'],
}}
scroll={{ x: 1200 }}
- className="[&_.ant-empty]:z-0 [&_.category-row>td]:bg-blue-50! [&_.category-row>td]:dark:bg-blue-900/30! [&_.category-row:hover>td]:bg-blue-100! [&_.category-row:hover>td]:dark:bg-blue-800/40!"
/>
);
From bfaccda189931e84978c0a26aff4ea1b17db7446 Mon Sep 17 00:00:00 2001
From: weizwz <1124725517@qq.com>
Date: Thu, 20 Nov 2025 10:22:37 +0800
Subject: [PATCH 6/8] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?=
=?UTF-8?q?=E5=BC=95=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/management/DataTable.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/management/DataTable.tsx b/components/management/DataTable.tsx
index bc0d1dc..a206e44 100644
--- a/components/management/DataTable.tsx
+++ b/components/management/DataTable.tsx
@@ -2,7 +2,7 @@
import React, { useState, useMemo, useEffect } from 'react';
import { Table, Button, Space, Popconfirm } from 'antd';
-import { EditOutlined, DeleteOutlined, RightOutlined, DownOutlined } from '@ant-design/icons';
+import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import { Link } from '@/types/link';
import { Category } from '@/types/category';
From 5a6b86f2a51d8b190d8476cdc74e278a82b490f6 Mon Sep 17 00:00:00 2001
From: weizwz <1124725517@qq.com>
Date: Thu, 20 Nov 2025 10:48:49 +0800
Subject: [PATCH 7/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A1=A8=E6=A0=BC?=
=?UTF-8?q?=E7=BB=86=E8=8A=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/management/DataTable.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/components/management/DataTable.tsx b/components/management/DataTable.tsx
index a206e44..af93b33 100644
--- a/components/management/DataTable.tsx
+++ b/components/management/DataTable.tsx
@@ -224,7 +224,7 @@ export const DataTable: React.FC
= ({
className="w-6 h-6 rounded border border-gray-300"
style={{ backgroundColor: color || '#d9d9d9' }}
/>
- {color || '#d9d9d9'}
+ {color || '#d9d9d9'}
),
},
From a2e027b3213fd4d3480ef9c3c58dc14c937c72e9 Mon Sep 17 00:00:00 2001
From: weizwz <1124725517@qq.com>
Date: Thu, 20 Nov 2025 11:01:41 +0800
Subject: [PATCH 8/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=9C=80=E6=96=B0?=
=?UTF-8?q?=E9=A2=84=E8=A7=88=E5=9B=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 14e6b05..f16b892 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-
+
现代化的个人前端导航网站,为开发者提供高效、美观的资源导航体验