Files
pure-note/cmd/pn/seed.go
T
wangairnan 5457aeaa33 feat: 新增发布日期自选、站点 Logo、回收站清空等十项改进
- 编辑页标题改 filled 变体;标签改 tags 选择器(可勾选既有/输入新建)
- 笔记发布日期可自选(schema v2 新增 published_at 并回填),前台展示发布日期
- 登录页移除「请输入管理密码以继续」「连续失败将被暂时锁定」文案
- 站点设置每页条数收敛为 10/20/30/50 选择器,后端白名单同源校验
- 站点设置两卡片宽屏左右/窄屏上下;修改密码按钮改常规大小
- 后台各页顶栏固定高度,切换页面不再抖动
- 站点 Logo:settings 新增 site_logo(站内路径),gc/孤儿清单豁免 Logo 图片,
  博客 header 站点名前展示,设置页支持上传/更换/清除
- 回收站右上角一键清空(DELETE /api/admin/trash,含确认弹窗)
- pn init 写入 Markdown 语法示例文档(slug welcome,公开)与程序生成的示例图片
2026-09-09 11:10:30 +08:00

184 lines
4.5 KiB
Go
Raw Permalink 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.
// init 种子内容:一篇展示常用 Markdown 语法的初始文档 + 一张程序生成的示例图片。
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"image"
"image/color"
"image/png"
"time"
"pure-note/internal/store"
)
// welcomeSlug 固定 slug,便于用户识别与重装后覆盖判断(init 幂等由口令守卫保证)。
const welcomeSlug = "welcome"
// seedWelcome 写入初始文档(公开)与其引用的示例图片;返回写入的笔记 id。
func seedWelcome(st *store.Store) (int64, error) {
imgID, err := seedWelcomeImage(st)
if err != nil {
return 0, fmt.Errorf("写入示例图片: %w", err)
}
content := welcomeMarkdown(imgID)
now := time.Now().Unix()
n := &store.Note{
Slug: welcomeSlug,
Title: "欢迎使用 Pure Note:Markdown 速览",
Summary: "一篇入门笔记,覆盖日常写作会用到的全部 Markdown 语法:标题、列表、引用、代码、表格与图片。",
Content: content,
Status: "public",
Tags: []string{"Markdown", "入门"},
PublishedAt: now,
CreatedAt: now,
UpdatedAt: now,
}
id, err := st.CreateNote(n)
if err != nil {
return 0, err
}
if err := st.RebuildImageRefs(id, content); err != nil {
return 0, err
}
return id, nil
}
// welcomeMarkdown 初始文档正文:覆盖常用语法,并引用示例图片。
func welcomeMarkdown(imgID int64) string {
return fmt.Sprintf(`这是一篇初始化时自动创建的示例笔记,覆盖日常写作会用到的绝大部分 Markdown 语法。随时可以编辑或删除它。
## 基础排版
普通段落之间用一个空行分隔。行内语法有:**加粗**、*斜体*、***粗斜体***、~~删除线~~,以及行内代码 `+"`pn start`"+`。也可以直接粘贴链接:<https://github.com>
## 标题层级
### 三级标题
#### 四级标题
标题会进入文章大纲,正文建议从二级标题用起。
## 列表
无序列表:
- 支持嵌套
- 子项缩进两个空格
- 快捷键 `+"`Ctrl/⌘ + S`"+` 可手动保存
有序列表:
1. 在编辑器里写 Markdown
2. 粘贴图片直接上传
3. 点击发布即可访问
任务列表:
- [x] 初始化站点
- [x] 阅读本文档
- [ ] 写第一篇笔记
## 引用
> 简单,可靠,只有一个数据文件。
> —— Pure Note 设计哲学
## 代码块
代码块支持语法高亮:
`+"```go"+`
package main
import "fmt"
func main() {
fmt.Println("Hello, Pure Note!")
}
`+"```"+`
`+"```"+`javascript
const note = { title: "你好", tags: ["Markdown"] };
console.log(`+"`开始写作:${note.title}`"+`);
`+"```"+`
## 表格
| 语法 | 用途 | 示例 |
| --- | --- | --- |
| **文本** | 加粗 | **重要** |
| `+"`代码`"+` | 行内代码 | `+"`npm run dev`"+` |
| [文本](url) | 超链接 | [首页](/) |
## 图片
在编辑器里直接粘贴或拖入图片即可上传(≤5MB),下面这张就是初始化时自动生成的示例图:
![示例图片](/api/images/%d)
## 其他
---
私有笔记仅自己可见,公开笔记会出现在首页与 RSS 中;删除的笔记进入回收站保留 30 天。祝写作愉快。
`, imgID)
}
// seedWelcomeImage 生成一张对角渐变 PNG(zinc 色系),入库后返回图片 id。
func seedWelcomeImage(st *store.Store) (int64, error) {
data, err := gradientPNG()
if err != nil {
return 0, err
}
return st.UpsertImage(sha256Hex(data), "image/png", len(data), data, time.Now().Unix())
}
// gradientPNG 绘制 960×360 对角渐变:zinc-950 → zinc-400,叠加一条高光斜带。
func gradientPNG() ([]byte, error) {
const w, h = 960, 360
img := image.NewNRGBA(image.Rect(0, 0, w, h))
from := color.RGBA{R: 24, G: 24, B: 27, A: 255} // #18181b
to := color.RGBA{R: 161, G: 161, B: 170, A: 255} // #a1a1aa
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
t := (float64(x)/float64(w-1) + float64(y)/float64(h-1)) / 2
// 高光斜带:在 t≈0.55 附近提亮,形成柔和的光泽过渡
band := 0.16 * float64(1) / (1 + pow2((t-0.55)*9))
c := color.RGBA{
R: lerp(from.R, to.R, t+band),
G: lerp(from.G, to.G, t+band),
B: lerp(from.B, to.B, t+band),
A: 255,
}
img.Set(x, y, c)
}
}
var buf bytes.Buffer
if err := png.Encode(&buf, img); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func lerp(a, b uint8, t float64) uint8 {
if t < 0 {
t = 0
} else if t > 1 {
t = 1
}
return uint8(float64(a) + (float64(b)-float64(a))*t)
}
func pow2(x float64) float64 { return x * x }
func sha256Hex(b []byte) string {
sum := sha256.Sum256(b)
return hex.EncodeToString(sum[:])
}