703 lines
24 KiB
Markdown
703 lines
24 KiB
Markdown
# 书签管理系统 - 数据库重构完整计划
|
||
|
||
## 一、重构背景
|
||
|
||
### 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
|
||
- 更新说明:完成前端重构
|