From 270af4e707ef338eaedd808f2a363e76fd163d79 Mon Sep 17 00:00:00 2001 From: O96u Date: Mon, 31 Aug 2026 16:05:53 +0800 Subject: [PATCH] =?UTF-8?q?release:=20v1.2.5=20=E2=80=94=20=E5=9B=BE?= =?UTF-8?q?=E5=BA=93=E9=A1=B5=E3=80=81=E5=9B=BE=E7=89=87=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E5=BC=B9=E5=B1=82=E4=B8=8E=E5=88=97=E8=A1=A8=E4=BD=93=E9=AA=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 16 ++ README.en.md | 14 ++ README.md | 14 ++ app/components/AppShell.vue | 2 +- app/components/ImageCard.vue | 29 ++- app/components/ImageGrid.vue | 6 +- app/components/ImagePreviewModal.vue | 256 +++++++++++++++++++++++++++ app/pages/{stats.vue => gallery.vue} | 87 ++++++++- app/pages/index.vue | 26 ++- app/types/image.ts | 2 + app/utils/image-display.ts | 24 +++ docs-site/en/guide/changelog.md | 16 ++ docs-site/guide/changelog.md | 16 ++ i18n/locales/en.json | 26 ++- i18n/locales/zh-CN.json | 26 ++- package-lock.json | 4 +- package.json | 2 +- server/api/images/index.get.ts | 5 +- server/api/images/search.get.ts | 5 +- server/utils/db.ts | 28 +++ server/utils/image-response.ts | 16 +- server/utils/process-image-upload.ts | 19 +- 22 files changed, 587 insertions(+), 52 deletions(-) create mode 100644 app/components/ImagePreviewModal.vue rename app/pages/{stats.vue => gallery.vue} (85%) create mode 100644 app/utils/image-display.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c003cd..5f92ce2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,22 @@ ## [Unreleased] +## [1.2.5] - 2026-08-31 + +### 新增 + +- 图库页(`/gallery`)替代原「统计」导航;图片点击放大详情弹层(尺寸、上传方式、存储路径、链接复制) +- 图库列表支持全选、反选;单张删除移至详情弹层 +- 图片列表 API 返回上传来源(网页 / API,来自活动日志) + +### 改进 + +- README 补充技术栈说明 + +### 移除 + +- `/stats` 路由(不再兼容跳转) + ## [1.2.4] - 2026-08-31 ### 修复 diff --git a/README.en.md b/README.en.md index 4931bbc..3ce6b9d 100644 --- a/README.en.md +++ b/README.en.md @@ -20,6 +20,7 @@ Docs · Screenshots · Features · + Tech Stack · Quick Start · 简体中文

@@ -47,6 +48,19 @@ - **API & Twikoo** — global / per-user tokens; `POST /api/index.php` compatible - **Zero-config Docker** — first-run web wizard, no secrets upfront +## Tech Stack + +| Layer | Technologies | +| ----- | ------------ | +| Frontend | [Nuxt 4](https://nuxt.com) · [Nuxt UI 4](https://ui.nuxt.com) · [Vue 3](https://vuejs.org) · [Tailwind CSS 4](https://tailwindcss.com) · TypeScript | +| Backend | [Nitro](https://nitro.build) (`node-server`) · REST API | +| Data | SQLite · local `data/pichost.db` | +| Images | [sharp](https://sharp.pixelplumbing.com) (server-side WebP) | +| Storage | Local disk · S3-compatible ([AWS SDK](https://aws.amazon.com/sdk-for-javascript/) · R2 / COS / OSS, etc.) | +| i18n | [@nuxtjs/i18n](https://i18n.nuxtjs.org) (zh-CN / English) | +| Quality & docs | [Vitest](https://vitest.dev) · [VitePress](https://vitepress.dev) docs site | +| Deploy | Docker · Node.js 22 | + ## Quick Start ```bash diff --git a/README.md b/README.md index 8a3d8cd..bb498d4 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ 文档 · 预览 · 特性 · + 技术栈 · 快速开始 · English

@@ -47,6 +48,19 @@ - **API 与 Twikoo**:全局 / 个人 Token;`POST /api/index.php` 兼容 - **Docker 零配置**:首次访问 Web 引导创建管理员 +## 技术栈 + +| 层级 | 技术 | +| ---- | ---- | +| 前端 | [Nuxt 4](https://nuxt.com) · [Nuxt UI 4](https://ui.nuxt.com) · [Vue 3](https://vuejs.org) · [Tailwind CSS 4](https://tailwindcss.com) · TypeScript | +| 后端 | [Nitro](https://nitro.build)(`node-server`)· REST API | +| 数据 | SQLite · 本地 `data/pichost.db` | +| 图片处理 | [sharp](https://sharp.pixelplumbing.com)(服务端 WebP 压缩) | +| 存储 | 本地磁盘 · S3 兼容([AWS SDK](https://aws.amazon.com/sdk-for-javascript/) · R2 / COS / OSS 等) | +| 国际化 | [@nuxtjs/i18n](https://i18n.nuxtjs.org)(简体中文 / English) | +| 质量与文档 | [Vitest](https://vitest.dev) · [VitePress](https://vitepress.dev) 文档站 | +| 部署 | Docker · Node.js 22 | + ## 快速开始 ```bash diff --git a/app/components/AppShell.vue b/app/components/AppShell.vue index d06ad8e..a8552f1 100644 --- a/app/components/AppShell.vue +++ b/app/components/AppShell.vue @@ -13,7 +13,7 @@ const mobileUserOpen = ref(false) const navItems = computed(() => { const items = [ { label: t('nav.api'), to: '/api', icon: 'i-lucide-code-2' }, - { label: t('nav.stats'), to: '/stats', icon: 'i-lucide-chart-column' } + { label: t('nav.gallery'), to: '/gallery', icon: 'i-lucide-images' } ] if (isAdmin.value) { items.push({ label: t('nav.storage'), to: '/storage', icon: 'i-lucide-hard-drive' }) diff --git a/app/components/ImageCard.vue b/app/components/ImageCard.vue index 184c2a8..ebcc7c0 100644 --- a/app/components/ImageCard.vue +++ b/app/components/ImageCard.vue @@ -5,7 +5,6 @@ import type { CopyFormat } from '~/composables/useUploadPreferences' const props = withDefaults(defineProps<{ image: ImageItem selected: boolean - deleting?: boolean selectable?: boolean showKey?: boolean showStorage?: boolean @@ -19,7 +18,7 @@ const props = withDefaults(defineProps<{ const emit = defineEmits<{ 'update:selected': [value: boolean] - 'delete': [] + 'preview': [] }>() const { formatFileSize } = useFileSize() @@ -118,14 +117,22 @@ function toggleSelected(value: boolean | 'indeterminate') {