完善论坛配置与发帖体验:TipTap 富文本、图片上传、修订历史、Feed 排序与后台参数管理。

同步更新 README 与 ROADMAP,反映最新功能与开发状态。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
freefire
2026-06-16 04:11:38 +08:00
parent 1d273066b0
commit b451703642
73 changed files with 1943 additions and 752 deletions

View File

@@ -3,10 +3,7 @@ package service
import (
"errors"
"fmt"
"io"
"mime/multipart"
"os"
"path/filepath"
"strings"
"time"
@@ -14,11 +11,12 @@ import (
)
type UserService struct {
filter *SensitiveFilter
filter *SensitiveFilter
settings *ForumSettingsService
}
func NewUserService(filter *SensitiveFilter) *UserService {
return &UserService{filter: filter}
func NewUserService(filter *SensitiveFilter, settings *ForumSettingsService) *UserService {
return &UserService{filter: filter, settings: settings}
}
// GetByID 获取用户信息
@@ -51,7 +49,7 @@ func (s *UserService) UpdateNickname(userID uint, nickname string) error {
// UpdatePassword 修改密码
func (s *UserService) UpdatePassword(userID uint, oldPass, newPass string) error {
if err := ValidatePassword(newPass); err != nil {
if err := ValidatePassword(newPass, s.settings.PasswordMinLen()); err != nil {
return err
}
var user model.User
@@ -70,32 +68,11 @@ func (s *UserService) UpdatePassword(userID uint, oldPass, newPass string) error
// UploadAvatar 上传头像到本地目录
func (s *UserService) UploadAvatar(userID uint, file *multipart.FileHeader, uploadDir string) (string, error) {
ext := strings.ToLower(filepath.Ext(file.Filename))
allowed := map[string]bool{".jpg": true, ".jpeg": true, ".png": true, ".gif": true, ".webp": true}
if !allowed[ext] {
return "", errors.New("仅支持 jpg/png/gif/webp 格式")
}
filename := fmt.Sprintf("%d%s", userID, ext)
destPath := filepath.Join(uploadDir, filename)
src, err := file.Open()
url, err := SaveUploadedImage(file, uploadDir, "/uploads/avatars", fmt.Sprintf("%d", userID))
if err != nil {
return "", err
}
defer src.Close()
dst, err := os.Create(destPath)
if err != nil {
return "", err
}
defer dst.Close()
if _, err := io.Copy(dst, src); err != nil {
return "", err
}
avatarURL := "/uploads/avatars/" + filename
return avatarURL, model.DB.Model(&model.User{}).Where("id = ?", userID).Update("avatar", avatarURL).Error
return url, model.DB.Model(&model.User{}).Where("id = ?", userID).Update("avatar", url).Error
}
// ListUsers 管理员列出用户