taxonomy

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package taxonomy 提供分类(树形)与标签。

这是第一个业务模块,也是模块形态的样板:自带迁移、经三平面注册面挂接口、 声明所用权限;核心对它一无所知,仅在 cmd/lumo/modules.go 装配。

Index

Constants

View Source
const Name = "taxonomy"

Name 是模块名,也是迁移版本表的后缀(goose_db_version_taxonomy)。

Variables

View Source
var (
	// ErrNotFound 表示分类或标签不存在。
	ErrNotFound = errors.New("对象不存在")
	// ErrSlugTaken 表示 slug 已被占用。
	ErrSlugTaken = errors.New("slug 已被占用")
	// ErrNameTaken 表示名称已被占用(分类为同级、标签为全局)。
	ErrNameTaken = errors.New("名称已被占用")
	// ErrParentNotFound 表示父分类不存在。
	ErrParentNotFound = errors.New("父分类不存在")
	// ErrCycle 表示移动会让分类树成环。
	ErrCycle = errors.New("父分类不能是自身或其后代")
	// ErrInvalid 表示字段违反了数据库约束。
	ErrInvalid = errors.New("字段不合法")
)

错误哨兵。处理器据此映射为 400 / 404 / 409。

Functions

This section is empty.

Types

type Category

type Category struct {
	bun.BaseModel `bun:"table:categories,alias:c"`

	ID          int64     `bun:"id,pk,autoincrement" json:"id" doc:"分类 ID"`
	ParentID    *int64    `bun:"parent_id"           json:"parentId" doc:"父分类 ID,根分类为 null"`
	Name        string    `bun:"name,notnull"        json:"name" doc:"名称,同一父分类下唯一"`
	Slug        string    `bun:"slug,notnull"        json:"slug" doc:"URL 片段,全局唯一"`
	Description string    `bun:"description"         json:"description" doc:"描述"`
	CoverURL    string    `bun:"cover_url"           json:"coverUrl" doc:"封面图地址"`
	Position    int       `bun:"position"            json:"position" doc:"同级排序,越小越靠前"`
	CreatedAt   time.Time `bun:"created_at,nullzero" json:"createdAt"`
	UpdatedAt   time.Time `bun:"updated_at,nullzero" json:"updatedAt"`
}

Category 是分类实体。分类构成一棵森林:ParentID 为 nil 的是根分类。

type CategoryNode

type CategoryNode struct {
	Category
	Children []*CategoryNode `json:"children" doc:"子分类,按 position 排序"`
}

CategoryNode 是分类树的节点:分类本身加上按 position 排序的子分类。

func BuildTree

func BuildTree(categories []Category) []*CategoryNode

BuildTree 由平铺列表构造分类森林。

同级按 position、name、id 排序;父分类不在列表中的节点当作根处理, 因此对任意子集都能得到一棵可渲染的树。叶子节点的 Children 为空切片而非 nil, 序列化后是 [] 而不是 null,前端不必做空值判断。

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler 提供分类与标签的 Console 与 Public 接口。

func NewHandler

func NewHandler(store *Store, slugify Slugger) *Handler

NewHandler 构造 Handler;slugify 为 nil 时使用保留中文的缺省策略。

func (*Handler) Register

func (h *Handler) Register(console, public huma.API)

Register 挂载接口:Console 平面读操作对任何已认证用户开放(作者选分类需要), 写操作要求 taxonomies:manage;Public 平面匿名只读。

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module 是分类与标签模块。

func New

func New() *Module

New 构造模块。

func (*Module) Migrations

func (m *Module) Migrations() fs.FS

Migrations 实现 app.Migrator。

func (*Module) Name

func (m *Module) Name() string

Name 实现 app.Module。

func (*Module) Navigation

func (m *Module) Navigation() app.Navigation

Navigation 实现 app.NavigationProvider。

分类与标签不设权限门槛:服务端对 Console 平面的读操作对任何已认证用户开放 (作者写文章要能选分类),写操作在页面内部按 taxonomies:manage 收起。

func (*Module) Permissions

func (m *Module) Permissions() []app.Permission

Permissions 实现 app.PermissionProvider。

func (*Module) Register

func (m *Module) Register(a *app.App) error

Register 实现 app.Module:只做装配,不访问数据库。

若 settings 模块先于本模块装配,slug 生成策略跟随站点设置;否则退回保留中文的缺省策略。

func (*Module) Routes

func (m *Module) Routes(r app.Router)

Routes 实现 app.RouteProvider。

type Slugger

type Slugger func(ctx context.Context, text string) string

Slugger 由文本生成 slug;站点设置决定保留中文还是转拼音。

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store 提供分类与标签的持久化操作。

func NewStore

func NewStore(db *bun.DB) *Store

NewStore 构造 Store。

func (*Store) CreateCategory

func (s *Store) CreateCategory(ctx context.Context, c *Category) error

CreateCategory 创建分类;成功后回填 ID 与时间戳。

func (*Store) CreateTag

func (s *Store) CreateTag(ctx context.Context, tag *Tag) error

CreateTag 创建标签;成功后回填 ID 与时间戳。

func (*Store) DeleteCategory

func (s *Store) DeleteCategory(ctx context.Context, id int64) error

DeleteCategory 删除分类,并把它的子分类挂到它的父分类下。

不做级联删除:误删一个顶层分类不该连带抹掉整棵子树。

func (*Store) DeleteTag

func (s *Store) DeleteTag(ctx context.Context, id int64) error

DeleteTag 删除标签。

func (*Store) GetCategory

func (s *Store) GetCategory(ctx context.Context, id int64) (*Category, error)

GetCategory 按 ID 查分类。

func (*Store) GetCategoryBySlug

func (s *Store) GetCategoryBySlug(ctx context.Context, slug string) (*Category, error)

GetCategoryBySlug 按 slug 查分类。

func (*Store) GetTag

func (s *Store) GetTag(ctx context.Context, id int64) (*Tag, error)

GetTag 按 ID 查标签。

func (*Store) GetTagBySlug

func (s *Store) GetTagBySlug(ctx context.Context, slug string) (*Tag, error)

GetTagBySlug 按 slug 查标签。

func (*Store) ListCategories

func (s *Store) ListCategories(ctx context.Context) ([]Category, error)

ListCategories 返回全部分类。

func (*Store) ListTags

func (s *Store) ListTags(ctx context.Context) ([]Tag, error)

ListTags 返回全部标签,按名称排序。

func (*Store) NextPosition

func (s *Store) NextPosition(ctx context.Context, parentID *int64) (int, error)

NextPosition 返回给定父分类下新分类应取的排序值(末尾)。

func (*Store) PageCategories

func (s *Store) PageCategories(ctx context.Context, params api.PageParams) ([]Category, int, error)

PageCategories 分页返回分类,并给出总数。

func (*Store) PageTags

func (s *Store) PageTags(ctx context.Context, q string, params api.PageParams) ([]Tag, int, error)

PageTags 分页返回标签;q 非空时按名称或 slug 模糊筛选。

func (*Store) UpdateCategory

func (s *Store) UpdateCategory(ctx context.Context, c *Category) error

UpdateCategory 更新分类的可编辑字段,并在事务内校验父分类存在且不成环。

func (*Store) UpdateTag

func (s *Store) UpdateTag(ctx context.Context, tag *Tag) error

UpdateTag 更新标签的可编辑字段。

type Tag

type Tag struct {
	bun.BaseModel `bun:"table:tags,alias:t"`

	ID          int64     `bun:"id,pk,autoincrement" json:"id" doc:"标签 ID"`
	Name        string    `bun:"name,notnull"        json:"name" doc:"名称,大小写不敏感唯一"`
	Slug        string    `bun:"slug,notnull"        json:"slug" doc:"URL 片段,全局唯一"`
	Description string    `bun:"description"         json:"description" doc:"描述"`
	Color       string    `bun:"color"               json:"color" doc:"展示颜色,如 #3b82f6;空串表示主题默认"`
	CreatedAt   time.Time `bun:"created_at,nullzero" json:"createdAt"`
	UpdatedAt   time.Time `bun:"updated_at,nullzero" json:"updatedAt"`
}

Tag 是标签实体。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL