Skip to content

About

桌面内容管理系统,面向个人用户,用于统一管理本地散落在各处的文件(视频、音频、文档、图片等)。

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Xiaokeer CMS

Xiaokeer CMS 是一个基于 .NET 8 的 Windows 桌面内容管理系统,面向个人用户,用于统一管理本地散落在各处的文件(视频、音频、文档、图片等)。

解决的问题

本地电脑中存在大量分散在不同文件夹中的文件,缺乏统一的管理方式,查找和利用效率低。Xiaokeer CMS 通过将文件托管到统一存储目录并建立元数据索引,提供高效的检索、查看和对外访问能力。

技术栈

项目 技术
语言 C#
框架 .NET 8 (LTS)
GUI WPF (MVVM)
数据库 SQLite (Entity Framework Core)
HTTP 服务 ASP.NET Core Minimal APIs (内嵌 Kestrel)
MVVM 工具 CommunityToolkit.Mvvm

现有功能

1. 内容托管(拖拽导入)

  • 从 Windows 文件资源管理器拖拽文件或文件夹到应用窗口
  • 自动识别文件类型(视频、音频、图片、文档、其他)
  • 将文件剪切(移动)到统一存储目录,原路径不再保留该文件
  • 为每个文件生成 UUID,记录元数据(原始文件名、类型、大小、导入时间等)存入 SQLite
  • Markdown 文件特殊处理:导入 .md 文件时自动解析其中的图片引用(base64 内嵌图片、HTTP/HTTPS 网络链接、本地相对路径),将图片提取并存储到 {contentId}_img/ 文件夹,同时将 Markdown 中的图片引用重写为相对路径,确保图片引用不会因文件移动而失效
  • 文件夹托管二次确认:拖拽文件夹时,先递归统计可托管文件数量,弹窗提示用户确认后才开始托管,取消则放弃操作
  • 托管进度窗口:批量导入时显示实时进度窗口,包含当前正在托管的文件名、成功/失败数量、预期总数、已耗时、进度条。导入完成前窗口不可关闭,完成后点击确认按钮关闭

2. 内容查看

  • 列表展示所有已托管的内容,显示文件名、文档栏、类型、大小、导入时间、扩展名、状态、MDX状态
  • 支持按文件名搜索、按文件类型筛选、按文件扩展名筛选、按文档栏筛选、按状态筛选、按MDX状态筛选、按日期范围过滤
  • 文件扩展名筛选:下拉列表提供所有已定义的扩展名选项,热门扩展名(.md、.txt、.pdf 等)排在前面
  • 文档栏筛选:下拉列表动态从数据库获取去重后的文档栏列表("ALL" + 去重列表),默认选择 "ALL" 表示不筛选,选择其他项则筛选对应的文档栏内容
  • 状态筛选:下拉列表提供选项("ALL"、"完整"、"不完整"),默认选择 "ALL" 表示不筛选,选择"完整"只显示文件存在的项目,选择"不完整"只显示文件丢失的项目
  • MDX状态筛选:下拉列表提供选项("ALL"、"不支持MDX"、"MDX不存在"、"MDX不同步"、"MDX同步"),默认选择 "ALL" 表示不筛选,选择其他项则筛选对应的MDX转储状态
  • 内容状态检验:每次查询时实时检验托管文件是否存在,显示绿色"完整"或红色"不完整"状态标签
  • MDX状态判断:对于 Markdown 文件,根据设置的"md转储mdx文档路径配置"判断 MDX 文件是否存在及同步状态
    • 不支持MDX(天蓝色):非 Markdown 文件
    • MDX不存在(橙色):MDX 文件不存在
    • MDX不同步(红色):MDX 文件存在但与源文件不同步(通过文件大小判断)
    • MDX同步(绿色):MDX 文件存在且与源文件同步(通过文件大小判断)
  • 日期格式校验:输入非法日期格式或起始日期大于结束日期时弹窗提示
  • 点击列头可排序
  • 双击打开文件:双击内容列表中的某一行可直接打开对应文件(需在 Settings tab 中启用"允许双击打开文件"选项)
  • 批量操作支持:所有右键菜单操作均支持多选批量执行。选中多个内容项后右键点击,操作将应用于所有选中项。批量操作遇到失败时立即停止,显示已成功处理的数量
  • 右键菜单:
    • Open File — 使用系统默认程序打开文件(文件不存在时弹窗提示)
    • Open MDX File — 使用系统默认程序打开转储的 MDX 文件(仅限 .md 文件,非MD文件或MDX文件不存在时弹窗提示)
    • Open File Location — 在 Windows 资源管理器中定位文件(文件不存在时弹窗提示)
    • Rename — 重命名内容项,弹出对话框输入新名称(支持 Enter 键确认和 X 键取消)
    • ReDocsSection — 修改文档栏,弹出对话框输入新的文档栏名称(只允许中文、英文、数字)
    • SyncMDX — 将 MD 文件转储为 MDX 格式到配置的目标路径。转储时自动生成 YAML Frontmatter(title = 文件名,section = 文档栏),并验证内容是否符合 xiaokeer-discover 项目的 Velite 配置要求。图片处理: 如果 MD 文件有关联的图片文件夹({uuid}_img),转储时会:(1) 将图片文件夹复制到 Settings 中配置的"MDX 图片路径";(2) 转换图片引用路径,将 MD 中的相对路径 ./ 开头替换为 /(MDX 使用绝对路径)
    • Restore — 还原内容对象到指定路径。将托管文件从 CMS 存储目录移动到用户指定的还原路径(默认为桌面),同时删除数据库记录。对于 MD 文件,会同时处理关联的图片文件夹({uuid}_img),将其重命名为 {文件名}_img 并与 MD 文件一起放入同名文件夹中
    • Delete — 删除内容记录及存储的文件(文件不存在时拒绝删除并提示恢复,文件被占用时提示关闭占用程序)

3. 工具(Tools Tab)

  • 创建 MD 文件 — 在 Tools tab 中点击"创建 MD"按钮,弹出对话框输入文件名和 Markdown 内容,确认后在 %USERPROFILE%\.xiaokeer_cms\collocation_create_md\ 目录下创建文件,创建成功后可打开文件所在目录
  • 根据ImgDir创建MD — 点击"根据ImgDir"按钮,弹出文件夹选择对话框,选择包含图片的文件夹后,系统会在 %USERPROFILE%\.xiaokeer_cms\tool_CreateMdByImgsDir\ 目录下创建新文件夹(格式:原文件夹名称_uuid),该文件夹内包含:
    • MD 文件(名称为原文件夹名称.md):每行一个图片名称 + 一个图片引用,格式为 图片名称\n![图片名称](./图片文件夹/图片名称)
    • 图片文件夹(使用随机UUID命名):复制原文件夹中的所有图片,文件名自动清理(只保留中文字符和英文字母,去除数字、符号、空格等)
    • 原文件夹重命名:处理成功后,原文件夹会自动重命名为 原文件夹名称_toMDok,标识已处理
    • 路径记忆:第二次使用时会自动定位到上次选择的父目录,方便继续处理同级其他文件夹
    • 支持图片格式:.jpg、.jpeg、.png、.gif、.bmp、.webp
  • 执行Python脚本1 — 点击"执行脚本1"按钮,弹出窗口执行 C:\p1.py 脚本,显示脚本内容和执行结果
  • 执行Python脚本2 — 点击"执行脚本2"按钮,弹出窗口执行 C:\p2.py 脚本,显示脚本内容和执行结果
  • 执行Python脚本3 — 点击"执行脚本3"按钮,弹出窗口执行 C:\p3.py 脚本,显示脚本内容和执行结果
  • 按扩展名分类文件 — 点击"按扩展名分类文件"按钮,弹出文件夹选择对话框,选择文件夹后程序会自动扫描该文件夹的一级文件(不包括子文件夹),根据文件扩展名创建对应的子文件夹并将文件移动到对应位置:
    • 文件夹以扩展名命名(如 pdf、docx、png)
    • 无扩展名的文件会被忽略
    • 如果目标位置已存在同名文件,会自动重命名为 文件名_1 格式
    • 处理完成后显示详细统计信息(总数、忽略数、成功数、失败数、按扩展名分布)

4. 设置(Settings Tab)

  • 允许双击打开文件 — CheckBox 选项,默认关闭。开启后双击内容列表行可直接打开文件,关闭后双击无反应。即时生效,无需 Apply 按钮
  • 删除文件时,无需二次确认 — CheckBox 选项,默认关闭。开启后删除内容时,不会弹窗二次确认,直接删除了, 关闭后删除内容时会弹窗二次确认, 询问用户是否确认删除, 即时生效, 无需 Apply 按钮
  • 仅托管md文件 — CheckBox 选项,默认关闭。勾选后,拖拽文件夹时仅处理.md文件,其他类型文件将被忽略。如果文件夹中没有任何.md文件,会显示错误提示并中断导入。适用于只托管 Markdown 文件而忽略其配套图片文件夹的场景
  • 窗口始终置顶 — CheckBox 选项,默认关闭。勾选后,窗口将始终显示在最前面,不被其他窗口遮挡。适用于需要窗口保持可见性的场景。即时生效,无需 Apply 按钮(非持久化设置,重启应用后恢复为默认值)

5. MDX 设置(Settings Tab)

  • md轉儲mdx文檔路徑配置 — 文本框 + 浏览/打开按钮,默认值:C:\project\xiaokeer-discover\content\docs
  • md圖片轉儲mdx文檔圖片路徑配置 — 文本框 + 浏览/打开按钮,默认值:C:\project\xiaokeer-discover\public\img

6. Python 设置(Settings Tab)

  • python解釋器路徑配置 — 文本框 + 浏览/打开按钮,默认值:C:\Users\Administrator\AppData\Local\Programs\Python\Python314\python.exe

7. 内容提供(HTTP API)

应用启动时内嵌 HTTP 服务器,监听 http://localhost:15080,提供以下接口:

方法 路径 说明
GET /api/contents 获取内容列表,支持查询参数 search、category、from、to、extension
GET /api/contents/{id} 根据 ID 获取内容元数据
GET /api/contents/{id}/download 下载文件(Markdown 文件含图片时返回 ZIP 包)
GET /api/contents/{id}/html 将 Markdown 文件转换为 HTML 页面返回(含目录导航、代码高亮、图片以 base64 内嵌展示)
GET /api/contents/{id}/images/{filename} 获取 Markdown 文件关联的单张图片

项目结构

XiaokeerCms/
├── Models/                     # 数据模型
│   ├── ContentItem.cs          # 内容实体(UUID、文件名、类型、路径、大小、时间)
│   ├── FileCategory.cs         # 文件分类枚举(Video, Audio, Image, Document, Other)
│   └── MdxExportStatus.cs     # MDX 转储状态枚举(NotSupported, MdxNotExists, MdxOutOfSync, MdxSynced)
├── Data/
│   └── AppDbContext.cs          # EF Core 数据库上下文
├── Services/                   # 业务逻辑层
│   ├── FileCategoryDetector.cs  # 根据扩展名识别文件分类
│   ├── IFileStorageService.cs
│   ├── FileStorageService.cs    # 文件移动、路径解析、删除
│   ├── IContentService.cs
│   ├── ContentService.cs       # 内容导入、查询、删除、重命名
│   ├── MarkdownImageProcessor.cs # Markdown 图片解析、提取、路径重写
│   └── MarkdownHtmlConverter.cs # Markdown 转 HTML 转换(Markdig + TOC + 代码高亮)
├── ViewModels/                 # MVVM ViewModel 层
│   ├── MainViewModel.cs         # 主界面逻辑(列表、筛选、命令)
│   └── ContentItemViewModel.cs  # 单条内容的显示包装
├── Views/                      # WPF 视图层
│   ├── MainWindow.xaml          # 主窗口布局
│   ├── MainWindow.xaml.cs       # 拖拽事件、列头排序
│   ├── CreateMarkdownDialog.xaml    # 创建 Markdown 文件对话框
│   ├── CreateMarkdownDialog.xaml.cs # 对话框交互逻辑
│   ├── ImportProgressDialog.xaml    # 托管进度对话框
│   ├── ImportProgressDialog.xaml.cs # 进度窗口逻辑(计时、进度更新、关闭拦截)
│   ├── RenameContentDialog.xaml     # 重命名内容对话框
│   ├── RenameContentDialog.xaml.cs  # 重命名对话框逻辑
│   ├── ReDocsSectionDialog.xaml    # 修改文档栏对话框
│   ├── ReDocsSectionDialog.xaml.cs # 修改文档栏对话框逻辑
│   ├── PythonScriptDialog.xaml      # Python 脚本执行对话框
│   └── PythonScriptDialog.xaml.cs   # Python 脚本执行对话框逻辑
├── Api/
│   └── ContentEndpoints.cs      # HTTP API 路由定义
├── DatabaseScripts/
│   └── InitializeDocsSection.sql # DocsSection 字段初始化脚本
├── Hosting/
│   └── AppHostBuilder.cs        # Generic Host 构建(DI、Kestrel、EF Core)
├── Helpers/
│   ├── PathHelper.cs            # 存储路径解析工具
│   └── ProcessHelper.cs         # 调用系统程序打开文件/文件夹
├── App.xaml
└── App.xaml.cs                  # 应用启动/退出生命周期管理

scripts/                         # Node.js 脚本目录
├── package.json                 # Node.js 依赖配置(@mdx-js/mdx 等)
└── validate-mdx.mjs             # MDX 验证脚本,使用与 xiaokeer-discover 相同的编译引擎

数据存储

所有数据存储在用户目录下的 .xiaokeer_cms 文件夹中:

%USERPROFILE%\.xiaokeer_cms\
├── xiaokeer_cms.db              # SQLite 数据库文件
├── collocation_create_md/       # "创建 MD 文件"工具的输出目录
├── tool_CreateMdByImgsDir/     # "根据ImgDir创建MD"工具的输出目录
└── storage/                     # 托管文件存储根目录
    ├── video/                   # 视频文件 ({uuid}.mp4, {uuid}.mkv, ...)
    ├── audio/                   # 音频文件 ({uuid}.mp3, {uuid}.flac, ...)
    ├── image/                   # 图片文件 ({uuid}.jpg, {uuid}.png, ...)
    ├── document/                # 文档文件 ({uuid}.pdf, {uuid}.docx, ...)
    │                            # Markdown 文件的关联图片存储在 {uuid}_img/ 子文件夹中
    └── other/                   # 其他文件 ({uuid}.zip, ...)
  • 文件以 UUID 重命名存储,避免命名冲突
  • 按文件分类放入对应子目录
  • 原始文件名保留在数据库中,用于显示和下载

数据库表结构

ContentItems 表:

字段 类型 说明
Id GUID 主键
OriginalFileName TEXT 原始文件名(不含后缀)
FileExtension TEXT 文件扩展名(如 .pdf)
FileCategory INTEGER 文件分类(0=Video, 1=Audio, 2=Image, 3=Document, 4=Other)
StorageRelativePath TEXT 相对存储路径(如 document/{uuid}.pdf)
FileSize INTEGER 文件大小(字节)
CreatedAt TEXT 导入时间(UTC)
OriginalPath TEXT 文件导入前的原始完整路径
DocsSection TEXT 文档栏(只允许中文、英文、数字,默认为"其他")

MDX 转储状态(临时字段):

  • 不支持MDX(天蓝色):非 Markdown 文件
  • MDX不存在(橙色):MDX 文件不存在
  • MDX不同步(红色):MDX 文件存在但与源文件不同步(当前通过文件大小判断)
  • MDX同步(绿色):MDX 文件存在且与源文件同步(当前通过文件大小判断)

构建与运行

# 还原依赖
dotnet restore

# 安装 Node.js 依赖(MDX 验证需要,首次运行前执行)
cd scripts && npm install && cd ..

# 编译
dotnet build

# 运行
dotnet run --project XiaokeerCms

应用启动后:

  • GUI 窗口自动打开
  • HTTP 服务监听 http://localhost:15080
  • 数据库和存储目录自动创建在 %USERPROFILE%\.xiaokeer_cms\

打包分发

dotnet publish -c Release -p:PublishProfile=FolderPublish

应用会被发布到 Publish/XiaokeerCms/ 目录(约 203MB),包含:

  • 自包含的 .NET 8 运行时(无需预先安装 .NET)
  • XiaokeerCms.exe 可执行文件
  • 完整的目录结构,包括 MDX 验证所需的 scripts 目录

分发方式:

  1. 将 Publish/XiaokeerCms/ 文件夹压缩为 zip 文件
  2. 发送给用户,用户解压后直接运行 XiaokeerCms.exe 即可使用

减小体积: 如果需要减小发布体积(约 50MB,但启动速度会变慢),可以禁用 ReadyToRun:

dotnet publish -c Release -p:PublishProfile=FolderPublish -p:PublishReadyToRun=false

文档维护规范

文档职责划分

文档 职责 维护原则
README.md 项目总览,面向所有读者 反映项目最新最全状态,任何功能变更都需同步更新
AGENTS.md 通用智能体开发指南 只包含构建命令、代码风格、架构概述,不包含具体功能描述
CLAUDE.md Claude智能体专用指南 保持现有风格,只包含构建命令、代码风格、架构概述、数据流描述

README.md 更新规则

  1. 功能新增:在对应章节添加功能描述
  2. 功能修改:直接修改原有描述,不追加补充说明
  3. 功能删除:删除对应描述,不留历史记录
  4. 数据库变更:同步更新数据库表结构说明
  5. API变更:同步更新API接口表格

禁止行为

  • ❌ 在 README.md 中追加"xxxx年xx月xx日已修改"类型的补充说明
  • ❌ 在 AGENTS.md 或 CLAUDE.md 中添加具体功能描述
  • ❌ 在 AGENTS.md 或 CLAUDE.md 中添加代码实现细节
  • ❌ 让 AGENTS.md 和 CLAUDE.md 内容完全相同(需保留各自风格)

About

桌面内容管理系统,面向个人用户,用于统一管理本地散落在各处的文件(视频、音频、文档、图片等)。

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages