work/docs/数据库重构计划.md
2025-12-25 23:05:20 +08:00

703 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 书签管理系统 - 数据库重构完整计划
## 一、重构背景
### 1.1 现有问题
原系统采用简化的数据表设计4 张表users, devices, bookmarks, refresh_tokens存在以下问题
| 问题 | 现状 | 影响 |
|------|------|------|
| **标签存储** | 书签表中的 `Tags` 字段使用 JSON 数组存储 | 无法高效查询、无法统计标签使用量、无法为标签设置颜色/图标 |
| **设备权限** | 书签表中的 `AllowedDevices` 字段使用 JSON 数组存储 | 无法建立外键约束、删除设备后残留无效数据 |
| **组织结构** | 书签只能通过标签分类,无层级结构 | 不支持文件夹嵌套、无法按目录组织书签 |
| **功能缺失** | 无收藏集合、分享、访问历史功能 | 用户体验受限 |
### 1.2 重构目标
将现有的 **4 张表**扩展为 **12 张表**,实现:
- **标签管理**:独立 Tag 表 + 关联表,支持标签元数据(颜色、图标、排序)
- **层级结构**:新增文件夹表,支持多级嵌套
- **设备权限**:改用关联表,支持外键约束和级联删除
- **新增功能**:收藏集合、分享链接、访问历史记录
### 1.3 表结构变化概览
| 类别 | 改造前 | 改造后 |
|------|--------|--------|
| 核心表 | users, devices, refresh_tokens | 保持不变 |
| 书签表 | bookmarks (含 JSON 字段) | bookmarks (精简) |
| 标签 | - | tags, bookmark_tags |
| 文件夹 | - | folders |
| 设备权限 | - | bookmark_device_permissions |
| 收藏集合 | - | collections, collection_bookmarks |
| 分享功能 | - | bookmark_shares |
| 访问历史 | - | bookmark_visits |
---
## 二、后端重构(已完成)
### 2.1 实体类变更
#### 修改的实体
| 文件 | 变更内容 |
|------|----------|
| `Bookmark.cs` | 移除 `Tags`(string[])、`AllowedDevices`(Guid[]);新增 `FolderId``Order` 从 long 改为 int`LastVisitTime` 改名为 `LastVisitAt`;新增导航属性 |
#### 新增的实体
| 文件 | 说明 |
|------|------|
| `Folder.cs` | 文件夹实体,支持 ParentId 自引用实现多级嵌套 |
| `Tag.cs` | 标签实体,包含 Color、Icon、Order 字段 |
| `BookmarkTag.cs` | 书签-标签多对多关联表 |
| `BookmarkDevicePermission.cs` | 书签-设备权限关联表 |
| `Collection.cs` | 收藏集合实体 |
| `CollectionBookmark.cs` | 集合-书签多对多关联表 |
| `BookmarkShare.cs` | 分享链接实体,支持密码保护、过期时间、查看次数限制 |
| `BookmarkVisit.cs` | 访问历史实体 |
#### 新增的枚举
| 文件 | 说明 |
|------|------|
| `ShareType.cs` | 分享类型Bookmark(1)/Folder(2)/Collection(3) |
### 2.2 DTO 变更
| DTO | 变更内容 |
|-----|----------|
| `BookmarkDto` | 新增 `FolderId``Tags` 从 `string[]` 改为 `List<TagDto>``LastVisitTime` 改名为 `LastVisitAt``Order` 从 long 改为 int |
| `TagDto` | 新增 `Id`、`Color`、`Icon`、`Order` 字段 |
| `CreateBookmarkRequest` | 新增 `FolderId` 字段 |
| `UpdateBookmarkRequest` | 新增 `FolderId`、`UpdateFolder` 字段 |
### 2.3 服务层重构
| 服务 | 变更内容 |
|------|----------|
| `BookmarkService` | 完全重写,使用 `IncludeMany` 加载 BookmarkTags 和 DevicePermissions新增 `SyncBookmarkTagsAsync`、`SyncDevicePermissionsAsync` 私有方法 |
| `TagService` | 完全重写,使用独立 Tag 表;新增 `CreateTagAsync`、`UpdateTagAsync`、`GetTagAsync` 方法 |
### 2.4 接口变更
| 接口 | 变更内容 |
|------|----------|
| `ITagService` | 新增 `CreateTagAsync`、`UpdateTagAsync`、`GetTagAsync` 方法签名 |
| `IBookmarkService` | `GetUserBookmarksAsync` 新增 `folderId` 参数 |
### 2.5 控制器变更
| 控制器 | 变更内容 |
|--------|----------|
| `TagsController` | 新增完整的 CRUD 操作(创建、更新、删除标签) |
| `BookmarksController` | `GetBookmarks` 新增 `folderId` 查询参数 |
| `AdminController` | 修复 GetUserBookmarks 方法,使用新的实体结构 |
### 2.6 数据库初始化
`FreeSqlSetup.cs` 已更新:
- 注册所有 12 个实体类型
- 启动时自动同步表结构
- 提供 `SyncAllTables()` 方法手动同步
- 提供 `CheckDatabaseStatusAsync()` 方法检查数据库状态
---
## 三、前端重构计划
### 3.1 需要修改的文件清单
#### 3.1.1 类型定义 (`src/frontend/src/types/index.ts`)
| 修改项 | 当前 | 修改后 |
|--------|------|--------|
| `Bookmark.tags` | `string[]` | `Tag[]` |
| `Bookmark.lastVisitTime` | `lastVisitTime` | `lastVisitAt` |
| 新增 `Bookmark.folderId` | - | `folderId?: string` |
| `Tag` 接口 | `{ name: string; count: number }` | `{ id: string; name: string; color?: string; icon?: string; order: number; count: number }` |
| 新增 | - | `Folder` 接口 |
| 新增 | - | `Collection` 接口 |
```typescript
// 修改后的 Tag 接口
interface Tag {
id: string;
name: string;
color?: string;
icon?: string;
order: number;
count: number;
}
// 修改后的 Bookmark 接口
interface Bookmark {
id: string;
folderId?: string; // 新增
title: string;
url: string;
description?: string;
icon?: string;
tags: Tag[]; // 从 string[] 改为 Tag[]
visitCount: number;
lastVisitAt?: string; // 重命名
order: number;
visibility: VisibilityType;
allowedDevices?: string[];
createdAt: string;
updatedAt: string;
}
// 新增 Folder 接口
interface Folder {
id: string;
parentId?: string;
name: string;
icon?: string;
order: number;
children?: Folder[];
bookmarks?: Bookmark[];
}
```
#### 3.1.2 API 层修改
**`src/frontend/src/api/bookmark.ts`**
| 方法 | 修改内容 |
|------|----------|
| `getBookmarks()` | 新增 `folderId` 参数:`getBookmarks(tag?: string, folderId?: string)` |
| 新增 | `getFolders()` - 获取文件夹列表 |
| 新增 | `createFolder()` - 创建文件夹 |
| 新增 | `updateFolder()` - 更新文件夹 |
| 新增 | `deleteFolder()` - 删除文件夹 |
| 新增 | `moveBookmark()` - 移动书签到文件夹 |
**`src/frontend/src/api/tag.ts`**
| 方法 | 修改内容 |
|------|----------|
| 新增 | `createTag(name, color?, icon?)` - 创建标签 |
| 新增 | `updateTag(id, name?, color?, icon?)` - 更新标签 |
| 修改 | `deleteTag(id)` - 参数从标签名改为标签ID |
| 修改 | `mergeTags(sourceTagIds, targetTagId)` - 参数从标签名改为标签ID |
#### 3.1.3 Store 层修改
**`src/frontend/src/stores/bookmark.ts`**
| 修改项 | 说明 |
|--------|------|
| 新增状态 | `currentFolderId: string \| null` - 当前文件夹 |
| 新增状态 | `folders: Folder[]` - 文件夹列表 |
| 修改 `fetchBookmarks` | 支持 `folderId` 参数 |
| 新增方法 | `fetchFolders()` - 获取文件夹列表 |
| 新增方法 | `createFolder()` - 创建文件夹 |
| 新增方法 | `deleteFolder()` - 删除文件夹 |
| 新增方法 | `setCurrentFolder()` - 切换文件夹 |
| 修改计算属性 | 适配新的 Tag 对象结构 |
**`src/frontend/src/stores/tag.ts`**
| 修改项 | 说明 |
|--------|------|
| 新增方法 | `createTag(name, color?, icon?)` |
| 新增方法 | `updateTag(id, name?, color?, icon?)` |
| 修改方法 | `deleteTag``mergeTags` 使用 ID 而非名称 |
#### 3.1.4 组件修改
**`src/frontend/src/components/bookmark/BookmarkList.vue`**
| 修改项 | 说明 |
|--------|------|
| 标签显示 | 从显示字符串改为显示带颜色的标签组件 |
| 新增 | 面包屑导航(显示当前文件夹路径) |
**`src/frontend/src/components/bookmark/BookmarkEditor.vue`**
| 修改项 | 说明 |
|--------|------|
| 标签选择 | 从字符串输入改为标签选择器(支持颜色预览) |
| 新增 | 文件夹选择器(树形结构) |
| 标签管理 | 支持创建带颜色的新标签 |
**新增组件**
| 组件 | 说明 |
|------|------|
| `FolderTree.vue` | 文件夹树形组件,支持展开/折叠、拖拽移动 |
| `TagBadge.vue` | 带颜色的标签徽章组件 |
| `TagManager.vue` | 标签管理弹窗(编辑颜色、图标、排序) |
#### 3.1.5 视图页面修改
**`src/frontend/src/views/HomeView.vue`**
| 修改项 | 说明 |
|--------|------|
| 左侧边栏 | 新增文件夹树导航 |
| 标签列表 | 显示标签颜色 |
| 面包屑 | 显示当前文件夹路径 |
### 3.2 前端修改优先级
| 优先级 | 任务 | 影响范围 |
|--------|------|----------|
| P0 | 修改类型定义 (types/index.ts) | 全局 |
| P0 | 修改 API 层适配新接口 | 全局 |
| P0 | 修改 Store 层适配新数据结构 | 全局 |
| P1 | 修改 BookmarkList 组件显示标签 | 书签列表 |
| P1 | 修改 BookmarkEditor 组件标签选择 | 书签编辑 |
| P2 | 新增文件夹相关组件和功能 | 新功能 |
| P2 | 新增标签管理功能 | 新功能 |
---
## 四、浏览器插件重构计划
### 4.1 需要修改的文件清单
#### 4.1.1 API 层 (`src/extension/shared/api.js`)
| 方法 | 修改内容 |
|------|----------|
| `getBookmarks(tag)` | 新增 `folderId` 参数:`getBookmarks(tag, folderId)` |
| `createBookmark(data)` | 请求体新增 `folderId` 字段 |
| 新增 | `getFolders()` - 获取文件夹列表 |
| 新增 | `createTag(name, color)` - 创建标签(可选) |
```javascript
// 修改后的 getBookmarks
async getBookmarks(tag = null, folderId = null) {
const params = new URLSearchParams();
if (tag) params.append('tag', tag);
if (folderId) params.append('folderId', folderId);
return this.request(`/bookmarks?${params.toString()}`);
}
// 修改后的 createBookmark
async createBookmark(data) {
return this.request('/bookmarks', {
method: 'POST',
body: JSON.stringify({
title: data.title,
url: data.url,
description: data.description,
tags: data.tags, // 标签名数组
folderId: data.folderId, // 新增
visibility: data.visibility || 0
})
});
}
```
#### 4.1.2 后台脚本 (`src/extension/background/background.js`)
| 修改项 | 说明 |
|--------|------|
| `onBookmarkCreated` | 收集标签时考虑新的标签对象结构 |
| 新增 | 支持将浏览器书签文件夹映射到系统文件夹(可选) |
#### 4.1.3 弹窗界面 (`src/extension/popup/`)
**popup.js 修改**
| 修改项 | 说明 |
|--------|------|
| 标签输入 | 保持逗号分隔输入方式(后端会自动创建标签) |
| 新增 | 文件夹选择下拉框(可选功能) |
**popup.html 修改**
| 修改项 | 说明 |
|--------|------|
| 新增 | 文件夹选择器 UI可选功能 |
#### 4.1.4 内容脚本 (`src/extension/content/content.js`)
| 修改项 | 说明 |
|--------|------|
| 搜索结果渲染 | 适配新的 Tag 对象结构,显示标签颜色 |
```javascript
// 修改后的搜索结果渲染
function renderSearchResult(bookmark) {
const tagsHtml = bookmark.tags.map(tag => {
const style = tag.color ? `background-color: ${tag.color}` : '';
return `<span class="tag" style="${style}">${tag.name}</span>`;
}).join('');
return `
<div class="search-result-item">
<img src="${bookmark.icon || 'default-icon.png'}" alt="">
<div class="info">
<div class="title">${bookmark.title}</div>
<div class="url">${bookmark.url}</div>
<div class="tags">${tagsHtml}</div>
</div>
</div>
`;
}
```
#### 4.1.5 新标签页 (`src/extension/newtab/index.html`)
| 修改项 | 说明 |
|--------|------|
| 书签卡片 | 适配新的 Tag 对象结构 |
| 标签显示 | 显示标签颜色 |
| 新增 | 文件夹导航(可选功能) |
### 4.2 插件修改优先级
| 优先级 | 任务 | 影响范围 |
|--------|------|----------|
| P0 | 修改 api.js 适配新接口 | 全局 |
| P0 | 修改 content.js 搜索结果渲染 | 全局搜索 |
| P0 | 修改 newtab 书签显示 | 新标签页 |
| P1 | 修改 popup 保存功能 | 快速保存 |
| P2 | 新增文件夹选择功能 | 新功能 |
---
## 五、API 接口变更说明
### 5.1 书签相关接口
| 接口 | 方法 | 变更 |
|------|------|------|
| `/api/bookmarks` | GET | 新增 `folderId` 查询参数 |
| `/api/bookmarks` | POST | 请求体新增 `folderId` 字段 |
| `/api/bookmarks/{id}` | PUT | 请求体新增 `folderId`、`updateFolder` 字段 |
### 5.2 标签相关接口
| 接口 | 方法 | 变更 |
|------|------|------|
| `/api/tags` | GET | 返回完整的 TagDto 对象(含 id, color, icon, order |
| `/api/tags` | POST | **新增** - 创建标签 |
| `/api/tags/{id}` | GET | **新增** - 获取标签详情 |
| `/api/tags/{id}` | PUT | **新增** - 更新标签 |
| `/api/tags/{id}` | DELETE | 参数从标签名改为标签 ID |
| `/api/tags/merge` | POST | 请求体使用标签 ID 数组 |
### 5.3 响应数据结构变更
**BookmarkDto 响应示例**
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"folderId": "660e8400-e29b-41d4-a716-446655440001",
"title": "Example Site",
"url": "https://example.com",
"description": "An example website",
"icon": "data:image/png;base64,...",
"tags": [
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"name": "工作",
"color": "#FF5733",
"icon": "briefcase",
"order": 1
},
{
"id": "880e8400-e29b-41d4-a716-446655440003",
"name": "技术",
"color": "#33FF57",
"icon": "code",
"order": 2
}
],
"visitCount": 42,
"lastVisitAt": "2024-12-25T10:30:00Z",
"order": 1,
"visibility": 0,
"allowedDevices": null,
"createdAt": "2024-12-01T00:00:00Z",
"updatedAt": "2024-12-25T10:30:00Z"
}
```
---
## 六、数据表详细设计
### 6.1 users 表(用户)- 保持不变
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 用户ID |
| Email | string(200) | Unique, Not Null | 邮箱 |
| UserName | string(100) | Not Null | 用户名 |
| PasswordHash | string(500) | Not Null | 密码哈希 |
| Avatar | string(500) | Nullable | 头像URL |
| Role | int | Default 0 | 角色 |
| Status | int | Default 0 | 状态 |
| CreatedAt | DateTime | Not Null | 创建时间 |
| LastLoginAt | DateTime | Nullable | 最后登录 |
### 6.2 devices 表(设备)- 保持不变
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 设备ID |
| UserId | Guid | FK | 所属用户 |
| DeviceName | string(200) | Not Null | 设备名称 |
| DeviceType | string(200) | Not Null | 设备类型 |
| DeviceFingerprint | string(500) | Nullable | 设备指纹 |
| IsAdmin | bool | Default false | 管理员设备 |
| Status | int | Default 0 | 状态 |
| CreatedAt | DateTime | Not Null | 创建时间 |
| LastActiveAt | DateTime | Not Null | 最后活跃 |
### 6.3 folders 表(文件夹)- 新增
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 文件夹ID |
| UserId | Guid | FK | 所属用户 |
| ParentId | Guid | FK, Nullable | 父文件夹 |
| Name | string(200) | Not Null | 名称 |
| Icon | string(100) | Nullable | 图标 |
| Order | int | Default 0 | 排序 |
| CreatedAt | DateTime | Not Null | 创建时间 |
| UpdatedAt | DateTime | Not Null | 更新时间 |
**索引:** `idx_folder_user_parent` (UserId, ParentId)
### 6.4 bookmarks 表(书签)- 重构
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 书签ID |
| UserId | Guid | FK | 所属用户 |
| FolderId | Guid | FK, Nullable | 所属文件夹 |
| Title | string(500) | Not Null | 标题 |
| Url | string(2000) | Not Null | URL |
| Description | string(2000) | Nullable | 描述 |
| Icon | string(MAX) | Nullable | 图标 |
| Order | int | Default 0 | 排序 |
| Visibility | int | Default 0 | 可见性 |
| VisitCount | int | Default 0 | 访问次数 |
| LastVisitAt | DateTime | Nullable | 最后访问 |
| CreatedAt | DateTime | Not Null | 创建时间 |
| UpdatedAt | DateTime | Not Null | 更新时间 |
**变更:** 移除 Tags、AllowedDevices新增 FolderId
### 6.5 tags 表(标签)- 新增
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 标签ID |
| UserId | Guid | FK | 所属用户 |
| Name | string(100) | Not Null | 名称 |
| Color | string(20) | Nullable | 颜色 |
| Icon | string(100) | Nullable | 图标 |
| Order | int | Default 0 | 排序 |
| CreatedAt | DateTime | Not Null | 创建时间 |
**索引:** `idx_tag_user_name` (UserId, Name) - Unique
### 6.6 bookmark_tags 表(书签-标签关联)- 新增
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 关联ID |
| BookmarkId | Guid | FK | 书签ID |
| TagId | Guid | FK | 标签ID |
| CreatedAt | DateTime | Not Null | 创建时间 |
**索引:** `idx_bookmark_tag_unique` (BookmarkId, TagId) - Unique
### 6.7 bookmark_device_permissions 表(设备权限)- 新增
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 权限ID |
| BookmarkId | Guid | FK | 书签ID |
| DeviceId | Guid | FK | 设备ID |
| CreatedAt | DateTime | Not Null | 创建时间 |
**索引:** `idx_permission_unique` (BookmarkId, DeviceId) - Unique
### 6.8 collections 表(收藏集合)- 新增
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 集合ID |
| UserId | Guid | FK | 所属用户 |
| Name | string(200) | Not Null | 名称 |
| Description | string(500) | Nullable | 描述 |
| Icon | string(100) | Nullable | 图标 |
| Color | string(20) | Nullable | 主题色 |
| IsPublic | bool | Default false | 是否公开 |
| Order | int | Default 0 | 排序 |
| CreatedAt | DateTime | Not Null | 创建时间 |
| UpdatedAt | DateTime | Not Null | 更新时间 |
### 6.9 collection_bookmarks 表(集合-书签关联)- 新增
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 关联ID |
| CollectionId | Guid | FK | 集合ID |
| BookmarkId | Guid | FK | 书签ID |
| Order | int | Default 0 | 排序 |
| CreatedAt | DateTime | Not Null | 添加时间 |
### 6.10 bookmark_shares 表(分享链接)- 新增
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 分享ID |
| UserId | Guid | FK | 创建者 |
| ShareCode | string(50) | Unique | 分享码 |
| ShareType | int | Not Null | 类型 |
| TargetId | Guid | Not Null | 目标ID |
| Title | string(200) | Nullable | 标题 |
| Password | string(100) | Nullable | 密码 |
| ViewCount | int | Default 0 | 查看次数 |
| MaxViews | int | Nullable | 最大查看 |
| ExpiresAt | DateTime | Nullable | 过期时间 |
| IsActive | bool | Default true | 是否启用 |
| CreatedAt | DateTime | Not Null | 创建时间 |
### 6.11 bookmark_visits 表(访问历史)- 新增
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | Guid | PK | 记录ID |
| UserId | Guid | FK | 用户ID |
| BookmarkId | Guid | FK | 书签ID |
| DeviceId | Guid | FK, Nullable | 设备ID |
| VisitedAt | DateTime | Not Null | 访问时间 |
---
## 七、实体关系图
```
┌─────────────┐
│ users │
└──────┬──────┘
│ 1:N
├────────────────┬────────────────┬────────────────┬────────────────┐
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ devices │ │ folders │ │ tags │ │ collections │ │ shares │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └─────────────┘
│ │ 1:N │ │
│ │ (self-ref) │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ bookmarks │◄────────┘ │
│ └──────┬──────┘ │
│ │ │
│ │ N:M │ N:M
│ ├─────────────────────────────────┤
│ │ │
│ ▼ ▼
│ ┌─────────────┐ ┌─────────────┐
│ │bookmark_tags│ │ collection_ │
│ └─────────────┘ │ bookmarks │
├─────────────────────────────────────────────────┐
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────┐
│ bookmark_device_ │ │ bookmark_ │
│ permissions │ │ visits │
└─────────────────────┘ └─────────────┘
```
---
## 八、重构进度跟踪
### 8.1 后端重构(已完成 ✅)
- [x] 修改 Bookmark.cs 实体
- [x] 新增 Folder.cs 实体
- [x] 新增 Tag.cs 实体
- [x] 新增 BookmarkTag.cs 实体
- [x] 新增 BookmarkDevicePermission.cs 实体
- [x] 新增 Collection.cs 实体
- [x] 新增 CollectionBookmark.cs 实体
- [x] 新增 BookmarkShare.cs 实体
- [x] 新增 BookmarkVisit.cs 实体
- [x] 新增 ShareType.cs 枚举
- [x] 修改 FreeSqlSetup.cs 注册新实体
- [x] 重构 BookmarkService.cs
- [x] 重构 TagService.cs
- [x] 更新 DTO 类
- [x] 更新控制器
- [x] 构建验证通过
### 8.2 前端重构(已完成 ✅)
- [x] 修改类型定义 (types/index.ts)
- Tag 接口新增 id、color、icon、order 字段
- Bookmark.tags 从 string[] 改为 Tag[]
- Bookmark.lastVisitTime 改名为 lastVisitAt
- 新增 folderId 字段
- 新增 Folder、Collection 接口
- [x] 修改 API 层 (api/bookmark.ts, api/tag.ts)
- getBookmarks 新增 folderId 参数
- 新增文件夹相关 API
- 标签 API 改用 ID
- [x] 修改 Store 层 (stores/bookmark.ts, stores/tag.ts)
- 新增 folders、currentFolderId 状态
- 新增文件夹操作方法
- 标签操作改用 ID
- [x] 修改 BookmarkList 组件
- 标签显示改为 tag.name
- 支持显示标签颜色
- [x] 修改 BookmarkEditor 组件
- 适配新的标签对象结构
- [x] 新增文件夹相关组件
- FolderTree.vue - 文件夹树形组件
- [x] 新增标签管理组件
- TagBadge.vue - 带颜色的标签徽章组件
- TagManager.vue - 标签管理弹窗
- [x] 修改 HomeView.vue
- 添加文件夹导航
- 标签显示颜色
- 面包屑导航
- 标签管理入口
- [x] 构建验证通过
### 8.3 浏览器插件重构(待开始)
- [ ] 修改 shared/api.js
- [ ] 修改 content/content.js 搜索结果渲染
- [ ] 修改 newtab/index.html 书签显示
- [ ] 修改 popup/popup.js 保存功能
---
## 九、注意事项
1. **数据迁移**:本次重构不考虑旧数据迁移,直接使用新表结构
2. **向后兼容**API 响应格式已变更,前端和插件必须同步更新
3. **标签创建**:创建书签时传入的标签名会自动创建不存在的标签
4. **级联删除**:删除用户时需级联删除所有关联数据
5. **性能考虑**bookmark_visits 表数据量可能很大,考虑定期清理
---
## 十、版本信息
- 文档版本v2.1
- 创建日期2024-12-25
- 最后更新2024-12-25
- 作者Claude Code
- 更新说明:完成前端重构