更新个人资料页实现评估会议记录,明确展示与编辑页字段一致性要求,补充技能字段的展示与编辑需求。优化小程序页面,增加联系方式完善弹窗,确保用户在使用找伙伴功能前填写手机号或微信号。调整相关文档以反映最新进展,提升用户体验与功能一致性。
This commit is contained in:
@@ -12,6 +12,9 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// excludeParts 排除序言、尾声、附录(不参与精选推荐/热门排序)
|
||||
var excludeParts = []string{"序言", "尾声", "附录"}
|
||||
|
||||
// BookAllChapters GET /api/book/all-chapters 返回所有章节(列表,来自 chapters 表)
|
||||
func BookAllChapters(c *gin.Context) {
|
||||
var list []model.Chapter
|
||||
@@ -174,13 +177,96 @@ func BookChapters(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "不支持的请求方法"})
|
||||
}
|
||||
|
||||
// BookHot GET /api/book/hot
|
||||
// bookHotChaptersSorted 按精选推荐算法排序:阅读量优先,同量按更新时间;排除序言/尾声/附录
|
||||
func bookHotChaptersSorted(db *gorm.DB, limit int) []model.Chapter {
|
||||
q := db.Model(&model.Chapter{})
|
||||
for _, p := range excludeParts {
|
||||
q = q.Where("part_title NOT LIKE ?", "%"+p+"%")
|
||||
}
|
||||
var all []model.Chapter
|
||||
if err := q.Order("sort_order ASC, id ASC").Find(&all).Error; err != nil || len(all) == 0 {
|
||||
return nil
|
||||
}
|
||||
// 从 reading_progress 统计阅读量
|
||||
ids := make([]string, 0, len(all))
|
||||
for _, c := range all {
|
||||
ids = append(ids, c.ID)
|
||||
}
|
||||
var counts []struct {
|
||||
SectionID string `gorm:"column:section_id"`
|
||||
Cnt int64 `gorm:"column:cnt"`
|
||||
}
|
||||
db.Table("reading_progress").Select("section_id, COUNT(*) as cnt").
|
||||
Where("section_id IN ?", ids).Group("section_id").Scan(&counts)
|
||||
countMap := make(map[string]int64)
|
||||
for _, r := range counts {
|
||||
countMap[r.SectionID] = r.Cnt
|
||||
}
|
||||
// 按阅读量降序、同量按 updated_at 降序
|
||||
type withSort struct {
|
||||
ch model.Chapter
|
||||
cnt int64
|
||||
}
|
||||
withCnt := make([]withSort, 0, len(all))
|
||||
for _, c := range all {
|
||||
withCnt = append(withCnt, withSort{ch: c, cnt: countMap[c.ID]})
|
||||
}
|
||||
for i := 0; i < len(withCnt)-1; i++ {
|
||||
for j := i + 1; j < len(withCnt); j++ {
|
||||
if withCnt[j].cnt > withCnt[i].cnt ||
|
||||
(withCnt[j].cnt == withCnt[i].cnt && withCnt[j].ch.UpdatedAt.After(withCnt[i].ch.UpdatedAt)) {
|
||||
withCnt[i], withCnt[j] = withCnt[j], withCnt[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
out := make([]model.Chapter, 0, limit)
|
||||
for i := 0; i < limit && i < len(withCnt); i++ {
|
||||
out = append(out, withCnt[i].ch)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// BookHot GET /api/book/hot 热门章节(按阅读量排序,排除序言/尾声/附录)
|
||||
func BookHot(c *gin.Context) {
|
||||
var list []model.Chapter
|
||||
database.DB().Order("sort_order ASC, id ASC").Limit(10).Find(&list)
|
||||
list := bookHotChaptersSorted(database.DB(), 10)
|
||||
if len(list) == 0 {
|
||||
// 兜底:按 sort_order 取前 10,同样排除序言/尾声/附录
|
||||
q := database.DB().Model(&model.Chapter{})
|
||||
for _, p := range excludeParts {
|
||||
q = q.Where("part_title NOT LIKE ?", "%"+p+"%")
|
||||
}
|
||||
q.Order("sort_order ASC, id ASC").Limit(10).Find(&list)
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "data": list})
|
||||
}
|
||||
|
||||
// BookRecommended GET /api/book/recommended 精选推荐(首页「为你推荐」前 3 章,带 热门/推荐/精选 标签)
|
||||
func BookRecommended(c *gin.Context) {
|
||||
list := bookHotChaptersSorted(database.DB(), 3)
|
||||
if len(list) == 0 {
|
||||
// 兜底:按 updated_at 取前 3,同样排除序言/尾声/附录
|
||||
q := database.DB().Model(&model.Chapter{})
|
||||
for _, p := range excludeParts {
|
||||
q = q.Where("part_title NOT LIKE ?", "%"+p+"%")
|
||||
}
|
||||
q.Order("updated_at DESC, id ASC").Limit(3).Find(&list)
|
||||
}
|
||||
tags := []string{"热门", "推荐", "精选"}
|
||||
out := make([]gin.H, 0, len(list))
|
||||
for i, ch := range list {
|
||||
tag := "精选"
|
||||
if i < len(tags) {
|
||||
tag = tags[i]
|
||||
}
|
||||
out = append(out, gin.H{
|
||||
"id": ch.ID, "mid": ch.MID, "sectionTitle": ch.SectionTitle, "partTitle": ch.PartTitle,
|
||||
"chapterTitle": ch.ChapterTitle, "tag": tag,
|
||||
"isFree": ch.IsFree, "price": ch.Price, "isNew": ch.IsNew,
|
||||
})
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "data": out})
|
||||
}
|
||||
|
||||
// BookLatestChapters GET /api/book/latest-chapters
|
||||
func BookLatestChapters(c *gin.Context) {
|
||||
var list []model.Chapter
|
||||
|
||||
@@ -16,6 +16,7 @@ type sectionListItem struct {
|
||||
Title string `json:"title"`
|
||||
Price float64 `json:"price"`
|
||||
IsFree *bool `json:"isFree,omitempty"`
|
||||
IsNew *bool `json:"isNew,omitempty"` // stitch_soul:标记最新新增
|
||||
PartID string `json:"partId"`
|
||||
PartTitle string `json:"partTitle"`
|
||||
ChapterID string `json:"chapterId"`
|
||||
@@ -48,6 +49,7 @@ func DBBookAction(c *gin.Context) {
|
||||
Title: r.SectionTitle,
|
||||
Price: price,
|
||||
IsFree: r.IsFree,
|
||||
IsNew: r.IsNew,
|
||||
PartID: r.PartID,
|
||||
PartTitle: r.PartTitle,
|
||||
ChapterID: r.ChapterID,
|
||||
@@ -81,6 +83,7 @@ func DBBookAction(c *gin.Context) {
|
||||
"title": ch.SectionTitle,
|
||||
"price": price,
|
||||
"content": ch.Content,
|
||||
"isNew": ch.IsNew,
|
||||
"partId": ch.PartID,
|
||||
"partTitle": ch.PartTitle,
|
||||
"chapterId": ch.ChapterID,
|
||||
@@ -101,7 +104,7 @@ func DBBookAction(c *gin.Context) {
|
||||
price = *r.Price
|
||||
}
|
||||
sections = append(sections, sectionListItem{
|
||||
ID: r.ID, Title: r.SectionTitle, Price: price, IsFree: r.IsFree,
|
||||
ID: r.ID, Title: r.SectionTitle, Price: price, IsFree: r.IsFree, IsNew: r.IsNew,
|
||||
PartID: r.PartID, PartTitle: r.PartTitle, ChapterID: r.ChapterID, ChapterTitle: r.ChapterTitle,
|
||||
})
|
||||
}
|
||||
@@ -181,6 +184,7 @@ func DBBookAction(c *gin.Context) {
|
||||
Content string `json:"content"`
|
||||
Price *float64 `json:"price"`
|
||||
IsFree *bool `json:"isFree"`
|
||||
IsNew *bool `json:"isNew"` // stitch_soul:标记最新新增
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil || body.ID == "" {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "缺少 id 或请求体无效"})
|
||||
@@ -202,6 +206,9 @@ func DBBookAction(c *gin.Context) {
|
||||
"price": price,
|
||||
"is_free": isFree,
|
||||
}
|
||||
if body.IsNew != nil {
|
||||
updates["is_new"] = *body.IsNew
|
||||
}
|
||||
err := db.Model(&model.Chapter{}).Where("id = ?", body.ID).Updates(updates).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
|
||||
@@ -207,24 +207,50 @@ func UserProfileGet(c *gin.Context) {
|
||||
}
|
||||
profileComplete := (user.Phone != nil && *user.Phone != "") || (user.WechatID != nil && *user.WechatID != "")
|
||||
hasAvatar := user.Avatar != nil && *user.Avatar != "" && len(*user.Avatar) > 0
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "data": gin.H{
|
||||
resp := gin.H{
|
||||
"id": user.ID, "openId": user.OpenID, "nickname": user.Nickname, "avatar": user.Avatar,
|
||||
"phone": user.Phone, "wechatId": user.WechatID, "referralCode": user.ReferralCode,
|
||||
"hasFullBook": user.HasFullBook, "earnings": user.Earnings, "pendingEarnings": user.PendingEarnings,
|
||||
"referralCount": user.ReferralCount, "profileComplete": profileComplete, "hasAvatar": hasAvatar,
|
||||
"createdAt": user.CreatedAt,
|
||||
}})
|
||||
}
|
||||
// P3 资料扩展
|
||||
if user.Mbti != nil { resp["mbti"] = user.Mbti }
|
||||
if user.Region != nil { resp["region"] = user.Region }
|
||||
if user.Industry != nil { resp["industry"] = user.Industry }
|
||||
if user.Position != nil { resp["position"] = user.Position }
|
||||
if user.BusinessScale != nil { resp["businessScale"] = user.BusinessScale }
|
||||
if user.Skills != nil { resp["skills"] = user.Skills }
|
||||
if user.StoryBestMonth != nil { resp["storyBestMonth"] = user.StoryBestMonth }
|
||||
if user.StoryAchievement != nil { resp["storyAchievement"] = user.StoryAchievement }
|
||||
if user.StoryTurning != nil { resp["storyTurning"] = user.StoryTurning }
|
||||
if user.HelpOffer != nil { resp["helpOffer"] = user.HelpOffer }
|
||||
if user.HelpNeed != nil { resp["helpNeed"] = user.HelpNeed }
|
||||
if user.ProjectIntro != nil { resp["projectIntro"] = user.ProjectIntro }
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "data": resp})
|
||||
}
|
||||
|
||||
// UserProfilePost POST /api/user/profile 更新用户资料
|
||||
func UserProfilePost(c *gin.Context) {
|
||||
var body struct {
|
||||
UserID string `json:"userId"`
|
||||
OpenID string `json:"openId"`
|
||||
Nickname *string `json:"nickname"`
|
||||
Avatar *string `json:"avatar"`
|
||||
Phone *string `json:"phone"`
|
||||
WechatID *string `json:"wechatId"`
|
||||
UserID string `json:"userId"`
|
||||
OpenID string `json:"openId"`
|
||||
Nickname *string `json:"nickname"`
|
||||
Avatar *string `json:"avatar"`
|
||||
Phone *string `json:"phone"`
|
||||
WechatID *string `json:"wechatId"`
|
||||
Mbti *string `json:"mbti"`
|
||||
Region *string `json:"region"`
|
||||
Industry *string `json:"industry"`
|
||||
Position *string `json:"position"`
|
||||
BusinessScale *string `json:"businessScale"`
|
||||
Skills *string `json:"skills"`
|
||||
StoryBestMonth *string `json:"storyBestMonth"`
|
||||
StoryAchievement *string `json:"storyAchievement"`
|
||||
StoryTurning *string `json:"storyTurning"`
|
||||
HelpOffer *string `json:"helpOffer"`
|
||||
HelpNeed *string `json:"helpNeed"`
|
||||
ProjectIntro *string `json:"projectIntro"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "请提供userId或openId"})
|
||||
@@ -264,6 +290,18 @@ func UserProfilePost(c *gin.Context) {
|
||||
if body.WechatID != nil {
|
||||
updates["wechat_id"] = *body.WechatID
|
||||
}
|
||||
if body.Mbti != nil { updates["mbti"] = *body.Mbti }
|
||||
if body.Region != nil { updates["region"] = *body.Region }
|
||||
if body.Industry != nil { updates["industry"] = *body.Industry }
|
||||
if body.Position != nil { updates["position"] = *body.Position }
|
||||
if body.BusinessScale != nil { updates["business_scale"] = *body.BusinessScale }
|
||||
if body.Skills != nil { updates["skills"] = *body.Skills }
|
||||
if body.StoryBestMonth != nil { updates["story_best_month"] = *body.StoryBestMonth }
|
||||
if body.StoryAchievement != nil { updates["story_achievement"] = *body.StoryAchievement }
|
||||
if body.StoryTurning != nil { updates["story_turning"] = *body.StoryTurning }
|
||||
if body.HelpOffer != nil { updates["help_offer"] = *body.HelpOffer }
|
||||
if body.HelpNeed != nil { updates["help_need"] = *body.HelpNeed }
|
||||
if body.ProjectIntro != nil { updates["project_intro"] = *body.ProjectIntro }
|
||||
if len(updates) == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "没有需要更新的字段"})
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user