Skip to content
Open

N2 #1

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
149 commits
Select commit Hold shift + click to select a range
73366d7
Update storage.js
kinga-a Jul 14, 2026
700db20
Update useDataSync.ts
kinga-a Jul 14, 2026
02ab22f
Refactor CategoriesProvider to use localStorage for unlocked categories
kinga-a Jul 14, 2026
ebfcf46
Update MainContent.tsx
kinga-a Jul 14, 2026
14d9fc5
Update Sidebar.tsx
kinga-a Jul 14, 2026
5723357
Update AppLayout.tsx
kinga-a Jul 14, 2026
e519e3b
Update AppLayout.tsx
kinga-a Jul 14, 2026
c0df14f
Update AppLayout.tsx
kinga-a Jul 14, 2026
9128962
Update CategoryActionAuthModal.tsx
kinga-a Jul 14, 2026
16336a0
Update storage.js
kinga-a Jul 14, 2026
357f9bd
Update useDataSync.ts
kinga-a Jul 14, 2026
b954f55
Update CategoriesContext.tsx
kinga-a Jul 14, 2026
a31597b
Update MainContent.tsx
kinga-a Jul 14, 2026
e0046a7
Update Sidebar.tsx
kinga-a Jul 14, 2026
fdc38e6
Update storage.js
kinga-a Jul 14, 2026
df080b2
Add files via upload
kinga-a Jul 14, 2026
3f4b2ef
Add files via upload
kinga-a Jul 14, 2026
7185a27
Add files via upload
kinga-a Jul 14, 2026
cc91327
Add files via upload
kinga-a Jul 14, 2026
5875b00
Add files via upload
kinga-a Jul 14, 2026
17b55a2
Update CategoryAuthModal.tsx
kinga-a Jul 14, 2026
6e0fa04
Update storage.js
kinga-a Jul 14, 2026
09b22f4
Update types.ts
kinga-a Jul 14, 2026
140317b
Update LinkModal.tsx
kinga-a Jul 14, 2026
7efd2ef
Update storage.js
kinga-a Jul 14, 2026
b380e11
Update LinksContext.tsx
kinga-a Jul 14, 2026
aec3d68
Update MainContent.tsx
kinga-a Jul 14, 2026
beb7563
Update LinkCard.tsx
kinga-a Jul 14, 2026
a8379c0
Update MainContent.tsx
kinga-a Jul 14, 2026
4340a98
Update LinkModal.tsx
kinga-a Jul 14, 2026
de8bb83
Update storage.js
kinga-a Jul 14, 2026
a46d357
Update index.html
kinga-a Jul 14, 2026
7ceb405
Update Header.tsx
kinga-a Jul 14, 2026
19f532b
Update Header.tsx
kinga-a Jul 14, 2026
0d845e1
Update index.html
kinga-a Jul 14, 2026
2599873
Update index.html
kinga-a Jul 14, 2026
6e2d909
Update Header.tsx
kinga-a Jul 14, 2026
2cc7415
Update LinkCard.tsx
kinga-a Jul 14, 2026
dd3b336
Update LinkCard.tsx
kinga-a Jul 14, 2026
5c8d66f
Update index.html
kinga-a Jul 14, 2026
add6441
Update Header.tsx
kinga-a Jul 14, 2026
d2a9720
Update Header.tsx
kinga-a Jul 14, 2026
60624c6
Update LinkCard.tsx
kinga-a Jul 14, 2026
f973796
Update index.html
kinga-a Jul 14, 2026
e183115
Fix missing newline at end of Header.tsx
kinga-a Jul 14, 2026
c7e740b
Update LinkCard.tsx
kinga-a Jul 14, 2026
f0e9f80
Update Header.tsx
kinga-a Jul 15, 2026
7e908d8
Update Header.tsx
kinga-a Jul 15, 2026
a4f7d2c
Update Header.tsx
kinga-a Jul 15, 2026
931e6de
Update Header.tsx
kinga-a Jul 15, 2026
74c7d08
Simplify viewport and theme-color meta tags
kinga-a Jul 15, 2026
cf65372
Update LinkCard.tsx
kinga-a Jul 15, 2026
945c0aa
Update index.css
kinga-a Jul 15, 2026
2f62e6b
Update Header.tsx
kinga-a Jul 15, 2026
fcab7b1
Update LinkModal.tsx
kinga-a Jul 15, 2026
cc4788d
Update Header.tsx
kinga-a Jul 15, 2026
db3c83f
Update Header.tsx
kinga-a Jul 15, 2026
1a4f1f6
前2个版本可用,该版本优化前2个版本,顶部工具栏
kinga-a Jul 15, 2026
8d00594
Update Header.tsx
kinga-a Jul 15, 2026
b2c66fe
Update Header.tsx
kinga-a Jul 15, 2026
9329146
同一排
kinga-a Jul 15, 2026
1c9d2ef
同一排2
kinga-a Jul 15, 2026
071c797
同一排3
kinga-a Jul 15, 2026
3386130
同一排4
kinga-a Jul 15, 2026
57962e8
更新展开关闭按钮
kinga-a Jul 15, 2026
6057d4f
Refactor Header component by removing duplicate button
kinga-a Jul 15, 2026
99d52bd
排布修改
kinga-a Jul 15, 2026
1d6daeb
排2
kinga-a Jul 15, 2026
b69359e
书签排序修复
kinga-a Jul 15, 2026
4893d01
书签排序修复
kinga-a Jul 15, 2026
00855d3
批量选中
kinga-a Jul 15, 2026
3fe1cb1
图标接口添加
kinga-a Jul 15, 2026
53a0336
图片接口添加
kinga-a Jul 15, 2026
202372f
图标接口添加
kinga-a Jul 15, 2026
4815e5b
图标接口修改
kinga-a Jul 15, 2026
24faa56
苹果手机长按问题修复
kinga-a Jul 15, 2026
08c88fa
苹果手机长按问题修复
kinga-a Jul 15, 2026
4f09306
修改苹果浏览器长按出现选择问题
kinga-a Jul 15, 2026
9040c1d
修改苹果浏览器长按出现选择问题
kinga-a Jul 15, 2026
83cbe0c
iOS Safari 长按优化:阻止卡片上的文本选择和系统菜单
kinga-a Jul 15, 2026
a557ecb
私人书签修改。🔒 图标从标题后面移到了**书签图标的左上角**,并加了紫色圆形背景,更醒目。
kinga-a Jul 15, 2026
cf81456
紫色圆形 + 🔒 图标 → 蓝色小圆点
kinga-a Jul 15, 2026
be44c4d
改为🔒
kinga-a Jul 15, 2026
9015034
Update LinkCard.tsx
kinga-a Jul 15, 2026
e244e29
Update index.css
kinga-a Jul 15, 2026
6531677
index.css一并修改到没修复长按时
kinga-a Jul 15, 2026
41ba743
私人书签修复🔒
kinga-a Jul 15, 2026
a1b84bc
苹果浏览器长按选择去掉
kinga-a Jul 15, 2026
5acb4e4
天气手机端大小优化
kinga-a Jul 16, 2026
898d18d
增加诗词功能
kinga-a Jul 16, 2026
c391c9b
增加诗词功能
kinga-a Jul 16, 2026
d2d0233
增加诗词功能
kinga-a Jul 16, 2026
e01e9d0
移除 behavior: 'smooth',修复苹果浏览器侧边栏问题
kinga-a Jul 16, 2026
e6e3b2f
iOS Safari 侧边栏问题修复
kinga-a Jul 16, 2026
00ed465
防止用户双指缩放时意外触发 Safari 的地址栏显示/隐藏逻辑
kinga-a Jul 16, 2026
d5ab42f
Safari浏览器侧边栏问题
kinga-a Jul 16, 2026
62dc110
Safari浏览器侧边栏问题
kinga-a Jul 16, 2026
b480974
侧边栏优化
kinga-a Jul 16, 2026
70cdf7d
侧边栏优化
kinga-a Jul 16, 2026
e645cc4
侧修
kinga-a Jul 16, 2026
f4122bc
侧修
kinga-a Jul 16, 2026
879bad2
侧修
kinga-a Jul 16, 2026
75dca4d
侧修
kinga-a Jul 16, 2026
d526e1a
侧修
kinga-a Jul 16, 2026
4f27e18
Add files via upload
kinga-a Jul 17, 2026
3d3919b
Add files via upload
kinga-a Jul 17, 2026
4003d9b
Add files via upload
kinga-a Jul 17, 2026
ea6fbb2
Add files via upload
kinga-a Jul 17, 2026
3371226
Add files via upload
kinga-a Jul 17, 2026
efa9a11
Add files via upload
kinga-a Jul 17, 2026
a37907e
Add files via upload
kinga-a Jul 17, 2026
3b8b02c
Add files via upload
kinga-a Jul 17, 2026
dcb41cf
Add files via upload
kinga-a Jul 17, 2026
8a203a8
Add files via upload
kinga-a Jul 17, 2026
eb8448b
Add files via upload
kinga-a Jul 17, 2026
dccaf31
Update AppLayout.tsx
kinga-a Jul 17, 2026
e4aafe2
Update CategoryManagerModal.tsx
kinga-a Jul 17, 2026
e0f3914
Update BackupModal.tsx
kinga-a Jul 17, 2026
dc44978
Update BackupModal.tsx
kinga-a Jul 17, 2026
aa4bf94
Update ImportModal.tsx
kinga-a Jul 17, 2026
e7a17c8
Update CategoryManagerModal.tsx
kinga-a Jul 17, 2026
d7e11aa
Update AppLayout.tsx
kinga-a Jul 17, 2026
3504ce5
Update index.css
kinga-a Jul 17, 2026
638680f
Delete src/components/layout/useToast.ts
kinga-a Jul 17, 2026
bfa74dc
Delete src/components/layout/ToastContainer.tsx
kinga-a Jul 17, 2026
3f5f33a
Delete src/components/layout/ToastContext.tsx
kinga-a Jul 17, 2026
786a959
Update AppLayout.tsx
kinga-a Jul 18, 2026
46b65c2
批量删除修复
kinga-a Jul 18, 2026
aae477f
Update AppLayout.tsx
kinga-a Jul 18, 2026
d7dfe98
Add files via upload
kinga-a Jul 18, 2026
f29ce83
Add files via upload
kinga-a Jul 18, 2026
bb86284
Add files via upload
kinga-a Jul 18, 2026
48cf349
Add files via upload
kinga-a Jul 18, 2026
ba56834
Add files via upload
kinga-a Jul 18, 2026
69a65df
Add files via upload
kinga-a Jul 18, 2026
3e9b155
Update _routes.json
kinga-a Jul 18, 2026
64ba8e0
Update LinksContext.tsx
kinga-a Jul 18, 2026
42ce88b
Update LinksContext.tsx
kinga-a Jul 18, 2026
45f84e7
Add files via upload
kinga-a Jul 18, 2026
0b8d21f
Add files via upload
kinga-a Jul 18, 2026
ee228dc
Add files via upload
kinga-a Jul 18, 2026
12dc870
Add files via upload
kinga-a Jul 18, 2026
afae68c
Add files via upload
kinga-a Jul 18, 2026
1ac94b1
Add files via upload
kinga-a Jul 18, 2026
b453e68
Update CategoryManagerModal.tsx
kinga-a Jul 18, 2026
416fa81
Update AppLayout.tsx
kinga-a Jul 18, 2026
1ecba6f
Update CategoryManagerModal.tsx
kinga-a Jul 18, 2026
d23becd
Update LinkModal.tsx
kinga-a Jul 18, 2026
0cd6231
Update AppLayout.tsx
kinga-a Jul 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
410 changes: 410 additions & 0 deletions api/storage.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion components/BackupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -512,4 +512,4 @@ const BackupModal: React.FC<BackupModalProps> = ({
);
};

export default BackupModal;
export default BackupModal;
134 changes: 56 additions & 78 deletions components/CategoryActionAuthModal.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,73 @@
import React, { useState } from 'react';
import { X, Lock, AlertCircle } from 'lucide-react';
import { Lock, ArrowRight, Loader2, X } from 'lucide-react';
import { Category } from '../types';
import { API_ENDPOINTS } from '../src/constants';

interface CategoryActionAuthModalProps {
interface CategoryAuthModalProps {
isOpen: boolean;
onClose: () => void;
onVerify: (password: string) => Promise<boolean>;
onVerified: () => void;
actionType: 'edit' | 'delete';
categoryName: string;
category: Category | null;
onUnlock: (categoryId: string) => void;
}

const CategoryActionAuthModal: React.FC<CategoryActionAuthModalProps> = ({
isOpen,
onClose,
onVerify,
onVerified,
actionType,
categoryName
}) => {
const CategoryAuthModal: React.FC<CategoryAuthModalProps> = ({ isOpen, onClose, category, onUnlock }) => {
const [password, setPassword] = useState('');
const [isVerifying, setIsVerifying] = useState(false);
const [error, setError] = useState('');
const [isLoading, setIsLoading] = useState(false);

if (!isOpen) return null;
if (!isOpen || !category) return null;

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!password.trim()) {
setError('请输入密码');
return;
}
if (!password.trim()) return;

setIsVerifying(true);
setIsLoading(true);
setError('');

try {
const success = await onVerify(password);
if (success) {
setPassword('');
onVerified();
} else {
setError('密码错误,请重试');
// 调用后端验证分类密码
const res = await fetch(`${API_ENDPOINTS.STORAGE}?getConfig=links&category=${encodeURIComponent(category.id)}&catPassword=${encodeURIComponent(password.trim())}`);

if (res.status === 403) {
setError('密码错误');
setIsLoading(false);
return;
}

if (!res.ok) {
setError('验证失败,请重试');
setIsLoading(false);
return;
}

// 密码正确,解锁分类
onUnlock(category.id);
setPassword('');
setError('');
setIsLoading(false);
onClose();
} catch (err) {
setError('验证失败,请重试');
} finally {
setIsVerifying(false);
console.error('Category auth error:', err);
setError('网络错误,请重试');
setIsLoading(false);
}
};

const handleClose = () => {
setPassword('');
setError('');
onClose();
};

const actionText = actionType === 'edit' ? '编辑' : '删除';
const colorClass = actionType === 'edit'
? 'amber'
: 'red';

return (
<div className="fixed inset-0 z-[60] flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm">
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-2xl w-full max-w-sm overflow-hidden border border-slate-200 dark:border-slate-700 p-6 relative">
<button onClick={handleClose} className="absolute top-4 right-4 p-1 hover:bg-slate-100 dark:hover:bg-slate-700 rounded-full">
<button onClick={onClose} className="absolute top-4 right-4 p-1 hover:bg-slate-100 dark:hover:bg-slate-700 rounded-full">
<X size={20} className="text-slate-400" />
</button>

<div className="flex flex-col items-center mb-6">
<div className={`w-14 h-14 bg-${colorClass}-100 dark:bg-${colorClass}-900/30 rounded-full flex items-center justify-center mb-4 text-${colorClass}-600 dark:text-${colorClass}-400`}>
<div className="w-14 h-14 bg-amber-100 dark:bg-amber-900/30 rounded-full flex items-center justify-center mb-4 text-amber-600 dark:text-amber-400">
<Lock size={28} />
</div>
<h2 className="text-lg font-bold dark:text-white">验证操作权限</h2>
<h2 className="text-lg font-bold dark:text-white">解锁 "{category.name}"</h2>
<p className="text-sm text-slate-500 dark:text-slate-400 text-center mt-2">
您正在{actionText}分类 "<span className="font-medium">{categoryName}</span>"
该目录受密码保护,请输入密码访问
</p>
<div className="flex items-center gap-2 mt-2 p-2 bg-amber-50 dark:bg-amber-900/20 rounded-lg">
<AlertCircle size={16} className="text-amber-600 dark:text-amber-400" />
<p className="text-xs text-amber-700 dark:text-amber-300">
请输入部署时设置的密码进行验证
</p>
</div>
</div>

<form onSubmit={handleSubmit} className="space-y-4">
Expand All @@ -89,41 +76,32 @@ const CategoryActionAuthModal: React.FC<CategoryActionAuthModalProps> = ({
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className={`w-full p-3 rounded-xl border border-slate-300 dark:border-slate-600 dark:bg-slate-700 dark:text-white focus:ring-2 focus:ring-${colorClass}-500 outline-none transition-all text-center tracking-widest`}
placeholder="请输入密码"
className="w-full p-3 rounded-xl border border-slate-300 dark:border-slate-600 dark:bg-slate-700 dark:text-white focus:ring-2 focus:ring-amber-500 outline-none transition-all text-center tracking-widest"
placeholder="目录密码"
autoFocus
disabled={isVerifying}
disabled={isLoading}
/>
</div>

{error && (
<div className={`p-2 bg-${colorClass}-50 dark:bg-${colorClass}-900/20 rounded-lg flex items-center gap-2`}>
<AlertCircle size={16} className={`text-${colorClass}-600 dark:text-${colorClass}-400`} />
<p className={`text-sm text-${colorClass}-700 dark:text-${colorClass}-300`}>{error}</p>
<div className="text-red-500 text-sm text-center font-medium animate-pulse">
{error}
</div>
)}

<div className="flex gap-2">
<button
type="button"
onClick={handleClose}
className="flex-1 px-4 py-2.5 bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-xl hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors font-medium"
disabled={isVerifying}
>
取消
</button>
<button
type="submit"
className={`flex-1 px-4 py-2.5 bg-${colorClass}-600 text-white rounded-xl hover:bg-${colorClass}-700 transition-colors font-medium disabled:opacity-50`}
disabled={isVerifying}
>
{isVerifying ? '验证中...' : `确认${actionText}`}
</button>
</div>

<button
type="submit"
disabled={!password || isLoading}
className="w-full bg-amber-500 hover:bg-amber-600 disabled:bg-amber-300 text-white font-bold py-3 px-4 rounded-xl transition-colors shadow-lg shadow-amber-500/30 flex items-center justify-center gap-2"
>
{isLoading ? <Loader2 size={18} className="animate-spin" /> : <>
解锁 <ArrowRight size={18} />
</>}
</button>
</form>
</div>
</div>
);
};

export default CategoryActionAuthModal;
export default CategoryAuthModal;
53 changes: 42 additions & 11 deletions components/CategoryAuthModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { Lock, ArrowRight, Loader2, X } from 'lucide-react';
import { Category } from '../types';
import { API_ENDPOINTS } from '../src/constants';

interface CategoryAuthModalProps {
isOpen: boolean;
Expand All @@ -12,18 +13,45 @@ interface CategoryAuthModalProps {
const CategoryAuthModal: React.FC<CategoryAuthModalProps> = ({ isOpen, onClose, category, onUnlock }) => {
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [isLoading, setIsLoading] = useState(false);

if (!isOpen || !category) return null;

const handleSubmit = (e: React.FormEvent) => {
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (password === category.password) {
onUnlock(category.id);
setPassword('');
setError('');
onClose();
} else {
if (!password.trim()) return;

setIsLoading(true);
setError('');

try {
// 调用后端验证分类密码
const res = await fetch(
`${API_ENDPOINTS.STORAGE}?getConfig=links&category=${encodeURIComponent(category.id)}&catPassword=${encodeURIComponent(password.trim())}`
);

if (res.status === 403) {
setError('密码错误');
setIsLoading(false);
return;
}

if (!res.ok) {
setError('验证失败,请重试');
setIsLoading(false);
return;
}

// 密码正确,解锁分类
onUnlock(category.id);
setPassword('');
setError('');
setIsLoading(false);
onClose();
} catch (err) {
console.error('Category auth error:', err);
setError('网络错误,请重试');
setIsLoading(false);
}
};

Expand Down Expand Up @@ -53,6 +81,7 @@ const CategoryAuthModal: React.FC<CategoryAuthModalProps> = ({ isOpen, onClose,
className="w-full p-3 rounded-xl border border-slate-300 dark:border-slate-600 dark:bg-slate-700 dark:text-white focus:ring-2 focus:ring-amber-500 outline-none transition-all text-center tracking-widest"
placeholder="目录密码"
autoFocus
disabled={isLoading}
/>
</div>

Expand All @@ -64,15 +93,17 @@ const CategoryAuthModal: React.FC<CategoryAuthModalProps> = ({ isOpen, onClose,

<button
type="submit"
disabled={!password}
className="w-full bg-amber-500 hover:bg-amber-600 text-white font-bold py-3 px-4 rounded-xl transition-colors shadow-lg shadow-amber-500/30 flex items-center justify-center gap-2"
disabled={!password || isLoading}
className="w-full bg-amber-500 hover:bg-amber-600 disabled:bg-amber-300 text-white font-bold py-3 px-4 rounded-xl transition-colors shadow-lg shadow-amber-500/30 flex items-center justify-center gap-2"
>
解锁 <ArrowRight size={18} />
{isLoading ? <Loader2 size={18} className="animate-spin" /> : <>
解锁 <ArrowRight size={18} />
</>}
</button>
</form>
</div>
</div>
);
};

export default CategoryAuthModal;
export default CategoryAuthModal;
30 changes: 29 additions & 1 deletion components/CategoryManagerModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react';
import { X, ArrowUp, ArrowDown, Trash2, Edit2, Plus, Check, Lock, Unlock, Palette, Save } from 'lucide-react';
import { toast } from './Toast';
import { Category } from '../types';
import Icon from './Icon';
import IconSelector from './IconSelector';
Expand All @@ -9,17 +10,21 @@ interface CategoryManagerModalProps {
isOpen: boolean;
onClose: () => void;
categories: Category[];
links: { id: string; categoryId: string; title: string }[];
onUpdateCategories: (newCategories: Category[]) => void;
onDeleteCategory: (id: string) => void;
onUpdateLinks?: (links: { id: string; categoryId: string; title: string }[]) => void;
onVerifyPassword?: (password: string) => Promise<boolean>;
}

const CategoryManagerModal: React.FC<CategoryManagerModalProps> = ({
isOpen,
onClose,
categories,
links,
onUpdateCategories,
onDeleteCategory,
onUpdateLinks,
onVerifyPassword
}) => {
// 本地编辑状态 - 不直接修改原始数据
Expand Down Expand Up @@ -140,6 +145,7 @@ const CategoryManagerModal: React.FC<CategoryManagerModalProps> = ({

onUpdateCategories(sorted);
setHasChanges(false);
toast.success('分类更改已保存');
onClose();
} catch (e) {
console.error('Save failed:', e);
Expand Down Expand Up @@ -172,6 +178,16 @@ const CategoryManagerModal: React.FC<CategoryManagerModalProps> = ({
if (!onVerifyPassword || hasVerifiedPermissions) {
if (confirm(`确定删除"${cat.name}"分类吗?该分类下的书签将移动到"常用推荐"。`)) {
const newCats = localCategories.filter(c => c.id !== cat.id);
// 迁移该分类下的书签到 common
if (onUpdateLinks && links) {
const linksToMigrate = links.filter(l => l.categoryId === cat.id);
if (linksToMigrate.length > 0) {
const migratedLinks = links.map(l =>
l.categoryId === cat.id ? { ...l, categoryId: 'common' } : l
);
onUpdateLinks(migratedLinks);
}
}
markChanged(newCats);
}
return;
Expand All @@ -189,7 +205,17 @@ const CategoryManagerModal: React.FC<CategoryManagerModalProps> = ({
if (cat) startEdit(cat);
} else if (pendingAction.type === 'delete') {
const cat = localCategories.find(c => c.id === pendingAction.categoryId);
if (cat && confirm(`确定删除"${cat.name}"分类吗?`)) {
if (cat && confirm(`确定删除"${cat.name}"分类吗?该分类下的书签将移动到"常用推荐"。`)) {
// 迁移该分类下的书签到 common
if (onUpdateLinks && links) {
const linksToMigrate = links.filter(l => l.categoryId === cat.id);
if (linksToMigrate.length > 0) {
const migratedLinks = links.map(l =>
l.categoryId === cat.id ? { ...l, categoryId: 'common' } : l
);
onUpdateLinks(migratedLinks);
}
}
markChanged(localCategories.filter(c => c.id !== cat.id));
}
}
Expand Down Expand Up @@ -227,6 +253,7 @@ const CategoryManagerModal: React.FC<CategoryManagerModalProps> = ({
return c;
});
markChanged(newCats);
toast.success(`已更新分类「${editName.trim()}」`);
setEditingId(null);
setEditParentId('');
};
Expand All @@ -244,6 +271,7 @@ const CategoryManagerModal: React.FC<CategoryManagerModalProps> = ({
weight: maxWeight + 1,
};
markChanged([...localCategories, newCat]);
toast.success(`已添加分类「${newCat.name}」`);
setNewCatName('');
setNewCatPassword('');
setNewCatIcon('Folder');
Expand Down
2 changes: 1 addition & 1 deletion components/ImportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -981,4 +981,4 @@ const ImportModal: React.FC<ImportModalProps> = ({
);
};

export default ImportModal;
export default ImportModal;
Loading