From da72843c7038e5b16c7e7ed157660c634a1b87a3 Mon Sep 17 00:00:00 2001 From: freefire Date: Fri, 9 Oct 2026 18:53:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BB=A3=E7=A0=81=E7=89=87=E6=AE=B5?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=B8=8E=20Markdown=20=E5=86=85=E5=B5=8C?= =?UTF-8?q?=E7=89=87=E6=AE=B5=E6=B8=B2=E6=9F=93=E3=80=81=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E6=88=AA=E5=9B=BE=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 220 +++- README.md | 422 ++++--- backend/handler/chat.go | 53 +- backend/handler/handlers.go | 1 + backend/handler/snippet.go | 424 +++++++ backend/model/db.go | 1 + backend/model/models.go | 69 ++ backend/router/router.go | 27 + backend/service/chat.go | 12 + backend/service/header_nav.go | 2 +- backend/service/header_nav_test.go | 11 +- backend/service/ratelimit.go | 2 + backend/service/snippet.go | 1022 +++++++++++++++++ docs/images/wechat.png | Bin 0 -> 67572 bytes docs/images/zfb.png | Bin 0 -> 70096 bytes docs/images/书库.png | Bin 0 -> 332931 bytes docs/images/代码片段.png | Bin 0 -> 563782 bytes docs/images/帖子详情.png | Bin 0 -> 404826 bytes docs/images/管理后台.png | Bin 0 -> 185878 bytes docs/images/访问统计.png | Bin 0 -> 163249 bytes docs/images/首页.png | Bin 0 -> 352290 bytes .../app/admin/settings/HeaderNavPanel.tsx | 5 +- frontend/app/admin/snippets/SnippetsAdmin.tsx | 277 +++++ frontend/app/admin/snippets/page.tsx | 20 + frontend/app/chat/[id]/ChatRoomClient.tsx | 6 +- frontend/app/globals.css | 323 +++++- frontend/app/register/RegisterClient.tsx | 6 +- frontend/app/reset-password/page.tsx | 2 +- frontend/app/sitemap.ts | 24 +- frontend/app/snippets/[id]/edit/page.tsx | 111 ++ frontend/app/snippets/[id]/page.tsx | 253 ++++ frontend/app/snippets/new/page.tsx | 52 + frontend/app/snippets/page.tsx | 49 + frontend/components/FavoriteButton.tsx | 11 +- frontend/components/Header.tsx | 10 +- frontend/components/LikeButton.tsx | 6 +- frontend/components/MarkdownBody.tsx | 5 + frontend/components/MarkdownBodyClient.tsx | 12 + frontend/components/MarkdownEditor.tsx | 16 + frontend/components/PostRow.tsx | 2 +- frontend/components/SnippetActions.tsx | 197 ++++ frontend/components/SnippetCodeView.tsx | 217 ++++ .../components/SnippetCommentCountChip.tsx | 48 + frontend/components/SnippetCommentSection.tsx | 702 +++++++++++ frontend/components/SnippetEditor.tsx | 331 ++++++ frontend/components/SnippetExplorer.tsx | 612 ++++++++++ frontend/components/SnippetHero.tsx | 254 ++++ frontend/components/SnippetLangSelect.tsx | 236 ++++ frontend/components/SnippetPickerModal.tsx | 185 +++ frontend/components/SnippetVersionModal.tsx | 239 ++++ frontend/components/admin/AdminShell.tsx | 7 + frontend/components/home/CheckinCard.tsx | 14 +- frontend/components/markdown/MdSnippet.tsx | 124 ++ .../components/markdown/shikiHighlighter.ts | 80 +- frontend/lib/api.ts | 400 +++++++ frontend/lib/directiveBlocks.ts | 29 +- frontend/lib/headerNav.test.ts | 4 +- frontend/lib/headerNav.ts | 3 +- frontend/lib/realtime.ts | 5 +- frontend/lib/snippetLangColors.ts | 48 + frontend/lib/urlStyle.test.ts | 33 + frontend/lib/urlStyle.ts | 60 +- frontend/middleware.ts | 7 + frontend/next-env.d.ts | 4 +- 64 files changed, 7047 insertions(+), 248 deletions(-) create mode 100644 backend/handler/snippet.go create mode 100644 backend/service/snippet.go create mode 100644 docs/images/wechat.png create mode 100644 docs/images/zfb.png create mode 100644 docs/images/书库.png create mode 100644 docs/images/代码片段.png create mode 100644 docs/images/帖子详情.png create mode 100644 docs/images/管理后台.png create mode 100644 docs/images/访问统计.png create mode 100644 docs/images/首页.png create mode 100644 frontend/app/admin/snippets/SnippetsAdmin.tsx create mode 100644 frontend/app/admin/snippets/page.tsx create mode 100644 frontend/app/snippets/[id]/edit/page.tsx create mode 100644 frontend/app/snippets/[id]/page.tsx create mode 100644 frontend/app/snippets/new/page.tsx create mode 100644 frontend/app/snippets/page.tsx create mode 100644 frontend/components/SnippetActions.tsx create mode 100644 frontend/components/SnippetCodeView.tsx create mode 100644 frontend/components/SnippetCommentCountChip.tsx create mode 100644 frontend/components/SnippetCommentSection.tsx create mode 100644 frontend/components/SnippetEditor.tsx create mode 100644 frontend/components/SnippetExplorer.tsx create mode 100644 frontend/components/SnippetHero.tsx create mode 100644 frontend/components/SnippetLangSelect.tsx create mode 100644 frontend/components/SnippetPickerModal.tsx create mode 100644 frontend/components/SnippetVersionModal.tsx create mode 100644 frontend/components/markdown/MdSnippet.tsx create mode 100644 frontend/lib/snippetLangColors.ts diff --git a/LICENSE b/LICENSE index fb5d833..bece6fd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,38 +1,202 @@ -姜十三论坛 专有软件许可协议 -Proprietary Software License Agreement + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Copyright (c) 2026 姜十三. All Rights Reserved. -版权所有 (c) 2026 姜十三。保留所有权利。 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -本软件(包括但不限于源代码、目标代码、文档、图像及其他随附资料, -以下统称"本软件")由版权方(以下称"授权方")开发并所有。本软件 -以源码可见的方式发布,但这并不构成任何形式的开源授权。 + 1. Definitions. -在未获得授权方事先书面许可之前,任何个人或组织不得: + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -1. 以任何目的(包括商业、内部生产、教学培训等)使用、运行或部署 - 本软件的全部或任何部分; -2. 复制、影印、转载、镜像、收录到任何数据库或以任何方式再现本软件; -3. 修改、改编、翻译、合并、反向工程、反编译、反汇编本软件,或基于 - 本软件创作衍生作品; -4. 出售、出租、出借、分销、再许可、托管(SaaS)或以其他方式向第三方 - 提供本软件或其任何副本; -5. 删除、遮盖或更改本软件中的版权声明、商标或其他权利声明。 + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -仅可出于个人学习、评估是否购买授权的目的浏览本仓库中的源代码;该等 -浏览不视为获得任何明示或默示的使用许可。 + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -商业使用、内部部署或其他任何形式的使用授权,均须与授权方另行签订 -书面许可协议。 + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -第三方开源组件按其各自附带的许可证条款授权,不受本协议约束。 + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -本软件按"现状"(AS IS)提供,不附带任何明示或默示的担保,包括但不限 -于适销性、特定用途适用性或不侵权的担保。在任何情况下,授权方均不对因 -使用或无法使用本软件而导致的任何直接、间接、附带、特殊或后果性损害 -承担责任。 + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -未经授权使用本软件的行为,均构成对授权方著作权及其他知识产权的侵犯, -授权方保留依法追究法律责任的权利。 + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -授权方联系方式:aarbbs@88.com + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that the copyright owner or their authorized + representative conspicuously designates in writing as "Not a + Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with the conditions + stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides their Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The boilerplate notice should be enclosed in + appropriate comment syntax for the file format. We also + recommend that a file or class name and description of purpose be + included on the same "printed page" as the copyright notice for + easier identification within third-party archives. + + Copyright 2026 姜十三 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index c74efd0..398a714 100644 --- a/README.md +++ b/README.md @@ -1,101 +1,128 @@ +
+ # 姜十三论坛(jiang13-bbs) -一个基于 Go + Next.js 的现代社区论坛系统,采用 SSR 直出 + HttpOnly Cookie 认证方案,具备完整的帖子/评论/通知/签到/管理后台功能。 +一个基于 **Go + Next.js** 构建的现代化社区论坛系统,SSR 直出、HttpOnly Cookie 认证,内置内容社区、代码片段、书库、积分体系、实时群聊与完整管理后台,开箱即用。 -> **许可声明:** 本项目为专有软件(Proprietary),源码可见但不构成开源授权。详见 [LICENSE](./LICENSE)。未经书面许可,不得使用、部署或分发。 +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE) +[![Version](https://img.shields.io/badge/version-0.2.9-green.svg)](./VERSION) +[![Go](https://img.shields.io/badge/Go-1.27-00ADD8?logo=go&logoColor=white)](https://go.dev/) +[![Next.js](https://img.shields.io/badge/Next.js-16-black?logo=nextdotjs&logoColor=white)](https://nextjs.org/) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](#贡献指南) + +
+ +--- + +## 目录 + +- [项目截图](#项目截图) +- [功能特性](#功能特性) +- [技术栈](#技术栈) +- [快速开始](#快速开始) +- [配置说明](#配置说明) +- [Docker 部署](#docker-部署) +- [项目结构](#项目结构) +- [安全设计](#安全设计) +- [开发与测试](#开发与测试) +- [更新日志](#更新日志) +- [贡献指南](#贡献指南) +- [许可证](#许可证) +- [联系方式](#联系方式) +- [赞赏支持](#赞赏支持) + +--- + +## 项目截图 + +| 首页信息流 | 帖子详情 | +| :---: | :---: | +| ![首页](docs/images/首页.png) | ![帖子详情](docs/images/帖子详情.png) | +| 代码片段广场 | 书库在线阅读 | +| ![代码片段](docs/images/代码片段.png) | ![书库](docs/images/书库.png) | +| 管理后台仪表盘 | 访问统计分析 | +| ![管理后台](docs/images/管理后台.png) | ![访问统计](docs/images/访问统计.png) | + + + +--- + +## 功能特性 + +### 内容社区 + +- 帖子发布 / 编辑 / 删除,支持普通帖、**问答帖**(采纳答案、状态流转)、**投票帖**、**悬赏帖**、**抽奖帖**,以及密码帖与付费解锁内容 +- Markdown 写作与渲染:Shiki 代码高亮、目录导航、图片灯箱、视频/附件 +- 楼层化评论:主评论占楼层、子评论不占楼层,最多 10 层嵌套,单次查询拼装评论树,无 N+1 +- 评论与帖子均提供**编辑历史**、软删除与回收站(恢复 / 彻底删除) +- 点赞、收藏、关注、置顶、推荐、锁定,联合唯一索引防止重复互动 +- 附件可设定积分价格,支持付费下载 + +### 积分与成长体系 + +- 每日签到 + 连续签到加成,积分余额与完整流水台账 +- 用户等级体系(经验值自动升级)与成就徽章(手动授予 / 自动通知) +- 全站积分排行榜与个人排名 + +### 代码片段 + +- 独立的代码片段广场:多语言语法高亮、按语言筛选、全站统计 +- Fork、一键复制计数、片段评论、版本历史、可见性管理 + +### 书库 / 文档中心 + +- 书籍文档管理,两级章节(章 → 节)结构 +- 支持 **EPUB 解析导入**、Markdown 单篇 / 批量导入、整库导出与单本导出 +- 内置在线阅读器,封面、附件下载一应俱全 + +### 私信与群聊 + +- 一对一私信、多人群聊房间、默认全站大厅 +- 群成员管理:邀请 / 移出、禁言、角色设置;消息撤回、未读汇总、会话置顶 + +### 实时通知 + +- 评论、回复、点赞、@、系统通知等多类型站内消息 +- 未读红点 **SSR 首屏直出**,WebSocket 实时推送,页面回到前台时 HTTP 校准,支持单条 / 全部已读 + +### 管理后台 + +- 仪表盘与分析概览(Recharts 图表) +- 内容审核队列(待审帖子 / 评论,板块管理员仅见授权板块)与内容回收站 +- 板块管理、版主授权、排序 +- 用户管理:角色、细粒度权限码、封禁、消息权限、登录日志、登录设备、积分调整 +- 公告文章、站点单页(CMS)管理 +- 广告位与赞助商配置(含用户自助购买提交、二维码、验证码) +- 友情链接:用户申请、后台审批 +- 侧边栏可视化布局配置 + 自定义 HTML 小部件 +- 背景图、品牌 Logo 上传裁剪;全站媒体库盘点 +- **访问统计**:概览、实时、来源、页面、访客、安全、事件等多维度分析 +- 旧站数据导入(WordPress / Typecho 等) +- 更新时间线:从 Git Commits / Releases 自动生成更新日志 +- 维护模式、系统诊断、SMTP 邮件配置(凭据加密存储) +- 支持 S3 / MinIO 对象存储:文件内容去重、自适应图片变体、WebP 自动转换 + +### SEO + +- 全站 SSR / ISR,title、description、OG 等关键内容均在初始 HTML 中 +- 帖子详情页输出 `DiscussionForumPosting` 类型 JSON-LD +- 动态 `sitemap`、`robots`、Canonical 链接 --- ## 技术栈 -| 层级 | 技术 | -|------|------| +| 层级 | 技术选型 | +|------|----------| | 后端 | Go 1.27 · Gin · GORM · PostgreSQL 17 | -| 前端 | Next.js 16 (App Router) · TypeScript · Tailwind CSS v4 | -| 认证 | JWT (HttpOnly Cookie) + Refresh Token 轮转 + CSRF 双提交 + Token Version 撤销 | -| 部署 | 官方:`deploy/` Docker Compose(Next SSR + Go + Postgres,反代自备);本地开发仅 Compose 起数据库 | - ---- - -## 功能概览 - -### 用户 - -- 注册 / 登录 / 登出(注册即登录,免二次跳转) -- 个人资料编辑:昵称、头像、邮箱、个性签名 -- 修改密码(改密后全端踢下线) -- 个人主页:发帖列表、评论列表(分页)、签到积分 -- 每日签到(积分 + 连续签到天数) - -### 内容 - -- 帖子发帖 / 编辑 / 删除(作者本人或管理员) -- 帖子类型:普通帖 / 问答帖 -- 帖子置顶 / 推荐(仅管理员) -- 评论楼层制:主评论 = 楼层,子评论不占楼层,最多 10 层嵌套 -- 楼层分页 + 内存拼装评论树(单次查询,无 N+1) -- Markdown 渲染(代码高亮、引用、列表等) -- 帖子点赞(联合唯一索引防重复) - -### 通知 - -- 站内通知:评论你的帖子、回复你的评论、点赞你的帖子 -- 未读红点 SSR 直出,实时靠 WebSocket 推送,回前台时 HTTP 校准 -- 单条标记已读 / 全部已读 - -### 管理后台 - -- 公告管理(草稿 / 发布、标签预设色) -- 仪表盘 - -### SEO - -- 全站 SSR/ISR,SEO 关键内容在初始 HTML 中 -- 帖子详情页输出 `DiscussionForumPosting` 类型 JSON-LD -- 动态 `sitemap.ts` + `robots.ts`(由 Next.js 对外提供,后端不重复挂 `/sitemap.xml` / `/robots.txt`) - -### 安全 - -- CSP / HSTS / X-Frame-Options: DENY / X-Content-Type-Options / Referrer-Policy -- 速率限制:登录 20/min、注册 10/min、发帖新用户 24h 冷静期 -- Refresh Token 一次性轮转 + 盗用检测(吊销后重放 → 杀全家族) -- 生产 HTTPS 启用 `__Host-` Cookie 前缀 - ---- - -## 项目结构 - -``` -jiang13-bbs/ -├── backend/ # Go 后端 -│ ├── cmd/jiang13/ # 入口 main.go -│ ├── config/ # 配置解析(app.ini + 环境变量) -│ ├── handler/ # HTTP 处理器 -│ ├── middleware/ # 认证 / CSRF / 限流 / 安全头 -│ ├── model/ # GORM 模型 + 数据库初始化 -│ ├── router/ # 路由注册 -│ ├── service/ # 业务逻辑层 -│ ├── app.ini.example # 配置模板 -│ └── go.mod -├── frontend/ # Next.js 前端 -│ ├── app/ # App Router 页面 -│ │ ├── settings/ # 账号设置(资料 + 密码) -│ │ ├── u/[id]/ # 用户主页 -│ │ ├── post/[id]/ # 帖子详情 -│ │ ├── compose/ # 发帖 -│ │ ├── notifications/ # 通知列表 -│ │ ├── admin/ # 管理后台 -│ │ └── ... -│ ├── components/ # 复用组件 -│ ├── lib/ # API 封装 / 工具函数 -│ ├── middleware.ts # SSR 登录态静默轮转 -│ ├── next.config.ts # Rewrite 代理 / 图片缓存 -│ └── .env.example -├── deploy/ # 官方运行时(web + api + Postgres,反代自备) -├── docker-compose.yml # 仅本地开发 Postgres -├── LICENSE # 专有软件许可协议 -└── .gitignore -``` +| 前端 | Next.js 16(App Router)· React 19 · TypeScript · Tailwind CSS v4 | +| 认证 | JWT(HttpOnly Cookie)+ Refresh Token 轮转 + CSRF 双提交 + Token Version 撤销 | +| 实时 | WebSocket(gorilla/websocket) | +| 存储 | 本地存储 / S3(MinIO),Markdown 引擎 Goldmark,代码高亮 Shiki | +| 部署 | Docker Compose:Next SSR + Go API + PostgreSQL(反向代理自备) | --- @@ -104,8 +131,8 @@ jiang13-bbs/ ### 前置条件 - Go 1.27+ -- Node.js 20+ / pnpm 或 npm -- PostgreSQL 17(或通过 Docker Compose 启动) +- Node.js 20+(npm) +- PostgreSQL 17(可通过 Docker Compose 启动) ### 1. 启动数据库 @@ -123,9 +150,9 @@ go mod download go run ./cmd/jiang13 ``` -**工作目录必须是 `backend/`。** 上传文件与 JWT 密钥落在 `backend/data/`(头像 `backend/data/uploads/avatars/`)。不要在仓库根或 `backend/cmd/jiang13/` 执行 `go run`,否则会另建一套 data,数据库里头像 URL 会对不上文件。启动日志应含 `workPath=.../backend` 和 `dataDir=.../backend/data`。需要覆盖时设置 `JIANG13_WORK_PATH` 指向 `backend/`。 +> **工作目录必须是 `backend/`。** 上传文件与 JWT 密钥落在 `backend/data/`(头像位于 `backend/data/uploads/avatars/`)。在仓库根或 `backend/cmd/jiang13/` 下执行会另建一套 data,导致数据库中的文件 URL 对不上。启动日志应包含 `workPath=.../backend`;需要覆盖时可设置 `JIANG13_WORK_PATH`。 -后端默认监听 `:3001`,首次启动自动执行数据库迁移并写入默认板块。同一时间只跑一个后端进程。 +后端默认监听 `:3001`,首次启动自动执行数据库迁移并写入默认板块。 ### 3. 启动前端 @@ -136,13 +163,17 @@ npm install npm run dev ``` -前端默认监听 `:3000`,通过 `next.config.ts` rewrite 将 `/api/*` 代理到后端。 +前端默认监听 `:3000`,通过 `next.config.ts` 的 rewrite 将 `/api/*` 代理到后端。 + +**空数据库首次注册的账号将自动成为站长。** + +> Windows 用户也可直接使用仓库根目录的 `start.bat`(或 `start.sh`)一键启动开发环境,停止使用 `stop.bat` / `stop.sh`。 --- ## 配置说明 -### 后端(`backend/app.ini`) +### 后端 `backend/app.ini` ```ini [server] @@ -152,108 +183,189 @@ HTTP_PORT = 3001 DSN = postgres://postgres:postgres@localhost:5432/jiang13?sslmode=disable [security] -; 留空则自动生成并持久化到 data/.jwt_secret -; 生产环境务必显式指定强随机值 +; 留空则自动生成并持久化到 data/.jwt_secret;生产环境务必显式指定强随机值 JWT_SECRET = +; 32 字节随机值的标准 Base64(openssl rand -base64 32),用于加密邮件 / S3 凭据 +SETTINGS_MASTER_KEY = [paths] DATA = data [app] DEV_MODE = true +SITE_URL = http://localhost:3000 +CORS_ORIGINS = ``` -环境变量优先级高于 app.ini:`HTTP_PORT`、`DB_DSN`、`JWT_SECRET`、`DEV_MODE`。`JIANG13_WORK_PATH` 可强制指定后端根目录(`app.ini` 与 `data/` 所在处)。 +环境变量优先级高于 `app.ini`:`HTTP_PORT`、`DB_DSN`、`JWT_SECRET`、`SETTINGS_MASTER_KEY`、`DEV_MODE`、`SITE_URL`、`CORS_ORIGINS`、`TRUSTED_PROXIES`。 -### 前端(`frontend/.env.local`) +### 前端 `frontend/.env.local` ```bash -# SSR 与 middleware 直连后端(本地开发) +# SSR 与 middleware 直连后端 NEXT_PUBLIC_API_URL=http://localhost:3001 -# 部署到 Cloudflare Workers 等边缘环境时必须显式配置 +# 仅服务端可见;生产构建必须显式配置 # BACKEND_URL=https://your-backend.example.com + +# 与后端 DEV_MODE 对齐 +DEV_MODE=true +``` + +完整环境变量清单见 [.env.example](./.env.example)、[frontend/.env.example](./frontend/.env.example)。 + +--- + +## Docker 部署 + +官方运行时位于 [`deploy/`](./deploy/),一体交付 **Next.js SSR + Go API + PostgreSQL 17**,不含反向代理(TLS 与同源路由由你的 Nginx / Caddy 处理)。 + +```bash +cd deploy +cp .env.example .env +# 编辑 .env:POSTGRES_PASSWORD、JWT_SECRET、SITE_URL +docker compose up -d --build +``` + +然后将同一 Host 反向代理到容器: + +- `/` → web `:3000` +- `/api/`(含 `/api/ws`)、`/uploads/`、`/health` → api `:3001` + +`GET https://你的域名/health` 返回 `{"status":"ok"}` 即部署成功。 + +详细说明、升级与备份命令见 [deploy/README.md](./deploy/README.md),Nginx 配置示例见 [deploy/nginx.example.conf](./deploy/nginx.example.conf),运行时契约见 [deploy/CONTRACT.md](./deploy/CONTRACT.md)。1Panel 面板部署可参考 [docs/deploy-1panel.md](./docs/deploy-1panel.md)。 + +--- + +## 项目结构 + +``` +jiang13-bbs/ +├── backend/ # Go 后端 +│ ├── cmd/jiang13/ # 程序入口 +│ ├── config/ # 配置解析(app.ini + 环境变量) +│ ├── handler/ # HTTP 处理器 +│ ├── middleware/ # 认证 / CSRF / 限流 / 安全头 / 访问捕获 +│ ├── model/ # GORM 模型与数据库初始化 +│ ├── realtime/ # WebSocket Hub +│ ├── router/ # 路由注册 +│ ├── service/ # 业务逻辑层 +│ ├── markdown/ # Markdown 扩展(隐藏内容等) +│ └── app.ini.example +├── frontend/ # Next.js 前端 +│ ├── app/ # App Router 页面(含 admin 后台) +│ ├── components/ # 通用组件 +│ ├── hooks/ # 自定义 Hooks +│ ├── lib/ # API 封装与工具函数 +│ ├── public/ # 静态资源(表情图等) +│ ├── middleware.ts # SSR 登录态静默轮转 +│ └── next.config.ts # Rewrite 代理 / 图片缓存 +├── deploy/ # 官方运行时(Docker Compose / Dockerfile) +├── docs/ # 文档与截图 +├── docker-compose.yml # 本地开发用(仅 PostgreSQL) +├── start.bat / start.sh # 本地一键启动 +├── VERSION +└── LICENSE ``` --- -## 认证架构 +## 安全设计 -采用三 Cookie + Token Version 方案,不使用 localStorage 存储 token: +采用三 Cookie 方案,令牌不落 localStorage: | Cookie | 用途 | 属性 | |--------|------|------| | `j13_token` | Access JWT(15 分钟) | HttpOnly · SameSite=Lax | -| `j13_refresh` | Refresh Token(7 天,DB 存储 SHA-256) | HttpOnly · SameSite=Lax · Path=/ | +| `j13_refresh` | Refresh Token(7 天,DB 存 SHA-256) | HttpOnly · SameSite=Lax · Path=/ | | `j13_csrf` | CSRF Token(JS 可读) | SameSite=Lax | -- **SSR 直出登录态:** `middleware.ts` 在页面/RSC 请求前本地解码 access token 的 exp,过期时静默调后端 refresh 轮转,新 cookie 注入请求头供 SSR 使用并透传浏览器。 -- **客户端续期:** `lib/api.ts` 的 `fetchWithRefresh` 遇到 401 自动调 `/api/auth/refresh` 重试。 -- **撤销机制:** 改密码 / 封禁 / 管理员强制下线时递增 `User.TokenVersion`,所有旧 JWT 立即失效。 -- **盗用检测:** Refresh Token 一次性轮转,已吊销 token 重放时撤销该用户全部 refresh token。 - -生产 HTTPS 下 cookie 名自动启用 `__Host-` 前缀。 - -若本机曾跑过早期构建,浏览器里可能还留着 `Path=/api/auth` 的 `j13_refresh`(HttpOnly,页面脚本删不掉)。打开开发者工具 → Application → Cookies,删掉该条,或对该源执行「清除站点数据」。之后只应存在 `Path=/` 的三枚 cookie。 +- **SSR 直出登录态**:`middleware.ts` 在渲染前检查 Access Token 过期时间,过期则静默轮转,新 Cookie 同时供 SSR 使用并透传浏览器 +- **Refresh Token 一次性轮转 + 盗用检测**:已吊销 Token 被重放时,撤销该用户全部 Refresh Token +- **Token Version 撤销**:改密 / 封禁 / 强制下线时递增版本号,旧 JWT 立即失效 +- **速率限制**:登录、注册、发帖(新用户 24h 冷静期)、评论、上传等分级限流,管理员豁免 +- **安全响应头**:CSP、HSTS、X-Frame-Options: DENY、X-Content-Type-Options、Referrer-Policy +- 生产 HTTPS 下 Cookie 自动启用 `__Host-` 前缀,要求前后端必须**同源部署**(不能拆分到子域) --- -## 部署 - -**官方运行时是 `deploy/docker-compose.yml`(Next SSR + Go + Postgres,不含反代)。** 说明与升级命令见 [deploy/README.md](./deploy/README.md),Nginx 示例见 [deploy/nginx.example.conf](./deploy/nginx.example.conf),契约见 [deploy/CONTRACT.md](./deploy/CONTRACT.md)。 - -本地开发仍用仓库根 `start.bat` / `start.sh` 与根目录 `docker-compose.yml`(只起 Postgres)。不要把开发流程改成必须打应用镜像。 - -更新应用(镜像已发布时): +## 开发与测试 ```bash -cd deploy -docker compose pull -docker compose up -d +# 后端测试 +cd backend && go test ./... + +# 前端测试(Node 内置 test runner) +cd frontend && npm test + +# 前端代码检查 +npm run lint ``` -后台一键更新、预编译包不在本期。Cloudflare Workers 不是官方运行时。 +开发约定: -### 生产环境要点 - -1. **官方 Compose:** `DEV_MODE=false`,强随机 `JWT_SECRET` 与 `POSTGRES_PASSWORD`;由你现有的 Nginx/Caddy 提供 HTTPS,并把页面与 `/api`、`/api/ws`、`/uploads` 挂到同一 Host。 -2. **CORS 与 Canonical:** 设 `SITE_URL` 为对外 origin(不要改 `router.go` 写死域名)。官方 Compose 会同时注入 api 与 web;web 用它生成 Canonical / sitemap,不要填 `http://api:3001`。 -3. **自管部署:** 仍须同源反代。Workers 前端须保持 `middleware.ts` 文件名(OpenNext 不识别 `proxy.ts`),实时通道由反代承接 `/api/ws`。 - -### WebSocket(开发 vs 生产) - -浏览器发起 WebSocket 握手**一定会带 `Origin`**。后端拒绝空 Origin,这只挡住 curl / 脚本探测,**不影响 `npm run dev`,也不影响生产浏览器**。 - -**开发环境(`DEV_MODE=true`)** - -- 页面在 `http://localhost:3000`,WS 直连 `ws://localhost:3001/api/ws`(Next.js rewrite 不透传 `Upgrade`)。 -- 二者端口不同,不是浏览器意义上的同源。后端因此放行 Origin 主机为 `localhost` / `127.0.0.1` 的**任意端口**。 -- Cookie 不按端口隔离,`:3000` 上的 `j13_token` 会随握手带到 `:3001`。不要把 `DEV_MODE` 改成 `false` 再跑这对端口,否则 Origin `localhost:3000` 对不上 Host `localhost:3001`,握手会被拒。 - -**生产环境(`DEV_MODE=false`)** - -- Origin 的 host(含端口)必须与请求 `Host` **完全一致**。请用 Nginx/Caddy 把前端与 `/api/`、`/api/ws` 挂到同一域名,例如 `https://bbs.example.com`。 -- 反向代理需透传 `Upgrade`、`Connection`,并保留原始 `Host` / `Origin`。 -- 生产 cookie 使用 `__Host-` 前缀,要求 `Secure`、`Path=/`、**不能设 Domain**。因此 API **不能**放到 `api.example.com` 这类另一子域,否则登录 cookie 与 WS 都会失效。 -- Cloudflare Workers / OpenNext **不能**透传任意 WebSocket。若前端部署在 Workers,实时通道必须由同源反代(Nginx 等)承接 `/api/ws`,而不是指望 Workers 升级连接。 -- 可用 `NEXT_PUBLIC_WS_URL` 覆盖前端连线地址;一旦覆盖,Origin 仍须与后端看到的 Host 一致。 +- Next.js 16 中 `params` / `searchParams` / `cookies()` / `headers()` 均需 `await` +- 权限校验只在 Go 后端执行,前端不做判定 +- 配色仅修改 `frontend/app/globals.css` 中的 CSS 令牌,不在组件内硬编码颜色 +- 所有公开页面保持 SSR / ISR,SEO 关键内容必须在初始 HTML 中 --- -## 开发约定 +## 更新日志 -- **Next.js 16:** `params` / `searchParams` / `cookies()` / `headers()` 必须 `await`。 -- **SEO:** 所有公开页面 SSR/ISR,SEO 关键内容(title、description、OG、JSON-LD)必须在初始 HTML 中。 -- **权限:** 权限校验只在 Go 后端执行,前端不做判定。 -- **配色:** 仅修改 `frontend/app/globals.css` 中的 CSS 令牌,禁止在组件内硬编码颜色。 -- **无障碍:** 文字对比度 ≥4.5:1,交互控件边界 ≥3:1(WCAG 2.1 AA)。 +版本发布与部署契约变更记录见 [deploy/CHANGELOG.md](./deploy/CHANGELOG.md),当前版本 **v0.2.9**。 + +--- + +## 贡献指南 + +欢迎提交 Issue 与 Pull Request! + +1. Fork 本仓库并创建特性分支:`git checkout -b feature/your-feature` +2. 提交前请确保测试通过:后端 `go test ./...`,前端 `npm test` +3. 提交代码并推送分支 +4. 在 GitHub 上发起 Pull Request,描述清楚改动内容与动机 + +- 提交信息建议遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范(`feat:` / `fix:` / `docs:` 等) +- 发现安全问题请**不要**直接提 Issue,发送邮件至 aarbbs@88.com 私下反馈 --- ## 许可证 -**专有软件(Proprietary)** — Copyright © 2026 姜十三,保留所有权利。 +本项目基于 [Apache License 2.0](./LICENSE) 开源。 -源码仅可见,未经书面许可不得使用、部署、修改或分发。详见 [LICENSE](./LICENSE)。 +``` +Copyright 2026 姜十三 -联系方式:aarbbs@88.com +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +``` + +--- + +## 联系方式 + +- QQ:97975089 + +- 邮箱:97975089@qq.com + +- Issue:[GitHub Issues](https://github.com/aarbbs/jiang13-bbs/issues) + +--- + +## 赞赏支持 + +如果本项目对你有帮助,欢迎请作者喝杯咖啡 ☕,你的支持是持续维护的动力。 + +

+ 微信打赏 +      + 支付宝打赏 +

+ +

微信打赏   |   支付宝打赏

diff --git a/backend/handler/chat.go b/backend/handler/chat.go index 49c2010..f13d0a9 100644 --- a/backend/handler/chat.go +++ b/backend/handler/chat.go @@ -4,6 +4,7 @@ import ( "errors" "net/http" "strconv" + "strings" "time" "github.com/freefire/jiang13-bbs/middleware" @@ -240,11 +241,32 @@ func (h *Handlers) JoinChatRoom(c *gin.Context) { if !ok { return } - _, _, err := h.Chat.Join(claims.ID, roomID) + member, joined, err := h.Chat.Join(claims.ID, roomID) if err != nil { c.JSON(chatErrToStatus(err), gin.H{"error": err.Error()}) return } + // 首次加入则向房间广播系统提示 + 成员变更 + if joined && member != nil { + displayName := h.Chat.DisplayName(claims.ID) + if displayName != "" { + sysMsg, _ := h.Chat.SendSystemMessage(roomID, displayName+" 加入了群聊") + if sysMsg != nil && sysMsg.ID > 0 { + h.Hub.BroadcastRoom(realtime.RoomChat(roomID), realtime.Envelope{ + Type: realtime.EventChatMessage, + Data: sysMsg, + }) + } + } + h.Hub.BroadcastRoom(realtime.RoomChat(roomID), realtime.Envelope{ + Type: realtime.EventChatMembership, + Data: gin.H{ + "room_id": roomID, + "status": "joined", + "user_id": claims.ID, + }, + }) + } c.JSON(http.StatusOK, gin.H{"ok": true}) } @@ -300,6 +322,35 @@ func (h *Handlers) InviteChatMembers(c *gin.Context) { Data: gin.H{"room_id": roomID, "status": "invited"}, }) } + // 被邀请者入群时向房间广播系统提示 + 成员变更 + if len(added) > 0 { + var names []string + for _, uid := range added { + if n := h.Chat.DisplayName(uid); n != "" { + names = append(names, n) + } + } + if len(names) > 0 { + content := strings.Join(names, "、") + " 加入了群聊" + sysMsg, _ := h.Chat.SendSystemMessage(roomID, content) + if sysMsg != nil && sysMsg.ID > 0 { + h.Hub.BroadcastRoom(realtime.RoomChat(roomID), realtime.Envelope{ + Type: realtime.EventChatMessage, + Data: sysMsg, + }) + } + } + for _, uid := range added { + h.Hub.BroadcastRoom(realtime.RoomChat(roomID), realtime.Envelope{ + Type: realtime.EventChatMembership, + Data: gin.H{ + "room_id": roomID, + "status": "joined", + "user_id": uid, + }, + }) + } + } c.JSON(http.StatusOK, gin.H{"added": added}) } diff --git a/backend/handler/handlers.go b/backend/handler/handlers.go index 6217744..a784a56 100644 --- a/backend/handler/handlers.go +++ b/backend/handler/handlers.go @@ -42,6 +42,7 @@ type Handlers struct { Badge *service.BadgeService LeaderboardSvc *service.LeaderboardService LibrarySvc *service.LibraryService + SnippetSvc *service.SnippetService } // resolvePublishStatus 决定新帖/新评的初始状态: diff --git a/backend/handler/snippet.go b/backend/handler/snippet.go new file mode 100644 index 0000000..f96b7fd --- /dev/null +++ b/backend/handler/snippet.go @@ -0,0 +1,424 @@ +package handler + +import ( + "errors" + "net/http" + "strconv" + + "github.com/freefire/jiang13-bbs/middleware" + "github.com/freefire/jiang13-bbs/model" + "github.com/freefire/jiang13-bbs/service" + "github.com/gin-gonic/gin" +) + +// snippetError 统一错误映射 +func snippetError(c *gin.Context, err error) { + switch { + case errors.Is(err, service.ErrSnippetNotFound): + c.JSON(http.StatusNotFound, gin.H{"error": "代码片段不存在"}) + case errors.Is(err, service.ErrSnippetForbidden): + c.JSON(http.StatusForbidden, gin.H{"error": "无权操作该代码片段"}) + case errors.Is(err, service.ErrSnippetBadInput): + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + case errors.Is(err, service.ErrCommentNotFound): + c.JSON(http.StatusNotFound, gin.H{"error": "评论不存在"}) + case errors.Is(err, service.ErrCommentForbidden): + c.JSON(http.StatusForbidden, gin.H{"error": "无权操作该评论"}) + default: + c.JSON(http.StatusInternalServerError, gin.H{"error": "服务器错误"}) + } +} + +// SnippetList 公开片段广场 +func (h *Handlers) SnippetList(c *gin.Context) { + q := c.Query("q") + lang := c.Query("lang") + sort := c.Query("sort") + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + size, _ := strconv.Atoi(c.DefaultQuery("size", "12")) + items, total, err := h.SnippetSvc.ListPublic(q, lang, sort, page, size) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "获取片段列表失败"}) + return + } + c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total}) +} + +// SnippetLanguages 语言白名单 +func (h *Handlers) SnippetLanguages(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"languages": service.SnippetLanguages()}) +} + +// SnippetStats 广场聚合统计 +func (h *Handlers) SnippetStats(c *gin.Context) { + stats, err := h.SnippetSvc.Stats() + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "获取统计失败"}) + return + } + c.JSON(http.StatusOK, gin.H{"stats": stats}) +} + +// SnippetDetail 公开片段详情 +func (h *Handlers) SnippetDetail(c *gin.Context) { + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + var viewerID uint + if claims := middleware.CurrentUser(c); claims != nil { + viewerID = claims.ID + } + isStaff := h.isStaff(c) + detail, err := h.SnippetSvc.GetPublic(uint(id), viewerID, isStaff) + if err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusOK, gin.H{"snippet": detail}) +} + +// SnippetMine 我的片段列表 +func (h *Handlers) SnippetMine(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + q := c.Query("q") + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + size, _ := strconv.Atoi(c.DefaultQuery("size", "12")) + items, total, err := h.SnippetSvc.ListMine(claims.ID, q, page, size) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "获取片段列表失败"}) + return + } + c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total}) +} + +// SnippetCreate 创建片段 +func (h *Handlers) SnippetCreate(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + var in service.SnippetInput + if err := c.ShouldBindJSON(&in); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"}) + return + } + snippet, err := h.SnippetSvc.Create(&in, claims.ID) + if err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusCreated, gin.H{"snippet": snippet}) +} + +// SnippetUpdate 更新片段 +func (h *Handlers) SnippetUpdate(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + var in service.SnippetInput + if err := c.ShouldBindJSON(&in); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"}) + return + } + snippet, err := h.SnippetSvc.Update(uint(id), &in, claims.ID, h.isStaff(c)) + if err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusOK, gin.H{"snippet": snippet}) +} + +// SnippetDelete 删除片段(owner 或 staff) +func (h *Handlers) SnippetDelete(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + if err := h.SnippetSvc.Delete(uint(id), claims.ID, h.isStaff(c)); err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusOK, gin.H{"ok": true}) +} + +// SnippetFork Fork 公开片段 +func (h *Handlers) SnippetFork(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + snippet, err := h.SnippetSvc.Fork(uint(id), claims.ID) + if err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusCreated, gin.H{"snippet": snippet}) +} + +// SnippetCopy 记录复制(节流由 service 内部处理) +func (h *Handlers) SnippetCopy(c *gin.Context) { + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + key := c.ClientIP() + if claims := middleware.CurrentUser(c); claims != nil { + key = "user:" + strconv.FormatUint(uint64(claims.ID), 10) + } + if err := h.SnippetSvc.RecordCopy(uint(id), key); err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusOK, gin.H{"ok": true}) +} + +// SnippetHistory 片段编辑历史 +func (h *Handlers) SnippetHistory(c *gin.Context) { + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + size, _ := strconv.Atoi(c.DefaultQuery("size", "10")) + items, total, err := h.SnippetSvc.ListHistory(uint(id), page, size) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "获取历史失败"}) + return + } + c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total}) +} + +// SnippetForks 公开 fork 列表 +func (h *Handlers) SnippetForks(c *gin.Context) { + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + size, _ := strconv.Atoi(c.DefaultQuery("size", "12")) + items, total, err := h.SnippetSvc.ListForks(uint(id), page, size) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "获取 Fork 列表失败"}) + return + } + c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total}) +} + +// SnippetComments 片段评论列表 +func (h *Handlers) SnippetComments(c *gin.Context) { + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + size, _ := strconv.Atoi(c.DefaultQuery("size", "20")) + items, total, err := h.SnippetSvc.ListComments(uint(id), page, size) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "获取评论失败"}) + return + } + c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total}) +} + +// SnippetCommentCreate 创建片段评论 +func (h *Handlers) SnippetCommentCreate(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + snippetID, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + var in struct { + Content string `json:"content"` + ParentID *uint `json:"parent_id"` + } + if err := c.ShouldBindJSON(&in); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"}) + return + } + comment, err := h.SnippetSvc.CreateComment(claims.ID, uint(snippetID), in.Content, in.ParentID) + if err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusCreated, gin.H{"comment": comment}) +} + +// SnippetCommentUpdate 更新片段评论 +func (h *Handlers) SnippetCommentUpdate(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + cid, err := strconv.ParseUint(c.Param("cid"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的评论 ID"}) + return + } + var in struct { + Content string `json:"content"` + } + if err := c.ShouldBindJSON(&in); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"}) + return + } + comment, err := h.SnippetSvc.UpdateComment(uint(cid), claims.ID, in.Content) + if err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusOK, gin.H{"comment": comment}) +} + +// SnippetCommentDelete 删除片段评论 +func (h *Handlers) SnippetCommentDelete(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + cid, err := strconv.ParseUint(c.Param("cid"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的评论 ID"}) + return + } + if err := h.SnippetSvc.DeleteComment(uint(cid), claims.ID, h.isStaff(c)); err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusOK, gin.H{"ok": true}) +} + +// SnippetCommentHistory 片段评论编辑历史(登录即可见;分页) +func (h *Handlers) SnippetCommentHistory(c *gin.Context) { + claims := middleware.CurrentUser(c) + cid, err := strconv.ParseUint(c.Param("cid"), 10, 64) + if err != nil || cid == 0 { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的评论 ID"}) + return + } + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + size, _ := strconv.Atoi(c.DefaultQuery("size", "10")) + items, total, err := h.SnippetSvc.ListCommentHistory(h.loadActor(claims.ID), uint(cid), page, size) + if err != nil { + switch { + case errors.Is(err, service.ErrCommentNotFound): + c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) + case errors.Is(err, service.ErrCommentForbidden): + c.JSON(http.StatusForbidden, gin.H{"error": err.Error()}) + default: + c.JSON(http.StatusInternalServerError, gin.H{"error": "获取编辑历史失败"}) + } + return + } + if page < 1 { + page = 1 + } + if size < 1 || size > 50 { + size = 10 + } + c.JSON(http.StatusOK, gin.H{ + "items": items, + "total": total, + "page": page, + "size": size, + }) +} + +// AdminSnippetList 管理端片段列表 +func (h *Handlers) AdminSnippetList(c *gin.Context) { + q := c.Query("q") + visibility := c.Query("visibility") + page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) + size, _ := strconv.Atoi(c.DefaultQuery("size", "20")) + items, total, err := h.SnippetSvc.AdminList(q, visibility, page, size) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "获取片段列表失败"}) + return + } + c.JSON(http.StatusOK, gin.H{"items": nonNilSlice(items), "total": total}) +} + +// AdminSnippetDelete 管理端软删片段 +func (h *Handlers) AdminSnippetDelete(c *gin.Context) { + claims := middleware.CurrentUser(c) + if claims == nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"}) + return + } + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + if err := h.SnippetSvc.AdminDelete(uint(id), claims.ID); err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusOK, gin.H{"ok": true}) +} + +// AdminSnippetSetVisibility 管理端强制修改可见性 +func (h *Handlers) AdminSnippetSetVisibility(c *gin.Context) { + id, err := strconv.ParseUint(c.Param("id"), 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "无效的片段 ID"}) + return + } + var in struct { + Visibility string `json:"visibility"` + } + if err := c.ShouldBindJSON(&in); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效"}) + return + } + if err := h.SnippetSvc.AdminSetVisibility(uint(id), in.Visibility); err != nil { + snippetError(c, err) + return + } + c.JSON(http.StatusOK, gin.H{"ok": true}) +} + +// isStaff 判断当前用户是否为管理角色 +func (h *Handlers) isStaff(c *gin.Context) bool { + claims := middleware.CurrentUser(c) + if claims == nil { + return false + } + return model.IsStaff(model.Role(claims.Role)) +} diff --git a/backend/model/db.go b/backend/model/db.go index d4c5428..9c659d3 100644 --- a/backend/model/db.go +++ b/backend/model/db.go @@ -64,6 +64,7 @@ func InitDB(dsn string) error { &Badge{}, &UserBadge{}, &PostPollVote{}, &PostLotteryEntry{}, &Ad{}, &SidebarWidget{}, &FriendLink{}, &ImportRecord{}, &LibraryDoc{}, &LibraryFile{}, &LibrarySection{}, + &CodeSnippet{}, &SnippetVersion{}, &SnippetComment{}, &SnippetCommentEditHistory{}, ); err != nil { return fmt.Errorf("自动迁移失败: %w", err) } diff --git a/backend/model/models.go b/backend/model/models.go index c623704..c927ac3 100644 --- a/backend/model/models.go +++ b/backend/model/models.go @@ -576,6 +576,75 @@ type LibrarySection struct { DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` } +// CodeSnippet 代码片段:用户所有,公开进广场,私有仅自己可见 +type CodeSnippet struct { + ID uint `gorm:"primaryKey" json:"id"` + Title string `gorm:"size:120;not null" json:"title"` + Description string `gorm:"type:text" json:"description"` + Language string `gorm:"size:32;not null;index" json:"language"` + Code string `gorm:"type:text;not null" json:"code"` + Visibility string `gorm:"size:16;not null;default:private;index" json:"visibility"` // public/private + UserID uint `gorm:"index;not null" json:"user_id"` + ForkedFromID *uint `gorm:"index" json:"forked_from_id"` + CopyCount int `gorm:"not null;default:0" json:"copy_count"` + ViewCount int `gorm:"not null;default:0" json:"view_count"` + CommentCount int `gorm:"not null;default:0" json:"comment_count"` + ForkCount int `gorm:"not null;default:0" json:"fork_count"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +// SnippetVersion 编辑前旧值快照(同 PostEditHistory 思路) +type SnippetVersion struct { + ID uint `gorm:"primaryKey" json:"id"` + SnippetID uint `gorm:"index;not null" json:"snippet_id"` + EditorID uint `gorm:"index;not null" json:"editor_id"` + OldTitle string `gorm:"size:120;not null;default:''" json:"old_title"` + OldLanguage string `gorm:"size:32;not null;default:''" json:"old_language"` + OldDescription string `gorm:"type:text" json:"old_description"` + OldCode string `gorm:"type:text;not null" json:"old_code"` + CreatedAt time.Time `gorm:"index" json:"created_at"` +} + +// SnippetComment 片段评论(楼层树:ParentID 空=主评,非空=回复;RootID=所属主楼) +type SnippetComment struct { + ID uint `gorm:"primaryKey" json:"id"` + SnippetID uint `gorm:"index;not null" json:"snippet_id"` + UserID uint `gorm:"index;not null" json:"user_id,omitempty"` + ParentID *uint `gorm:"index" json:"parent_id"` + RootID *uint `gorm:"index" json:"root_id"` + Depth int `gorm:"not null;default:0" json:"depth"` + Content string `gorm:"type:text;not null" json:"content"` + DeleteType string `gorm:"size:32;default:''" json:"delete_type,omitempty"` + DeletedBy uint `gorm:"not null;default:0" json:"deleted_by,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` +} + +// SnippetCommentEditHistory 片段评论修订快照(每次编辑前的旧正文;登录用户可见) +type SnippetCommentEditHistory struct { + ID uint `gorm:"primaryKey" json:"id"` + CommentID uint `gorm:"index;not null" json:"comment_id"` + EditorID uint `gorm:"index;not null" json:"editor_id"` + OldContent string `gorm:"type:text;not null" json:"old_content"` + CreatedAt time.Time `gorm:"index" json:"created_at"` +} + +const ( + SnippetVisibilityPublic = "public" + SnippetVisibilityPrivate = "private" +) + +// NormalizeSnippetVisibility 归一化可见性:空或未知值一律回落 private +func NormalizeSnippetVisibility(v string) string { + if v == SnippetVisibilityPublic { + return SnippetVisibilityPublic + } + return SnippetVisibilityPrivate +} + // SiteSetting 站点级键值设置(如历史在线峰值 peak_online) type SiteSetting struct { Key string `gorm:"primaryKey;size:64" json:"key"` diff --git a/backend/router/router.go b/backend/router/router.go index 5e9219f..f1e486f 100644 --- a/backend/router/router.go +++ b/backend/router/router.go @@ -104,6 +104,7 @@ func Setup(cfg *config.Config) (*gin.Engine, error) { librarySvc := service.NewLibraryService(model.DB, cfg.DataDir). WithSetting(settingSvc). WithUploadsDir(filepath.Join(cfg.DataDir, "uploads")) + snippetSvc := service.NewSnippetService(model.DB) adminUserSvc := service.NewAdminUserService(model.DB) legacyImportSvc := service.NewLegacyImportService(model.DB, filepath.Join(cfg.DataDir, "uploads")) moderationSvc := service.NewModerationService(model.DB, notifSvc) @@ -165,6 +166,7 @@ func Setup(cfg *config.Config) (*gin.Engine, error) { Badge: badgeSvc, LeaderboardSvc: leaderboardSvc, LibrarySvc: librarySvc, + SnippetSvc: snippetSvc, } // 通知落库后统一推 WS 红点(点赞/评论/审核/@ 等共用) notifSvc.OnNotifyNew = func(userID uint) { @@ -229,6 +231,13 @@ func Setup(cfg *config.Config) (*gin.Engine, error) { pubAPI.GET("/library", h.LibraryList) pubAPI.GET("/library/:slug", h.LibraryDetail) pubAPI.GET("/library/files/:fid/download", h.LibraryFileDownload) + // 代码片段(公开广场/详情/评论/Fork 列表) + pubAPI.GET("/snippets", h.SnippetList) + pubAPI.GET("/snippets/languages", h.SnippetLanguages) + pubAPI.GET("/snippets/stats", h.SnippetStats) + pubAPI.GET("/snippets/:id", h.SnippetDetail) + pubAPI.GET("/snippets/:id/comments", h.SnippetComments) + pubAPI.GET("/snippets/:id/forks", h.SnippetForks) pubAPI.GET("/site-state", h.SiteState) // 自适应图片变体(?u=<源图URL>&w=<白名单宽度>,公开只读、immutable 缓存) pubAPI.GET("/img", h.ImageVariant) @@ -308,6 +317,19 @@ func Setup(cfg *config.Config) (*gin.Engine, error) { // 时间线:从 Git releases 页导入更新日志 api.POST("/timeline/from-releases", middleware.StaffExempt(middleware.RateLimitUserMiddleware(limiter, service.RateTimelineGit)), h.TimelineFromReleases) + // 代码片段(登录区) + api.POST("/snippets", middleware.StaffExempt(middleware.RateLimitMiddleware(limiter, service.RateSnippet)), h.SnippetCreate) + api.GET("/snippets/mine", h.SnippetMine) + api.PUT("/snippets/:id", h.SnippetUpdate) + api.DELETE("/snippets/:id", h.SnippetDelete) + api.POST("/snippets/:id/fork", middleware.StaffExempt(middleware.RateLimitMiddleware(limiter, service.RateSnippet)), h.SnippetFork) + api.POST("/snippets/:id/copy", h.SnippetCopy) + api.GET("/snippets/:id/history", h.SnippetHistory) + api.POST("/snippets/:id/comments", middleware.StaffExempt(middleware.RateLimitMiddleware(limiter, service.RateComment)), h.SnippetCommentCreate) + api.PUT("/snippets/:id/comments/:cid", middleware.StaffExempt(middleware.RateLimitMiddleware(limiter, service.RateComment)), h.SnippetCommentUpdate) + api.DELETE("/snippets/:id/comments/:cid", h.SnippetCommentDelete) + api.GET("/snippets/:id/comments/:cid/history", h.SnippetCommentHistory) + // 群聊(二期):建群/成员/消息/未读;全站关闭消息时前台一律 403 chatAPI := api.Group("/chat", h.RequireMessagesOpen) { @@ -508,6 +530,11 @@ func Setup(cfg *config.Config) (*gin.Engine, error) { usersAPI.GET("/users/:id/messages", h.AdminUserAuditMessages) } + // 代码片段管理(任意 staff) + staffAPI.GET("/snippets", h.AdminSnippetList) + staffAPI.DELETE("/snippets/:id", h.AdminSnippetDelete) + staffAPI.PUT("/snippets/:id/visibility", h.AdminSnippetSetVisibility) + // 板块管理(仅站长):增删改、排序、版主授权 boardsAPI := staffAPI.Group("", authMW.RequirePerm(service.PermBoards)) { diff --git a/backend/service/chat.go b/backend/service/chat.go index 9e24efa..5acebdc 100644 --- a/backend/service/chat.go +++ b/backend/service/chat.go @@ -767,6 +767,18 @@ func (s *ChatService) Kick(operatorID, roomID, targetID uint, oversee bool) erro return s.removeMember(roomID, targetID) } +// DisplayName 取用户群聊展示名(昵称优先,退回用户名);用户不存在/封禁时返回空串 +func (s *ChatService) DisplayName(userID uint) string { + var u model.User + if err := s.db.Select("id", "nickname", "username").First(&u, userID).Error; err != nil { + return "" + } + if u.Nickname != "" { + return u.Nickname + } + return u.Username +} + // SendSystemMessage 向房间落库一条系统提示消息(sender_id=0,is_system=true)。 // 只推进房间 updated_at,不推进 last_message_id:系统提示不作为会话预览, // 也不参与排序顶置,避免禁言/解禁等管理动作在会话列表伪装成「新消息」。 diff --git a/backend/service/header_nav.go b/backend/service/header_nav.go index eee8e73..dde66a7 100644 --- a/backend/service/header_nav.go +++ b/backend/service/header_nav.go @@ -24,7 +24,7 @@ const ( // HeaderNavBuiltinKeys 内置菜单 key 白名单(顺序即默认顺序); // 与前端 lib/headerNav.ts 的 HEADER_NAV_BUILTIN_KEYS 保持一致。 -var HeaderNavBuiltinKeys = []string{"home", "leaderboard", "library"} +var HeaderNavBuiltinKeys = []string{"home", "leaderboard", "library", "snippets"} // HeaderNavItem 顶部导航菜单项: // diff --git a/backend/service/header_nav_test.go b/backend/service/header_nav_test.go index 72df41b..02f5703 100644 --- a/backend/service/header_nav_test.go +++ b/backend/service/header_nav_test.go @@ -25,18 +25,19 @@ func newHeaderNavTestService(t *testing.T) *SettingService { func TestHeaderNavDefaultWhenMissing(t *testing.T) { s := newHeaderNavTestService(t) got := s.HeaderNav() - if len(got) != 3 || + if len(got) != 4 || got[0] != (HeaderNavItem{Type: HeaderNavItemBuiltin, Key: "home"}) || got[1] != (HeaderNavItem{Type: HeaderNavItemBuiltin, Key: "leaderboard"}) || - got[2] != (HeaderNavItem{Type: HeaderNavItemBuiltin, Key: "library"}) { + got[2] != (HeaderNavItem{Type: HeaderNavItemBuiltin, Key: "library"}) || + got[3] != (HeaderNavItem{Type: HeaderNavItemBuiltin, Key: "snippets"}) { t.Fatalf("missing row should fall back to builtin defaults, got %+v", got) } pub, err := s.Public() if err != nil { t.Fatal(err) } - if len(pub.HeaderNav) != 3 { - t.Fatalf("Public().HeaderNav len = %d, want 3", len(pub.HeaderNav)) + if len(pub.HeaderNav) != 4 { + t.Fatalf("Public().HeaderNav len = %d, want 4", len(pub.HeaderNav)) } } @@ -133,7 +134,7 @@ func TestNormalizeHeaderNavDedupesBuiltins(t *testing.T) { func TestParseHeaderNavJSONTolerant(t *testing.T) { // 坏 JSON 回落默认 - if got := parseHeaderNavJSON("{bad"); len(got) != 3 { + if got := parseHeaderNavJSON("{bad"); len(got) != 4 { t.Fatalf("bad json should fall back to defaults, got %+v", got) } // 空数组 = 全部隐藏 diff --git a/backend/service/ratelimit.go b/backend/service/ratelimit.go index dbdbdb5..5fb9aa0 100644 --- a/backend/service/ratelimit.go +++ b/backend/service/ratelimit.go @@ -85,6 +85,7 @@ const ( RateAdSubmit = "ad_submit" // 广告申购 5/分钟(按 IP) RateCaptcha = "captcha" // 验证码刷新 30/分钟 RateTelemetry = "telemetry" // 页面浏览埋点 120/分钟(按 IP) + RateSnippet = "snippet" // 代码片段创建/Fork 10/分钟 ) // DefaultRateLimiter 创建默认速率限制器 @@ -102,5 +103,6 @@ func DefaultRateLimiter() *RateLimiter { rl.SetLimit(RateAdSubmit, 5) // 广告申购 5/分钟 rl.SetLimit(RateCaptcha, 30) // 验证码 30/分钟 rl.SetLimit(RateTelemetry, 120) // 埋点 120/分钟 + rl.SetLimit(RateSnippet, 10) // 代码片段 10/分钟 return rl } diff --git a/backend/service/snippet.go b/backend/service/snippet.go new file mode 100644 index 0000000..c2338dc --- /dev/null +++ b/backend/service/snippet.go @@ -0,0 +1,1022 @@ +package service + +import ( + "errors" + "fmt" + "strings" + "sync" + "time" + "unicode/utf8" + + "github.com/freefire/jiang13-bbs/model" + "gorm.io/gorm" +) + +// 代码片段语言白名单(与前端 highlight.js 注册表对齐) +var snippetLanguages = map[string]struct{}{ + "plaintext": {}, "bash": {}, "c": {}, "cpp": {}, "csharp": {}, "css": {}, + "dart": {}, "diff": {}, "dockerfile": {}, "go": {}, "graphql": {}, "html": {}, + "ini": {}, "java": {}, "javascript": {}, "json": {}, "jsonc": {}, "jsx": {}, + "kotlin": {}, "lua": {}, "makefile": {}, "markdown": {}, "nginx": {}, "php": {}, + "powershell": {}, "prisma": {}, "python": {}, "r": {}, "regex": {}, "ruby": {}, + "rust": {}, "scss": {}, "shell": {}, "sql": {}, "swift": {}, "toml": {}, + "tsx": {}, "typescript": {}, "vue": {}, "xml": {}, "yaml": {}, +} + +const ( + snippetTitleMaxRunes = 120 + snippetDescMaxBytes = 8 << 10 // 8KB + snippetCodeMaxBytes = 64 << 10 // 64KB + snippetCommentMaxLen = 2000 + snippetCopyThrottle = 10 * time.Second +) + +var ( + ErrSnippetNotFound = errors.New("代码片段不存在") + ErrSnippetForbidden = errors.New("无权操作该代码片段") + ErrSnippetBadInput = errors.New("代码片段参数无效") +) + +// SnippetLanguages 返回支持的语言白名单(排序固定,便于前端渲染) +func SnippetLanguages() []string { + out := make([]string, 0, len(snippetLanguages)) + for k := range snippetLanguages { + out = append(out, k) + } + // 固定排序:plaintext 置顶,其余按字典序 + plaintext := []string{"plaintext"} + var rest []string + for _, v := range out { + if v != "plaintext" { + rest = append(rest, v) + } + } + for i := 0; i < len(rest)-1; i++ { + for j := i + 1; j < len(rest); j++ { + if rest[i] > rest[j] { + rest[i], rest[j] = rest[j], rest[i] + } + } + } + return append(plaintext, rest...) +} + +// normalizeSnippetLanguage 空值回落 plaintext,不在白名单则报错 +func normalizeSnippetLanguage(lang string) (string, error) { + lang = strings.ToLower(strings.TrimSpace(lang)) + if lang == "" { + return "plaintext", nil + } + if _, ok := snippetLanguages[lang]; !ok { + return "", ErrSnippetBadInput + } + return lang, nil +} + +// SnippetInput 创建/更新代码片段入参 +type SnippetInput struct { + Title string `json:"title"` + Language string `json:"language"` + Description string `json:"description"` + Code string `json:"code"` + Visibility string `json:"visibility"` +} + +// badInput 输入校验错误(wrap ErrSnippetBadInput,handler 据此返回 400) +func badInput(msg string) error { + return fmt.Errorf("%w: %s", ErrSnippetBadInput, msg) +} + +func (in *SnippetInput) normalize() error { + in.Title = strings.TrimSpace(in.Title) + if in.Title == "" { + return badInput("标题不能为空") + } + if utf8.RuneCountInString(in.Title) > snippetTitleMaxRunes { + return badInput("标题不能超过 120 字") + } + lang, err := normalizeSnippetLanguage(in.Language) + if err != nil { + return badInput("不支持的语言") + } + in.Language = lang + if strings.TrimSpace(in.Code) == "" { + return badInput("代码不能为空") + } + if len(in.Code) > snippetCodeMaxBytes { + return badInput("代码不能超过 64KB") + } + in.Description = strings.TrimSpace(in.Description) + if len(in.Description) > snippetDescMaxBytes { + return badInput("描述不能超过 8KB") + } + in.Visibility = model.NormalizeSnippetVisibility(in.Visibility) + return nil +} + +// SnippetOwner 片段所有者摘要 +type SnippetOwner struct { + ID uint `json:"id"` + Username string `json:"username"` + Nickname string `json:"nickname"` + Avatar string `json:"avatar"` +} + +// SnippetForkedFrom 源片段摘要 +type SnippetForkedFrom struct { + ID uint `json:"id"` + Title string `json:"title"` +} + +// SnippetDetail 片段详情(含所有者与源片段摘要) +type SnippetDetail struct { + model.CodeSnippet + User *SnippetOwner `json:"user,omitempty"` + ForkedFrom *SnippetForkedFrom `json:"forked_from,omitempty"` +} + +// SnippetListItem 广场/我的列表项(不含 code 全文,仅前 300 字符作预览) +type SnippetListItem struct { + ID uint `json:"id"` + Title string `json:"title"` + Language string `json:"language"` + Description string `json:"description"` + Preview string `json:"preview"` // code 前 300 字符 + Visibility string `json:"visibility"` + UserID uint `json:"user_id"` + CopyCount int `json:"copy_count"` + ViewCount int `json:"view_count"` + CommentCount int `json:"comment_count"` + ForkCount int `json:"fork_count"` + ForkedFromID *uint `json:"forked_from_id,omitempty"` + User *SnippetOwner `json:"user,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// SnippetCommentNode 片段评论节点(主评带 replies,软删 tombstone 占位) +type SnippetCommentNode struct { + model.SnippetComment + Floor int `json:"floor"` // 主评楼层号(含软删) + Deleted bool `json:"deleted"` // 软删标记 + Edited bool `json:"edited"` // 相对创建已编辑 + User *SnippetOwner `json:"user,omitempty"` + Replies []SnippetCommentNode `json:"replies,omitempty"` +} + +// SnippetService 代码片段服务 +type SnippetService struct { + db *gorm.DB + copyMu sync.Mutex + copyRecords map[string]time.Time // key=userID 或 IP,10s 内只计一次 + statsMu sync.Mutex + statsCache *SnippetStats + statsAt time.Time +} + +func NewSnippetService(db *gorm.DB) *SnippetService { + return &SnippetService{db: db, copyRecords: make(map[string]time.Time)} +} + +// escapeILike 转义 ILIKE 特殊字符 % 和 _ +func escapeILike(s string) string { + s = strings.ReplaceAll(s, `\`, `\\`) + s = strings.ReplaceAll(s, `%`, `\%`) + s = strings.ReplaceAll(s, `_`, `\_`) + return s +} + +// SnippetLangStat 语言分布项 +type SnippetLangStat struct { + Language string `json:"language"` + Count int64 `json:"count"` +} + +// SnippetStats 片段广场聚合统计(仅公开片段) +type SnippetStats struct { + TotalSnippets int64 `json:"total_snippets"` + TotalCopies int64 `json:"total_copies"` + TotalViews int64 `json:"total_views"` + TotalComments int64 `json:"total_comments"` + TotalForks int64 `json:"total_forks"` + Contributors int64 `json:"contributors"` + TopLanguages []SnippetLangStat `json:"top_languages"` +} + +const snippetStatsTTL = 30 * time.Second + +// Stats 广场聚合统计(30s 内存缓存) +func (s *SnippetService) Stats() (*SnippetStats, error) { + s.statsMu.Lock() + if s.statsCache != nil && time.Since(s.statsAt) < snippetStatsTTL { + cached := s.statsCache + s.statsMu.Unlock() + return cached, nil + } + s.statsMu.Unlock() + + pub := func() *gorm.DB { + return s.db.Model(&model.CodeSnippet{}).Where("visibility = ?", model.SnippetVisibilityPublic) + } + + var agg struct { + Total int64 + Copies int64 + Views int64 + Comments int64 + Forks int64 + } + if err := pub(). + Select("COUNT(*) AS total, COALESCE(SUM(copy_count),0) AS copies, COALESCE(SUM(view_count),0) AS views, COALESCE(SUM(comment_count),0) AS comments, COALESCE(SUM(fork_count),0) AS forks"). + Scan(&agg).Error; err != nil { + return nil, err + } + + var contributors int64 + if err := pub().Distinct("user_id").Count(&contributors).Error; err != nil { + return nil, err + } + + langs := make([]SnippetLangStat, 0, 6) + if err := pub(). + Select("language, COUNT(*) AS count"). + Group("language"). + Order("count DESC, language ASC"). + Limit(6). + Scan(&langs).Error; err != nil { + return nil, err + } + + st := &SnippetStats{ + TotalSnippets: agg.Total, + TotalCopies: agg.Copies, + TotalViews: agg.Views, + TotalComments: agg.Comments, + TotalForks: agg.Forks, + Contributors: contributors, + TopLanguages: langs, + } + + s.statsMu.Lock() + s.statsCache = st + s.statsAt = time.Now() + s.statsMu.Unlock() + return st, nil +} + +// toListItem 模型转列表项(截断 code 生成 preview) +func toSnippetListItem(s model.CodeSnippet, owner *SnippetOwner) SnippetListItem { + preview := s.Code + if len(preview) > 300 { + preview = preview[:300] + } + return SnippetListItem{ + ID: s.ID, + Title: s.Title, + Language: s.Language, + Description: s.Description, + Preview: preview, + Visibility: s.Visibility, + UserID: s.UserID, + CopyCount: s.CopyCount, + ViewCount: s.ViewCount, + CommentCount: s.CommentCount, + ForkCount: s.ForkCount, + ForkedFromID: s.ForkedFromID, + User: owner, + CreatedAt: s.CreatedAt, + UpdatedAt: s.UpdatedAt, + } +} + +// ownerMap 批量取所有者摘要(避免 N+1) +func (s *SnippetService) ownerMap(ids []uint) map[uint]*SnippetOwner { + if len(ids) == 0 { + return map[uint]*SnippetOwner{} + } + uniq := make([]uint, 0, len(ids)) + seen := map[uint]bool{} + for _, id := range ids { + if !seen[id] { + seen[id] = true + uniq = append(uniq, id) + } + } + var users []model.User + if err := s.db.Select("id, username, nickname, avatar").Where("id IN ?", uniq).Find(&users).Error; err != nil { + return map[uint]*SnippetOwner{} + } + m := make(map[uint]*SnippetOwner, len(users)) + for i := range users { + u := &users[i] + m[u.ID] = &SnippetOwner{ID: u.ID, Username: u.Username, Nickname: u.Nickname, Avatar: u.Avatar} + } + return m +} + +// Create 创建代码片段 +func (s *SnippetService) Create(in *SnippetInput, userID uint) (*model.CodeSnippet, error) { + if err := in.normalize(); err != nil { + return nil, err + } + snippet := &model.CodeSnippet{ + Title: in.Title, + Language: in.Language, + Description: in.Description, + Code: in.Code, + Visibility: in.Visibility, + UserID: userID, + } + if err := s.db.Create(snippet).Error; err != nil { + return nil, err + } + return snippet, nil +} + +// Update 更新代码片段(仅 owner 或 staff;编辑前落 SnippetVersion) +func (s *SnippetService) Update(id uint, in *SnippetInput, editorID uint, isStaff bool) (*model.CodeSnippet, error) { + var snippet model.CodeSnippet + if err := s.db.First(&snippet, id).Error; err != nil { + return nil, ErrSnippetNotFound + } + if snippet.UserID != editorID && !isStaff { + return nil, ErrSnippetForbidden + } + if err := in.normalize(); err != nil { + return nil, err + } + + // 判断是否有实际字段变化 + changed := snippet.Title != in.Title || + snippet.Language != in.Language || + snippet.Description != in.Description || + snippet.Code != in.Code || + snippet.Visibility != in.Visibility + + if changed { + ver := model.SnippetVersion{ + SnippetID: snippet.ID, + EditorID: editorID, + OldTitle: snippet.Title, + OldLanguage: snippet.Language, + OldDescription: snippet.Description, + OldCode: snippet.Code, + } + if err := s.db.Create(&ver).Error; err != nil { + return nil, err + } + } + + snippet.Title = in.Title + snippet.Language = in.Language + snippet.Description = in.Description + snippet.Code = in.Code + oldVisibility := snippet.Visibility + snippet.Visibility = in.Visibility + + err := s.db.Transaction(func(tx *gorm.DB) error { + if err := tx.Model(&snippet).Updates(map[string]interface{}{ + "title": snippet.Title, + "language": snippet.Language, + "description": snippet.Description, + "code": snippet.Code, + "visibility": snippet.Visibility, + }).Error; err != nil { + return err + } + // fork 副本在私有/公开之间切换时,同步源片段的公开 fork 计数 + if snippet.ForkedFromID != nil && oldVisibility != snippet.Visibility { + expr := "GREATEST(fork_count - 1, 0)" + if snippet.Visibility == model.SnippetVisibilityPublic { + expr = "fork_count + 1" + } + if err := tx.Model(&model.CodeSnippet{}).Where("id = ?", *snippet.ForkedFromID). + UpdateColumn("fork_count", gorm.Expr(expr)).Error; err != nil { + return err + } + } + return nil + }) + if err != nil { + return nil, err + } + return &snippet, nil +} + +// GetPublic 获取片段详情(public 或 owner/staff 可见) +func (s *SnippetService) GetPublic(id uint, viewerID uint, isStaff bool) (*SnippetDetail, error) { + var snippet model.CodeSnippet + if err := s.db.First(&snippet, id).Error; err != nil { + return nil, ErrSnippetNotFound + } + if snippet.Visibility != model.SnippetVisibilityPublic && snippet.UserID != viewerID && !isStaff { + return nil, ErrSnippetNotFound + } + // ViewCount++(失败不影响主流程) + s.db.Model(&snippet).UpdateColumn("view_count", gorm.Expr("view_count + 1")) + + ownerMap := s.ownerMap([]uint{snippet.UserID}) + detail := &SnippetDetail{ + CodeSnippet: snippet, + User: ownerMap[snippet.UserID], + } + if snippet.ForkedFromID != nil { + var src model.CodeSnippet + if err := s.db.Select("id, title").First(&src, *snippet.ForkedFromID).Error; err == nil { + detail.ForkedFrom = &SnippetForkedFrom{ID: src.ID, Title: src.Title} + } + } + return detail, nil +} + +// ListPublic 公开广场列表(仅 public 未删) +func (s *SnippetService) ListPublic(q, lang, sort string, page, size int) ([]SnippetListItem, int64, error) { + if page < 1 { + page = 1 + } + if size < 1 || size > 50 { + size = 12 + } + db := s.db.Model(&model.CodeSnippet{}).Where("visibility = ?", model.SnippetVisibilityPublic) + + if q = strings.TrimSpace(q); q != "" { + like := "%" + escapeILike(q) + "%" + db = db.Where("title ILIKE ? OR description ILIKE ? OR code ILIKE ?", like, like, like) + } + if lang != "" { + if _, ok := snippetLanguages[lang]; ok { + db = db.Where("language = ?", lang) + } + } + + var total int64 + if err := db.Count(&total).Error; err != nil { + return nil, 0, err + } + + switch sort { + case "copy": + db = db.Order("copy_count DESC, id DESC") + case "comment": + db = db.Order("comment_count DESC, id DESC") + case "fork": + db = db.Order("fork_count DESC, id DESC") + default: + db = db.Order("created_at DESC, id DESC") + } + + var snippets []model.CodeSnippet + if err := db.Offset((page - 1) * size).Limit(size).Find(&snippets).Error; err != nil { + return nil, 0, err + } + ownerIDs := make([]uint, 0, len(snippets)) + for _, sn := range snippets { + ownerIDs = append(ownerIDs, sn.UserID) + } + owners := s.ownerMap(ownerIDs) + items := make([]SnippetListItem, 0, len(snippets)) + for _, sn := range snippets { + items = append(items, toSnippetListItem(sn, owners[sn.UserID])) + } + return items, total, nil +} + +// ListMine 我的片段列表(含私有) +func (s *SnippetService) ListMine(userID uint, q string, page, size int) ([]SnippetListItem, int64, error) { + if page < 1 { + page = 1 + } + if size < 1 || size > 50 { + size = 12 + } + db := s.db.Model(&model.CodeSnippet{}).Where("user_id = ?", userID) + if q = strings.TrimSpace(q); q != "" { + like := "%" + escapeILike(q) + "%" + db = db.Where("title ILIKE ? OR description ILIKE ? OR code ILIKE ?", like, like, like) + } + + var total int64 + if err := db.Count(&total).Error; err != nil { + return nil, 0, err + } + + var snippets []model.CodeSnippet + if err := db.Order("created_at DESC, id DESC").Offset((page - 1) * size).Limit(size).Find(&snippets).Error; err != nil { + return nil, 0, err + } + ownerIDs := make([]uint, 0, len(snippets)) + for _, sn := range snippets { + ownerIDs = append(ownerIDs, sn.UserID) + } + owners := s.ownerMap(ownerIDs) + items := make([]SnippetListItem, 0, len(snippets)) + for _, sn := range snippets { + items = append(items, toSnippetListItem(sn, owners[sn.UserID])) + } + return items, total, nil +} + +// Fork 复制公开片段为自己的私有片段 +func (s *SnippetService) Fork(id uint, userID uint) (*model.CodeSnippet, error) { + var src model.CodeSnippet + if err := s.db.First(&src, id).Error; err != nil { + return nil, ErrSnippetNotFound + } + if src.Visibility != model.SnippetVisibilityPublic { + return nil, ErrSnippetForbidden + } + + fork := &model.CodeSnippet{ + Title: src.Title, + Language: src.Language, + Description: src.Description, + Code: src.Code, + Visibility: model.SnippetVisibilityPrivate, + UserID: userID, + ForkedFromID: &src.ID, + } + // 源标题本身已受限长约束,无需再次截断 + + // 副本初始为私有,不计入源片段的公开 fork 数; + // 作者将其改为公开时(见 Update)再计数。 + if err := s.db.Create(fork).Error; err != nil { + return nil, err + } + return fork, nil +} + +// RecordCopy 复制计数(按 key 节流 10s) +func (s *SnippetService) RecordCopy(id uint, key string) error { + s.copyMu.Lock() + now := time.Now() + if t, ok := s.copyRecords[key]; ok && now.Sub(t) < snippetCopyThrottle { + s.copyMu.Unlock() + return nil + } + s.copyRecords[key] = now + // 清理过期记录(简单 LRU,防止内存膨胀) + if len(s.copyRecords) > 10000 { + for k, v := range s.copyRecords { + if now.Sub(v) > time.Minute { + delete(s.copyRecords, k) + } + } + } + s.copyMu.Unlock() + + var snippet model.CodeSnippet + if err := s.db.First(&snippet, id).Error; err != nil { + return ErrSnippetNotFound + } + return s.db.Model(&snippet).UpdateColumn("copy_count", gorm.Expr("copy_count + 1")).Error +} + +// Delete 软删片段(owner 或 staff) +func (s *SnippetService) Delete(id uint, actorID uint, isStaff bool) error { + var snippet model.CodeSnippet + if err := s.db.First(&snippet, id).Error; err != nil { + return ErrSnippetNotFound + } + if snippet.UserID != actorID && !isStaff { + return ErrSnippetForbidden + } + return s.db.Transaction(func(tx *gorm.DB) error { + if err := tx.Delete(&snippet).Error; err != nil { + return err + } + // 删除公开的 fork 副本时,回溯源片段的公开 fork 计数; + // 私有副本从未计入,无需回溯。 + if snippet.ForkedFromID != nil && snippet.Visibility == model.SnippetVisibilityPublic { + if err := tx.Model(&model.CodeSnippet{}).Where("id = ?", *snippet.ForkedFromID). + UpdateColumn("fork_count", gorm.Expr("GREATEST(fork_count - 1, 0)")).Error; err != nil { + return err + } + } + return nil + }) +} + +// ListHistory 版本历史(倒序分页) +func (s *SnippetService) ListHistory(snippetID uint, page, size int) ([]model.SnippetVersion, int64, error) { + if page < 1 { + page = 1 + } + if size < 1 || size > 50 { + size = 10 + } + var total int64 + if err := s.db.Model(&model.SnippetVersion{}).Where("snippet_id = ?", snippetID).Count(&total).Error; err != nil { + return nil, 0, err + } + var versions []model.SnippetVersion + if err := s.db.Where("snippet_id = ?", snippetID). + Order("created_at DESC, id DESC"). + Offset((page - 1) * size).Limit(size). + Find(&versions).Error; err != nil { + return nil, 0, err + } + return versions, total, nil +} + +// ListForks 公开 fork 列表(一层) +func (s *SnippetService) ListForks(id uint, page, size int) ([]SnippetListItem, int64, error) { + if page < 1 { + page = 1 + } + if size < 1 || size > 50 { + size = 12 + } + db := s.db.Model(&model.CodeSnippet{}). + Where("forked_from_id = ? AND visibility = ?", id, model.SnippetVisibilityPublic) + + var total int64 + if err := db.Count(&total).Error; err != nil { + return nil, 0, err + } + + var snippets []model.CodeSnippet + if err := db.Order("created_at DESC, id DESC").Offset((page - 1) * size).Limit(size).Find(&snippets).Error; err != nil { + return nil, 0, err + } + ownerIDs := make([]uint, 0, len(snippets)) + for _, sn := range snippets { + ownerIDs = append(ownerIDs, sn.UserID) + } + owners := s.ownerMap(ownerIDs) + items := make([]SnippetListItem, 0, len(snippets)) + for _, sn := range snippets { + items = append(items, toSnippetListItem(sn, owners[sn.UserID])) + } + return items, total, nil +} + +// snippetFloorNumber 主评楼层号(含软删,按 created_at/id 升序) +func (s *SnippetService) snippetFloorNumber(snippetID, commentID uint) int { + var c model.SnippetComment + if err := s.db.Unscoped().Select("id", "snippet_id", "parent_id", "root_id", "created_at"). + Where("id = ? AND snippet_id = ?", commentID, snippetID).First(&c).Error; err != nil { + return 0 + } + floorID := c.ID + floorCreated := c.CreatedAt + if c.ParentID != nil { + rootID := c.ID + if c.RootID != nil { + rootID = *c.RootID + } + var root model.SnippetComment + if err := s.db.Unscoped().Select("id", "created_at"). + Where("id = ? AND snippet_id = ? AND parent_id IS NULL", rootID, snippetID).First(&root).Error; err != nil { + return 0 + } + floorID = root.ID + floorCreated = root.CreatedAt + } + var ahead int64 + s.db.Unscoped().Model(&model.SnippetComment{}). + Where("snippet_id = ? AND parent_id IS NULL AND (created_at < ? OR (created_at = ? AND id < ?))", + snippetID, floorCreated, floorCreated, floorID). + Count(&ahead) + return int(ahead) + 1 +} + +// toSnippetCommentNode 转评论节点(软删 tombstone 清空正文) +func toSnippetCommentNode(c model.SnippetComment, user *SnippetOwner, replies []SnippetCommentNode, floor int) SnippetCommentNode { + edited := c.UpdatedAt.Sub(c.CreatedAt) > time.Minute + if c.DeletedAt.Valid { + c.Content = "" + return SnippetCommentNode{ + SnippetComment: c, + Floor: floor, + Deleted: true, + Edited: edited, + User: user, + Replies: replies, + } + } + return SnippetCommentNode{ + SnippetComment: c, + Floor: floor, + Deleted: false, + Edited: edited, + User: user, + Replies: replies, + } +} + +// ListComments 片段评论列表(主评分页,含回复) +func (s *SnippetService) ListComments(snippetID uint, page, size int) ([]SnippetCommentNode, int64, error) { + if page < 1 { + page = 1 + } + if size < 1 || size > 100 { + size = 20 + } + // tombstone 语义:软删评论保留占位壳(内容清空,前端显示"该评论已删除"), + // 其子回复仍挂在壳下;因此列表/计数均使用 Unscoped 包含软删行。 + base := s.db.Unscoped().Model(&model.SnippetComment{}).Where("snippet_id = ?", snippetID) + + var total int64 + if err := base.Count(&total).Error; err != nil { + return nil, 0, err + } + + var roots []model.SnippetComment + if err := s.db.Unscoped().Where("snippet_id = ? AND parent_id IS NULL", snippetID). + Order("created_at ASC, id ASC"). + Offset((page - 1) * size).Limit(size). + Find(&roots).Error; err != nil { + return nil, 0, err + } + if len(roots) == 0 { + return []SnippetCommentNode{}, total, nil + } + + rootIDs := make([]uint, len(roots)) + for i, r := range roots { + rootIDs[i] = r.ID + } + var replies []model.SnippetComment + if err := s.db.Unscoped().Where("snippet_id = ? AND root_id IN ?", snippetID, rootIDs). + Order("created_at ASC, id ASC").Find(&replies).Error; err != nil { + return nil, 0, err + } + + children := make(map[uint][]model.SnippetComment, len(replies)) + for _, r := range replies { + if r.ParentID != nil { + children[*r.ParentID] = append(children[*r.ParentID], r) + } + } + + allRows := make([]model.SnippetComment, 0, len(roots)+len(replies)) + allRows = append(allRows, roots...) + allRows = append(allRows, replies...) + userIDs := make([]uint, 0, len(allRows)) + for _, c := range allRows { + userIDs = append(userIDs, c.UserID) + } + users := s.ownerMap(userIDs) + + var build func(pid uint) []SnippetCommentNode + build = func(pid uint) []SnippetCommentNode { + out := []SnippetCommentNode{} + for _, c := range children[pid] { + out = append(out, toSnippetCommentNode(c, users[c.UserID], build(c.ID), 0)) + } + return out + } + + result := make([]SnippetCommentNode, 0, len(roots)) + for _, r := range roots { + floor := s.snippetFloorNumber(snippetID, r.ID) + result = append(result, toSnippetCommentNode(r, users[r.UserID], build(r.ID), floor)) + } + return result, total, nil +} + +// CreateComment 创建片段评论 +func (s *SnippetService) CreateComment(userID, snippetID uint, content string, parentID *uint) (*model.SnippetComment, error) { + content = strings.TrimSpace(content) + if content == "" { + return nil, badInput("评论内容不能为空") + } + if utf8.RuneCountInString(content) > snippetCommentMaxLen { + return nil, badInput("评论不能超过 2000 字") + } + + var snippet model.CodeSnippet + if err := s.db.First(&snippet, snippetID).Error; err != nil { + return nil, ErrSnippetNotFound + } + if snippet.Visibility != model.SnippetVisibilityPublic { + return nil, ErrSnippetNotFound + } + + comment := &model.SnippetComment{ + SnippetID: snippetID, + UserID: userID, + Content: content, + } + + if parentID != nil { + var parent model.SnippetComment + if err := s.db.Where("id = ? AND snippet_id = ? AND deleted_at IS NULL", *parentID, snippetID).First(&parent).Error; err != nil { + return nil, badInput("回复的评论不存在") + } + if parent.Depth >= maxReplyDepth { + return nil, badInput("回复层级过深") + } + rootID := parent.ID + if parent.RootID != nil { + rootID = *parent.RootID + } + comment.ParentID = parentID + comment.RootID = &rootID + comment.Depth = parent.Depth + 1 + } + + err := s.db.Transaction(func(tx *gorm.DB) error { + if err := tx.Create(comment).Error; err != nil { + return err + } + return tx.Model(&snippet).UpdateColumn("comment_count", gorm.Expr("comment_count + 1")).Error + }) + if err != nil { + return nil, err + } + return comment, nil +} + +// UpdateComment 更新评论(仅本人) +func (s *SnippetService) UpdateComment(commentID, userID uint, content string) (*model.SnippetComment, error) { + content = strings.TrimSpace(content) + if content == "" { + return nil, badInput("评论内容不能为空") + } + if utf8.RuneCountInString(content) > snippetCommentMaxLen { + return nil, badInput("评论不能超过 2000 字") + } + var comment model.SnippetComment + if err := s.db.First(&comment, commentID).Error; err != nil { + return nil, ErrCommentNotFound + } + if comment.UserID != userID { + return nil, ErrCommentForbidden + } + if comment.Content == content { + return nil, ErrCommentNotChanged + } + old := comment.Content + if err := s.db.Transaction(func(tx *gorm.DB) error { + hist := model.SnippetCommentEditHistory{ + CommentID: comment.ID, + EditorID: userID, + OldContent: old, + } + if err := tx.Create(&hist).Error; err != nil { + return err + } + return tx.Model(&comment).Update("content", content).Error + }); err != nil { + return nil, err + } + if err := s.db.First(&comment, comment.ID).Error; err != nil { + return nil, err + } + return &comment, nil +} + +// DeleteComment 软删评论(本人或 staff;tombstone:DeleteType/DeletedBy) +// 保留占位壳与楼层计数:评论数不减,列表中显示"该评论已删除",子回复仍挂其下。 +func (s *SnippetService) DeleteComment(commentID, userID uint, isStaff bool) error { + var comment model.SnippetComment + if err := s.db.First(&comment, commentID).Error; err != nil { + return ErrCommentNotFound + } + if comment.UserID != userID && !isStaff { + return ErrCommentForbidden + } + deleteType := "self" + if comment.UserID != userID { + deleteType = "admin" + } + if err := s.db.Model(&comment).Updates(map[string]interface{}{ + "delete_type": deleteType, + "deleted_by": userID, + }).Error; err != nil { + return err + } + return s.db.Delete(&comment).Error +} + +// SnippetCommentHistoryItem 片段评论历史项 +type SnippetCommentHistoryItem struct { + ID uint `json:"id"` + Editor *SnippetOwner `json:"editor"` + OldContent string `json:"old_content"` + CreatedAt time.Time `json:"created_at"` +} + +// ListCommentHistory 片段评论编辑历史(登录即可见;含软删评论;倒序分页) +func (s *SnippetService) ListCommentHistory(actor *Actor, commentID uint, page, size int) ([]SnippetCommentHistoryItem, int64, error) { + if page < 1 { + page = 1 + } + if size < 1 || size > 50 { + size = 10 + } + var comment model.SnippetComment + if err := s.db.Unscoped().Select("id").First(&comment, commentID).Error; err != nil { + return nil, 0, ErrCommentNotFound + } + if actor == nil { + return nil, 0, ErrCommentForbidden + } + + q := s.db.Model(&model.SnippetCommentEditHistory{}).Where("comment_id = ?", commentID) + var total int64 + if err := q.Count(&total).Error; err != nil { + return nil, 0, err + } + + var rows []model.SnippetCommentEditHistory + if err := s.db.Where("comment_id = ?", commentID). + Order("created_at DESC"). + Offset((page - 1) * size).Limit(size). + Find(&rows).Error; err != nil { + return nil, 0, err + } + + editorIDs := make([]uint, 0, len(rows)) + seen := map[uint]struct{}{} + for _, r := range rows { + if _, ok := seen[r.EditorID]; ok { + continue + } + seen[r.EditorID] = struct{}{} + editorIDs = append(editorIDs, r.EditorID) + } + editors := s.ownerMap(editorIDs) + + items := make([]SnippetCommentHistoryItem, 0, len(rows)) + for _, r := range rows { + ed := editors[r.EditorID] + if ed == nil { + ed = &SnippetOwner{ID: r.EditorID, Username: "已注销", Nickname: "已注销"} + } + items = append(items, SnippetCommentHistoryItem{ + ID: r.ID, + Editor: ed, + OldContent: r.OldContent, + CreatedAt: r.CreatedAt, + }) + } + return items, total, nil +} + +// AdminListSnippetItem 管理端片段列表项(含 code) +type AdminListSnippetItem struct { + model.CodeSnippet + User *SnippetOwner `json:"user,omitempty"` +} + +// AdminList 管理端全量列表(含 code) +func (s *SnippetService) AdminList(q, visibility string, page, size int) ([]AdminListSnippetItem, int64, error) { + if page < 1 { + page = 1 + } + if size < 1 || size > 50 { + size = 20 + } + db := s.db.Model(&model.CodeSnippet{}) + if q = strings.TrimSpace(q); q != "" { + like := "%" + escapeILike(q) + "%" + db = db.Where("title ILIKE ? OR description ILIKE ? OR code ILIKE ?", like, like, like) + } + if visibility != "" { + db = db.Where("visibility = ?", model.NormalizeSnippetVisibility(visibility)) + } + + var total int64 + if err := db.Count(&total).Error; err != nil { + return nil, 0, err + } + + var snippets []model.CodeSnippet + if err := db.Order("created_at DESC, id DESC").Offset((page - 1) * size).Limit(size).Find(&snippets).Error; err != nil { + return nil, 0, err + } + ownerIDs := make([]uint, 0, len(snippets)) + for _, sn := range snippets { + ownerIDs = append(ownerIDs, sn.UserID) + } + owners := s.ownerMap(ownerIDs) + items := make([]AdminListSnippetItem, 0, len(snippets)) + for _, sn := range snippets { + items = append(items, AdminListSnippetItem{CodeSnippet: sn, User: owners[sn.UserID]}) + } + return items, total, nil +} + +// AdminSetVisibility 管理端强制修改可见性 +func (s *SnippetService) AdminSetVisibility(id uint, visibility string) error { + visibility = model.NormalizeSnippetVisibility(visibility) + result := s.db.Model(&model.CodeSnippet{}).Where("id = ?", id).Update("visibility", visibility) + if result.Error != nil { + return result.Error + } + if result.RowsAffected == 0 { + return ErrSnippetNotFound + } + return nil +} + +// AdminDelete 管理端软删(DeleteType=admin) +func (s *SnippetService) AdminDelete(id uint, adminID uint) error { + var snippet model.CodeSnippet + if err := s.db.First(&snippet, id).Error; err != nil { + return ErrSnippetNotFound + } + return s.db.Delete(&snippet).Error +} diff --git a/docs/images/wechat.png b/docs/images/wechat.png new file mode 100644 index 0000000000000000000000000000000000000000..91f605b882ccd90edcc277dc7e1e19cac7799eef GIT binary patch literal 67572 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