feat(settings): 个人资料编辑 + 头像上传/裁切 + 自定义裁切弹窗

**新增功能:**

用户名编辑:输入框替换静态文本,白名单验证(中文/英文/数字/下划线/连字符),前端计数器(n/16),utf8对齐PG VARCHAR,XSS防控。

个性签名编辑:Textarea,128字符上限,实时计数器。

头像上传管线:校验→解码→裁切→CatmullRom缩放→WebP二分编码≤100KB→原子写入(.tmp→os.Rename)。限制5MB,128-3840px,JPEG/PNG/WebP。输出512x512 WebP。文件名 {uid}_{timestamp}.webp。清理旧头像。

自定义裁切弹窗:浅色主题,固定裁切框+图片平移/缩放(1×-3×滚轮),box-shadow遮罩,三等分网格。坐标映射pan/zoom→原图像素→subImage。

CSP修复:img-src允许data:URI(FileReader预览)。

**文件变更:**
修改: README, docs/{development,structure}.md, go.{mod,sum}, cmd/server/main.go, controller/settings, middleware/security, router, templates/settings/{index.html,css}
新增: internal/service/avatar_service.go, docs/settings.md
This commit is contained in:
2026-05-27 01:03:16 +08:00
parent debaa17127
commit c3dec09dae
13 changed files with 923 additions and 17 deletions

View File

@ -9,8 +9,9 @@ import (
func SecurityHeaders() gin.HandlerFunc {
return func(c *gin.Context) {
// Content-Security-Policy仅允许本站资源 + 内联样式/脚本
// img-src 允许 data: URI 用于头像裁切预览等场景
c.Header("Content-Security-Policy",
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'")
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:")
// 禁止 MIME 类型嗅探
c.Header("X-Content-Type-Options", "nosniff")