This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/cmd/server/main.go
Victor_Jay 03a01a09be feat: 实现内容系统 MVC(Post CRUD + 审核流转)
按 content-system.md 设计文档,实现帖子内容系统的最小可行 MVC。

新增:
- Model: Post 模型,含 5 种状态(draft/pending/approved/rejected/locked)
- Repository: post_repo.go,分页查询(前台 approved 列表 + 后台全状态筛选)
- Service: post_service.go,核心业务逻辑(状态流转、Markdown 渲染 Goldmark)
- Controller: post_controller + admin_post_controller,SSR 页面 6 个 + API 13 个
- Template: 列表/详情/编辑器/404 + 管理员列表,各配 CSS/JS
- 路由: /posts, /posts/:id, /posts/new, /posts/:id/edit, REST API, Admin API
- gomod: + github.com/yuin/goldmark v1.8.2

修改:
- Main: AutoMigrate Post 表
- Router: deps 注册 PostService/Controller,路由注册
- Nav: 新增“帖子”导航链接
- Admin Sidebar: 新增“内容管理”入口

设计:
- 审核开关复用 audit.enabled,开启时帖子为 draft,关闭后直接 approved
- 仅 approved 公开可见,作者/admin 可预览非公开状态帖子
- 严格分层 ISP 接口: Controller → postUseCase, Service → postStore, Repo → *PostRepo
- 状态保护: pending/locked 禁止编辑,rejected 编辑后自动重置为 draft
2026-05-27 18:22:48 +08:00

80 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"log"
"metazone.cc/metalab/internal/config"
"metazone.cc/metalab/internal/model"
"metazone.cc/metalab/internal/router"
"metazone.cc/metalab/internal/theme"
"github.com/gin-gonic/gin"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func main() {
// 配置
cfg := config.Load("config.yaml")
// 从配置初始化角色系统OCP新增角色无需修改源代码
model.InitRoles(cfg.Roles.Levels, cfg.Roles.Names, cfg.Roles.Permissions.OperableRoles)
// 数据库
db, err := gorm.Open(postgres.Open(cfg.Database.DSN()), &gorm.Config{})
if err != nil {
log.Fatalf("连接数据库失败: %v", err)
}
if err := db.AutoMigrate(&model.User{}, &model.AuditSubmission{}, &model.SiteSetting{}, &model.Notification{}, &model.Post{}); err != nil {
log.Fatalf("数据库迁移失败: %v", err)
}
// 邮箱唯一索引迁移:从全表唯一改为部分唯一(仅 deleted_at IS NULL 的行)
// 支持软删除用户邮箱复用
migrations := []string{
`DROP INDEX IF EXISTS idx_users_email`,
`CREATE INDEX IF NOT EXISTS idx_users_email ON users (email)`,
`CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email_active ON users (email) WHERE deleted_at IS NULL`,
}
for _, m := range migrations {
if err := db.Exec(m).Error; err != nil {
log.Fatalf("数据库迁移失败 (%s): %v", m, err)
}
}
log.Println("数据库连接成功")
// Gin 模式
gin.SetMode(cfg.Server.Mode)
r := gin.Default()
// 模板加载(前端主题 + 管理后台)
tmpl, err := theme.LoadTemplates(
theme.TemplateRoot{Dir: "templates/MetaLab-2026/html", Prefix: ""},
theme.TemplateRoot{Dir: "templates/admin/html", Prefix: "admin/"},
)
if err != nil {
panic("加载模板失败: " + err.Error())
}
r.SetHTMLTemplate(tmpl)
// 静态资源
r.Static("/static", "./templates/MetaLab-2026/static")
r.Static("/admin/static", "./templates/admin/static")
r.Static("/shared/static", "./templates/shared/static")
r.Static("/uploads/avatars", "./storage/uploads/avatars")
// 站点设置管理器DB 持久化 + 内存缓存)
siteSettings, err := config.NewSiteSettings(db)
if err != nil {
log.Fatalf("初始化站点设置失败: %v", err)
}
// 路由注册
router.Setup(r, db, cfg, siteSettings)
// 启动
log.Printf("MetaZone.FAN 启动于 0.0.0.0:%s", cfg.Server.Port)
r.Run("0.0.0.0:" + cfg.Server.Port)
}