From 5bac272f6dba4d588234c7f0a85e4d1e070c1def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=81=E5=86=9C=E9=98=BF=E6=A5=A0?= Date: Wed, 9 Sep 2026 11:51:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=89=8D=E5=8F=B0=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=20antd=20=E7=BB=84=E4=BB=B6=E3=80=81?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=B0=81=E9=9D=A2=E5=9B=BE=E3=80=81favicon?= =?UTF-8?q?=20=E9=9A=8F=E7=AB=99=E7=82=B9=20Logo=20=E5=8F=8A=E4=BE=A7?= =?UTF-8?q?=E6=A0=8F=E6=94=B6=E7=AA=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 前台列表/详情/标签页标签统一 antd Tag;标签页改 CheckableTagGroup 单选 (选中态由组件承接,再点已选标签回到全部);移除首页标签筛选条, 标签入口收敛至顶部「标签」页 - 公开列表新增 cover 字段(取正文第一张站内图,store.FirstImageRef), 首页条目左侧显示封面缩略图,无图条目保持纯文字 - favicon 随站点 Logo:webui.Meta.Icon 服务端注入 index.html, 前端 useSiteTitle 兜底(dev 模板占位符场景)并即时生效; 设置页「重置默认」清空 Logo 后回退内置 /favicon.svg - 后台侧栏改 antd Menu(inline 分组),宽度 256→208、窄侧栏档 224→184 --- internal/httpapi/public.go | 4 +- internal/httpapi/server.go | 9 +++ internal/store/images.go | 10 +++ internal/store/notes.go | 3 +- internal/webui/webui.go | 1 + web/index.html | 3 +- web/src/components/Layout.tsx | 63 ++++++++++----- web/src/features/site.ts | 11 ++- web/src/index.css | 132 +++++++++++++------------------- web/src/lib/api.ts | 2 + web/src/pages/AdminSettings.tsx | 8 +- web/src/pages/Home.tsx | 85 +++++++++----------- web/src/pages/TagPage.tsx | 42 +++++----- 13 files changed, 199 insertions(+), 174 deletions(-) diff --git a/internal/httpapi/public.go b/internal/httpapi/public.go index 53b4518..838a836 100644 --- a/internal/httpapi/public.go +++ b/internal/httpapi/public.go @@ -40,13 +40,14 @@ func (s *Server) handleSiteInfo(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, ss) } -// publicNoteItem 公开列表项(元信息,不含全文)。 +// publicNoteItem 公开列表项(元信息 + 封面图,不含全文)。 type publicNoteItem struct { Slug string `json:"slug"` Title string `json:"title"` Summary string `json:"summary"` Tags []string `json:"tags"` Pinned bool `json:"pinned"` + Cover string `json:"cover,omitempty"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` PublishedAt int64 `json:"published_at"` @@ -71,6 +72,7 @@ func (s *Server) handlePublicNotes(w http.ResponseWriter, r *http.Request) { items = append(items, publicNoteItem{ Slug: n.Slug, Title: n.Title, Summary: n.Summary, Tags: n.Tags, Pinned: n.Pinned, + Cover: store.FirstImageRef(n.Content), CreatedAt: n.CreatedAt, UpdatedAt: n.UpdatedAt, PublishedAt: n.PublishedAt, }) } diff --git a/internal/httpapi/server.go b/internal/httpapi/server.go index 1ce0831..dae1ef1 100644 --- a/internal/httpapi/server.go +++ b/internal/httpapi/server.go @@ -299,6 +299,7 @@ func (s *Server) ResolveMeta(r *http.Request) webui.Meta { OGType: "website", SiteName: ss.SiteTitle, OGURL: baseURL(r) + "/", + Icon: favicon(ss.SiteLogo), } slug := metaSlug(r.URL.Path) if slug == "" { @@ -318,6 +319,14 @@ func (s *Server) ResolveMeta(r *http.Request) webui.Meta { return s.noteMeta(r, m, note) } +// favicon favicon 地址:站点 Logo 优先,未设置回退内置图标。 +func favicon(siteLogo string) string { + if siteLogo != "" { + return siteLogo + } + return "/favicon.svg" +} + func (s *Server) noteMeta(r *http.Request, base webui.Meta, n *store.Note) webui.Meta { desc := n.Summary if desc == "" { diff --git a/internal/store/images.go b/internal/store/images.go index 9934e72..9160d1c 100644 --- a/internal/store/images.go +++ b/internal/store/images.go @@ -64,6 +64,16 @@ func (s *Store) ImageIsPublic(id int64) (bool, error) { // imageRefRe 扫描 content 中对 /api/images/{id} 的引用(§6.2 引用维护)。 var imageRefRe = regexp.MustCompile(`/api/images/(\d+)`) +// FirstImageRef 返回 content 中按出现顺序的第一张站内图片路径(无则空串)。 +// 供公开列表推导封面图使用。 +func FirstImageRef(content string) string { + m := imageRefRe.FindStringSubmatch(content) + if len(m) < 2 { + return "" + } + return m[0] +} + // RebuildImageRefs 在**同一事务**内重建笔记的图片引用: // 删除该笔记全部 refs → 正则扫描 content → 重建(§6.2)。 func (s *Store) RebuildImageRefs(noteID int64, content string) error { diff --git a/internal/store/notes.go b/internal/store/notes.go index ae9b373..c598f26 100644 --- a/internal/store/notes.go +++ b/internal/store/notes.go @@ -167,7 +167,8 @@ func (s *Store) ListPublicNotes(page, pageSize int, tag string) ([]Note, int, er if err := s.db.QueryRow(`SELECT COUNT(*) FROM notes n WHERE `+where, args...).Scan(&total); err != nil { return nil, 0, err } - q := `SELECT n.id, n.slug, n.title, n.summary, '' AS content, n.status, n.tags, n.pinned, n.deleted_at, n.created_at, n.updated_at, COALESCE(n.published_at, n.created_at) AS published_at + // 含全文:列表页需从正文推导封面图(FirstImageRef),个人规模条数有限可接受 + q := `SELECT n.id, n.slug, n.title, n.summary, n.content, n.status, n.tags, n.pinned, n.deleted_at, n.created_at, n.updated_at, COALESCE(n.published_at, n.created_at) AS published_at FROM notes n WHERE ` + where + ` ORDER BY n.pinned DESC, n.updated_at DESC, n.id DESC LIMIT ? OFFSET ?` rows, err := s.db.Query(q, append(args, pageSize, (page-1)*pageSize)...) diff --git a/internal/webui/webui.go b/internal/webui/webui.go index ff01c3a..78f8935 100644 --- a/internal/webui/webui.go +++ b/internal/webui/webui.go @@ -30,6 +30,7 @@ type Meta struct { OGURL string OGImage string SiteName string + Icon string // favicon:站点 Logo,未设置回退 /favicon.svg } // UI 静态资源服务。 diff --git a/web/index.html b/web/index.html index b0da037..621f707 100644 --- a/web/index.html +++ b/web/index.html @@ -2,7 +2,8 @@ - + +