# photo_gallery **Repository Path**: hwxus/photo_gallery ## Basic Information - **Project Name**: photo_gallery - **Description**: Nikon 照片库 Web 应用 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-11 - **Last Updated**: 2026-09-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: Python, WorkBuddy, MongoDB, Pillow, Vue ## README # photo_gallery Nikon 照片库 Web 应用 — 专业级本地照片浏览与多维度筛选系统 # 介绍 专为尼康(Nikon)拍摄照片设计的本地归档浏览系统。利用 MongoDB `$facet` 单次聚合完成**八维联动筛选**,提供美观的瀑布流照片墙 + 快速下钻查看原图与元数据,支持 AI 场景标签筛选、趋势分析。 - 后端:FastAPI + Uvicorn 原生异步,纯 API 设计,仅监听本地回环 `127.0.0.1:8765` - 前端:Vue 3 + Vite 组件化,响应式布局,现代化渐变卡片与悬浮交互 - 数据库:MongoDB 8.x 聚合引擎,Motor 异步驱动,多维度索引优化 - 图片处理:Pillow 按需生成缩略图 + EXIF Orientation 自动旋转 + LANCZOS 重采样,磁盘缓存复用 # 架构设计 ## 整体分层 | 层 | 技术 | 说明 | |----|------|------| | 后端框架 | FastAPI + Uvicorn | 原生异步,自动 Swagger 文档,Python 3.12+ 兼容 | | 数据库 | MongoDB 8.x + Motor 异步驱动 | 集合 `photos`,统一存储多地点照片,`location` 字段区分 | | 图片处理 | Pillow | 缩略图按需生成 + EXIF Orientation 自动旋转 + LANCZOS 重采样 | | 渲染模式 | 前后端分离(v2.0+) | 后端纯 API(8765),前端 Vue 3 + Vite(5173) | | 前端框架 | Vue 3 + Vite | 组件化照片墙与趋势页,适配千级照片规模 | ## 模块化路由(`routers/` 包,职责分离) ``` routers/ ├── database.py # Motor 异步客户端单例 ├── photos.py # 照片查询 API(列表投影 + 单张全量详情) ├── stats.py # 统计聚合 API($facet 八维联动 + 独立维度端点 + overview) ├── images.py # 图片服务(缩略图磁盘缓存 + 原图 StreamingResponse) ├── api_logs.py # 接口日志(异步批量写入 + TTL 自动清理) └── versions.py # 版本发布信息接口 ``` ## 核心特性 ### $facet 八维聚合引擎 单次 MongoDB `$facet` 聚合返回全部 **8 个维度**(地点 / 标签 / 年份 / 测光 / 相机型号 / 镜头型号 / 曝光程序 / AI 模型)的联动统计,每个维度服务端排除自身筛选条件。**筛选变化时前端仅调用 2 次 HTTP**(facets + photos),从最初 8 次请求降至 2 次。 端点内置 **TTL(4s) 内存缓存 + 并发去重**:同条件在 TTL 内直接命中,并发同条件仅计算一次,重复聚合响应从 ~30ms 降至 ~7ms。 ### 接口日志与观测 - 采用异步队列 + 批量落库,日志写入不阻塞请求响应 - 新增语义化筛选摘要、响应字节大小、缓存命中标记等字段 - MongoDB TTL 索引(30 天)自动清理过期日志,无需手动维护 - 极端场景丢弃策略保护:队列满时丢弃最旧数据,绝不阻塞主流程 ### 投影与缩略图策略 - **投影优化**:列表接口排除 `filepath`(安全防护)、`scene_description`、`composition`(大文本),payload 减小约 40%。弹窗打开时异步调用 `/api/photos/{filename}` 获取完整字段并缓存。 - **缩略图策略**:按需生成 → 磁盘缓存 → 固定宽 400px + JPEG 质量 85。首次访问生成,后续直接返回 `FileResponse`(毫秒级)。原图采用 `StreamingResponse` 64KB 分块流式返回。 - **缓存控制**:缩略图 / 原图响应头 `Cache-Control: public, max-age=86400`,前端通过 JS 版本号 + 图片 URL 版本号独立控制缓存刷新。 ### 前端布局与交互 - **顶栏精简收纳**:排序常驻 +「筛选」按钮弹出抽屉收纳 6 个维度(时间 / 设备:相机·镜头·AI模型 / 拍摄参数:测光·曝光),已选维度以可删除胶囊显示,筛选按钮角标标记已选数量,大幅节省首页空间。 - **可收起侧栏**:点击 ☰ 按钮收起/展开左侧栏(地点列表 + 标签云),收起后照片区域自动变宽适配全屏。 - **瀑布流网格**:CSS Grid 响应式布局,从 5 列 → 4 → 3 → 2 列自动适配屏幕宽度。 - **懒加载与骨架占位**:`IntersectionObserver` 预加载 200px,缩略图使用 `shimmer` 骨架动画占位,加载完成后淡入,消除 pop-in 闪烁。 - **细节交互升级**: - 照片卡片悬停:轻微上浮放大 + 渐变阴影加深 + 底部半透明遮罩 +「查看大图」提示浮层 - 地点标签:透明底色 + 文字阴影,适配任何背景照片 - 大圆角 + 柔和阴影 + 渐变毛玻璃背景,现代精致视觉风格 - 分页按钮采用药丸形状,当前页计数显示色块强调 ### 详情弹窗功能 - **一键缩放**:工具栏提供放大/缩小/1:1重置按钮,双击弹窗空白也可复位缩放比例 - **滚轮缩放**:鼠标滚轮直接对照片缩放(无需任何修饰键),范围 25% ~ 300% - **平移查看细节**:放大后保持左键按住拖拽即可平移查看局部细节 - **元数据自动收起**:打开弹窗时元数据默认展示 10 秒,10 秒后自动在右侧收起,可点击侧边按钮手动展开/收起 - **键盘导航**:← / → 切换上下照片,Esc 关闭弹窗 - **原图缺失占位**:内联 SVG 插画美观占位,不显示破图 ### 维度筛选(八维联动) | 维度 | 位置 | 说明 | |------|------|------| | 地点 | 左侧侧栏 | 点击筛选当前地点,显示带计数的地点列表 | | 标签 | 左侧侧栏 | 标签云,默认显示前 5 个,支持展开全部,多标签 AND 筛选 | | 年份 | 筛选抽屉 | 下拉单选,按年份筛选 | | 测光模式 | 筛选抽屉 | 下拉单选,按 EXIF 测光模式筛选 | | 相机型号 | 筛选抽屉 | 下拉单选,按相机机身筛选 | | 镜头型号 | 筛选抽屉 | 下拉单选,按镜头筛选 | | 曝光程序 | 筛选抽屉 | 下拉单选,按曝光程序筛选 | | AI 模型 | 筛选抽屉 | 下拉单选,按生成场景标签所用 AI 模型筛选 | ## MongoDB 索引(8 个) | 索引 | 字段 | 用途 | |------|------|------| | `idx_location` | `location` | 地点筛选 | | `idx_tags` | `scene_tags` | 标签筛选 | | `idx_shooting_time` | `shooting_time` (降序) | 时间排序 | | `idx_loc_time` | `location` + `shooting_time` | 地点 + 时间复合查询 | | `idx_lens_model` | `lens_model` | 镜头型号筛选 | | `idx_exposure_program` | `exposure_program` | 曝光程序筛选 | | `idx_metering_mode` | `metering_mode` | 测光模式筛选 | | `idx_camera_model` | `camera_model` | 相机型号筛选 | # 效果预览 > 浏览器访问前端 `http://localhost:5173/` 的首页效果 ![Nikon 照片库主界面(v2.1.3)](screenshots/gallery_main.png) > 照片卡片悬停效果 ![照片卡片悬停](screenshots/gallery_hover.png) # 安装部署 ## 环境要求 - Python 3.12+ - MongoDB 8.x(本地运行,默认端口 27017) - Node.js 18+(前端构建) ## 安装依赖 ```bash pip install fastapi "uvicorn[standard]" motor pillow python-multipart pymongo cd frontend && npm install ``` ## 克隆与配置 ```bash git clone https://gitee.com/hwxus/photo_gallery.git cd photo_gallery ``` 修改 `config.py` 中的 `PHOTO_ROOT_DIR` 为你的照片根目录路径,MongoDB 连接地址按需调整。 ## 创建 MongoDB 索引(提升查询性能) ```python from pymongo import MongoClient db = MongoClient('mongodb://localhost:27017')['nikon_photos'] db.photos.create_index([('location', 1)], name='idx_location') db.photos.create_index([('scene_tags', 1)], name='idx_tags') db.photos.create_index([('shooting_time', -1)], name='idx_shooting_time') db.photos.create_index([('location', 1), ('shooting_time', -1)], name='idx_loc_time') db.photos.create_index([('lens_model', 1)], name='idx_lens_model') db.photos.create_index([('exposure_program', 1)], name='idx_exposure_program') db.photos.create_index([('metering_mode', 1)], name='idx_metering_mode') db.photos.create_index([('camera_model', 1)], name='idx_camera_model') ``` # 快速启动(推荐) 项目提供一键启动/停止脚本,后台静默运行不弹黑窗口: ```bat start_photo_gallery.bat ``` 执行后等待 4~6 秒,服务启动完成,浏览器访问: - 照片墙首页:`http://localhost:5173/` - 趋势分析:`http://localhost:5173/stats` - 后端 API:`http://127.0.0.1:8765/api/stats/facets` 停止服务执行: ```bat stop_photo_gallery.bat ``` 脚本保持结果窗口可见,展示关闭结果。 ## 手动启动 ```bash # 后端 python -m uvicorn app:app --host 127.0.0.1 --port 8765 # 前端(另开终端) cd frontend && npm run dev ``` # 功能速览 ## 照片墙首页 (`/`) - CSS Grid 瀑布流布局,滚动懒加载缩略图 - 骨架占位 + 图片淡入消除闪烁 - 悬停照片卡片上浮 + 放大预览提示 - 渐变标题 + 胶囊式页码统计 ## 顶部工具栏 - **排序**:按拍摄时间 / 文件大小 / 焦距 / ISO 排序(支持升序/降序) - **筛选按钮**:点击弹出抽屉,选择时间/设备/拍摄参数筛选条件 - **已选胶囊**:已选维度以可删除胶囊显示在顶栏,点胶囊即可快速清除 - **筛选角标**:筛选按钮显示已选维度数量角标 - **版本入口**:点击「i」查看版本更新记录 - **趋势入口**:图标按钮紧凑进入趋势分析页 ## 左侧筛选栏 - **地点列表**:每条显示照片计数,当前选中项紫色渐变高亮 - **标签云**:多标签可同时选中,默认折叠前 5 个,可点击展开全部 - **清除筛选**:一键清除所有筛选条件,重置为初始状态 ## 详情弹窗(点击缩略图) - 原图展示,支持缩放(0.25~3.0)与平移 - 地点名称 + AI 场景标签 + AI 场景描述 + 构图说明 - EXIF 完整信息两栏网格布局:相机、镜头、焦距、光圈、快门、ISO、白平衡等 - 左侧箭头导航,Esc 关闭,左右方向键切换上下照片 ## 趋势分析页 (`/stats`) - 地点拍摄量柱状图 - AI 模型使用占比饼图 - 年度拍摄趋势折线图 - 热门标签 TOP10 条形图 # 版本记录 | 版本 | 日期 | 主要更新 | |------|------|----------| | **v2.1.3** | 2026-08-27 | 首页视觉整体美化(品牌标识/圆角/阴影/渐变毛玻璃),「趋势分析」入口紧凑化,地点标签透明底色适配所有照片;下弹窗新增元数据自动收起、大图缩放与平移;接口日志异步批量落库;新增版本发布面板 | | v2.1.2 | 2026-08-27 | 顶栏筛选收纳为抽屉+胶囊,`/api/stats/facets`增加 TTL 内存缓存+并发去重 | | v2.1.1 | 2026-08-27 | 修复 AI 维度未联动计数 bug,修复下钻弹窗索引错位,原图缺失 SVG 占位 | | v2.1.0 | 2026-08 | 接口日志接入,收紧后端安全策略(仅监听回环),前后端分离重构 | 可在前端点击顶部「i」查看完整版本更新记录。 # 启动脚本安全说明 - `start_photo_gallery.bat` 使用 `start /b` 启动后台进程,无可见窗口,日志写入 `logs/backend.log` 与 `logs/frontend.log` - `stop_photo_gallery.bat` 按端口查找并终止进程,执行后窗口停留查看结果,不会一闪而过 - 后端强制监听 `127.0.0.1`,CORS 仅允许 `localhost:5173` `127.0.0.1:5173` GET 请求,不暴露到局域网 # 许可证 MIT License - 详见 [LICENSE](LICENSE)