Help us shape the future of Go! Take the 2026 Go Developer Survey

character

package
v1.7.0 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrGroupNotFound     = errors.New("分组不存在或不属于当前小说")
	ErrGroupNameTaken    = errors.New("当前小说已存在同名分组")
	ErrCharacterNotFound = errors.New("角色不存在或不属于当前小说")
)

Functions

func CleanupOrphanGroupMembers added in v1.6.1

func CleanupOrphanGroupMembers(tx *gorm.DB, novelID int64) error

CleanupOrphanGroupMembers 在回退事务末尾移除失去角色或分组的归属。 手动归属可能不属于被回退的 AI 轮次;此处不生成新日志,避免将回退记成用户操作。

Types

type Character

type Character struct {
	ID          int64     `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
	NovelID     int64     `gorm:"column:novel_id;not null;index"    json:"novel_id"`
	Name        string    `gorm:"column:name;not null;index"        json:"name"`
	Description string    `gorm:"column:description"                json:"description"` // 自然语言描述,LLM 填写
	Personality string    `gorm:"column:personality"                json:"personality"` // JSON 自由格式,LLM 填写。如 {"traits":["勇敢","冲动"],"brief":"一个热血青年"}
	Abilities   string    `gorm:"column:abilities"                  json:"abilities"`   // JSON 数组,如 ["剑术","隐身"]
	CreatedAt   time.Time `gorm:"column:created_at;autoCreateTime"  json:"created_at"`
	UpdatedAt   time.Time `gorm:"column:updated_at;autoUpdateTime"  json:"updated_at"`
}

Character 是角色元数据。 personality 和 abilities 为 JSON 自由格式,由 LLM 填写和读取,不做结构化约束。

func (Character) TableName

func (Character) TableName() string

TableName 指定 GORM 表名。

type CharacterRelation

type CharacterRelation struct {
	ID                int64     `gorm:"column:id;primaryKey;autoIncrement"           json:"id"`
	NovelID           int64     `gorm:"column:novel_id;not null;index"              json:"novel_id"`
	SourceCharacterID int64     `gorm:"column:source_character_id;not null;index"   json:"source_character_id"` // 关系发出方
	TargetCharacterID int64     `gorm:"column:target_character_id;not null;index"   json:"target_character_id"` // 关系接收方
	RelationDescribe  string    `gorm:"column:relation_describe;not null"          json:"relation_describe"`    // 自由文本,LLM 自行描述,如 "亦师亦敌"、"朋友、高中同学",工具描述的时候需要告诉llm详细描述而不是简单的type
	Description       string    `gorm:"column:description"                          json:"description"`         // 当前关系阶段的详细描述
	ChapterID         *int64    `gorm:"column:chapter_id;index"                     json:"chapter_id"`          // 此关系在哪个章节确立/变更;nil 表示未关联具体章节
	IsCurrent         bool      `gorm:"column:is_current;not null;index"            json:"is_current"`          // true=当前有效关系,false=历史记录
	CreatedAt         time.Time `gorm:"column:created_at;autoCreateTime"            json:"created_at"`
}

CharacterRelation 是角色之间有向关系的当前快照。

设计原则(与 Python 版本的关键差异):

  1. 自由文本 relation_describe — LLM 用自然语言描述关系(如 "朋友、高中同学、暗中嫉妒"), 不再受枚举 18 种类型的限制。单行可表达多面关系。
  2. 追加不可变 (append-only) — 关系变更时不修改旧行,而是 INSERT 新行并将旧行 is_current 置 false。 同一对 (source_id, target_id) 的全部记录按 created_at 排序即为完整演变历史。
  3. 不需要 evolved_from_id 指针链 — 用 (source,target) 配对 + 时间戳隐式排序替代显式链表, 消除断链风险和并发分叉问题。Python 因为枚举 type 导致一对角色需要多行并行记录, 每行各自演化,才被迫引入自引用链;自由文本 relation_describe 从根上消除了这个需求。
  4. 不需要 status 字段 — is_current 布尔替代 active/dormant/resolved/severed 四状态枚举, 关系状态只需区分"当前"和"历史"。

图查询支持:

  • 全图:WHERE novel_id = ? AND is_current = true → 所有节点+边,前端可渲染关系图
  • 单角色邻域:WHERE (source_id = ? OR target_id = ?) AND is_current = true
  • 两角色之间:WHERE (source_id = A AND target_id = B) OR (source_id = B AND target_id = A)

MCP 工具实现参考:

  • update_character_relationship: 变更时开启事务,旧行 SET is_current = false,INSERT 新行,COMMIT
  • get_character_network: 查当前全图,返回 nodes(Character 列表) + edges(CharacterRelation 列表) 可以加入ids参数只查涉及到的人的关系网
  • get_character_history: WHERE source_id = X AND target_id = Y ORDER BY created_at, 可选通过 chapter_number JOIN chapters 拉取对应章节摘要补充上下文

TODO 后续可实现前端的可视化关系图绘制

func (CharacterRelation) TableName

func (CharacterRelation) TableName() string

TableName 指定 GORM 表名。

type Group added in v1.6.1

type Group struct {
	ID          int64     `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
	NovelID     int64     `gorm:"column:novel_id;not null;uniqueIndex:uk_character_group_name" json:"novel_id"`
	Name        string    `gorm:"column:name;not null;uniqueIndex:uk_character_group_name" json:"name"`
	Description string    `gorm:"column:description" json:"description"`
	CreatedAt   time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
	UpdatedAt   time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
}

Group 是小说内的角色分类;Description 说明分类用途,不承载阵营演变历史。

func (Group) TableName added in v1.6.1

func (Group) TableName() string

type GroupMember added in v1.6.1

type GroupMember struct {
	ID          int64     `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
	NovelID     int64     `gorm:"column:novel_id;not null;index" json:"novel_id"`
	GroupID     int64     `gorm:"column:group_id;not null;uniqueIndex:uk_character_group_member" json:"group_id"`
	CharacterID int64     `gorm:"column:character_id;not null;uniqueIndex:uk_character_group_member;index" json:"character_id"`
	CreatedAt   time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
}

GroupMember 独立记录每条归属,便于逐行审计和回退。

func (GroupMember) TableName added in v1.6.1

func (GroupMember) TableName() string

type GroupView added in v1.6.1

type GroupView struct {
	Group
	MemberCount int64 `gorm:"column:member_count;->;-:migration" json:"member_count"`
}

GroupView 的人数由查询计算,不写入分组记录或操作日志。

type ListByNovelOptions

type ListByNovelOptions struct {
	PageParams storage.PageParams
	GroupID    *int64 // nil=全部,0=未分组,正整数=指定分组
	Search     string // 空字符串=不过滤,按 name LIKE 模糊匹配
	Order      string // 空字符串=默认 "updated_at DESC";否则直接作为 ORDER BY 子句(如 "name ASC")
}

ListByNovelOptions 是 ListByNovel 的可选参数。

type ListGroupMembersOptions added in v1.6.1

type ListGroupMembersOptions struct {
	PageParams  storage.PageParams
	GroupID     int64  // 0=不过滤,正整数=指定分组
	CharacterID int64  // 0=不过滤,正整数=指定角色
	Search      string // 空字符串=不过滤,按角色 name LIKE 模糊匹配
	Order       string // 空字符串=默认 group_id ASC, character_id ASC;按成员表字段排序
}

ListGroupMembersOptions 是 ListGroupMembers 的可选参数。

type ListGroupsOptions added in v1.6.1

type ListGroupsOptions struct {
	PageParams storage.PageParams
	Search     string // 空字符串=不过滤,按 name LIKE OR description LIKE 模糊匹配
	Order      string // 空字符串=默认 name ASC, id ASC;调用方可显式指定排序
}

ListGroupsOptions 是 ListGroups 的可选参数。

type Store

type Store struct {
	DB *gorm.DB
	// contains filtered or unexported fields
}

Store 管理 Character 和 CharacterRelation 持久化。DB 导出供调用方做简单 CRUD。

func NewStore

func NewStore(db *gorm.DB, logger *slog.Logger) *Store

NewStore 创建 character 存储。

func (*Store) ChapterDeletionBlockers added in v1.6.0

func (s *Store) ChapterDeletionBlockers(ctx context.Context, novelID, chapterID int64) ([]deletion.Blocker, error)

ChapterDeletionBlockers 返回关联到指定章节的角色关系历史。

func (*Store) CreateGroup added in v1.6.1

func (s *Store) CreateGroup(ctx context.Context, novelID int64, name, description string) (*Group, error)

func (*Store) Deactivate

func (s *Store) Deactivate(ctx context.Context, relationID int64) error

Deactivate 将一条关系标记为非当前(is_current=false)。

func (*Store) DeleteCharacter added in v1.6.1

func (s *Store) DeleteCharacter(ctx context.Context, novelID, characterID int64) error

DeleteCharacter 逐行删除附属记录,保证删除及回退包含分组归属和关系历史。

func (*Store) DeleteGroup added in v1.6.1

func (s *Store) DeleteGroup(ctx context.Context, novelID, groupID int64) error

DeleteGroup 仅解除归属,角色和其他组的归属保持不变。

func (*Store) GetByIDs

func (s *Store) GetByIDs(ctx context.Context, ids []int64) ([]Character, error)

GetByIDs 批量按 ID 取角色,用于关系查询时解析角色名。

func (*Store) GetGroupsByCharacterIDs added in v1.6.1

func (s *Store) GetGroupsByCharacterIDs(ctx context.Context, novelID int64, characterIDs []int64) (map[int64][]Group, error)

GetGroupsByCharacterIDs 批量获取指定角色所属分组,供分页角色结果附带归属信息。

func (*Store) GetHistory

func (s *Store) GetHistory(ctx context.Context, charA, charB int64) ([]CharacterRelation, error)

GetHistory 返回两角色间全部关系记录(含历史),按时间升序。 不考虑方向——A→B 或 B→A 都算。

func (*Store) ListBetweenCharacters

func (s *Store) ListBetweenCharacters(ctx context.Context, characterIDs []int64) ([]CharacterRelation, error)

ListBetweenCharacters 返回给定角色集合内部的当前关系边(两端都在集合内)。

func (*Store) ListByCharacter

func (s *Store) ListByCharacter(ctx context.Context, characterID int64) ([]CharacterRelation, error)

ListByCharacter 返回某角色所有当前关系(is_current=true),不限方向。

func (*Store) ListByCharacters

func (s *Store) ListByCharacters(ctx context.Context, characterIDs []int64) ([]CharacterRelation, error)

ListByCharacters 批量按角色 ID 取当前关系,用于 LLM 按需查询指定角色群的关系网。

func (*Store) ListByNovel

func (s *Store) ListByNovel(ctx context.Context, novelID int64, opts ListByNovelOptions) (*storage.PageResult[Character], error)

ListByNovel 分页列出某小说的角色,支持 name 搜索。

func (*Store) ListCurrentByNovel

func (s *Store) ListCurrentByNovel(ctx context.Context, novelID int64) ([]CharacterRelation, error)

ListCurrentByNovel 返回某小说全部当前有效关系(is_current=true)。 前端关系图渲染用,数据量大时不建议直接给 LLM。

func (*Store) ListGroupMembers added in v1.6.1

func (s *Store) ListGroupMembers(ctx context.Context, novelID int64, opts ListGroupMembersOptions) (*storage.PageResult[GroupMember], error)

ListGroupMembers 分页列出某小说的成员归属,支持分组/角色过滤和角色名搜索。

func (*Store) ListGroups added in v1.6.1

func (s *Store) ListGroups(ctx context.Context, novelID int64, opts ListGroupsOptions) (*storage.PageResult[GroupView], error)

ListGroups 分页列出某小说的分组及成员数量,支持名称/描述搜索。

func (*Store) UpdateGroup added in v1.6.1

func (s *Store) UpdateGroup(ctx context.Context, novelID, groupID int64, name, description string) error

UpdateGroup 使用 PUT 语义,允许清空描述。

func (*Store) UpdateGroupMemberships added in v1.6.1

func (s *Store) UpdateGroupMemberships(ctx context.Context, novelID int64, characterIDs, addGroupIDs, removeGroupIDs []int64) error

UpdateGroupMemberships 对多个角色增量调整归属,全部校验后在同一事务内逐行写入。 重复加入或移出视为无操作;不会覆盖调用方没有指定的其他归属。

Jump to

Keyboard shortcuts

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