work/docs/开发文档.md
2025-12-17 22:30:44 +08:00

1176 lines
29 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.

# v2.0 开发文档
> **版本**: 2.0.0
> **状态**: ✅ 已完成
> **最后更新**: 2025-12-15
> **文档类型**: 技术开发文档
---
## 文档概述
本文档详细记录了书签管理系统 v2.0 的完整技术实现,包括:
- 从 v1.0(本地单用户)到 v2.0(云端多用户)的架构升级
- 后端 APIASP.NET Core + FreeSql完整实现
- 前端应用Vue 3 + TypeScript技术栈
- 浏览器扩展自动同步机制
- 后台管理系统实现细节
---
## 核心任务完成情况
### ✅ 已完成功能
**后端 API100%**
- [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<Device> Devices { get; set; }
[Navigate(nameof(Bookmark.UserId))]
public List<Bookmark> 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<IFreeSql>(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<TEntity> where TEntity : class
{
ISelect<TEntity> Select { get; }
Task<TEntity> GetAsync(object id);
Task<List<TEntity>> GetListAsync();
Task<TEntity> InsertAsync(TEntity entity);
Task<int> UpdateAsync(TEntity entity);
Task<int> DeleteAsync(object id);
}
// 实现
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly IFreeSql _freeSql;
public Repository(IFreeSql freeSql)
{
_freeSql = freeSql;
}
public ISelect<TEntity> Select => _freeSql.Select<TEntity>();
public Task<TEntity> GetAsync(object id)
=> _freeSql.Select<TEntity>().WhereDynamic(id).FirstAsync();
public Task<List<TEntity>> GetListAsync()
=> _freeSql.Select<TEntity>().ToListAsync();
public Task<TEntity> InsertAsync(TEntity entity)
=> _freeSql.Insert(entity).ExecuteInsertedAsync();
public Task<int> UpdateAsync(TEntity entity)
=> _freeSql.Update<TEntity>().SetSource(entity).ExecuteAffrowsAsync();
public Task<int> DeleteAsync(object id)
=> _freeSql.Delete<TEntity>().WhereDynamic(id).ExecuteAffrowsAsync();
}
```
#### 4.3 UnitOfWork 工作单元
```csharp
// IUnitOfWork.cs
public interface IUnitOfWork : IDisposable
{
void BeginTransaction();
void Commit();
void Rollback();
IRepository<TEntity> GetRepository<TEntity>() 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<TEntity> GetRepository<TEntity>() where TEntity : class
{
return new Repository<TEntity>(_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<List<Bookmark>> GetUserBookmarksAsync(Guid userId, Guid deviceId, bool isAdminDevice)
{
var query = _freeSql.Select<Bookmark>()
.Where(b => b.UserId == userId)
.Where(b =>
b.Visibility == VisibilityType.Public ||
(b.Visibility == VisibilityType.Private && isAdminDevice) ||
(b.Visibility == VisibilityType.Specified &&
_freeSql.Select<Bookmark>()
.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<BookmarksController> _logger;
public BookmarksController(IFreeSql freeSql, ILogger<BookmarksController> logger)
{
_freeSql = freeSql;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<List<BookmarkDto>>> GetBookmarks()
{
var userId = GetCurrentUserId();
var deviceId = GetCurrentDeviceId();
var isAdmin = await IsAdminDeviceAsync(deviceId);
var bookmarks = await _freeSql.Select<Bookmark>()
.Where(b => b.UserId == userId)
.WhereIf(!isAdmin, b => b.Visibility == VisibilityType.Public)
.OrderByDescending(b => b.Order)
.ToListAsync();
return Ok(bookmarks);
}
[HttpPost]
public async Task<ActionResult<BookmarkDto>> 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<string>(),
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<User>()
.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 <repository>
# 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<User>()
.Where(u => u.Status == UserStatus.Normal)
.Page(1, 20)
.ToListAsync();
// 插入
var user = new User { /* ... */ };
await _freeSql.Insert(user).ExecuteAffrowsAsync();
// 更新
await _freeSql.Update<User>()
.Set(u => u.LastLoginAt, DateTime.UtcNow)
.Where(u => u.Id == userId)
.ExecuteAffrowsAsync();
// 删除
await _freeSql.Delete<User>()
.Where(u => u.Id == userId)
.ExecuteAffrowsAsync();
// 事务
using var uow = _freeSql.CreateUnitOfWork();
try
{
var repo = uow.GetRepository<Bookmark>();
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/`