# v2.0 开发文档 > **版本**: 2.0.0 > **状态**: ✅ 已完成 > **最后更新**: 2025-12-15 > **文档类型**: 技术开发文档 --- ## 文档概述 本文档详细记录了书签管理系统 v2.0 的完整技术实现,包括: - 从 v1.0(本地单用户)到 v2.0(云端多用户)的架构升级 - 后端 API(ASP.NET Core + FreeSql)完整实现 - 前端应用(Vue 3 + TypeScript)技术栈 - 浏览器扩展自动同步机制 - 后台管理系统实现细节 --- ## 核心任务完成情况 ### ✅ 已完成功能 **后端 API(100%)** - [x] JWT 认证系统(包含 RefreshToken 机制) - [x] 用户注册/登录/登出 - [x] 设备自动注册与管理(设备指纹识别) - [x] 书签 CRUD(含搜索、批量操作、可见性控制) - [x] 标签管理 - [x] 后台管理接口(用户管理、设备管理、统计数据) **前端应用(100%)** - [x] 用户认证界面(登录/注册) - [x] 书签管理界面(列表、编辑、搜索) - [x] 设备管理界面 - [x] 可见性控制界面 - [x] Pinia 状态管理(auth、bookmark、device、tag) **浏览器扩展(90%)** - [x] 书签自动同步(监听浏览器书签创建事件) - [x] 文件夹路径转标签 - [x] URL 重复检测 - [x] 同步状态提示 - [ ] 删除/修改同步(预留接口) **后台管理系统(100%)** - [x] 仪表盘(系统统计数据) - [x] 用户管理(列表、详情、禁用、重置密码) - [x] 设备管理(强制下线、禁用设备) - [x] 书签管理(查看、删除) --- ## 技术架构变化 ### ```mermaid graph LR v1[v1.0_本地单用户] v2[v2.0_云端多用户] v1 -->|架构升级| v2 subgraph v1_arch [v1.0架构] fe1[Vue前端] idb[IndexedDB] ext1[扩展监控] fe1 --> idb ext1 -.-> fe1 end subgraph v2_arch [v2.0架构] fe2[Vue前端] api[.NET_API] db[(SQL数据库)] admin[Vue后台] ext2[扩展增强] fe2 --> api ext2 --> api admin --> api api --> db end ``` ### 技术栈选型 基于用户确认的技术选型: | 组件 | 技术选择 | 说明 | |------|---------|------| | 后端框架 | ASP.NET Core 8 (LTS) | 长期支持版本,稳定可靠 | | 数据库 | SQL Server / PostgreSQL | 通过 FreeSql 支持多数据库 | | ORM | FreeSql | 高性能 .NET ORM,支持多数据库、CodeFirst、丰富的查询功能 | | 认证 | JWT Bearer Token | 无状态认证,支持多设备 | | 后台管理 | Vue 3 + Element Plus | 与前端技术栈统一 | | API 文档 | Swagger / OpenAPI | 自动生成接口文档 | ### FreeSql 核心优势 - 支持多种数据库(SQL Server、PostgreSQL、MySQL、Oracle 等) - CodeFirst 自动同步实体结构到数据库 - 强大的表达式解析引擎,支持复杂查询 - 内置分页、软删除、乐观锁等功能 - Repository + UnitOfWork 模式支持 - 性能优秀,支持批量操作 ## 文档结构设计 新文档 `v2.0-开发文档.md` 将包含以下章节: ### 1. 项目概述 - v2.0 产品定位和核心变化 - 从 MVP 到生产级的演进路径 - 多用户、多设备、云同步的业务价值 ### 2. 系统架构 **完整架构图**: ``` 用户层 ├── Bookmark SPA (Vue 3) ├── Browser Extension (Manifest V3) └── Admin Panel (Vue 3) ↓ API 网关层 ├── ASP.NET Core 8 Web API ├── JWT 认证中间件 ├── 设备识别中间件 └── 可见性过滤中间件 ↓ 业务逻辑层 ├── 用户服务 (UserService) ├── 设备服务 (DeviceService) ├── 书签服务 (BookmarkService) └── 标签服务 (TagService) ↓ 数据访问层 ├── FreeSql IFreeSql 实例 ├── Repository 模式 └── UnitOfWork 工作单元 ↓ 数据库层 (SQL Server / PostgreSQL) ``` ### 3. 数据模型设计 #### 3.1 核心实体 **Users (用户表)** ```csharp using FreeSql.DataAnnotations; [Table(Name = "users")] public class User { [Column(IsPrimary = true)] public Guid Id { get; set; } [Column(IsNullable = false, StringLength = 200)] [Index("idx_user_email", IsUnique = true)] public string Email { get; set; } [Column(IsNullable = false, StringLength = 100)] public string UserName { get; set; } [Column(IsNullable = false, StringLength = 500)] public string PasswordHash { get; set; } [Column(StringLength = 500)] public string? Avatar { get; set; } [Column(ServerTime = DateTimeKind.Utc)] public DateTime CreatedAt { get; set; } [Column(IsNullable = true)] public DateTime? LastLoginAt { get; set; } [Column(MapType = typeof(int))] public UserStatus Status { get; set; } // 导航属性 [Navigate(nameof(Device.UserId))] public List Devices { get; set; } [Navigate(nameof(Bookmark.UserId))] public List Bookmarks { get; set; } } public enum UserStatus { Normal = 0, Disabled = 1 } ``` **Devices (设备表)** ```csharp [Table(Name = "devices")] public class Device { [Column(IsPrimary = true)] public Guid Id { get; set; } [Column(IsNullable = false)] public Guid UserId { get; set; } [Column(IsNullable = false, StringLength = 200)] public string DeviceName { get; set; } [Column(IsNullable = false, StringLength = 200)] public string DeviceType { get; set; } [Column(IsNullable = false)] [Index("idx_device_user_admin")] public bool IsAdmin { get; set; } [Column(ServerTime = DateTimeKind.Utc)] public DateTime CreatedAt { get; set; } [Column(ServerTime = DateTimeKind.Utc, IsOnUpdateValue = true)] public DateTime LastActiveAt { get; set; } [Column(MapType = typeof(int))] public DeviceStatus Status { get; set; } // 导航属性 [Navigate(nameof(UserId))] public User User { get; set; } } public enum DeviceStatus { Normal = 0, Disabled = 1 } ``` **Bookmarks (书签表)** ```csharp [Table(Name = "bookmarks")] [Index("idx_bookmark_user_order", nameof(UserId), nameof(Order))] public class Bookmark { [Column(IsPrimary = true)] public Guid Id { get; set; } [Column(IsNullable = false)] public Guid UserId { get; set; } [Column(IsNullable = false, StringLength = 500)] public string Title { get; set; } [Column(IsNullable = false, StringLength = 2000)] public string Url { get; set; } [Column(StringLength = 2000)] public string? Description { get; set; } [Column(StringLength = -1)] // TEXT/NTEXT public string? Icon { get; set; } [Column(MapType = typeof(string), StringLength = -1)] // JSON 存储 public string[] Tags { get; set; } [Column(IsNullable = false)] public int VisitCount { get; set; } public DateTime? LastVisitTime { get; set; } [Column(IsNullable = false)] public long Order { get; set; } [Column(MapType = typeof(int))] public VisibilityType Visibility { get; set; } [Column(MapType = typeof(string), StringLength = -1)] // JSON 存储 public Guid[]? AllowedDevices { get; set; } [Column(ServerTime = DateTimeKind.Utc)] public DateTime CreatedAt { get; set; } [Column(ServerTime = DateTimeKind.Utc, IsOnUpdateValue = true)] public DateTime UpdatedAt { get; set; } // 导航属性 [Navigate(nameof(UserId))] public User User { get; set; } } public enum VisibilityType { Public = 0, Private = 1, Specified = 2 } ``` #### 3.2 数据库索引策略 - Users: Email 唯一索引 - Devices: UserId + IsAdmin 复合索引(用于快速查找管理员设备) - Bookmarks: UserId + Order 复合索引(列表查询优化) ### 4. FreeSql 配置与使用 #### 4.1 IFreeSql 实例配置 ```csharp // Program.cs using FreeSql; var builder = WebApplication.CreateBuilder(args); // 配置 FreeSql var freeSqlBuilder = new FreeSqlBuilder() .UseConnectionString(GetDataType(), builder.Configuration.GetConnectionString("DefaultConnection")) .UseAutoSyncStructure(builder.Environment.IsDevelopment()) // 开发环境自动同步结构 .UseMonitorCommand(cmd => Console.WriteLine(cmd.CommandText)) // 监控 SQL .Build(); // 注册为单例 builder.Services.AddSingleton(freeSqlBuilder); // 辅助方法:根据配置获取数据库类型 DataType GetDataType() { var provider = builder.Configuration["DatabaseProvider"]; return provider?.ToLower() switch { "postgresql" => DataType.PostgreSQL, "sqlserver" => DataType.SqlServer, _ => DataType.SqlServer }; } // appsettings.json { "ConnectionStrings": { "DefaultConnection": "Server=.;Database=BookmarkDb;..." }, "DatabaseProvider": "SqlServer" // 或 "PostgreSQL" } ``` #### 4.2 Repository 模式 ```csharp // IRepository.cs public interface IRepository where TEntity : class { ISelect Select { get; } Task GetAsync(object id); Task> GetListAsync(); Task InsertAsync(TEntity entity); Task UpdateAsync(TEntity entity); Task DeleteAsync(object id); } // 实现 public class Repository : IRepository where TEntity : class { private readonly IFreeSql _freeSql; public Repository(IFreeSql freeSql) { _freeSql = freeSql; } public ISelect Select => _freeSql.Select(); public Task GetAsync(object id) => _freeSql.Select().WhereDynamic(id).FirstAsync(); public Task> GetListAsync() => _freeSql.Select().ToListAsync(); public Task InsertAsync(TEntity entity) => _freeSql.Insert(entity).ExecuteInsertedAsync(); public Task UpdateAsync(TEntity entity) => _freeSql.Update().SetSource(entity).ExecuteAffrowsAsync(); public Task DeleteAsync(object id) => _freeSql.Delete().WhereDynamic(id).ExecuteAffrowsAsync(); } ``` #### 4.3 UnitOfWork 工作单元 ```csharp // IUnitOfWork.cs public interface IUnitOfWork : IDisposable { void BeginTransaction(); void Commit(); void Rollback(); IRepository GetRepository() where TEntity : class; } // 实现 public class UnitOfWork : IUnitOfWork { private readonly IFreeSql _freeSql; private DbTransaction? _transaction; public UnitOfWork(IFreeSql freeSql) { _freeSql = freeSql; } public void BeginTransaction() { _transaction = _freeSql.Ado.BeginTransaction(); } public void Commit() { _transaction?.Commit(); _transaction?.Dispose(); _transaction = null; } public void Rollback() { _transaction?.Rollback(); _transaction?.Dispose(); _transaction = null; } public IRepository GetRepository() where TEntity : class { return new Repository(_freeSql); } public void Dispose() { _transaction?.Dispose(); } } ``` ### 5. 后端 API 设计 #### 5.1 RESTful API 规范 **认证接口 (`/api/auth`)** - `POST /register` - 用户注册 - `POST /login` - 用户登录(返回 JWT + 自动注册设备) - `POST /logout` - 退出登录 - `POST /refresh` - 刷新 Token - `POST /password/reset` - 重置密码(P1) **用户接口 (`/api/user`)** - `GET /profile` - 获取用户信息 - `PUT /profile` - 更新用户信息 **设备接口 (`/api/devices`)** - `GET /` - 获取设备列表 - `PUT /{id}` - 更新设备信息(重命名) - `DELETE /{id}` - 移除设备 - `PUT /{id}/admin` - 设置/取消管理员设备(P1) **书签接口 (`/api/bookmarks`)** - `GET /` - 获取书签列表(根据设备可见性自动过滤) - `POST /` - 新增书签 - `GET /{id}` - 获取书签详情 - `PUT /{id}` - 更新书签 - `DELETE /{id}` - 删除书签 - `PUT /{id}/visibility` - 设置可见性 - `POST /batch` - 批量操作(P1) - `POST /{id}/visit` - 记录访问 **标签接口 (`/api/tags`)** - `GET /` - 获取标签列表及统计 - `PUT /{name}` - 重命名标签(P1) - `DELETE /{name}` - 删除标签(P1) #### 5.2 可见性过滤实现(FreeSql) ```csharp // BookmarkService.cs public async Task> GetUserBookmarksAsync(Guid userId, Guid deviceId, bool isAdminDevice) { var query = _freeSql.Select() .Where(b => b.UserId == userId) .Where(b => b.Visibility == VisibilityType.Public || (b.Visibility == VisibilityType.Private && isAdminDevice) || (b.Visibility == VisibilityType.Specified && _freeSql.Select() .Where(x => x.Id == b.Id) .Where($"AllowedDevices LIKE '%{deviceId}%'") .Any() ) ) .OrderByDescending(b => b.Order); return await query.ToListAsync(); } ``` #### 5.3 示例 API Controller ```csharp [ApiController] [Route("api/[controller]")] [Authorize] public class BookmarksController : ControllerBase { private readonly IFreeSql _freeSql; private readonly ILogger _logger; public BookmarksController(IFreeSql freeSql, ILogger logger) { _freeSql = freeSql; _logger = logger; } [HttpGet] public async Task>> GetBookmarks() { var userId = GetCurrentUserId(); var deviceId = GetCurrentDeviceId(); var isAdmin = await IsAdminDeviceAsync(deviceId); var bookmarks = await _freeSql.Select() .Where(b => b.UserId == userId) .WhereIf(!isAdmin, b => b.Visibility == VisibilityType.Public) .OrderByDescending(b => b.Order) .ToListAsync(); return Ok(bookmarks); } [HttpPost] public async Task> CreateBookmark([FromBody] CreateBookmarkDto dto) { var userId = GetCurrentUserId(); var bookmark = new Bookmark { Id = Guid.NewGuid(), UserId = userId, Title = dto.Title, Url = dto.Url, Description = dto.Description, Tags = dto.Tags ?? Array.Empty(), Visibility = dto.Visibility, AllowedDevices = dto.AllowedDevices, Order = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), CreatedAt = DateTime.UtcNow }; await _freeSql.Insert(bookmark).ExecuteAffrowsAsync(); return CreatedAtAction(nameof(GetBookmark), new { id = bookmark.Id }, bookmark); } // 其他 API 方法... } ``` ### 6. 前端架构更新 #### 6.1 数据层变化 **v1.0**: IndexedDB (Dexie) → **v2.0**: RESTful API + Axios **新增服务层**: - `src/services/api/client.js` - Axios 实例配置(拦截器、Token 注入) - `src/services/api/authApi.js` - 认证接口封装 - `src/services/api/userApi.js` - 用户接口 - `src/services/api/deviceApi.js` - 设备接口 - `src/services/api/bookmarkApi.js` - 书签接口 - `src/services/api/tagApi.js` - 标签接口 - `src/services/auth/tokenService.js` - JWT Token 管理(localStorage) - `src/services/auth/deviceService.js` - 设备指纹识别 #### 6.2 Pinia Store 更新 **新增**: - `stores/auth.js` - 用户认证状态(登录、登出、Token 管理) - `stores/device.js` - 设备信息(当前设备、是否管理员) **更新**: - `stores/links.js` - 从 Dexie 调用改为 API 调用 - `stores/settings.js` - 部分设置迁移到服务器端 #### 6.3 新增功能组件 **用户认证**: - `components/auth/LoginDialog.vue` - 登录对话框 - `components/auth/RegisterDialog.vue` - 注册对话框 - `components/auth/PasswordResetDialog.vue` - 密码重置(P1) **设备管理**: - `components/devices/DeviceList.vue` - 设备列表 - `components/devices/DeviceCard.vue` - 设备卡片 - `components/devices/DeviceManageDialog.vue` - 设备管理对话框 **可见性控制**: - `components/links/VisibilitySelector.vue` - 可见性选择器 - `components/links/VisibilityBadge.vue` - 可见性徽章 ### 7. 浏览器扩展增强 #### 7.1 新增核心功能 **自动同步** (`background/sync.js`): - 监听 `chrome.bookmarks.onCreated` 事件 - 提取书签信息(标题、URL、图标、文件夹路径) - 文件夹路径转标签(如:「工作/项目A」→ ["工作", "项目A"]) - 调用云端 API 保存书签 - 显示同步成功/失败通知 **新标签页替换**: ```json // manifest.json { "chrome_url_overrides": { "newtab": "app/index.html" } } ``` **全局快捷键搜索** (`content/search-overlay.js`): - Content Script 注入所有页面 - 监听快捷键(Alt+K 或自定义) - 浮层搜索框(遮罩层 + 搜索输入 + 结果列表) - 调用 API 实时搜索 - 键盘导航(上下键、回车打开) **一键收藏** (`popup/quick-save.js`): - Popup 中的快速收藏表单 - 自动填充当前页标题和 URL - 可编辑标签、可见性 - 可选择是否同时保存到浏览器书签 - 收藏成功提示 #### 7.2 认证集成 - 使用 `chrome.storage.local` 存储 JWT Token 和设备 ID - API 请求时自动携带 Token - Token 过期时自动刷新或提示登录 - 未登录时提示用户登录 ### 8. 后台管理系统 #### 8.1 技术栈与项目结构 **技术栈**: Vue 3 + Vite + Vue Router + Pinia + Element Plus + Axios ``` admin-panel/ ├── src/ │ ├── views/ │ │ ├── Dashboard.vue # 仪表盘 │ │ ├── users/ │ │ │ ├── UserList.vue # 用户列表 │ │ │ └── UserDetail.vue # 用户详情 │ │ ├── devices/ │ │ │ └── DeviceList.vue # 设备管理 │ │ └── bookmarks/ │ │ └── BookmarkList.vue # 书签管理 │ ├── components/ │ ├── stores/ │ │ └── admin.js # 管理员状态 │ ├── services/ │ │ └── adminApi.js # 后台 API │ └── router/ │ └── index.js ├── package.json └── vite.config.js ``` #### 8.2 核心功能页面 **仪表盘**: - 关键指标卡片(用户总数、活跃用户、书签总数、设备总数) - 趋势图表(P2 优先级,使用 ECharts) **用户管理**: - 用户列表(分页、搜索、筛选) - 禁用/启用用户操作 - 查看用户详情(基本信息、设备列表、书签统计) - 重置密码(P1) **设备管理**: - 查看用户的所有设备 - 强制设备下线(P1) - 禁用设备(P1) **书签管理**: - 查看用户的书签列表(分页、搜索) - 按可见性筛选 - 删除违规书签(P1) ### 9. 数据库迁移与种子数据 #### 9.1 CodeFirst 自动同步 ```csharp // Program.cs var freeSql = new FreeSqlBuilder() .UseConnectionString(dataType, connectionString) .UseAutoSyncStructure(true) // 自动同步实体结构到数据库 .Build(); // 首次运行时自动创建表和索引 ``` #### 9.2 种子数据 ```csharp // 创建超级管理员账号 public static async Task SeedDataAsync(IFreeSql freeSql) { var adminExists = await freeSql.Select() .Where(u => u.Email == "admin@bookmarks.local") .AnyAsync(); if (!adminExists) { var admin = new User { Id = Guid.NewGuid(), Email = "admin@bookmarks.local", UserName = "Administrator", PasswordHash = BCrypt.Net.BCrypt.HashPassword("Admin@123"), Status = UserStatus.Normal, CreatedAt = DateTime.UtcNow }; await freeSql.Insert(admin).ExecuteAffrowsAsync(); } } ``` ### 10. 开发指南 #### 10.1 环境搭建 **后端环境**: - .NET 8 SDK - SQL Server 2019+ 或 PostgreSQL 14+ - Visual Studio 2022 / Rider / VS Code + C# 扩展 - Postman / Swagger UI **前端环境**: - Node.js 20+ - npm 8+ - Chrome 90+ #### 10.2 本地开发流程 ```bash # 1. 克隆项目 git clone # 2. 后端启动 cd backend-api dotnet restore dotnet run # 首次运行会自动创建数据库表 # 3. 前端启动 cd bookmark-spa npm install npm run dev # 4. 后台管理启动 cd admin-panel npm install npm run dev # 5. 浏览器扩展 cd bookmark-spa npm run build cp -r dist/* ../browser-extension/app/ # 在 Chrome 中加载扩展 ``` #### 10.3 FreeSql 常用操作示例 ```csharp // 查询 var users = await _freeSql.Select() .Where(u => u.Status == UserStatus.Normal) .Page(1, 20) .ToListAsync(); // 插入 var user = new User { /* ... */ }; await _freeSql.Insert(user).ExecuteAffrowsAsync(); // 更新 await _freeSql.Update() .Set(u => u.LastLoginAt, DateTime.UtcNow) .Where(u => u.Id == userId) .ExecuteAffrowsAsync(); // 删除 await _freeSql.Delete() .Where(u => u.Id == userId) .ExecuteAffrowsAsync(); // 事务 using var uow = _freeSql.CreateUnitOfWork(); try { var repo = uow.GetRepository(); await repo.InsertAsync(bookmark); uow.Commit(); } catch { uow.Rollback(); throw; } ``` ### 11. 部署指南 #### 11.1 后端部署 **Docker 容器化**: ```dockerfile FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /app COPY publish/ . EXPOSE 80 ENTRYPOINT ["dotnet", "BookmarkApi.dll"] ``` **环境变量**: - `ConnectionStrings__DefaultConnection` - `DatabaseProvider` (SqlServer / PostgreSQL) - `JwtSettings__SecretKey` - `JwtSettings__Issuer` - `JwtSettings__Audience` - `JwtSettings__ExpiryMinutes` #### 11.2 前端部署 - Bookmark SPA: Nginx / Vercel / Netlify - Admin Panel: Nginx(需配置访问控制) - Browser Extension: Chrome Web Store #### 11.3 数据库部署 - SQL Server: Azure SQL / 自托管 - PostgreSQL: Azure PostgreSQL / AWS RDS / 自托管 - 定期备份策略 ### 12. 安全实践 #### 12.1 认证与授权 - 密码使用 BCrypt 或 Argon2 哈希 - JWT Token 有效期设置(1 小时) - Refresh Token 机制(7 天有效期) - 设备绑定(Token 包含设备 ID) #### 12.2 API 安全 - HTTPS 强制传输 - CORS 跨域配置 - 速率限制(ASP.NET Core Rate Limiting) - FreeSql 自动参数化防止 SQL 注入 - 输入验证和输出编码防止 XSS ### 13. 测试策略 #### 13.1 后端测试 - 单元测试: xUnit + Moq - FreeSql 内存数据库测试 - API 集成测试: WebApplicationFactory ```csharp [Fact] public async Task GetBookmarks_ReturnsUserBookmarks() { // Arrange var freeSql = new FreeSqlBuilder() .UseConnectionString(DataType.Sqlite, ":memory:") .Build(); // Act & Assert } ``` #### 13.2 前端测试 - 单元测试: Vitest - E2E 测试: Playwright(包含登录流程) ## v2.0 实际实现情况 ### ✅ P0 核心功能(已全部完成) **后端 API** - ✅ ASP.NET Core 8 项目搭建 - ✅ FreeSql 配置与实体定义(User、Device、Bookmark、RefreshToken) - ✅ JWT 认证中间件(包含 RefreshToken 机制) - ✅ 用户注册/登录 API(含设备自动注册) - ✅ 书签 CRUD API(含搜索、批量删除、可见性控制) - ✅ 设备管理 API(重命名、删除、设置管理员) - ✅ 标签管理 API - ✅ 后台管理 API(用户管理、设备管理、统计数据) **前端应用** - ✅ Vue 3 + TypeScript + Pinia - ✅ 登录/注册界面 - ✅ JWT Token 管理(自动刷新) - ✅ 书签列表迁移到 API 调用 - ✅ 设备管理界面 - ✅ 可见性控制界面 - ✅ 全局搜索组件 **浏览器扩展** - ✅ 用户认证集成 - ✅ Token 存储与管理 - ✅ 书签自动同步(监听 chrome.bookmarks.onCreated) - ✅ 文件夹路径转标签 - ✅ URL 重复检测 - ✅ 同步状态通知 **后台管理系统** - ✅ Vue 3 + Element Plus - ✅ 仪表盘统计(用户数、活跃度、书签数、设备数) - ✅ 用户管理(列表、详情、禁用/启用、重置密码) - ✅ 设备管理(查看、强制下线、禁用) - ✅ 书签管理(查看用户书签、删除) - ✅ 权限控制(Admin/SuperAdmin) ### 📋 P2-P3 增强功能(v3.0 规划) **扩展增强** - 📋 新标签页替换为书签应用 - 📋 全局快捷键搜索(任意页面触发) - 📋 右键菜单添加书签 - 📋 Popup 快速收藏 **高级功能** - 📋 统计报表和趋势图 - 📋 标签管理增强(合并、排序) - 📋 邮箱验证 - 📋 数据导出功能 --- ## 已实现的 API 接口清单 ### 认证接口 (/api/auth) | 方法 | 路径 | 描述 | 状态 | |------|------|------|------| | POST | /register | 用户注册 | ✅ | | POST | /login | 用户登录(含设备注册) | ✅ | | POST | /logout | 退出登录 | ✅ | | POST | /refresh | 刷新 Access Token | ✅ | ### 用户接口 (/api/user) | 方法 | 路径 | 描述 | 状态 | |------|------|------|------| | GET | /profile | 获取用户信息 | ✅ | | PUT | /profile | 更新用户信息 | ✅ | | PUT | /password | 修改密码 | ✅ | ### 设备接口 (/api/devices) | 方法 | 路径 | 描述 | 状态 | |------|------|------|------| | GET | / | 获取设备列表 | ✅ | | GET | /{id} | 获取设备详情 | ✅ | | PUT | /{id} | 更新设备名称 | ✅ | | DELETE | /{id} | 删除设备 | ✅ | | PUT | /{id}/admin | 设置/取消管理员设备 | ✅ | ### 书签接口 (/api/bookmarks) | 方法 | 路径 | 描述 | 状态 | |------|------|------|------| | GET | / | 获取书签列表(自动过滤可见性) | ✅ | | GET | /search | 搜索书签 | ✅ | | GET | /{id} | 获取书签详情 | ✅ | | POST | / | 新增书签 | ✅ | | PUT | /{id} | 更新书签 | ✅ | | DELETE | /{id} | 删除书签 | ✅ | | POST | /batch/delete | 批量删除 | ✅ | | PUT | /{id}/visibility | 设置可见性 | ✅ | | POST | /{id}/visit | 记录访问 | ✅ | | PUT | /{id}/order | 更新排序 | ✅ | | GET | /check-url | 检查 URL 是否存在 | ✅ | | POST | /import | 导入书签 | ✅ | | GET | /export | 导出书签 | ✅ | ### 标签接口 (/api/tags) | 方法 | 路径 | 描述 | 状态 | |------|------|------|------| | GET | / | 获取标签列表及统计 | ✅ | | PUT | /{name} | 重命名标签 | ✅ | | DELETE | /{name} | 删除标签 | ✅ | ### 后台管理接口 (/api/admin) | 方法 | 路径 | 描述 | 状态 | |------|------|------|------| | GET | /statistics | 获取系统统计数据 | ✅ | | GET | /users | 获取用户列表(分页、搜索、筛选) | ✅ | | GET | /users/{id} | 获取用户详情 | ✅ | | PUT | /users/{id}/status | 禁用/启用用户 | ✅ | | POST | /users/{id}/reset-password | 重置用户密码 | ✅ | | GET | /users/{id}/bookmarks | 获取用户书签列表 | ✅ | | DELETE | /users/{userId}/bookmarks/{bookmarkId} | 删除用户书签 | ✅ | | POST | /devices/{id}/force-logout | 强制设备下线 | ✅ | | PUT | /devices/{id}/status | 禁用/启用设备 | ✅ | --- ## 部署说明 ### 环境要求 **后端环境** - .NET 8 SDK - SQL Server 2019+ 或 PostgreSQL 14+ - 依赖包: - FreeSql (ORM) - BCrypt.Net-Next (密码加密) - System.IdentityModel.Tokens.Jwt (JWT) - Swashbuckle.AspNetCore (API 文档) **前端环境** - Node.js 20+ - Vue 3 + TypeScript - Pinia - Element Plus **浏览器扩展** - Chrome 90+ (Manifest V3) ### 配置说明 **appsettings.json** ```json { "ConnectionStrings": { "DefaultConnection": "Server=.;Database=BookmarkDb;..." }, "DatabaseProvider": "SqlServer", "JwtSettings": { "SecretKey": "your-256-bit-secret", "Issuer": "BookmarkApi", "Audience": "BookmarkClient", "ExpiryMinutes": 60, "RefreshTokenDays": 7 } } ``` --- ## 技术亮点 1. **JWT + RefreshToken 双令牌机制** - Access Token 有效期 1 小时 - Refresh Token 有效期 7 天 - 自动刷新,无感登录体验 2. **设备指纹识别** - Canvas 指纹、屏幕分辨率、时区等多因子识别 - 自动注册设备,支持设备管理 - 管理员设备机制,灵活权限控制 3. **书签可见性控制** - Public:所有设备可见 - Private:仅管理员设备可见 - Specified:仅指定设备可见 - API 层自动过滤,确保数据安全 4. **自动同步机制** - 监听浏览器书签事件 - 文件夹路径自动转标签 - URL 重复检测 - 同步状态实时反馈 5. **后台管理系统** - 完整的用户管理功能 - 系统统计数据实时更新 - 设备管理(强制下线、禁用) - 基于角色的权限控制 6. **TypeScript 支持** - 前端全面使用 TypeScript - 类型安全,减少运行时错误 - 更好的开发体验和代码维护性 --- ## 后续优化建议 1. **性能优化** - 实现 Redis 缓存,提高 API 响应速度 - 添加 CDN 支持前端资源 - 数据库查询优化和索引优化 2. **功能增强** - 实现新标签页替换 - 添加全局快捷键搜索 - 支持邮箱验证 - 实现数据备份和恢复 3. **监控与日志** - 添加结构化日志 - 实现监控告警 - 错误追踪和性能分析 4. **安全加固** - 实现 2FA 双因素认证 - 添加操作日志审计 - API 速率限制增强 - XSS 和 CSRF 防护加强 --- > **v2.0 开发完成时间**: 2025-12-15 > > **代码位置**: `/src/` 目录 > - 后端: `/src/backend/` > - 前端: `/src/frontend/` > - 扩展: `/src/extension/` > - 后台管理: `/src/admin/`