feat: enhance member detail page with dynamic tabs and image handling
- Introduced member business tabs for profile and dynamics, improving navigation and user experience. - Implemented image parsing and normalization functions to handle article images effectively. - Updated the UI to display article thumbnails and manage loading states, enhancing visual feedback. - Refactored data synchronization methods to ensure member business tabs reflect current content accurately. This update aims to streamline member profile interactions and improve the overall presentation of member-related content.
This commit is contained in:
@@ -164,6 +164,53 @@ func MiniprogramSuperArticleFeed(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func deriveSuperArticleTitleFromContent(content string) string {
|
||||
content = strings.TrimSpace(content)
|
||||
if content == "" {
|
||||
return ""
|
||||
}
|
||||
parts := strings.SplitN(content, "\n", 2)
|
||||
line := strings.TrimSpace(parts[0])
|
||||
line = strings.TrimRight(line, "\r")
|
||||
if line == "" {
|
||||
return ""
|
||||
}
|
||||
rs := []rune(line)
|
||||
if len(rs) > 40 {
|
||||
return string(rs[:40])
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
// finalizeSuperArticleTitleAndBody 发动态:标题可省略(由正文首行或默认文案补齐);正文与配图至少一项。
|
||||
func finalizeSuperArticleTitleAndBody(title, content string, imageCount int) (outTitle, outBody, errMsg string) {
|
||||
title = strings.TrimSpace(title)
|
||||
content = strings.TrimSpace(content)
|
||||
if content == "" && imageCount == 0 {
|
||||
return "", "", "请填写文字或添加配图"
|
||||
}
|
||||
if len([]rune(content)) > 5000 {
|
||||
return "", "", "正文最多 5000 字"
|
||||
}
|
||||
outTitle = title
|
||||
if outTitle != "" && len([]rune(outTitle)) > 40 {
|
||||
outTitle = string([]rune(outTitle)[:40])
|
||||
}
|
||||
if outTitle == "" {
|
||||
outTitle = deriveSuperArticleTitleFromContent(content)
|
||||
}
|
||||
if outTitle == "" && imageCount > 0 {
|
||||
outTitle = "分享图片"
|
||||
}
|
||||
if outTitle == "" {
|
||||
outTitle = "动态"
|
||||
}
|
||||
if len([]rune(outTitle)) > 40 {
|
||||
outTitle = string([]rune(outTitle)[:40])
|
||||
}
|
||||
return outTitle, content, ""
|
||||
}
|
||||
|
||||
func normalizeSuperArticleImageURLs(in []string) ([]string, string) {
|
||||
if len(in) == 0 {
|
||||
return []string{}, ""
|
||||
@@ -208,16 +255,8 @@ func MiniprogramSuperArticleCreate(c *gin.Context) {
|
||||
req.UserID = strings.TrimSpace(req.UserID)
|
||||
req.Title = strings.TrimSpace(req.Title)
|
||||
req.Content = strings.TrimSpace(req.Content)
|
||||
if req.UserID == "" || req.Title == "" || req.Content == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "标题和正文不能为空"})
|
||||
return
|
||||
}
|
||||
if len([]rune(req.Title)) > 40 {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "标题最多 40 字"})
|
||||
return
|
||||
}
|
||||
if len([]rune(req.Content)) > 5000 {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "正文最多 5000 字"})
|
||||
if req.UserID == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "参数错误"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -232,6 +271,13 @@ func MiniprogramSuperArticleCreate(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
title, body, verr := finalizeSuperArticleTitleAndBody(req.Title, req.Content, len(imgURLs))
|
||||
if verr != "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": verr})
|
||||
return
|
||||
}
|
||||
req.Title, req.Content = title, body
|
||||
|
||||
db := database.DB()
|
||||
if _, ok := miniprogramSuperIndividualPerson(db, req.UserID); !ok {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "仅超级个体可发文章", "forbidden": true})
|
||||
@@ -468,16 +514,8 @@ func MiniprogramSuperArticleUpdate(c *gin.Context) {
|
||||
req.UserID = strings.TrimSpace(req.UserID)
|
||||
req.Title = strings.TrimSpace(req.Title)
|
||||
req.Content = strings.TrimSpace(req.Content)
|
||||
if req.UserID == "" || req.Title == "" || req.Content == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "标题和正文不能为空"})
|
||||
return
|
||||
}
|
||||
if len([]rune(req.Title)) > 40 {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "标题最多 40 字"})
|
||||
return
|
||||
}
|
||||
if len([]rune(req.Content)) > 5000 {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "正文最多 5000 字"})
|
||||
if req.UserID == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "参数错误"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -492,6 +530,13 @@ func MiniprogramSuperArticleUpdate(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
title, body, verr := finalizeSuperArticleTitleAndBody(req.Title, req.Content, len(imgURLs))
|
||||
if verr != "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": verr})
|
||||
return
|
||||
}
|
||||
req.Title, req.Content = title, body
|
||||
|
||||
db := database.DB()
|
||||
var row model.SuperArticle
|
||||
if err := db.First(&row, id).Error; err != nil {
|
||||
@@ -531,3 +576,42 @@ func MiniprogramSuperArticleUpdate(c *gin.Context) {
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||
}
|
||||
|
||||
// MiniprogramSuperArticleDelete 删除动态(作者本人 + 超级个体)。
|
||||
// DELETE /api/miniprogram/super/articles/:id?userId=
|
||||
// POST /api/miniprogram/super/articles/:id/delete?userId= (与 DELETE 等价,便于不支持 DELETE 的客户端调试)
|
||||
func MiniprogramSuperArticleDelete(c *gin.Context) {
|
||||
idRaw := strings.TrimSpace(c.Param("id"))
|
||||
id, err := strconv.ParseUint(idRaw, 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "参数错误"})
|
||||
return
|
||||
}
|
||||
userID := strings.TrimSpace(c.Query("userId"))
|
||||
if userID == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "缺少 userId"})
|
||||
return
|
||||
}
|
||||
|
||||
db := database.DB()
|
||||
if _, ok := miniprogramSuperIndividualPerson(db, userID); !ok {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "仅超级个体可操作", "forbidden": true})
|
||||
return
|
||||
}
|
||||
|
||||
var row model.SuperArticle
|
||||
if err := db.First(&row, id).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "动态不存在"})
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(row.UserID) != userID {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "无权删除"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.Delete(&row).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user