Documentation
¶
Index ¶
- Variables
- func CleanupOrphanGroupMembers(tx *gorm.DB, novelID int64) error
- type Character
- type CharacterRelation
- type Group
- type GroupMember
- type GroupView
- type ListByNovelOptions
- type ListGroupMembersOptions
- type ListGroupsOptions
- type Store
- func (s *Store) ChapterDeletionBlockers(ctx context.Context, novelID, chapterID int64) ([]deletion.Blocker, error)
- func (s *Store) CreateGroup(ctx context.Context, novelID int64, name, description string) (*Group, error)
- func (s *Store) Deactivate(ctx context.Context, relationID int64) error
- func (s *Store) DeleteCharacter(ctx context.Context, novelID, characterID int64) error
- func (s *Store) DeleteGroup(ctx context.Context, novelID, groupID int64) error
- func (s *Store) GetByIDs(ctx context.Context, ids []int64) ([]Character, error)
- func (s *Store) GetGroupsByCharacterIDs(ctx context.Context, novelID int64, characterIDs []int64) (map[int64][]Group, error)
- func (s *Store) GetHistory(ctx context.Context, charA, charB int64) ([]CharacterRelation, error)
- func (s *Store) ListBetweenCharacters(ctx context.Context, characterIDs []int64) ([]CharacterRelation, error)
- func (s *Store) ListByCharacter(ctx context.Context, characterID int64) ([]CharacterRelation, error)
- func (s *Store) ListByCharacters(ctx context.Context, characterIDs []int64) ([]CharacterRelation, error)
- func (s *Store) ListByNovel(ctx context.Context, novelID int64, opts ListByNovelOptions) (*storage.PageResult[Character], error)
- func (s *Store) ListCurrentByNovel(ctx context.Context, novelID int64) ([]CharacterRelation, error)
- func (s *Store) ListGroupMembers(ctx context.Context, novelID int64, opts ListGroupMembersOptions) (*storage.PageResult[GroupMember], error)
- func (s *Store) ListGroups(ctx context.Context, novelID int64, opts ListGroupsOptions) (*storage.PageResult[GroupView], error)
- func (s *Store) UpdateGroup(ctx context.Context, novelID, groupID int64, name, description string) error
- func (s *Store) UpdateGroupMemberships(ctx context.Context, novelID int64, ...) error
Constants ¶
This section is empty.
Variables ¶
Functions ¶
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 填写和读取,不做结构化约束。
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 版本的关键差异):
- 自由文本 relation_describe — LLM 用自然语言描述关系(如 "朋友、高中同学、暗中嫉妒"), 不再受枚举 18 种类型的限制。单行可表达多面关系。
- 追加不可变 (append-only) — 关系变更时不修改旧行,而是 INSERT 新行并将旧行 is_current 置 false。 同一对 (source_id, target_id) 的全部记录按 created_at 排序即为完整演变历史。
- 不需要 evolved_from_id 指针链 — 用 (source,target) 配对 + 时间戳隐式排序替代显式链表, 消除断链风险和并发分叉问题。Python 因为枚举 type 导致一对角色需要多行并行记录, 每行各自演化,才被迫引入自引用链;自由文本 relation_describe 从根上消除了这个需求。
- 不需要 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 说明分类用途,不承载阵营演变历史。
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 ¶
Store 管理 Character 和 CharacterRelation 持久化。DB 导出供调用方做简单 CRUD。
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 (*Store) Deactivate ¶
Deactivate 将一条关系标记为非当前(is_current=false)。
func (*Store) DeleteCharacter ¶ added in v1.6.1
DeleteCharacter 逐行删除附属记录,保证删除及回退包含分组归属和关系历史。
func (*Store) DeleteGroup ¶ added in v1.6.1
DeleteGroup 仅解除归属,角色和其他组的归属保持不变。
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 ¶
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 ¶
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 分页列出某小说的分组及成员数量,支持名称/描述搜索。