feat(hide): 密码可见隐藏块,发帖双栏预览与门禁体验修复
增加密码解锁与游客签名 cookie;发帖页对齐 1440 并默认双栏预览;修复 locked 解析、按钮对比度与回复聚焦。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -30,6 +30,7 @@ type Handlers struct {
|
||||
Chat *service.ChatService
|
||||
Telemetry *service.TelemetryService
|
||||
Analytics *service.AnalyticsService
|
||||
HidePwd *service.HidePasswordCookie
|
||||
}
|
||||
|
||||
// resolvePublishStatus 决定新帖/新评的初始状态:
|
||||
|
||||
@@ -78,7 +78,8 @@ func (h *Handlers) PostDetail(c *gin.Context) {
|
||||
viewerID = claims.ID
|
||||
loadActor = h.actorLoader(claims.ID)
|
||||
}
|
||||
post, err := h.Post.GetByIDForViewer(uint(id), viewerID, loadActor)
|
||||
pwdUnlocked := h.HidePwd.ReadUnlocked(c, uint(id))
|
||||
post, err := h.Post.GetByIDForViewer(uint(id), viewerID, loadActor, pwdUnlocked)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "帖子不存在"})
|
||||
return
|
||||
@@ -189,6 +190,56 @@ func (h *Handlers) UnlockPostContent(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"post": post})
|
||||
}
|
||||
|
||||
// UnlockPostPasswordRequest 密码解锁隐藏块
|
||||
type UnlockPostPasswordRequest struct {
|
||||
Password string `json:"password" binding:"required,min=1,max=64"`
|
||||
}
|
||||
|
||||
// UnlockPostPassword 输入密码解锁正文密码隐藏块(游客可用,签名 cookie 记住)
|
||||
func (h *Handlers) UnlockPostPassword(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的帖子 ID"})
|
||||
return
|
||||
}
|
||||
var req UnlockPostPasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "请输入密码"})
|
||||
return
|
||||
}
|
||||
matched, err := h.Post.UnlockByPassword(uint(id), req.Password)
|
||||
if err != nil {
|
||||
if errors.Is(err, service.ErrPostNotFound) {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "帖子不存在"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
h.HidePwd.WriteUnlocked(c, uint(id), matched)
|
||||
|
||||
claims := middleware.CurrentUser(c)
|
||||
var viewerID uint
|
||||
var loadActor func() *service.Actor
|
||||
if claims != nil {
|
||||
viewerID = claims.ID
|
||||
loadActor = h.actorLoader(claims.ID)
|
||||
}
|
||||
pwdUnlocked := h.HidePwd.ReadUnlocked(c, uint(id))
|
||||
for _, i := range matched {
|
||||
pwdUnlocked[i] = true
|
||||
}
|
||||
post, err := h.Post.GetByIDForViewer(uint(id), viewerID, loadActor, pwdUnlocked)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "帖子不存在"})
|
||||
return
|
||||
}
|
||||
if claims != nil {
|
||||
post.Liked = h.Like.HasLiked(post.ID, claims.ID)
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"post": post})
|
||||
}
|
||||
|
||||
// GetPointsBalance 当前用户积分余额
|
||||
func (h *Handlers) GetPointsBalance(c *gin.Context) {
|
||||
claims := middleware.CurrentUser(c)
|
||||
|
||||
Reference in New Issue
Block a user