--- tags: [] aliases: - Project Context Aggregation date created: 星期三, 十二月 10日 2025, 12:10:59 凌晨 date modified: 星期三, 十二月 10日 2025, 12:06:29 中午 --- # Project Context Aggregation > Source Items: 6 # ⚙️ Go 模块根路径约束 (Module Root Path Constraint) **核心约束:** - **项目 Go Module 路径 (Root Path):** `gitea-aliyun/Klein/enterprise-cms-core` - **用途:** 所有内部导入(Internal Imports)必须以此路径作为前缀。 - **示例:** - **错误:** `import "internal/pkg/ecode"` - **正确:** `import "gitea-aliyun/Klein/enterprise-cms-core/internal/pkg/ecode"` **AI 约束实施规则:** 1. 在生成任何包含 `import` 语句的代码时,必须检查并使用上述 Root Path。 2. 若代码位于 `internal` 目录下,且引用了另一个 `internal` 目录下的包,必须使用完整的 Root Path。 ==== 00_ 软件产品全生命周期管理规范.md ==== ```markdown --- tags: [] aliases: - 📘 软件产品全生命周期管理规范 (PDLC Guidelines) date created: 星期日, 十二月 7日 2025, 12:49:19 下午 date modified: 星期日, 十二月 7日 2025, 12:49:54 下午 --- 这是一个通用的、标准化的《互联网软件产品全生命周期(PDLC)管理规范》。此文档旨在为从灵感到交付的全过程提供顶层指导,适用于中大型项目或追求工程卓越的小型团队。 --- # 📘 软件产品全生命周期管理规范 (PDLC Guidelines) 版本: 2.0 (通用标准版) 适用范围: 全栈开发、SaaS 产品、企业级应用系统 核心目标: 降低不确定性,确保交付质量,实现可预测的工程化产出。Shutterstock --- ## 阶段概览 (Phase Overview) 我们将产品落地过程划分为 7 个核心阶段(P0 - P6)。每个阶段都有明确的准入(Entry)和准出(Exit)标准。 |**阶段代号**|**阶段名称**|**核心角色**|**关键产出物**| |---|---|---|---| |**P0**|**立项与价值验证 (Inception)**|PM, Tech Lead, Stakeholder|BRD, 可行性分析报告| |**P1**|**需求定义与原型 (Definition)**|PM, UI/UX|PRD, 原型图 (Figma)| |**P2**|**技术方案设计 (Technical Design)**|Architect, Backend, Frontend|TDD, API 契约, ER 图| |**P3**|**开发与实现 (Development)**|Developers|源代码, 单元测试| |**P4**|**质量保障与验证 (Verification)**|QA, Developers|测试报告, Bug 清单| |**P5**|**发布与部署 (Release)**|DevOps, Tech Lead|镜像, Release Note| |**P6**|**运维与迭代 (Operations)**|SRE, Ops, PM|监控面板, 运营数据报告| --- ## 📅 详细阶段拆解 ### P0: 立项与价值验证 (Inception & Strategy) **目的:** 明确“为什么要做”。防止团队在伪需求或技术不可行的方向上浪费资源。 - **主要工作:** 1. **商业需求分析:** 确定业务痛点、目标用户及商业价值。 2. **技术可行性预研 (PoC):** 针对关键技术难点(如 AI 模型效果、高并发瓶颈)进行快速验证。 3. **资源评估:** 粗略估算所需人力、时间及服务器成本。 - **关键产出 (Artifacts):** - `BRD (Business Requirement Document)`:商业需求文档。 - `PoC Demo`:概念验证原型(如有必要)。 - **决策门 (Gate):** **Go / No-Go**。如果 ROI(投入产出比)过低,在此阶段终止。 ### P1: 需求定义与产品设计 (Product Definition) **目的:** 明确“要做成什么样”。将模糊的想法转化为具象的功能逻辑和视觉形态。 - **主要工作:** 1. **需求细化:** 编写详细的功能列表、用户故事 (User Stories) 和验收标准 (AC)。 2. **交互设计 (UX):** 绘制用户流程图 (User Flow)、低保真线框图。 3. **视觉设计 (UI):** 输出高保真设计稿、UI 切图、设计规范 (Design System)。 - **关键产出 (Artifacts):** - `PRD (Product Requirement Document)`:产品需求规格说明书(唯一真理来源)。 - `Figma/Sketch Files`:高保真设计稿。 - **决策门 (Gate):** **需求评审 (PRD Review)**。开发团队确认需求逻辑闭环,无歧义。 ### P2: 技术方案设计 (Technical Design) **目的:** 明确“怎么实现”。**这是程序员最重要的规划阶段,严禁跳过此阶段直接编码。** - **主要工作:** 1. **架构设计:** 确定微服务拆分、技术选型、中间件依赖(Redis/MQ/DB)。 2. **数据建模 (Schema Design):** 绘制 ER 图,编写 DDL (SQL 建表语句),确定索引策略。 3. **接口定义 (API Contract):** 定义 URL、Method、Request/Response JSON 结构、错误码。 4. **详细设计 (TDD):** 核心算法逻辑、状态机流转图、时序图、缓存策略设计。 - **关键产出 (Artifacts):** - `TDD (Technical Design Document)`:技术设计文档。 - `ER Diagram & SQL Scripts`:数据库模型与迁移脚本。 - `OpenAPI/Swagger Spec`:API 接口定义文档。 - **决策门 (Gate):** **技术评审 (Design Review)**。架构师或 Tech Lead 确认方案具备扩展性、安全性及性能达标。 ### P3: 开发与实现 (Implementation) **目的:** 将设计转化为代码。注重代码质量与规范。 - **主要工作:** 1. **环境准备:** 本地开发环境搭建、Mock 数据生成。 2. **编码 (Coding):** 后端 API 开发、前端组件开发、业务逻辑实现。 3. **单元测试 (Unit Test):** 编写核心逻辑的单元测试,确保覆盖率。 4. **代码审查 (Code Review):** 提交 Merge Request,进行同行评审。 - **关键产出 (Artifacts):** - `Source Code`:符合规范的源码。 - `Unit Test Report`:单元测试通过报告。 - **决策门 (Gate):** **代码合并 (Merge)**。CI 流水线检查通过(Lint, Test, Build)。 ### P4: 质量保障与验证 (Quality Assurance) **目的:** 确保交付物符合需求且无重大缺陷。 - **主要工作:** 1. **集成测试:** 前后端联调,确保接口数据交互正常。 2. **系统测试:** QA 团队根据测试用例进行全量测试。 3. **非功能测试:** 性能测试 (Load Test)、安全扫描 (Security Scan)。 4. **Bug 修复:** 开发修复 QA 发现的问题并回归。 - **关键产出 (Artifacts):** - `Test Cases`:测试用例。 - `Bug List`:缺陷清单及修复记录。 - `Performance Report`:压测报告(可选)。 - **决策门 (Gate):** **验收评审 (UAT)**。Bug 清零或无 P0/P1 级 Bug,PM 验收通过。 ### P5: 发布与部署 (Release & Deployment) **目的:** 安全、平滑地将产品推向生产环境。 - **主要工作:** 1. **构建交付:** 编译二进制文件、构建 Docker 镜像。 2. **预发布验证 (Staging):** 在仿真环境中进行最后一次冒烟测试。 3. **正式部署 (Production):** 灰度发布 (Canary) 或 蓝绿部署,执行数据库迁移。 4. **回滚预案:** 准备好一旦失败的一键回滚脚本。 - **关键产出 (Artifacts):** - `Release Note`:发布说明(变更日志)。 - `Docker Image / Binaries`:制品。 - **决策门 (Gate):** **上线检查清单 (Checklist)**。确认配置、密钥、数据库备份均已就绪。 ### P6: 运维与持续迭代 (Operations & Maintenance) **目的:** 保障系统稳定性,根据反馈进行优化。 - **主要工作:** 1. **监控告警:** 配置 CPU/内存、QPS、错误率监控,设置 PagerDuty 告警。 2. **日志审计:** 收集与分析运行日志 (ELK/Loki)。 3. **数据复盘:** 分析用户行为数据,验证 P0 阶段的商业假设。 4. **事故复盘 (Post-mortem):** 若发生故障,撰写复盘报告,制定改进措施。 - **关键产出 (Artifacts):** - `SLA Report`:服务可用性报告。 - `User Analytics`:用户数据分析报表。 --- ## ⚙️ 关键支撑体系 (Supporting Pillars) 除了上述流程,以下三个支撑体系贯穿始终: 1. **项目管理 (Project Management):** 使用 Jira/Trello 管理任务看板,每日站会同步进度,识别风险。 2. **配置管理 (Configuration Management):** 代码版本控制 (Git Flow),环境配置隔离 (Env Vars)。 3. **文档工程 (Documentation):** 保持 BRD, PRD, API 文档与代码的同步更新,避免“文档腐烂”。 ``` ==== 关于个人开发者的开发模式.md ==== ```markdown --- tags: [] aliases: - 渐进式开发最佳实践 date created: 星期一, 十二月 8日 2025, 12:04:31 凌晨 date modified: 星期一, 十二月 8日 2025, 12:05:12 凌晨 --- # 渐进式开发最佳实践 ## 1. 必须在写代码前锁定的“硬约束” (The Non-Negotiables) 即使是后规划细节,但这 **4 样东西** 是一旦开工就很难改的,必须在骨架阶段定死: 1. **目录结构 (Directory Layout):** `cmd`, `internal`, `pkg` 怎么分。这决定了你能不能顺畅地加代码。 - _现状:_ 我们已经定好了 (Modular Clean Architecture)。 2. **核心技术栈与基础设施:** 选 Gin 还是 Echo,用 GORM 还是 SQLX,依赖注入用 Wire 还是手写。 - _现状:_ 我们已经定好了 (Gin+GORM+Wire+Viper)。 3. **统一的交互规范:** API 怎么返回错误?数据库怎么管理变更?日志打在哪里? - _现状:_ 我们已经定好了 (JSON Envelope, Golang-Migrate, Zap)。 4. **核心领域模型 (Core Schema):** 最关键的表(User, Role)。 - _原因:_ 它们是系统的地基,地基不稳,后面写 Service 逻辑会反复推倒重来。 --- ## 2. 可以(且应该)推迟设计的“软逻辑” (The Deferrables) 这些内容不要现在想,想了也是白想,等写到那个函数时再具体的“具体问题具体分析”: 1. **复杂的业务算法:** 比如“文章的热度排名算法”、“复杂的权限递归校验逻辑”。 - _策略:_ 先写个 `return true` 或简单的逻辑占位,跑通流程再说。 2. **极致的性能优化:** 比如“这里要不要加 Redis 缓存?”、“这里 SQL 要不要分表?”。 - _策略:_ 先跑通功能 (Make it work),再优化性能 (Make it fast)。 3. **非核心字段的定义:** 比如文章表里要不要加 `seo_keywords`,用户表要不要加 `wechat_id`。 - _策略:_ 用到了再加 migration,不要为了“未来可能用到”而过度设计。 4. **具体的 API 参数细节:** 比如“更新文章是传 ID 还是传 UUID”。 - _策略:_ 写 Handler 的时候,顺手定义 DTO 就行。 --- ## 3. 个人开发者的“曳光弹”开发流 (The Tracer Bullet Workflow) 不要试图“横向”开发(先把所有 50 张表设计完,再把所有 API 定义完)。 要进行 “纵向”切片开发(Vertical Slice)。 **推荐的实操步骤:** ### 第一阶段:搭建“行走的骨架” (Day 1 - 也就是你现在该做的) **目标:** 一个能跑起来、能连数据库、有日志、有 Swagger 文档,但没有任何业务功能的空壳。 1. **初始化项目:** 建立文件夹,`go mod init`。 2. **配置基础设施:** 放入 `Makefile`, `docker-compose.yml`, `config.yaml`。 3. **连通性测试:** 写一个简单的 `GET /ping` 接口,确保能读到配置,能连上 DB,能打出日志。 4. **依赖注入跑通:** 确保 `wire` 能自动生成代码并启动 Server。 5. **结果:** 你拥有了一个**“生产级”的 Hello World**。 ### 第二阶段:第一个“核心切片” (Day 2-3) **目标:** 打通 User 模块的完整闭环。 1. **DB:** 设计 `users` 表,执行 Migrate。 2. **Entity:** 生成 User Struct。 3. **Repo:** 写 `CreateUser` 和 `FindUser` 的 CRUD。 4. **Service:** 写 `Register` 逻辑(这里涉及到密码加密,此时再去查 Argon2 怎么用)。 5. **API:** 定义 `RegisterReq` DTO,写 Handler。 6. **测试:** 用 Postman/Swagger 调通注册接口。 ### 第三阶段:具体问题具体分析 (Day 4+) **目标:** 遇到什么写什么。 - _场景:_ 比如你做到了“文章发布”,突然发现需要“敏感词过滤”。 - _动作:_ 停下来,在 `pkg/util` 里设计一个敏感词过滤函数(或者找个库),然后在 Service 层调用它。 - _这就是你说的:_ “进行到具体的业务逻辑的时候进行设计”。 --- ## 4. 总结给你的建议 你现在的焦虑在于试图**预见未来**。 **作为个人开发者,你的代码就是你的设计文档。** **你的下一步行动:** 1. **停止**思考复杂的业务场景。 2. **立即**按照我们之前确定的目录结构,新建文件夹。 3. **立即**把 `docker-compose` 跑起来,把 `main.go` 跑起来。 4. **立即**实现“用户注册”这一个功能。 只要“骨架”(架构分层、依赖注入、数据库管理方式)是对的,后面你往里面填什么肉(业务逻辑),怎么填,都不会把楼盖歪。 **准备好开始初始化项目文件夹了吗?** ``` ==== 关于项目的顶层设计模式和风格.md ==== ```markdown --- tags: [] aliases: - 🏗️ Project Architecture & Design Guidelines (v1.0) date created: 星期日, 十二月 7日 2025, 11:57:43 中午 date modified: 星期二, 十二月 9日 2025, 11:00:14 晚上 --- # 🏗️ Project Architecture & Design Guidelines (v1.0) 项目代号: Enterprise-CMS-Core 架构风格: 模块化整洁架构 (Modular Clean Architecture) 核心原则: 实用主义 (Pragmatic)、Go 原生思维 (Idiomatic)、领域驱动 (DDD-Lite) ## 1. 技术栈约束 (Tech Stack Constraints) - **Language:** Go 1.21+ - **Web Framework:** Gin - **Database:** PostgreSQL (Primary), Redis (Cache) - **ORM:** GORM (With Migration Tools) - **Dependency Injection:** Google Wire - **Configuration:** Viper (YAML) - **Observability:** Zap (Log), Prometheus (Metrics), Jaeger (Trace) - **Documentation:** Swagger / OpenAPI 3.0 --- ## 2. 目录结构规范 (Directory Structure) 采用 **“按领域分包 (Package by Domain)”** 的扁平化结构,而非传统的按层分包。 ```Plaintext root/ ├── cmd/server/ │ ├── main.go # 仅包含 wire 初始化与 app.Run() │ └── wire.go # 顶层依赖注入定义 ├── config/ # 配置文件模板 (config.yaml) ├── internal/ │ ├── api/ # [API层] 全局通用的 HTTP DTO (Request/Response) │ ├── middleware/ # [中间件] Gin 中间件 (Auth, CORS, Logger) │ ├── pkg/ # [基础设施] 内部通用组件 (AppResult, ErrorCode) │ │ │ │ # --- 核心业务领域 (Domain Modules) --- │ │ # 每个领域包内部扁平化,自包含所有逻辑 │ ├── user/ # [示例] 用户领域 │ │ ├── entity.go # 核心实体 (GORM Model) │ │ ├── repository.go # 仓储接口定义 + GORM 实现 │ │ ├── service.go # 业务逻辑 (Service Struct) │ │ ├── handler.go # HTTP 控制器 (Controller) │ │ └── provider.go # Wire ProviderSet │ │ │ └── article/ # [示例] 文章领域 (结构同上) │ ├── pkg/ # [外部库] 可抽离的通用工具 (Hash, JWT, Logger封装) ├── migrations/ # 数据库迁移 SQL 文件 (up/down) ├── go.mod └── Makefile ``` --- ## 3. 核心架构设计规则 (Architectural Rules) ### 3.1. 依赖倒置与注入 (IoC & DI) - **规则:** 严禁在业务代码中手动 `New()` 依赖对象。 - **实现:** 所有依赖关系必须通过 `NewStruct(dep Interface)` 构造函数声明,并由 `Google Wire` 在编译期自动组装。 - **模块化注入:** 每个领域包(如 `internal/user`)必须包含一个 `provider.go`,导出 `var ProviderSet = wire.NewSet(…)`,供顶层 `cmd/server/wire.go` 聚合。 ### 3.2. 接口策略 (Interface Strategy) - **Repository (必须):** 仓储层**必须**定义接口(例如 `UserRepository`),以支持 Mock 测试和数据库切换。 - **Service (按需):** 默认**不需要**定义 Service 接口,直接使用 Struct。仅在以下情况提取接口: 1. 出现循环依赖。 2. 需要对 Service 进行 Mock 测试。 3. 该 Service 存在多种策略实现(如 `PaymentService` 有支付宝/微信两种实现)。 ### 3.3. 领域包扁平化 (Flat Domain Package) - **规则:** 在 `internal/user/` 等领域包内,**不再**建立 `service/`, `repo/` 子目录。 - **原因:** 利用 Go 的 `package` 级私有可见性,隐藏领域内部细节(如辅助函数、内部 DTO),仅暴露必要的 Handler 和 Service 方法。 ### 3.4. 数据模型 (Model Vs Entity) - **策略:** 采用 **"Pragmatic Entity"** 模式。 - **定义:** `entity.go` 中的结构体既是业务实体,也是 GORM 模型(带 `gorm:"…"` 标签)。 - **例外:** 只有当数据库存储结构与业务逻辑结构差异巨大时,才在 Repository 内部引入独立的 PO (Persistent Object) 并进行转换。 --- ## 4. 编码实施标准 (Implementation Standards) ### 4.1. 错误处理 (Error Handling) - **禁止:** 严禁直接返回 `error` 字符串给前端。 - **必须:** Service 层返回标准 `error`,Controller 层通过 `pkg/app` 将其转换为统一响应格式。 - **格式:** ```Go // Response JSON { "code": 20001, "msg": "User already exists", "data": null } ``` ### 4.2. 数据库交互 (Database Interaction) - **禁止:** Controller 层严禁导入 `gorm` 包,严禁执行 SQL。 - **迁移:** 生产环境严禁使用 `AutoMigrate`。必须使用 `migrations/` 目录下的版本化 SQL 脚本进行变更。 ### 4.3. 路由注册 (Router Registration) - **规则:** 路由不再集中管理。 - **实现:** 每个领域包暴露一个 `RegisterRoutes(r *gin.RouterGroup)` 方法。在 `main.go` 启动时,统一调用各模块的注册方法。 --- ## 5. AI 编程指令 (Instruction for AI Agent) > **当作为 AI 助手编写代码时,请严格遵守以下指令:** 1. **Context Check:** 在生成代码前,检查当前目录结构是否符合 `Section 2`。如果不符,请优先建议重构或遵循现有结构。 2. **No Logic Leak:** 确保 HTTP 处理逻辑(解析参数、校验参数)留在 `handler.go`,业务规则(判断权限、计算)留在 `service.go`,SQL 操作留在 `repository.go`。 3. **Wire Awareness:** 每当新增 Service 或 Repository,必须自动更新同目录下的 `provider.go`,并在 `cmd/server/wire.go` 中检查是否需要重新生成。 4. **Testability:** 编写 Repository 代码时,优先考虑“如何 Mock”。 ```bash ==== 规范数据库设计 & 变更管理及工程流操作.md ==== ```markdown --- tags: [] aliases: - 🛠️ Database Engineering & Migration Standard (v1.0) date created: 星期日, 十二月 7日 2025, 10:31:59 晚上 date modified: 星期二, 十二月 9日 2025, 10:14:44 晚上 --- # 🛠️ Database Engineering & Migration Standard (v1.0) 文档用途: 规范数据库设计、变更管理及工程流操作。 适用范围: 所有涉及 Schema 变更的后端开发任务。 核心原则: Code First (Logic) but SQL First (Schema). 严禁生产环境使用 ORM 自动建表。 --- ## 1. 基础设施与工具链 (Infrastructure & Tools) 本项目采用 **“容器化数据库 + 版本化迁移工具”** 的架构。 | **组件** | **选型** | **说明** | | --------------- | ------------------ | ----------------------------------------- | | **Database** | **PostgreSQL 15+** | 运行于 Docker 容器中,保证开发/生产环境一致。 | | **Schema Mgmt** | **Golang-Migrate** | CLI 工具,用于生成和执行版本化 SQL 脚本。 | | **GUI Client** | **Navicat** | 推荐 Navicat / DataGrip / DBeaver,仅用于设计和验证。 | | **Automation** | **Make** | 封装常用命令,屏蔽底层复杂参数。 | ### 1.1 目录结构规范 Plaintext ```bash project-root/ ├── migrations/ # [Source of Truth] 存放所有 SQL 变更文件 │ ├── 000001_init_users.up.sql │ └── 000001_init_users.down.sql ├── internal/ │ └── {domain}/ # 领域包 │ └── entity.go # [Code Mapping] GORM 结构体定义 ├── docker-compose.yml # 定义本地 DB 容器 └── Makefile # 集成迁移命令 ``` --- ## 2. 数据库设计规范 (Design Standards) ### 2.1 命名约定 - **表名:** 必须使用**复数**形式,`snake_case` (e.g., `users`, `order_items`). - **字段名:** 全小写,`snake_case` (e.g., `created_at`, `user_id`). - **索引名:** - 普通索引: `idx_tablename_column` - 唯一索引: `uniq_tablename_column` - **外键名:** `fk_tablename_ref_tablename` ### 2.2 关键字段约束 所有业务表**必须**包含以下基础字段: ```SQL id BIGSERIAL PRIMARY KEY, -- 或 UUID created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), deleted_at TIMESTAMPTZ -- 仅在需要软删除时添加 ``` ### 2.3 设计禁忌 1. **严禁** 使用物理外键的级联删除 (`ON DELETE CASCADE`),除非是关联性极强的子表(如文章标签关联)。核心业务数据必须使用 `ON DELETE RESTRICT`。 2. **严禁** 在涉及金额的字段使用 `FLOAT` 或 `DOUBLE`,必须使用 `DECIMAL` 或 `BIGINT` (分)。 3. **严禁** 将 `NULL` 作为布尔值的第三种状态。布尔字段必须设置 `NOT NULL DEFAULT FALSE`。 --- ## 3. 标准作业流程 (SOP) 开发人员需严格遵循以下 **5 步闭环** 进行数据库变更: ### Step 1: 启动环境 确保本地 Docker 数据库正在运行。 ```Bash make network # 对应 docker-compose up -d ``` ### Step 2: 创建迁移文件 (Create) 使用 Makefile 生成成对的 `.sql` 文件(up/down)。 - `name` 参数应简短描述变更内容(如 `add_avatar_to_users`)。 ```Bash make new_migration name=init_schema # 输出: # Created migrations/000001_init_schema.up.sql # Created migrations/000001_init_schema.down.sql ``` ### Step 3: 编写 SQL (Edit) - **UP 文件:** 填入 `CREATE TABLE`, `ALTER TABLE`, `CREATE INDEX` 等正向操作。 - _技巧:_ 可在 GUI 工具中设计好表结构,复制生成的 DDL 语句粘贴至此。 - **DOWN 文件:** 填入对应的回滚操作(如 `DROP TABLE`, `DROP INDEX`)。 ### Step 4: 执行变更 (Apply) 将 SQL 应用到本地数据库。 ```Bash make migrate_up ``` _验证:_ 使用 GUI 工具连接数据库,确认表结构已更新。 ### Step 5: 代码映射 (Mapping) 在 `internal/{domain}/entity.go` 中编写对应的 Go Struct。 - 确保 `gorm` tag 与数据库定义一致。 - 确保 `json` tag 符合 API 契约。 --- ## 4. 自动化配置 (Automation) 将以下内容固化到项目根目录的 `Makefile` 中。 > **注意:** 确保 `DB_DSN` 与 `docker-compose.yml` 中的配置完全一致。 ```Makefile # ============================================================================== # Database & Migration Logic # ============================================================================== # Database Connection String # 格式: postgres://user:password@host:port/dbname?sslmode=disable DB_DSN := postgres://postgres:secret@localhost:5432/cms_core?sslmode=disable .PHONY: network new_migration migrate_up migrate_down migrate_force # 1. 启动本地环境 network: docker-compose up -d # 2. 创建新的迁移文件 (Usage: make new_migration name=create_users) new_migration: @if [ -z "$(name)" ]; then echo "Error: name is required"; exit 1; fi migrate create -ext sql -dir migrations -seq $(name) # 3. 执行所有未执行的迁移 (Up) migrate_up: migrate -path migrations -database "$(DB_DSN)" up # 4. 回滚上一次迁移 (Down 1 step) migrate_down: migrate -path migrations -database "$(DB_DSN)" down 1 # 5. 强制修复版本 (当 dirty database 时使用, version 为具体的版本号) migrate_force: migrate -path migrations -database "$(DB_DSN)" force $(version) ``` --- ## 5. 故障排查 (Troubleshooting) **Q: 执行 migrate_up 时报错 "Dirty database version x".** - **原因:** 上一次迁移执行到一半失败了(可能是 SQL 语法错误),导致版本锁死。 - **解决:** 1. 手动修复 SQL 文件中的语法错误。 2. 执行 `make migrate_force version=x` (x 是失败前的那个版本号)。 3. 再次执行 `make migrate_up`。 **Q: 多人协作时产生版本冲突。** - **现象:** 你有一个 `0003_add_xx.up.sql`,同事提交代码后也有一个 `0003_add_yy.up.sql`。 - **解决:** 重命名你的迁移文件编号为 `0004`,确保序列号在时间轴上是递增且唯一的。 ```bash ==== 七七八八的接口设计相关问题.md ==== ```markdown --- tags: [] aliases: - 1. 接口版本控制策略 (API Versioning Strategy) date created: 星期日, 十二月 7日 2025, 11:38:52 晚上 date modified: 星期日, 十二月 7日 2025, 11:42:18 晚上 --- # 七七八八的接口设计相关问题 ## 1. 接口版本控制策略 (API Versioning Strategy) **核心问题:** 当你发布了 V1 版本后,某天需要修改接口字段(比如把 `name` 拆分为 `first_name` 和 `last_name`),如何保证老版本的 App 不会崩溃? **三种主流流派:** 1. **URI Path Versioning (推荐):** - **格式:** `https://api.example.com/v1/users` - **优点:** 直观、易于调试、缓存友好。这也是 GitHub, Twitter, Google API 采用的主流方案。 - **落地:** 我们在 Gin 的 Router Group 中直接体现: Go ```bash v1 := r.Group("/api/v1") { v1.GET("/users", ...) } ``` 2. **Header Versioning:** - **格式:** Header 中添加 `Accept: application/vnd.myapi.v1+json` - **优点:** URL 干净。 - **缺点:** 调试麻烦(浏览器直接访问 URL 看不到结果),CDN 缓存配置复杂。**不推荐 MVP 阶段使用。** 3. **Query Parameter:** - **格式:** `/users?version=1` - **评价:** 看起来很土,通常不用于 RESTful API。 **👉 你的策略:** 坚定选择 **URI Path Versioning (`/api/v1`)**。只在发生**破坏性变更 (Breaking Change)** 时才升级到 v2。新增字段不算破坏性变更,不需要升级版本。 --- ## 2. HTTP 方法的精准语义 (Verbs Semantics) 很多新手只会用 `GET` 和 `POST`。企业级 API 必须精准区分以下方法的含义: |**方法**|**语义**|**幂等性 (Idempotency)**|**典型场景**| |---|---|---|---| |**GET**|获取资源|✅ 是|获取文章列表、详情| |**POST**|新建资源|❌ 否|发布新文章、提交评论| |**PUT**|**全量替换**资源|✅ 是|修改文章(客户端发送文章的完整 JSON,没传的字段会被置空)| |**PATCH**|**局部更新**资源|❌ 否 (理论上)|修改文章状态(只传 `{"status": "published"}`,其他字段不变)| |**DELETE**|删除资源|✅ 是|删除文章| ⚠️ 重点关注 PUT vs PATCH: 在 Go 语言中实现 PATCH 有点麻烦(因为 Go 的结构体默认值问题,你很难区分用户是传了 0 还是没传这个字段)。 - **最佳实践:** 对于 CMS 这种表单复杂的系统,**修改接口首选 `PUT` (全量)**,或者针对特定状态修改提供独立接口(如 `POST /articles/:id/publish`)。如果必须做 `PATCH`,DTO 需使用指针类型 `*string` 来判断是否为 `nil`。 --- ## 3. RESTful URL 设计模式 (Resource Naming) **原则:URL 中只出现名词,不出现动词。** - ❌ **反例 (RPC 风格 - 不要这么做):** - `/api/getUsers` - `/api/createUser` - `/api/deleteArticle?id=1` - ✅ **正例 (REST 风格):** - `GET /api/v1/users` (获取列表) - `POST /api/v1/users` (创建) - `DELETE /api/v1/articles/1` (删除 ID 为 1 的文章) **复杂关系的嵌套设计:** - _场景:_ 获取某篇文章下的评论。 - _设计:_ `GET /api/v1/articles/{article_id}/comments` - _场景:_ 获取某个作者的所有文章。 - _设计:_ `GET /api/v1/users/{user_id}/articles` --- ## 4. 列表接口三剑客:分页、排序、筛选 (Pagination, Sorting, Filtering) 你的 CMS 一定会有“文章列表”页面,这个接口是最复杂的。不要为每种查询都写一个新接口,要设计一个**通用的查询接口**。 **最佳实践标准:** 1. **分页 (Pagination):** - 使用 `page` (页码) 和 `page_size` (每页条数)。 - URL 示例: `/articles?page=2&page_size=20` - **注意:** 要限制 `page_size` 的最大值(如 100),防止恶意用户一次请求 100 万条数据把数据库打挂。 2. **排序 (Sorting):** - 使用 `sort` 参数。`-` 代表降序,无符号代表升序。 - URL 示例: `/articles?sort=-created_at` (按创建时间倒序) - URL 示例: `/articles?sort=view_count,-created_at` (先按浏览量升序,再按时间倒序) 3. **筛选 (Filtering):** - 直接使用字段名作为参数。 - URL 示例: `/articles?category_id=1&status=published` --- ## 5. 状态码与错误处理 (Status Codes & Error Handling) **不要永远只返回 200 OK!** 前端开发最恨的就是:HTTP 状态码是 200,结果 Body 里写着 `{"code": 500, "msg": "Error"}`。这会让监控系统失效。 **你需要遵守的“HTTP 状态码地图”:** - **2xx (成功):** - `200 OK`: 通用成功。 - `201 Created`: 创建成功 (POST 返回)。 - `204 No Content`: 删除成功 (DELETE 返回,不带 Body)。 - **4xx (客户端错误 - 前端背锅):** - `400 Bad Request`: 参数校验失败(如邮箱格式不对)。 - `401 Unauthorized`: 未登录/Token 过期。 - `403 Forbidden`: 登录了,但没权限(如普通用户想删文章)。 - `404 Not Found`: 资源不存在。 - **5xx (服务端错误 - 你背锅):** - `500 Internal Server Error`: 代码崩了/数据库挂了。 统一错误响应格式 (JSON Envelope): 无论发生什么错误,Body 必须保持结构一致,方便前端拦截: JSON ```bash { "code": 40001, // 业务错误码 (你在 pkg/e 定义的) "message": "标题已存在", // 给用户看的提示 "request_id": "abc-123" // 方便查日志的 Trace ID } ``` --- ## 6. 进阶知识:幂等性 (Idempotency) **概念:** 用户因为网络卡顿,连续点击了 3 次“发布文章”按钮,你的系统会创建 1 篇文章还是 3 篇? - **非幂等:** `POST`。点 3 次创建 3 篇。 - **幂等:** `PUT` / `DELETE`。改 3 次和改 1 次结果一样;删 3 次和删 1 次结果一样(都是没了)。 如何处理 POST 的幂等性? 对于关键业务(如支付、核心数据创建),通常要求前端在 Header 带一个 Idempotency-Key (UUID)。后端 Redis 记录这个 Key,如果短时间内收到相同的 Key,直接返回上次的结果,不执行数据库插入。 (注:MVP 阶段可以先不做,但面试或者做高可靠系统时必须知道) --- ## 总结:在你开始定义 API 之前 请在心中建立这套标准: 1. **URL:** `/api/v1/名词` 2. **Method:** 查询用 GET,新建用 POST,修改用 PUT,删除用 DELETE。 3. **List:** 永远记得预留 `page`, `page_size`。 4. **Response:** 永远返回统一的 JSON 结构,报错必须用 4xx/5xx 状态码。 **准备好了吗?我们可以开始基于这些原则,设计 User 模块的 API 了。** ```bash ==== 产品需求规格说明书 (PRD) - V1.1.md ==== ```markdown --- tags: [] aliases: - 📝 产品需求规格说明书 (PRD) - V1.1 date created: 星期日, 十二月 7日 2025, 12:14:41 中午 date modified: 星期日, 十二月 7日 2025, 12:49:19 下午 --- # 📝 产品需求规格说明书 (PRD) - V1.1 > **更新日志:** > > - v1.0: 初始版本,定义功能列表。 > > - **v1.1:** [2025-12-07] 补充项目战略背景;优化软删除与缓存策略的灵活性;明确长文本存储类型。 项目名称: Enterprise-CMS-Core (企业级内容管理系统核心) 版本: 1.1.0 状态: [✅ 已锁定] 适用对象: 后端开发人员、架构师、测试人员 --- ## 1. 项目战略概述 (Strategic Overview) ### 1.1 项目背景与目标 本项目并非单纯为了交付一个 CMS 软件,而是为了构建一个**“Go 语言企业级后端架构样板间”**。 - **核心目标:** 验证并固化一套“模块化整洁架构”工程实践,使其具备**高可维护性**、**可扩展性**和**安全性**。 - **衍生价值:** 产出的源码将作为团队未来的“SaaS 启动脚手架 (Boilerplate)”,或作为独立的高价值技术资产(源码付费产品)进行商业变现。 ### 1.2 核心用户与价值 - **系统管理员 (Admin):** 痛点是“安全与失控风险”。核心价值是提供**银行级的 RBAC 权限控制**,确保没人能越权操作。 - **内容编辑 (Editor):** 痛点是“流程混乱”。核心价值是提供**状态明确的内容流转机制**(草稿 ->审核 ->发布),防止误发。 - **二开开发者 (Developer):** 痛点是“屎山代码”。核心价值是提供**清晰的依赖边界**和**开箱即用的基础设施**。 ### 1.3 成功指标 (Success Metrics) 1. **业务完整性:** 必须完整支持 3 种标准角色(Admin/Editor/Subscriber)的权限隔离,且文章状态流转无逻辑漏洞。 2. **工程质量:** 核心业务模块(User/Auth)单元测试覆盖率 > 80%;通过静态代码分析,无循环依赖。 3. **性能基线:** 在单机 2C4G 配置下,并发 100 QPS 时,API P99 响应时间 < 200ms。 --- ## 2. 核心功能范围 (In-Scope) ### 2.1 认证与鉴权模块 (Auth & IAM) **唯一来源:** 必须使用 JWT 双令牌机制 + RBAC 模型。 - **F-AUTH-01 用户注册:** 仅支持“用户名 + 密码”注册。密码必须经过 Argon2 或 Bcrypt 哈希存储。 - **F-AUTH-02 用户登录:** 校验账号密码,返回 `Access Token` (短效 15min) 和 `Refresh Token` (长效 7 天)。 - **F-AUTH-03 令牌刷新:** 使用有效的 Refresh Token 换取新的 Access Token。**旧的 Refresh Token 若被复用需触发安全警报(可选)或直接失效**。 - **F-AUTH-04 统一登出:** 强制使 Refresh Token 失效(需在 Redis 中建立黑名单或白名单机制)。 - **F-AUTH-05 密码重置:** 登录状态下修改密码,修改成功后强制吊销所有 Token。 ### 2.2 用户与权限模块 (User & RBAC) **预设角色:** 系统初始化必须包含以下三种角色。 |**角色代码**|**名称**|**权限描述**| |---|---|---| |`admin`|超级管理员|拥有系统所有权限 (用户管理、角色分配、内容强制删除)。| |`editor`|内容编辑|拥有文章发布、审核、标签管理权限。不可管理用户。| |`subscriber`|普通用户|仅拥有修改自身资料、发布评论、查看公开文章权限。| - **F-USER-01 个人资料:** 查询与更新当前登录用户的昵称、头像 URL、简介。 - **F-USER-02 用户管理 (Admin):** 管理员可查看用户列表,封禁/解封用户状态。 - **F-RBAC-01 角色分配 (Admin):** 管理员可修改用户的角色(如将 User 提权为 Editor)。 ### 2.3 内容核心模块 (CMS Core) **核心逻辑:** 文章必须包含状态流转。 - **F-ART-01 文章 CRUD:** - **创建:** 默认为 `Draft` (草稿) 状态。 - **字段:** 标题、内容、封面图 URL、作者 ID。 - **数据类型约束:** 文章内容字段在数据库层面建议使用 `TEXT` 或 `LONGTEXT` 类型,以完整承载 Markdown/HTML 长文本。 - **F-ART-02 文章状态流转:** - 支持状态: `Draft` (草稿) -> `Pending` (待审核) -> `Published` (已发布) -> `Archived` (归档/软删除)。 - **F-ART-03 分类与标签:** - 文章必须归属一个分类 (Category)。 - 文章可关联多个标签 (Tags)。 - **F-ART-04 内容审核 (Editor/Admin):** - 拥有审核权限的角色可将 `Pending` 状态的文章改为 `Published` 或驳回至 `Draft`。 - **F-ART-05 公开检索:** - 仅 `Published` 状态的文章对外接口可见。支持按 分类、标签、标题关键词 搜索。 ### 2.4 互动模块 (Interaction) - **F-CMT-01 评论发布:** 登录用户可对 `Published` 文章发表评论。 - **F-CMT-02 评论管理:** 作者可删除自己文章下的评论;Admin/Editor 可删除任何违规评论。 --- ## 3. 非功能性需求 (Non-Functional Requirements) **开发人员必须严格遵守以下技术约束:** ### 3.1 数据一致性 - **删除策略 [优化]:** 核心业务数据(用户、文章)原则上必须使用 Soft Delete (`deleted_at` 字段)。 - _例外条款:_ 涉及法律合规(如 GDPR 用户遗忘权)或垃圾数据清理时,经系统管理员明确审批操作后,允许提供物理删除接口。 - **事务:** 文章发布与标签关联必须在同一个 Database Transaction 中完成。 ### 3.2 性能与缓存 - **API 响应:** 95% 的请求响应时间需 < 200ms (不含网络延迟)。 - **缓存策略:** - 建议对 **高频读取且低频修改** 的数据(如用户信息 `/profile`、热门文章详情 `/article/:id`)实施缓存策略。 - 具体的缓存实现(Redis Key 设计、TTL 时长、Cache-Aside 或 Write-Through 模式)由开发团队根据实际压测结果灵活调整,不强制硬编码 TTL。 ### 3.3 安全性 - **SQL 注入:** 严禁拼接 SQL,必须使用 GORM 参数化查询。 - **敏感数据:** 密码、RefreshToken 严禁明文出现在日志中。 - **接口保护:** 除登录、注册、公开文章列表外,所有接口必须通过 JWT 中间件校验。 ### 3.4 工程规范 - **Schema:** 数据库表结构变更必须提供 Up/Down SQL 迁移脚本。 - **Doc:** 所有 API 必须自动生成 Swagger 文档。 --- ## 4. 不在范围 (Out of Scope) **以下功能明确不包含在本次 Phase 1 开发中:** 1. **❌ 第三方登录:** 不做微信/GitHub/Google 登录。 2. **❌ 消息推送/通知:** 不做系统内通知。 3. **❌ 文件存储服务 (OSS):** 仅处理 URL 字符串,不处理文件流上传。 4. **❌ 复杂的富文本处理:** 后端仅存储字符串,不解析 HTML。 5. **❌ 支付与订单:** 不包含任何电商逻辑。 --- ## 5. 核心数据实体关系图 (ER 简述) - **User** (1) <-> (N) **Article** - **User** (1) <-> (N) **Comment** - **Article** (1) <-> (N) **Comment** - **Article** (N) <-> (1) **Category** - **Article** (N) <-> (N) **Tag** (Many-to-Many) ```