78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
package state
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"strings"
|
||
|
||
"github.com/voocel/ainovel-cli/domain"
|
||
)
|
||
|
||
// SavePremise 保存故事前提到 premise.md。
|
||
func (s *Store) SavePremise(content string) error {
|
||
return s.writeMarkdown("premise.md", content)
|
||
}
|
||
|
||
// LoadPremise 读取 premise.md。不存在时返回空字符串。
|
||
func (s *Store) LoadPremise() (string, error) {
|
||
data, err := s.readFile("premise.md")
|
||
if os.IsNotExist(err) {
|
||
return "", nil
|
||
}
|
||
return string(data), err
|
||
}
|
||
|
||
// SaveOutline 同时保存 outline.json(机器读)和 outline.md(人读)。
|
||
func (s *Store) SaveOutline(entries []domain.OutlineEntry) error {
|
||
if err := s.writeJSON("outline.json", entries); err != nil {
|
||
return err
|
||
}
|
||
return s.writeMarkdown("outline.md", renderOutline(entries))
|
||
}
|
||
|
||
// LoadOutline 从 outline.json 读取结构化大纲。
|
||
func (s *Store) LoadOutline() ([]domain.OutlineEntry, error) {
|
||
var entries []domain.OutlineEntry
|
||
if err := s.readJSON("outline.json", &entries); err != nil {
|
||
if os.IsNotExist(err) {
|
||
return nil, nil
|
||
}
|
||
return nil, err
|
||
}
|
||
return entries, nil
|
||
}
|
||
|
||
// GetChapterOutline 获取指定章节的大纲条目。
|
||
func (s *Store) GetChapterOutline(chapter int) (*domain.OutlineEntry, error) {
|
||
entries, err := s.LoadOutline()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
for i := range entries {
|
||
if entries[i].Chapter == chapter {
|
||
return &entries[i], nil
|
||
}
|
||
}
|
||
return nil, fmt.Errorf("chapter %d not found in outline", chapter)
|
||
}
|
||
|
||
func renderOutline(entries []domain.OutlineEntry) string {
|
||
var b strings.Builder
|
||
b.WriteString("# 大纲\n\n")
|
||
for _, e := range entries {
|
||
fmt.Fprintf(&b, "## 第 %d 章:%s\n\n", e.Chapter, e.Title)
|
||
fmt.Fprintf(&b, "**核心事件**:%s\n\n", e.CoreEvent)
|
||
if e.Hook != "" {
|
||
fmt.Fprintf(&b, "**钩子**:%s\n\n", e.Hook)
|
||
}
|
||
if len(e.Scenes) > 0 {
|
||
b.WriteString("**场景**:\n")
|
||
for i, sc := range e.Scenes {
|
||
fmt.Fprintf(&b, "%d. %s\n", i+1, sc)
|
||
}
|
||
b.WriteString("\n")
|
||
}
|
||
}
|
||
return b.String()
|
||
}
|