Merge branch 'r/paopao-ce-plus' into r/paopao-ce-xtra

r/paopao-ce-xtra
Michael Li 2 years ago
commit 2ee7b9e1fc
No known key found for this signature in database

@ -147,6 +147,7 @@ All notable changes to paopao-ce are documented in this file.
WHERE is_del=0 WHERE is_del=0
GROUP BY user_id; GROUP BY user_id;
``` ```
- add message filter support for message page.
## 0.4.2 ## 0.4.2
### Fixed ### Fixed

@ -220,13 +220,17 @@ func RegisterCoreServant(e *gin.Engine, s Core) {
default: default:
} }
req := new(web.GetMessagesReq) req := new(web.GetMessagesReq)
var bv _binding_ = req if err := s.Bind(c, req); err != nil {
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err) s.Render(c, nil, err)
return return
} }
resp, err := s.GetMessages(req) resp, err := s.GetMessages(req)
s.Render(c, resp, err) if err != nil {
s.Render(c, nil, err)
return
}
var rv _render_ = resp
rv.Render(c)
}) })
router.Handle("GET", "/user/info", func(c *gin.Context) { router.Handle("GET", "/user/info", func(c *gin.Context) {
select { select {

@ -0,0 +1,66 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Trends interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
GetIndexTrends(*web.GetIndexTrendsReq) (*web.GetIndexTrendsResp, mir.Error)
mustEmbedUnimplementedTrendsServant()
}
// RegisterTrendsServant register Trends servant to gin
func RegisterTrendsServant(e *gin.Engine, s Trends) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("GET", "/trends/index", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.GetIndexTrendsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetIndexTrends(req)
if err != nil {
s.Render(c, nil, err)
return
}
var rv _render_ = resp
rv.Render(c)
})
}
// UnimplementedTrendsServant can be embedded to have forward compatible implementations.
type UnimplementedTrendsServant struct{}
func (UnimplementedTrendsServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedTrendsServant) GetIndexTrends(req *web.GetIndexTrendsReq) (*web.GetIndexTrendsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedTrendsServant) mustEmbedUnimplementedTrendsServant() {}

@ -29,6 +29,8 @@ const (
PrefixIdxTweetsNewest = "paopao:index:tweets:newest:" PrefixIdxTweetsNewest = "paopao:index:tweets:newest:"
PrefixIdxTweetsHots = "paopao:index:tweets:hots:" PrefixIdxTweetsHots = "paopao:index:tweets:hots:"
PrefixIdxTweetsFollowing = "paopao:index:tweets:following:" PrefixIdxTweetsFollowing = "paopao:index:tweets:following:"
PrefixIdxTrends = "paopao:index:trends:"
PrefixMessages = "paopao:messages:"
PrefixUserInfo = "paopao:userinfo:" PrefixUserInfo = "paopao:userinfo:"
PrefixUserInfoById = "paopao:userinfo:id:" PrefixUserInfoById = "paopao:userinfo:id:"
PrefixUserInfoByName = "paopao:userinfo:name:" PrefixUserInfoByName = "paopao:userinfo:name:"

@ -12,9 +12,11 @@ Cache:
UserTweetsExpire: 60 # 获取用户推文列表过期时间,单位秒, 默认60s UserTweetsExpire: 60 # 获取用户推文列表过期时间,单位秒, 默认60s
IndexTweetsExpire: 120 # 获取广场推文列表过期时间,单位秒, 默认120s IndexTweetsExpire: 120 # 获取广场推文列表过期时间,单位秒, 默认120s
TweetCommentsExpire: 180 # 获取推文评论过期时间,单位秒, 默认180s TweetCommentsExpire: 180 # 获取推文评论过期时间,单位秒, 默认180s
IndexTrendsExpire: 300 # 获取广场动态信息过期时间,单位秒, 默认300s
OnlineUserExpire: 300 # 标记在线用户 过期时间,单位秒, 默认300s OnlineUserExpire: 300 # 标记在线用户 过期时间,单位秒, 默认300s
UserInfoExpire: 300 # 获取用户信息过期时间,单位秒, 默认300s UserInfoExpire: 300 # 获取用户信息过期时间,单位秒, 默认300s
UserRelationExpire: 600 # 用户关系信息过期时间,单位秒, 默认600s UserRelationExpire: 600 # 用户关系信息过期时间,单位秒, 默认600s
MessagesExpire: 60 # 消息列表过期时间,单位秒, 默认60s
EventManager: # 事件管理器的配置参数 EventManager: # 事件管理器的配置参数
MinWorker: 64 # 最小后台工作者, 设置范围[5, ++], 默认64 MinWorker: 64 # 最小后台工作者, 设置范围[5, ++], 默认64
MaxEventBuf: 128 # 最大log缓存条数, 设置范围[10, ++], 默认128 MaxEventBuf: 128 # 最大log缓存条数, 设置范围[10, ++], 默认128

@ -102,6 +102,8 @@ type cacheConf struct {
UnreadMsgExpire int64 UnreadMsgExpire int64
UserTweetsExpire int64 UserTweetsExpire int64
IndexTweetsExpire int64 IndexTweetsExpire int64
MessagesExpire int64
IndexTrendsExpire int64
TweetCommentsExpire int64 TweetCommentsExpire int64
OnlineUserExpire int64 OnlineUserExpire int64
UserInfoExpire int64 UserInfoExpire int64

@ -21,9 +21,13 @@ type DataService interface {
TweetHelpService TweetHelpService
// 推文指标服务 // 推文指标服务
UserMetricServantA
TweetMetricServantA TweetMetricServantA
CommentMetricServantA CommentMetricServantA
// 动态信息相关服务
TrendsManageServantA
// 评论服务 // 评论服务
CommentService CommentService
CommentManageService CommentManageService

@ -0,0 +1,16 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
const (
// 消息列表样式
StyleMsgAll MessageStyle = "all"
StyleMsgSystem MessageStyle = "system"
StyleMsgWhisper MessageStyle = "whisper"
StyleMsgRequesting MessageStyle = "requesting"
StyleMsgUnread MessageStyle = "unread"
)
type MessageStyle string

@ -2,11 +2,13 @@
// Use of this source code is governed by a MIT style // Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package cs contain core data service interface type
// model define
package cs package cs
const (
MetricActionCreateTweet uint8 = iota
MetricActionDeleteTweet
)
type TweetMetric struct { type TweetMetric struct {
PostId int64 PostId int64
CommentCount int64 CommentCount int64

@ -0,0 +1,12 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
type TrendsItem struct {
Username string `json:"username"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
IsFresh bool `json:"is_fresh" gorm:"-" db:"-"`
}

@ -5,6 +5,7 @@
package core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/core/ms" "github.com/rocboss/paopao-ce/internal/core/ms"
) )
@ -14,6 +15,5 @@ type MessageService interface {
GetUnreadCount(userID int64) (int64, error) GetUnreadCount(userID int64) (int64, error)
GetMessageByID(id int64) (*ms.Message, error) GetMessageByID(id int64) (*ms.Message, error)
ReadMessage(message *ms.Message) error ReadMessage(message *ms.Message) error
GetMessages(userId int64, offset, limit int) ([]*ms.MessageFormated, error) GetMessages(userId int64, style cs.MessageStyle, limit, offset int) ([]*ms.MessageFormated, int64, error)
GetMessageCount(userId int64) (int64, error)
} }

@ -0,0 +1,14 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
import (
"github.com/rocboss/paopao-ce/internal/core/cs"
)
// TrendsManageServantA 动态信息管理服务
type TrendsManageServantA interface {
GetIndexTrends(userId int64, limit int, offset int) ([]*cs.TrendsItem, int64, error)
}

@ -4,7 +4,9 @@
package core package core
import "github.com/rocboss/paopao-ce/internal/core/ms" import (
"github.com/rocboss/paopao-ce/internal/core/ms"
)
// UserManageService 用户管理服务 // UserManageService 用户管理服务
type UserManageService interface { type UserManageService interface {

@ -39,7 +39,9 @@ type dataSrv struct {
core.CommentService core.CommentService
core.CommentManageService core.CommentManageService
core.CommentMetricServantA core.CommentMetricServantA
core.TrendsManageServantA
core.UserManageService core.UserManageService
core.UserMetricServantA
core.ContactManageService core.ContactManageService
core.FollowingManageService core.FollowingManageService
core.UserRelationService core.UserRelationService
@ -59,11 +61,13 @@ func NewDataService() (core.DataService, core.VersionInfo) {
db := conf.MustGormDB() db := conf.MustGormDB()
pvs := security.NewPhoneVerifyService() pvs := security.NewPhoneVerifyService()
tms := newTweetMetricServentA(db) tms := newTweetMetricServentA(db)
ums := newUserMetricServentA(db)
cms := newCommentMetricServentA(db) cms := newCommentMetricServentA(db)
cis := cache.NewEventCacheIndexSrv(tms) cis := cache.NewEventCacheIndexSrv(tms)
ds := &dataSrv{ ds := &dataSrv{
TweetMetricServantA: tms, TweetMetricServantA: tms,
CommentMetricServantA: cms, CommentMetricServantA: cms,
UserMetricServantA: ums,
WalletService: newWalletService(db), WalletService: newWalletService(db),
MessageService: newMessageService(db), MessageService: newMessageService(db),
TopicService: newTopicService(db), TopicService: newTopicService(db),
@ -72,7 +76,8 @@ func NewDataService() (core.DataService, core.VersionInfo) {
TweetHelpService: newTweetHelpService(db), TweetHelpService: newTweetHelpService(db),
CommentService: newCommentService(db), CommentService: newCommentService(db),
CommentManageService: newCommentManageService(db), CommentManageService: newCommentManageService(db),
UserManageService: newUserManageService(db), TrendsManageServantA: newTrendsManageServentA(db),
UserManageService: newUserManageService(db, ums),
ContactManageService: newContactManageService(db), ContactManageService: newContactManageService(db),
FollowingManageService: newFollowingManageService(db), FollowingManageService: newFollowingManageService(db),
UserRelationService: newUserRelationService(db), UserRelationService: newUserRelationService(db),

@ -6,6 +6,7 @@ package jinzhu
import ( import (
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/core/ms" "github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm" "gorm.io/gorm"
@ -46,19 +47,35 @@ func (s *messageSrv) ReadMessage(message *ms.Message) error {
return message.Update(s.db) return message.Update(s.db)
} }
func (s *messageSrv) GetMessages(userId int64, offset, limit int) ([]*ms.MessageFormated, error) { func (s *messageSrv) GetMessages(userId int64, style cs.MessageStyle, limit int, offset int) (res []*ms.MessageFormated, total int64, err error) {
messages, err := (&dbr.Message{}).List(s.db, userId, offset, limit) var messages []*dbr.Message
if err != nil { db := s.db.Table(_message_)
return nil, err // 1动态2评论3回复4私信5好友申请99系统通知'
switch style {
case cs.StyleMsgSystem:
db = db.Where("receiver_user_id=? AND type IN (1, 2, 3, 99)", userId)
case cs.StyleMsgWhisper:
db = db.Where("(receiver_user_id=? OR sender_user_id=?) AND type=4", userId, userId)
case cs.StyleMsgRequesting:
db = db.Where("receiver_user_id=? AND type=5", userId)
case cs.StyleMsgUnread:
db = db.Where("receiver_user_id=? AND is_read=0", userId)
case cs.StyleMsgAll:
fallthrough
default:
db = db.Where("receiver_user_id=? OR (sender_user_id=? AND type=4)", userId, userId)
}
if err = db.Count(&total).Error; err != nil || total == 0 {
return
}
if offset >= 0 && limit > 0 {
db = db.Limit(limit).Offset(offset)
}
if err = db.Order("id DESC").Find(&messages).Error; err != nil {
return
} }
mfs := []*dbr.MessageFormated{}
for _, message := range messages { for _, message := range messages {
mf := message.Format() res = append(res, message.Format())
mfs = append(mfs, mf)
} }
return mfs, nil return
}
func (s *messageSrv) GetMessageCount(userId int64) (int64, error) {
return (&dbr.Message{}).Count(s.db, userId)
} }

@ -63,9 +63,23 @@ func (s *commentMetricSrvA) DeleteCommentMetric(commentId int64) (err error) {
return (&dbr.CommentMetric{CommentId: commentId}).Delete(s.db) return (&dbr.CommentMetric{CommentId: commentId}).Delete(s.db)
} }
func (s *userMetricSrvA) UpdateUserMetric(userId int64, action uint8) error { func (s *userMetricSrvA) UpdateUserMetric(userId int64, action uint8) (err error) {
// TODO metric := &dbr.UserMetric{}
return cs.ErrNotImplemented db := s.db.Model(metric)
if err = db.Where("user_id=?", userId).First(metric).Error; err != nil {
metric = &dbr.UserMetric{
UserId: userId,
}
}
switch action {
case cs.MetricActionCreateTweet:
metric.TweetsCount++
case cs.MetricActionDeleteTweet:
if metric.TweetsCount > 0 {
metric.TweetsCount--
}
}
return db.Save(metric).Error
} }
func (s *userMetricSrvA) AddUserMetric(userId int64) (err error) { func (s *userMetricSrvA) AddUserMetric(userId int64) (err error) {

@ -0,0 +1,38 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package jinzhu
import (
"fmt"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/cs"
"gorm.io/gorm"
)
type trendsSrvA struct {
db *gorm.DB
}
func (s *trendsSrvA) GetIndexTrends(userId int64, limit int, offset int) (res []*cs.TrendsItem, total int64, err error) {
db := s.db.Table(_user_).
Joins(fmt.Sprintf("JOIN %s c ON c.friend_id=%s.id AND c.user_id=? AND c.is_del=0", _contact_, _user_), userId).
Joins(fmt.Sprintf("JOIN %s m ON c.friend_id=m.user_id AND m.tweets_count>0 AND m.is_del=0", _userMetric_)).
Where(fmt.Sprintf("%s.is_del=0", _user_))
if err = db.Count(&total).Error; err != nil || total == 0 {
return
}
if offset >= 0 && limit > 0 {
db = db.Limit(limit).Offset(offset)
}
err = db.Find(&res).Error
return
}
func newTrendsManageServentA(db *gorm.DB) core.TrendsManageServantA {
return &trendsSrvA{
db: db,
}
}

@ -508,7 +508,7 @@ func (s *tweetSrv) getUserRelation(userId int64) (beFriendIds []int64, beFollowI
// 找到item即删数据库已经保证唯一性 // 找到item即删数据库已经保证唯一性
if beFollowIds[i] == id { if beFollowIds[i] == id {
lastIdx := len(beFollowIds) - 1 lastIdx := len(beFollowIds) - 1
beFriendIds[i] = beFriendIds[lastIdx] beFollowIds[i] = beFollowIds[lastIdx]
beFollowIds = beFollowIds[:lastIdx] beFollowIds = beFollowIds[:lastIdx]
break break
} }

@ -18,16 +18,18 @@ var (
) )
type userManageSrv struct { type userManageSrv struct {
db *gorm.DB db *gorm.DB
ums core.UserMetricServantA
} }
type userRelationSrv struct { type userRelationSrv struct {
db *gorm.DB db *gorm.DB
} }
func newUserManageService(db *gorm.DB) core.UserManageService { func newUserManageService(db *gorm.DB, ums core.UserMetricServantA) core.UserManageService {
return &userManageSrv{ return &userManageSrv{
db: db, db: db,
ums: ums,
} }
} }
@ -81,8 +83,12 @@ func (s *userManageSrv) GetUsersByKeyword(keyword string) ([]*ms.User, error) {
} }
} }
func (s *userManageSrv) CreateUser(user *dbr.User) (*ms.User, error) { func (s *userManageSrv) CreateUser(user *dbr.User) (res *ms.User, err error) {
return user.Create(s.db) if res, err = user.Create(s.db); err == nil {
// 宽松处理错误
s.ums.AddUserMetric(res.ID)
}
return
} }
func (s *userManageSrv) UpdateUser(user *ms.User) error { func (s *userManageSrv) UpdateUser(user *ms.User) error {

@ -26,23 +26,30 @@ const (
_Comment_GetCommentReplyById = `SELECT * FROM @comment_reply WHERE id=? AND is_del=0` _Comment_GetCommentReplyById = `SELECT * FROM @comment_reply WHERE id=? AND is_del=0`
_Comment_GetCommentThumbs = `SELECT user_id, tweet_id, comment_id, reply_id, comment_type, is_thumbs_up, is_thumbs_down FROM @tweet_comment_thumbs WHERE user_id=? AND tweet_id=?` _Comment_GetCommentThumbs = `SELECT user_id, tweet_id, comment_id, reply_id, comment_type, is_thumbs_up, is_thumbs_down FROM @tweet_comment_thumbs WHERE user_id=? AND tweet_id=?`
_Comment_GetCommmentRepliesByIds = `SELECT * FROM @comment_reply WHERE comment_id IN (?) ORDER BY id ASC` _Comment_GetCommmentRepliesByIds = `SELECT * FROM @comment_reply WHERE comment_id IN (?) ORDER BY id ASC`
_Comment_GetDefaultComments = `SELECT * FROM @comment WHERE post_id=? AND is_del=0 ORDER BY id ASC LIMIT ? OFFSET ?` _Comment_GetDefaultComments = `SELECT * FROM @comment WHERE post_id=? AND is_del=0 ORDER BY is_essence DESC, id ASC LIMIT ? OFFSET ?`
_Comment_GetHotsComments = `SELECT * FROM @comment WHERE post_id=? AND is_del=0 ORDER BY thumbs_up_count DESC, id DESC LIMIT ? OFFSET ?` _Comment_GetHotsComments = `SELECT c.* FROM @comment c LEFT JOIN @comment_metric m ON c.id=m.comment_id WHERE c.post_id=? AND c.is_del=0 AND m.is_del=0 ORDER BY is_essence DESC, m.rank_score DESC, id DESC LIMIT ? OFFSET ?`
_Comment_GetNewestComments = `SELECT * FROM @comment WHERE post_id=? AND is_del=0 ORDER BY id DESC LIMIT ? OFFSET ?` _Comment_GetNewestComments = `SELECT * FROM @comment WHERE post_id=? AND is_del=0 ORDER BY is_essence DESC, id DESC LIMIT ? OFFSET ?`
_Comment_GetUsersByIds = `SELECT id, nickname, username, status, avatar, is_admin FROM @user WHERE id IN (?)` _Comment_GetUsersByIds = `SELECT id, nickname, username, status, avatar, is_admin FROM @user WHERE id IN (?)`
_CommentManage_CreateComment = `INSERT INTO @comment (post_id, user_id, ip, ip_loc, created_on) VALUES (?, ?, ?, ?, ?)` _CommentManage_CreateComment = `INSERT INTO @comment (post_id, user_id, ip, ip_loc, created_on) VALUES (?, ?, ?, ?, ?)`
_CommentManage_CreateCommentContent = `INSERT INTO @comment_content (comment_id, user_id, content, type, sort, created_on) VALUES (?, ?, ?, ?, ?, ?)` _CommentManage_CreateCommentContent = `INSERT INTO @comment_content (comment_id, user_id, content, type, sort, created_on) VALUES (?, ?, ?, ?, ?, ?)`
_CommentManage_CreateCommentReply = `INSERT INTO @comment_reply (comment_id, user_id, content, at_user_id, ip, ip_loc, created_on) VALUES (?, ?, ?, ?, ?, ?, ?)` _CommentManage_CreateCommentReply = `INSERT INTO @comment_reply (comment_id, user_id, content, at_user_id, ip, ip_loc, created_on) VALUES (?, ?, ?, ?, ?, ?, ?)`
_CommentManage_CreateThumbsUpdownComment = `INSERT INTO @tweet_comment_thumbs (user_id, tweet_id, comment_id, reply_id, is_thumbs_up, is_thumbs_down, comment_type, created_on) VALUES (:user_id, :tweet_id, :comment_id, :reply_id, :is_thumbs_up, :is_thumbs_down, :comment_type, :created_on)` _CommentManage_CreateThumbsUpdownComment = `INSERT INTO @tweet_comment_thumbs (user_id, tweet_id, comment_id, reply_id, is_thumbs_up, is_thumbs_down, comment_type, created_on) VALUES (:user_id, :tweet_id, :comment_id, :reply_id, :is_thumbs_up, :is_thumbs_down, :comment_type, :created_on)`
_CommentManage_DecrCommentReplyCount = `UPDATE @comment SET reply_count=reply_count-1, modified_on=? WHERE id=? AND is_del=0`
_CommentManage_DeleteComment = `UPDATE @comment SET deleted_on=?, is_del=1 WHERE id=? AND is_del=0` _CommentManage_DeleteComment = `UPDATE @comment SET deleted_on=?, is_del=1 WHERE id=? AND is_del=0`
_CommentManage_DeleteCommentReply = `UPDATE @comment_reply SET deleted_on=?, is_del=1 WHERE id=? AND is_del=0` _CommentManage_DeleteCommentReply = `UPDATE @comment_reply SET deleted_on=?, is_del=1 WHERE id=? AND is_del=0`
_CommentManage_DeleteCommentThumbs = `UPDATE @tweet_comment_thumbs SET deleted_on=?, is_del=1 WHERE user_id=? AND tweet_id=? AND comment_id=? AND is_del=0` _CommentManage_DeleteCommentThumbs = `UPDATE @tweet_comment_thumbs SET deleted_on=?, is_del=1 WHERE user_id=? AND tweet_id=? AND comment_id=? AND is_del=0`
_CommentManage_DeleteReplyThumbs = `UPDATE @tweet_comment_thumbs SET deleted_on=?, is_del=1 WHERE user_id=? AND comment_id=? AND reply_id=? AND is_del=0` _CommentManage_DeleteReplyThumbs = `UPDATE @tweet_comment_thumbs SET deleted_on=?, is_del=1 WHERE user_id=? AND comment_id=? AND reply_id=? AND is_del=0`
_CommentManage_GetCommentReplyThumb = `SELECT * FROM @tweet_comment_thumbs WHERE user_id=? AND tweet_id=? AND comment_id=? AND reply_id=? AND comment_type=1 AND is_del=0` _CommentManage_GetCommentReplyThumb = `SELECT * FROM @tweet_comment_thumbs WHERE user_id=? AND tweet_id=? AND comment_id=? AND reply_id=? AND comment_type=1 AND is_del=0`
_CommentManage_GetTweetCommentThumb = `SELECT * FROM @tweet_comment_thumbs WHERE user_id=? AND tweet_id=? AND comment_id=? AND comment_type=0 AND is_del=0` _CommentManage_GetTweetCommentThumb = `SELECT * FROM @tweet_comment_thumbs WHERE user_id=? AND tweet_id=? AND comment_id=? AND comment_type=0 AND is_del=0`
_CommentManage_IncrCommentReplyCount = `UPDATE @comment SET reply_count=reply_count+1, modified_on=? WHERE id=? AND is_del=0`
_CommentManage_UpdateCommentThumbsCount = `UPDATE @comment SET thumbs_up_count=?, thumbs_down_count=?, modified_on=? WHERE id=? AND is_del=0` _CommentManage_UpdateCommentThumbsCount = `UPDATE @comment SET thumbs_up_count=?, thumbs_down_count=?, modified_on=? WHERE id=? AND is_del=0`
_CommentManage_UpdateReplyThumbsCount = `UPDATE @comment_reply SET thumbs_up_count=?, thumbs_down_count=?, modified_on=? WHERE id=? AND is_del=0` _CommentManage_UpdateReplyThumbsCount = `UPDATE @comment_reply SET thumbs_up_count=?, thumbs_down_count=?, modified_on=? WHERE id=? AND is_del=0`
_CommentManage_UpdateThumbsUpdownComment = `UPDATE @tweet_comment_thumbs SET is_thumbs_up=:is_thumbs_up, is_thumbs_down=:is_thumbs_down, modified_on=:modified_on WHERE id=:id AND is_del=0` _CommentManage_UpdateThumbsUpdownComment = `UPDATE @tweet_comment_thumbs SET is_thumbs_up=:is_thumbs_up, is_thumbs_down=:is_thumbs_down, modified_on=:modified_on WHERE id=:id AND is_del=0`
_CommentMetrics_AddCommentMetric = `INSERT INTO @comment_metric (comment_id, created_on) VALUES (?, ?)`
_CommentMetrics_DeleteCommentMetric = `UPDATE @comment_metric SET is_del=1, deleted_on=? WHERE comment_id=? AND is_del=0`
_CommentMetrics_GetMotivationFactor = `SELECT motivation_factor FROM @comment_metric WHERE comment_id=? AND is_del=0`
_CommentMetrics_UpdateRankScore = `UPDATE @comment_metric SET rank_score=?, modified_on=? WHERE comment_id=? AND is_del=0`
_CommentMetrics_UpsertCommentMetric = `INSERT INTO @comment_metric (comment_id, rank_score, created_on) VALUES (?, ?, ?)`
_ContactManager_AddFriendMsgsUpdate = `UPDATE @message SET reply_id=?, modified_on=? WHERE ((sender_user_id = ? AND receiver_user_id = ?) OR (sender_user_id = ? AND receiver_user_id = ?)) AND type = ? AND reply_id = ?` _ContactManager_AddFriendMsgsUpdate = `UPDATE @message SET reply_id=?, modified_on=? WHERE ((sender_user_id = ? AND receiver_user_id = ?) OR (sender_user_id = ? AND receiver_user_id = ?)) AND type = ? AND reply_id = ?`
_ContactManager_CreateContact = `INSERT INTO @contact (user_id, friend_id, status, created_on) VALUES (?, ?, ?, ?)` _ContactManager_CreateContact = `INSERT INTO @contact (user_id, friend_id, status, created_on) VALUES (?, ?, ?, ?)`
_ContactManager_CreateMessage = `INSERT INTO @message (sender_user_id, receiver_user_id, type, brief, content, reply_id, created_on) VALUES (:sender_user_id, :receiver_user_id, :type, :brief, :content, :reply_id, :created_on)` _ContactManager_CreateMessage = `INSERT INTO @message (sender_user_id, receiver_user_id, type, brief, content, reply_id, created_on) VALUES (:sender_user_id, :receiver_user_id, :type, :brief, :content, :reply_id, :created_on)`
@ -62,11 +69,19 @@ const (
_FollowingManager_ExistFollowing = `SELECT 1 FROM @following WHERE user_id=? AND follow_id=? AND is_del=0` _FollowingManager_ExistFollowing = `SELECT 1 FROM @following WHERE user_id=? AND follow_id=? AND is_del=0`
_FollowingManager_ListFollowings = `SELECT u.id user_id, u.username username, u.nickname nickname, u.avatar avatar, u.created_on created_on FROM @following f JOIN @user u ON f.user_id=u.id WHERE f.follow_id=? AND f.is_del=0 ORDER BY u.nickname ASC LIMIT ? OFFSET ?` _FollowingManager_ListFollowings = `SELECT u.id user_id, u.username username, u.nickname nickname, u.avatar avatar, u.created_on created_on FROM @following f JOIN @user u ON f.user_id=u.id WHERE f.follow_id=? AND f.is_del=0 ORDER BY u.nickname ASC LIMIT ? OFFSET ?`
_FollowingManager_ListFollows = `SELECT u.id user_id, u.username username, u.nickname nickname, u.avatar avatar, u.created_on created_on FROM @following f JOIN @user u ON f.follow_id=u.id WHERE f.user_id=? AND f.is_del=0 ORDER BY u.nickname ASC LIMIT ? OFFSET ?` _FollowingManager_ListFollows = `SELECT u.id user_id, u.username username, u.nickname nickname, u.avatar avatar, u.created_on created_on FROM @following f JOIN @user u ON f.follow_id=u.id WHERE f.user_id=? AND f.is_del=0 ORDER BY u.nickname ASC LIMIT ? OFFSET ?`
_Message_CountAllMessages = `SELECT count(*) FROM @message WHERE (receiver_user_id=? OR (sender_user_id=? AND type=4)) AND is_del=0`
_Message_CountRequestingMessages = `SELECT count(*) FROM @message WHERE receiver_user_id=? AND type=5 AND is_del=0`
_Message_CountSystemMessages = `SELECT count(*) FROM @message WHERE receiver_user_id=? AND type IN (1, 2, 3, 99) AND is_del=0`
_Message_CountUnreadMessages = `SELECT count(*) FROM @message WHERE receiver_user_id=? AND is_read=0 AND is_del=0`
_Message_CountWhisperMessages = `SELECT count(*) FROM @message WHERE ((receiver_user_id=? OR sender_user_id=?) AND type=4) AND is_del=0`
_Message_CreateMessage = `INSERT INTO @message (sender_user_id, receiver_user_id, type, brief, content, post_id, comment_id, reply_id, created_on) VALUES (:sender_user_id, :receiver_user_id, :type, :brief, :content, :post_id, :comment_id, :reply_id, :created_on)` _Message_CreateMessage = `INSERT INTO @message (sender_user_id, receiver_user_id, type, brief, content, post_id, comment_id, reply_id, created_on) VALUES (:sender_user_id, :receiver_user_id, :type, :brief, :content, :post_id, :comment_id, :reply_id, :created_on)`
_Message_GetAllMessages = `SELECT * FROM @message WHERE (receiver_user_id=? OR (sender_user_id=? AND type=4)) AND is_del=0 ORDER BY id DESC LIMIT ? OFFSET ?`
_Message_GetMessageById = `SELECT * FROM @message WHERE id=? AND is_del=0` _Message_GetMessageById = `SELECT * FROM @message WHERE id=? AND is_del=0`
_Message_GetMessageCount = `SELECT count(*) FROM @message WHERE (receiver_user_id=? OR (sender_user_id=? AND type=4)) AND is_del=0` _Message_GetRequestingMessages = `SELECT * FROM @message WHERE receiver_user_id=? AND type=5 AND is_del=0 ORDER BY id DESC LIMIT ? OFFSET ?`
_Message_GetMessages = `SELECT * FROM @message WHERE (receiver_user_id=? OR (sender_user_id=? AND type=4)) AND is_del=0 ORDER BY id DESC LIMIT ? OFFSET ?` _Message_GetSystemMessages = `SELECT * FROM @message WHERE receiver_user_id=? AND type IN (1, 2, 3, 99) AND is_del=0 ORDER BY id DESC LIMIT ? OFFSET ?`
_Message_GetUnreadCount = `SELECT count(*) FROM @message WHERE receiver_user_id=? AND is_read=0 AND is_del=0` _Message_GetUnreadCount = `SELECT count(*) FROM @message WHERE receiver_user_id=? AND is_read=0 AND is_del=0`
_Message_GetUnreadMessages = `SELECT * FROM @message WHERE receiver_user_id=? AND is_read=0 AND is_del=0 ORDER BY id DESC LIMIT ? OFFSET ?`
_Message_GetWhisperMessages = `SELECT * FROM @message WHERE ((receiver_user_id=? OR sender_user_id=?) AND type=4) AND is_del=0 ORDER BY id DESC LIMIT ? OFFSET ?`
_Message_ReadMessage = `UPDATE @message SET is_read=1, modified_on=? WHERE id=?` _Message_ReadMessage = `UPDATE @message SET is_read=1, modified_on=? WHERE id=?`
_Security_CreatePhoneCaptcha = `INSERT INTO @captcha (phone, captcha, expired_on, created_on) VALUES (:phone, :captcha, :expired_on, :created_on)` _Security_CreatePhoneCaptcha = `INSERT INTO @captcha (phone, captcha, expired_on, created_on) VALUES (:phone, :captcha, :expired_on, :created_on)`
_Security_GetLatestPhoneCaptcha = `SELECT * FROM @captcha WHERE phone=? AND is_del=0` _Security_GetLatestPhoneCaptcha = `SELECT * FROM @captcha WHERE phone=? AND is_del=0`
@ -79,6 +94,8 @@ const (
_ShipIndex_IndexCountBySelf = `SELECT count(*) FROM @post WHERE is_del=0 AND (visibility=90 OR (visibility=0 AND user_id=?) OR (visibility=50 AND user_id IN (?)))` _ShipIndex_IndexCountBySelf = `SELECT count(*) FROM @post WHERE is_del=0 AND (visibility=90 OR (visibility=0 AND user_id=?) OR (visibility=50 AND user_id IN (?)))`
_SimpleIndex_Index = `SELECT * FROM @post WHERE visibility=90 ORDER BY is_top DESC, latest_replied_on DESC LIMIT ? OFFSET ?` _SimpleIndex_Index = `SELECT * FROM @post WHERE visibility=90 ORDER BY is_top DESC, latest_replied_on DESC LIMIT ? OFFSET ?`
_SimpleIndex_IndexCount = `SELECT count(*) FROM @post WHERE visibility=90` _SimpleIndex_IndexCount = `SELECT count(*) FROM @post WHERE visibility=90`
_TrendsManager_CountIndexTrends = `SELECT count(*) FROM @contact c JOIN @user u ON c.friend_id=u.id JOIN @user_metric m ON c.friend_id=m.user_id WHERE c.user_id=? AND c.is_del=0 AND u.is_del=0 AND m.is_del=0 AND m.tweets_count>0`
_TrendsManager_GetIndexTrends = `SELECT u.username username, u.nickname nickname, u.avatar avatar FROM @contact c JOIN @user u ON c.friend_id=u.id JOIN @user_metric m ON c.friend_id=m.user_id WHERE c.user_id=? AND c.is_del=0 AND u.is_del=0 AND m.is_del=0 AND m.tweets_count>0 LIMIT ? OFFSET ?`
_Tweet_CountFollowingTweets = `SELECT count(*) FROM @post WHERE user_id=? AND is_del=0` _Tweet_CountFollowingTweets = `SELECT count(*) FROM @post WHERE user_id=? AND is_del=0`
_Tweet_CountFollowingTweetsFollow = `SELECT count(*) FROM @post WHERE (user_id=? OR (visibility>=60 AND user_id IN(?))) AND is_del=0` _Tweet_CountFollowingTweetsFollow = `SELECT count(*) FROM @post WHERE (user_id=? OR (visibility>=60 AND user_id IN(?))) AND is_del=0`
_Tweet_CountFollowingTweetsFriend = `SELECT count(*) FROM @post WHERE (user_id=? OR (visibility>=50 AND user_id IN(?))) AND is_del=0` _Tweet_CountFollowingTweetsFriend = `SELECT count(*) FROM @post WHERE (user_id=? OR (visibility>=50 AND user_id IN(?))) AND is_del=0`
@ -137,6 +154,7 @@ const (
_TweetMetrics_DeleteTweetMetric = `UPDATE @post_metric SET is_del=1, deleted_on=? WHERE post_id=? AND is_del=0` _TweetMetrics_DeleteTweetMetric = `UPDATE @post_metric SET is_del=1, deleted_on=? WHERE post_id=? AND is_del=0`
_TweetMetrics_GetMotivationFactor = `SELECT motivation_factor FROM @post_metric WHERE post_id=? AND is_del=0` _TweetMetrics_GetMotivationFactor = `SELECT motivation_factor FROM @post_metric WHERE post_id=? AND is_del=0`
_TweetMetrics_UpdateRankScore = `UPDATE @post_metric SET rank_score=?, modified_on=? WHERE post_id=? AND is_del=0` _TweetMetrics_UpdateRankScore = `UPDATE @post_metric SET rank_score=?, modified_on=? WHERE post_id=? AND is_del=0`
_TweetMetrics_UpsertTweetMetric = `INSERT INTO @post_metric (post_id, rank_score, created_on) VALUES (?, ?, ?)`
_Tweet_UserCommentTweetsByFriend = `SELECT id, user_id, comment_count, collection_count, upvote_count, share_count, visibility, is_top, is_essence, is_lock, latest_replied_on, tags, attachment_price, ip, ip_loc, created_on, modified_on, deleted_on, is_del FROM @post_by_comment WHERE is_del=0 AND comment_user_id=? AND visibility>=50 ORDER BY latest_replied_on DESC LIMIT ? OFFSET ?` _Tweet_UserCommentTweetsByFriend = `SELECT id, user_id, comment_count, collection_count, upvote_count, share_count, visibility, is_top, is_essence, is_lock, latest_replied_on, tags, attachment_price, ip, ip_loc, created_on, modified_on, deleted_on, is_del FROM @post_by_comment WHERE is_del=0 AND comment_user_id=? AND visibility>=50 ORDER BY latest_replied_on DESC LIMIT ? OFFSET ?`
_Tweet_UserCommentTweetsByGuest = `SELECT id, user_id, comment_count, collection_count, upvote_count, share_count, visibility, is_top, is_essence, is_lock, latest_replied_on, tags, attachment_price, ip, ip_loc, created_on, modified_on, deleted_on, is_del FROM @post_by_comment WHERE is_del=0 AND comment_user_id=? AND visibility>=90 ORDER BY latest_replied_on DESC LIMIT ? OFFSET ?` _Tweet_UserCommentTweetsByGuest = `SELECT id, user_id, comment_count, collection_count, upvote_count, share_count, visibility, is_top, is_essence, is_lock, latest_replied_on, tags, attachment_price, ip, ip_loc, created_on, modified_on, deleted_on, is_del FROM @post_by_comment WHERE is_del=0 AND comment_user_id=? AND visibility>=90 ORDER BY latest_replied_on DESC LIMIT ? OFFSET ?`
_Tweet_UserCommentTweetsBySelf = `SELECT id, user_id, comment_count, collection_count, upvote_count, share_count, visibility, is_top, is_essence, is_lock, latest_replied_on, tags, attachment_price, ip, ip_loc, created_on, modified_on, deleted_on, is_del FROM @post_by_comment WHERE is_del=0 AND comment_user_id=? ORDER BY latest_replied_on DESC LIMIT ? OFFSET ?` _Tweet_UserCommentTweetsBySelf = `SELECT id, user_id, comment_count, collection_count, upvote_count, share_count, visibility, is_top, is_essence, is_lock, latest_replied_on, tags, attachment_price, ip, ip_loc, created_on, modified_on, deleted_on, is_del FROM @post_by_comment WHERE is_del=0 AND comment_user_id=? ORDER BY latest_replied_on DESC LIMIT ? OFFSET ?`
@ -166,6 +184,12 @@ const (
_UserManage_GetUsersByIds = `SELECT * FROM @user WHERE id IN (?) AND is_del=0` _UserManage_GetUsersByIds = `SELECT * FROM @user WHERE id IN (?) AND is_del=0`
_UserManage_GetUsersByKeyword = `SELECT * FROM @user WHERE username LIKE ? AND is_del=0 limit 6` _UserManage_GetUsersByKeyword = `SELECT * FROM @user WHERE username LIKE ? AND is_del=0 limit 6`
_UserManage_UpdateUser = `UPDATE @user SET username=:username, nickname=:nickname, phone=:phone, password=:password, salt=:salt, status=:status, avatar=:avatar, balance=:balance, is_admin=:is_admin, modified_on=:modified_on WHERE id=? AND is_del=0` _UserManage_UpdateUser = `UPDATE @user SET username=:username, nickname=:nickname, phone=:phone, password=:password, salt=:salt, status=:status, avatar=:avatar, balance=:balance, is_admin=:is_admin, modified_on=:modified_on WHERE id=? AND is_del=0`
_UserMetrics_AddUserMetric = `INSERT INTO @user_metric (user_id, created_on) VALUES (?, ?)`
_UserMetrics_DeleteUserMetric = `UPDATE @user_metric SET is_del=1, deleted_on=? WHERE user_id=? AND is_del=0`
_UserMetrics_GetTweetsCount = `SELECT tweets_count FROM @user_metric WHERE user_id=? AND is_del=0`
_UserMetrics_UpdateUserMetric = `UPDATE @user_metric SET tweets_count=?, modified_on=? WHERE user_id=? AND is_del=0`
_UserRelation_MyFollowIds = `SELECT follow_id FROM @following WHERE user_id=? AND is_del=0`
_UserRelation_MyFriendIds = `SELECT friend_id FROM @contact WHERE user_id=? AND is_del=0`
_Wallet_AddUserBalance = `UPDATE @user SET balance=balance+?, modified_on=? WHERE id=? AND is_del=0` _Wallet_AddUserBalance = `UPDATE @user SET balance=balance+?, modified_on=? WHERE id=? AND is_del=0`
_Wallet_CreateRecharge = `INSERT INTO @wallet_recharge (user_id, amount, created_on) VALUES (?, ?, ?)` _Wallet_CreateRecharge = `INSERT INTO @wallet_recharge (user_id, amount, created_on) VALUES (?, ?, ?)`
_Wallet_CreateWalletStatement = `INSERT INTO @wallet_statement (user_id, change_amount, balance_snapshot, reason, created_on) VALUES (?, ?, ?, ?, ?)` _Wallet_CreateWalletStatement = `INSERT INTO @wallet_statement (user_id, change_amount, balance_snapshot, reason, created_on) VALUES (?, ?, ?, ?, ?)`
@ -226,18 +250,29 @@ type CommentManage struct {
CreateComment *sqlx.Stmt `yesql:"create_comment"` CreateComment *sqlx.Stmt `yesql:"create_comment"`
CreateCommentContent *sqlx.Stmt `yesql:"create_comment_content"` CreateCommentContent *sqlx.Stmt `yesql:"create_comment_content"`
CreateCommentReply *sqlx.Stmt `yesql:"create_comment_reply"` CreateCommentReply *sqlx.Stmt `yesql:"create_comment_reply"`
DecrCommentReplyCount *sqlx.Stmt `yesql:"decr_comment_reply_count"`
DeleteComment *sqlx.Stmt `yesql:"delete_comment"` DeleteComment *sqlx.Stmt `yesql:"delete_comment"`
DeleteCommentReply *sqlx.Stmt `yesql:"delete_comment_reply"` DeleteCommentReply *sqlx.Stmt `yesql:"delete_comment_reply"`
DeleteCommentThumbs *sqlx.Stmt `yesql:"delete_comment_thumbs"` DeleteCommentThumbs *sqlx.Stmt `yesql:"delete_comment_thumbs"`
DeleteReplyThumbs *sqlx.Stmt `yesql:"delete_reply_thumbs"` DeleteReplyThumbs *sqlx.Stmt `yesql:"delete_reply_thumbs"`
GetCommentReplyThumb *sqlx.Stmt `yesql:"get_comment_reply_thumb"` GetCommentReplyThumb *sqlx.Stmt `yesql:"get_comment_reply_thumb"`
GetTweetCommentThumb *sqlx.Stmt `yesql:"get_tweet_comment_thumb"` GetTweetCommentThumb *sqlx.Stmt `yesql:"get_tweet_comment_thumb"`
IncrCommentReplyCount *sqlx.Stmt `yesql:"incr_comment_reply_count"`
UpdateCommentThumbsCount *sqlx.Stmt `yesql:"update_comment_thumbs_count"` UpdateCommentThumbsCount *sqlx.Stmt `yesql:"update_comment_thumbs_count"`
UpdateReplyThumbsCount *sqlx.Stmt `yesql:"update_reply_thumbs_count"` UpdateReplyThumbsCount *sqlx.Stmt `yesql:"update_reply_thumbs_count"`
CreateThumbsUpdownComment *sqlx.NamedStmt `yesql:"create_thumbs_updown_comment"` CreateThumbsUpdownComment *sqlx.NamedStmt `yesql:"create_thumbs_updown_comment"`
UpdateThumbsUpdownComment *sqlx.NamedStmt `yesql:"update_thumbs_updown_comment"` UpdateThumbsUpdownComment *sqlx.NamedStmt `yesql:"update_thumbs_updown_comment"`
} }
type CommentMetrics struct {
yesql.Namespace `yesql:"comment_metrics"`
AddCommentMetric *sqlx.Stmt `yesql:"add_comment_metric"`
DeleteCommentMetric *sqlx.Stmt `yesql:"delete_comment_metric"`
GetMotivationFactor *sqlx.Stmt `yesql:"get_motivation_factor"`
UpdateRankScore *sqlx.Stmt `yesql:"update_rank_score"`
UpsertCommentMetric *sqlx.Stmt `yesql:"upsert_comment_metric"`
}
type ContactManager struct { type ContactManager struct {
yesql.Namespace `yesql:"contact_manager"` yesql.Namespace `yesql:"contact_manager"`
AddFriendMsgsUpdate *sqlx.Stmt `yesql:"add_friend_msgs_update"` AddFriendMsgsUpdate *sqlx.Stmt `yesql:"add_friend_msgs_update"`
@ -266,13 +301,21 @@ type FollowingManager struct {
} }
type Message struct { type Message struct {
yesql.Namespace `yesql:"message"` yesql.Namespace `yesql:"message"`
GetMessageById *sqlx.Stmt `yesql:"get_message_by_id"` CountAllMessages *sqlx.Stmt `yesql:"count_all_messages"`
GetMessageCount *sqlx.Stmt `yesql:"get_message_count"` CountRequestingMessages *sqlx.Stmt `yesql:"count_requesting_messages"`
GetMessages *sqlx.Stmt `yesql:"get_messages"` CountSystemMessages *sqlx.Stmt `yesql:"count_system_messages"`
GetUnreadCount *sqlx.Stmt `yesql:"get_unread_count"` CountUnreadMessages *sqlx.Stmt `yesql:"count_unread_messages"`
ReadMessage *sqlx.Stmt `yesql:"read_message"` CountWhisperMessages *sqlx.Stmt `yesql:"count_whisper_messages"`
CreateMessage *sqlx.NamedStmt `yesql:"create_message"` GetAllMessages *sqlx.Stmt `yesql:"get_all_messages"`
GetMessageById *sqlx.Stmt `yesql:"get_message_by_id"`
GetRequestingMessages *sqlx.Stmt `yesql:"get_requesting_messages"`
GetSystemMessages *sqlx.Stmt `yesql:"get_system_messages"`
GetUnreadCount *sqlx.Stmt `yesql:"get_unread_count"`
GetUnreadMessages *sqlx.Stmt `yesql:"get_unread_messages"`
GetWhisperMessages *sqlx.Stmt `yesql:"get_whisper_messages"`
ReadMessage *sqlx.Stmt `yesql:"read_message"`
CreateMessage *sqlx.NamedStmt `yesql:"create_message"`
} }
type Security struct { type Security struct {
@ -298,6 +341,12 @@ type SimpleIndex struct {
IndexCount *sqlx.Stmt `yesql:"index_count"` IndexCount *sqlx.Stmt `yesql:"index_count"`
} }
type TrendsManager struct {
yesql.Namespace `yesql:"trends_manager"`
CountIndexTrends *sqlx.Stmt `yesql:"count_index_trends"`
GetIndexTrends *sqlx.Stmt `yesql:"get_index_trends"`
}
type Tweet struct { type Tweet struct {
yesql.Namespace `yesql:"tweet"` yesql.Namespace `yesql:"tweet"`
CountFollowingTweetsFollow string `yesql:"count_following_tweets_follow"` CountFollowingTweetsFollow string `yesql:"count_following_tweets_follow"`
@ -390,6 +439,7 @@ type TweetMetrics struct {
DeleteTweetMetric *sqlx.Stmt `yesql:"delete_tweet_metric"` DeleteTweetMetric *sqlx.Stmt `yesql:"delete_tweet_metric"`
GetMotivationFactor *sqlx.Stmt `yesql:"get_motivation_factor"` GetMotivationFactor *sqlx.Stmt `yesql:"get_motivation_factor"`
UpdateRankScore *sqlx.Stmt `yesql:"update_rank_score"` UpdateRankScore *sqlx.Stmt `yesql:"update_rank_score"`
UpsertTweetMetric *sqlx.Stmt `yesql:"upsert_tweet_metric"`
} }
type UserManage struct { type UserManage struct {
@ -405,6 +455,20 @@ type UserManage struct {
UpdateUser *sqlx.NamedStmt `yesql:"update_user"` UpdateUser *sqlx.NamedStmt `yesql:"update_user"`
} }
type UserMetrics struct {
yesql.Namespace `yesql:"user_metrics"`
AddUserMetric *sqlx.Stmt `yesql:"add_user_metric"`
DeleteUserMetric *sqlx.Stmt `yesql:"delete_user_metric"`
GetTweetsCount *sqlx.Stmt `yesql:"get_tweets_count"`
UpdateUserMetric *sqlx.Stmt `yesql:"update_user_metric"`
}
type UserRelation struct {
yesql.Namespace `yesql:"user_relation"`
MyFollowIds *sqlx.Stmt `yesql:"my_follow_ids"`
MyFriendIds *sqlx.Stmt `yesql:"my_friend_ids"`
}
type Wallet struct { type Wallet struct {
yesql.Namespace `yesql:"wallet"` yesql.Namespace `yesql:"wallet"`
AddUserBalance *sqlx.Stmt `yesql:"add_user_balance"` AddUserBalance *sqlx.Stmt `yesql:"add_user_balance"`
@ -494,6 +558,9 @@ func BuildCommentManage(p PreparexBuilder, ctx ...context.Context) (obj *Comment
if obj.CreateCommentReply, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_CreateCommentReply))); err != nil { if obj.CreateCommentReply, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_CreateCommentReply))); err != nil {
return nil, fmt.Errorf("prepare _CommentManage_CreateCommentReply error: %w", err) return nil, fmt.Errorf("prepare _CommentManage_CreateCommentReply error: %w", err)
} }
if obj.DecrCommentReplyCount, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_DecrCommentReplyCount))); err != nil {
return nil, fmt.Errorf("prepare _CommentManage_DecrCommentReplyCount error: %w", err)
}
if obj.DeleteComment, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_DeleteComment))); err != nil { if obj.DeleteComment, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_DeleteComment))); err != nil {
return nil, fmt.Errorf("prepare _CommentManage_DeleteComment error: %w", err) return nil, fmt.Errorf("prepare _CommentManage_DeleteComment error: %w", err)
} }
@ -512,6 +579,9 @@ func BuildCommentManage(p PreparexBuilder, ctx ...context.Context) (obj *Comment
if obj.GetTweetCommentThumb, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_GetTweetCommentThumb))); err != nil { if obj.GetTweetCommentThumb, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_GetTweetCommentThumb))); err != nil {
return nil, fmt.Errorf("prepare _CommentManage_GetTweetCommentThumb error: %w", err) return nil, fmt.Errorf("prepare _CommentManage_GetTweetCommentThumb error: %w", err)
} }
if obj.IncrCommentReplyCount, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_IncrCommentReplyCount))); err != nil {
return nil, fmt.Errorf("prepare _CommentManage_IncrCommentReplyCount error: %w", err)
}
if obj.UpdateCommentThumbsCount, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_UpdateCommentThumbsCount))); err != nil { if obj.UpdateCommentThumbsCount, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentManage_UpdateCommentThumbsCount))); err != nil {
return nil, fmt.Errorf("prepare _CommentManage_UpdateCommentThumbsCount error: %w", err) return nil, fmt.Errorf("prepare _CommentManage_UpdateCommentThumbsCount error: %w", err)
} }
@ -527,6 +597,32 @@ func BuildCommentManage(p PreparexBuilder, ctx ...context.Context) (obj *Comment
return return
} }
func BuildCommentMetrics(p PreparexBuilder, ctx ...context.Context) (obj *CommentMetrics, err error) {
var c context.Context
if len(ctx) > 0 && ctx[0] != nil {
c = ctx[0]
} else {
c = context.Background()
}
obj = &CommentMetrics{}
if obj.AddCommentMetric, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentMetrics_AddCommentMetric))); err != nil {
return nil, fmt.Errorf("prepare _CommentMetrics_AddCommentMetric error: %w", err)
}
if obj.DeleteCommentMetric, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentMetrics_DeleteCommentMetric))); err != nil {
return nil, fmt.Errorf("prepare _CommentMetrics_DeleteCommentMetric error: %w", err)
}
if obj.GetMotivationFactor, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentMetrics_GetMotivationFactor))); err != nil {
return nil, fmt.Errorf("prepare _CommentMetrics_GetMotivationFactor error: %w", err)
}
if obj.UpdateRankScore, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentMetrics_UpdateRankScore))); err != nil {
return nil, fmt.Errorf("prepare _CommentMetrics_UpdateRankScore error: %w", err)
}
if obj.UpsertCommentMetric, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_CommentMetrics_UpsertCommentMetric))); err != nil {
return nil, fmt.Errorf("prepare _CommentMetrics_UpsertCommentMetric error: %w", err)
}
return
}
func BuildContactManager(p PreparexBuilder, ctx ...context.Context) (obj *ContactManager, err error) { func BuildContactManager(p PreparexBuilder, ctx ...context.Context) (obj *ContactManager, err error) {
var c context.Context var c context.Context
if len(ctx) > 0 && ctx[0] != nil { if len(ctx) > 0 && ctx[0] != nil {
@ -614,18 +710,42 @@ func BuildMessage(p PreparexBuilder, ctx ...context.Context) (obj *Message, err
c = context.Background() c = context.Background()
} }
obj = &Message{} obj = &Message{}
if obj.CountAllMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_CountAllMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_CountAllMessages error: %w", err)
}
if obj.CountRequestingMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_CountRequestingMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_CountRequestingMessages error: %w", err)
}
if obj.CountSystemMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_CountSystemMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_CountSystemMessages error: %w", err)
}
if obj.CountUnreadMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_CountUnreadMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_CountUnreadMessages error: %w", err)
}
if obj.CountWhisperMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_CountWhisperMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_CountWhisperMessages error: %w", err)
}
if obj.GetAllMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetAllMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_GetAllMessages error: %w", err)
}
if obj.GetMessageById, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetMessageById))); err != nil { if obj.GetMessageById, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetMessageById))); err != nil {
return nil, fmt.Errorf("prepare _Message_GetMessageById error: %w", err) return nil, fmt.Errorf("prepare _Message_GetMessageById error: %w", err)
} }
if obj.GetMessageCount, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetMessageCount))); err != nil { if obj.GetRequestingMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetRequestingMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_GetMessageCount error: %w", err) return nil, fmt.Errorf("prepare _Message_GetRequestingMessages error: %w", err)
} }
if obj.GetMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetMessages))); err != nil { if obj.GetSystemMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetSystemMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_GetMessages error: %w", err) return nil, fmt.Errorf("prepare _Message_GetSystemMessages error: %w", err)
} }
if obj.GetUnreadCount, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetUnreadCount))); err != nil { if obj.GetUnreadCount, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetUnreadCount))); err != nil {
return nil, fmt.Errorf("prepare _Message_GetUnreadCount error: %w", err) return nil, fmt.Errorf("prepare _Message_GetUnreadCount error: %w", err)
} }
if obj.GetUnreadMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetUnreadMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_GetUnreadMessages error: %w", err)
}
if obj.GetWhisperMessages, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_GetWhisperMessages))); err != nil {
return nil, fmt.Errorf("prepare _Message_GetWhisperMessages error: %w", err)
}
if obj.ReadMessage, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_ReadMessage))); err != nil { if obj.ReadMessage, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Message_ReadMessage))); err != nil {
return nil, fmt.Errorf("prepare _Message_ReadMessage error: %w", err) return nil, fmt.Errorf("prepare _Message_ReadMessage error: %w", err)
} }
@ -698,6 +818,23 @@ func BuildSimpleIndex(p PreparexBuilder, ctx ...context.Context) (obj *SimpleInd
return return
} }
func BuildTrendsManager(p PreparexBuilder, ctx ...context.Context) (obj *TrendsManager, err error) {
var c context.Context
if len(ctx) > 0 && ctx[0] != nil {
c = ctx[0]
} else {
c = context.Background()
}
obj = &TrendsManager{}
if obj.CountIndexTrends, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_TrendsManager_CountIndexTrends))); err != nil {
return nil, fmt.Errorf("prepare _TrendsManager_CountIndexTrends error: %w", err)
}
if obj.GetIndexTrends, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_TrendsManager_GetIndexTrends))); err != nil {
return nil, fmt.Errorf("prepare _TrendsManager_GetIndexTrends error: %w", err)
}
return
}
func BuildTweet(p PreparexBuilder, ctx ...context.Context) (obj *Tweet, err error) { func BuildTweet(p PreparexBuilder, ctx ...context.Context) (obj *Tweet, err error) {
var c context.Context var c context.Context
if len(ctx) > 0 && ctx[0] != nil { if len(ctx) > 0 && ctx[0] != nil {
@ -938,6 +1075,9 @@ func BuildTweetMetrics(p PreparexBuilder, ctx ...context.Context) (obj *TweetMet
if obj.UpdateRankScore, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_TweetMetrics_UpdateRankScore))); err != nil { if obj.UpdateRankScore, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_TweetMetrics_UpdateRankScore))); err != nil {
return nil, fmt.Errorf("prepare _TweetMetrics_UpdateRankScore error: %w", err) return nil, fmt.Errorf("prepare _TweetMetrics_UpdateRankScore error: %w", err)
} }
if obj.UpsertTweetMetric, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_TweetMetrics_UpsertTweetMetric))); err != nil {
return nil, fmt.Errorf("prepare _TweetMetrics_UpsertTweetMetric error: %w", err)
}
return return
} }
@ -978,6 +1118,46 @@ func BuildUserManage(p PreparexBuilder, ctx ...context.Context) (obj *UserManage
return return
} }
func BuildUserMetrics(p PreparexBuilder, ctx ...context.Context) (obj *UserMetrics, err error) {
var c context.Context
if len(ctx) > 0 && ctx[0] != nil {
c = ctx[0]
} else {
c = context.Background()
}
obj = &UserMetrics{}
if obj.AddUserMetric, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_UserMetrics_AddUserMetric))); err != nil {
return nil, fmt.Errorf("prepare _UserMetrics_AddUserMetric error: %w", err)
}
if obj.DeleteUserMetric, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_UserMetrics_DeleteUserMetric))); err != nil {
return nil, fmt.Errorf("prepare _UserMetrics_DeleteUserMetric error: %w", err)
}
if obj.GetTweetsCount, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_UserMetrics_GetTweetsCount))); err != nil {
return nil, fmt.Errorf("prepare _UserMetrics_GetTweetsCount error: %w", err)
}
if obj.UpdateUserMetric, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_UserMetrics_UpdateUserMetric))); err != nil {
return nil, fmt.Errorf("prepare _UserMetrics_UpdateUserMetric error: %w", err)
}
return
}
func BuildUserRelation(p PreparexBuilder, ctx ...context.Context) (obj *UserRelation, err error) {
var c context.Context
if len(ctx) > 0 && ctx[0] != nil {
c = ctx[0]
} else {
c = context.Background()
}
obj = &UserRelation{}
if obj.MyFollowIds, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_UserRelation_MyFollowIds))); err != nil {
return nil, fmt.Errorf("prepare _UserRelation_MyFollowIds error: %w", err)
}
if obj.MyFriendIds, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_UserRelation_MyFriendIds))); err != nil {
return nil, fmt.Errorf("prepare _UserRelation_MyFriendIds error: %w", err)
}
return
}
func BuildWallet(p PreparexBuilder, ctx ...context.Context) (obj *Wallet, err error) { func BuildWallet(p PreparexBuilder, ctx ...context.Context) (obj *Wallet, err error) {
var c context.Context var c context.Context
if len(ctx) > 0 && ctx[0] != nil { if len(ctx) > 0 && ctx[0] != nil {

@ -17,6 +17,7 @@ var (
) )
const ( const (
_Comment_GetHotsComments = `SELECT c.* FROM @comment c LEFT JOIN @comment_metric m ON c.id=m.comment_id WHERE c.post_id=? AND c.is_del=0 AND m.is_del=0 ORDER BY is_essence DESC, m.rank_score DESC NULLS LAST, id DESC LIMIT ? OFFSET ?`
_CommentManage_CreateComment = `INSERT INTO @comment (post_id, user_id, ip, ip_loc, created_on) VALUES (?, ?, ?, ?, ?) RETURNING *` _CommentManage_CreateComment = `INSERT INTO @comment (post_id, user_id, ip, ip_loc, created_on) VALUES (?, ?, ?, ?, ?) RETURNING *`
_CommentManage_CreateCommentContent = `INSERT INTO @comment_content (comment_id, user_id, content, type, sort, created_on) VALUES (?, ?, ?, ?, ?, ?) RETURNING *` _CommentManage_CreateCommentContent = `INSERT INTO @comment_content (comment_id, user_id, content, type, sort, created_on) VALUES (?, ?, ?, ?, ?, ?) RETURNING *`
_CommentManage_CreateCommentReply = `INSERT INTO @comment_reply (comment_id, user_id, content, at_user_id, ip, ip_loc, created_on) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING *` _CommentManage_CreateCommentReply = `INSERT INTO @comment_reply (comment_id, user_id, content, at_user_id, ip, ip_loc, created_on) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING *`
@ -52,6 +53,11 @@ type PreparexBuilder interface {
QueryHook(query string) string QueryHook(query string) string
} }
type Comment struct {
yesql.Namespace `yesql:"comment"`
GetHotsComments *sqlx.Stmt `yesql:"get_hots_comments"`
}
type CommentManage struct { type CommentManage struct {
yesql.Namespace `yesql:"comment_manage"` yesql.Namespace `yesql:"comment_manage"`
CreateComment *sqlx.Stmt `yesql:"create_comment"` CreateComment *sqlx.Stmt `yesql:"create_comment"`
@ -93,6 +99,20 @@ type Wallet struct {
CreateRecharge *sqlx.Stmt `yesql:"create_recharge"` CreateRecharge *sqlx.Stmt `yesql:"create_recharge"`
} }
func BuildComment(p PreparexBuilder, ctx ...context.Context) (obj *Comment, err error) {
var c context.Context
if len(ctx) > 0 && ctx[0] != nil {
c = ctx[0]
} else {
c = context.Background()
}
obj = &Comment{}
if obj.GetHotsComments, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_Comment_GetHotsComments))); err != nil {
return nil, fmt.Errorf("prepare _Comment_GetHotsComments error: %w", err)
}
return
}
func BuildCommentManage(p PreparexBuilder, ctx ...context.Context) (obj *CommentManage, err error) { func BuildCommentManage(p PreparexBuilder, ctx ...context.Context) (obj *CommentManage, err error) {
var c context.Context var c context.Context
if len(ctx) > 0 && ctx[0] != nil { if len(ctx) > 0 && ctx[0] != nil {

@ -156,8 +156,9 @@ func (s *commentManageSrv) CreateComment(r *ms.Comment) (*ms.Comment, error) {
} }
func (s *commentManageSrv) CreateCommentReply(r *ms.CommentReply) (*ms.CommentReply, error) { func (s *commentManageSrv) CreateCommentReply(r *ms.CommentReply) (*ms.CommentReply, error) {
now := time.Now().Unix()
res, err := s.q.CreateCommentReply.Exec(r.CommentID, r.UserID, r.Content, res, err := s.q.CreateCommentReply.Exec(r.CommentID, r.UserID, r.Content,
r.AtUserID, r.IP, r.IPLoc, time.Now().Unix()) r.AtUserID, r.IP, r.IPLoc, now)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -166,17 +167,22 @@ func (s *commentManageSrv) CreateCommentReply(r *ms.CommentReply) (*ms.CommentRe
return nil, err return nil, err
} }
r.Model = &ms.Model{ID: id} r.Model = &ms.Model{ID: id}
// 宽松处理错误
s.q.IncrCommentReplyCount.Exec(now, r.CommentID)
return r, nil return r, nil
} }
func (s *commentManageSrv) DeleteCommentReply(r *ms.CommentReply) error { func (s *commentManageSrv) DeleteCommentReply(r *ms.CommentReply) error {
return s.db.Withx(func(tx *sqlx.Tx) error { return s.db.Withx(func(tx *sqlx.Tx) (err error) {
now := time.Now().Unix() now := time.Now().Unix()
if _, err := tx.Stmtx(s.q.DeleteCommentReply).Exec(now, r.ID); err != nil { if _, err = tx.Stmtx(s.q.DeleteCommentReply).Exec(now, r.ID); err != nil {
return err return
} }
_, err := tx.Stmtx(s.q.DeleteCommentThumbs).Exec(now, r.UserID, r.CommentID, r.ID) if _, err = tx.Stmtx(s.q.DeleteCommentThumbs).Exec(now, r.UserID, r.CommentID, r.ID); err == nil {
return err // 宽松处理错误
tx.Stmtx(s.q.DecrCommentReplyCount).Exec(now, r.CommentID)
}
return
}) })
} }
@ -393,11 +399,20 @@ func (s *commentManageSrv) HighlightComment(userId, commentId int64) (int8, erro
return 0, cs.ErrNotImplemented return 0, cs.ErrNotImplemented
} }
func newCommentService(db *sqlx.DB) core.CommentService { func newCommentService(db *sqlx.DB) (s core.CommentService) {
return &commentSrv{ cs := &commentSrv{
sqlxSrv: newSqlxSrv(db), sqlxSrv: newSqlxSrv(db),
q: ccBuild(db, cc.BuildComment), q: ccBuild(db, cc.BuildComment),
} }
s = cs
if cfg.Any("PostgreSQL", "PgSQL", "Postgres") {
s = &pgcCommentSrv{
commentSrv: cs,
p: pgcBuild(db, pgc.BuildComment),
}
}
return
} }
func newCommentManageService(db *sqlx.DB) (s core.CommentManageService) { func newCommentManageService(db *sqlx.DB) (s core.CommentManageService) {

@ -9,6 +9,7 @@ import (
"github.com/bitbus/sqlx/db" "github.com/bitbus/sqlx/db"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/core/ms" "github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/dao/sakila/auto/pgc" "github.com/rocboss/paopao-ce/internal/dao/sakila/auto/pgc"
) )
@ -22,19 +23,48 @@ type pgcCommentManageSrv struct {
p *pgc.CommentManage p *pgc.CommentManage
} }
type pgcCommentSrv struct {
*commentSrv
p *pgc.Comment
}
func (s *pgcCommentManageSrv) CreateComment(r *ms.Comment) (*ms.Comment, error) { func (s *pgcCommentManageSrv) CreateComment(r *ms.Comment) (*ms.Comment, error) {
return db.Get[ms.Comment](s.p.CreateComment, r.PostID, r.UserID, r.IP, r.IPLoc, time.Now().Unix()) return db.Get[ms.Comment](s.p.CreateComment, r.PostID, r.UserID, r.IP, r.IPLoc, time.Now().Unix())
} }
func (s *pgcCommentManageSrv) CreateCommentReply(r *ms.CommentReply) (*ms.CommentReply, error) { func (s *pgcCommentManageSrv) CreateCommentReply(r *ms.CommentReply) (res *ms.CommentReply, err error) {
return db.Get[ms.CommentReply](s.p.CreateCommentReply, r.CommentID, now := time.Now().Unix()
if res, err = db.Get[ms.CommentReply](s.p.CreateCommentReply, r.CommentID,
r.UserID, r.Content, r.AtUserID, r.UserID, r.Content, r.AtUserID,
r.IP, r.IPLoc, time.Now().Unix()) r.IP, r.IPLoc, now); err == nil {
// 宽松处理错误
s.q.IncrCommentReplyCount.Exec(now, r.CommentID)
}
return
} }
func (s *pgcCommentManageSrv) CreateCommentContent(r *ms.CommentContent) (*ms.CommentContent, error) { func (s *pgcCommentManageSrv) CreateCommentContent(r *ms.CommentContent) (*ms.CommentContent, error) {
return db.Get[ms.CommentContent](s.p.CreateCommentContent, return db.Get[ms.CommentContent](s.p.CreateCommentContent,
r.CommentID, r.UserID, r.Content, r.CommentID, r.UserID, r.Content,
r.Type, r.Sort, time.Now().Unix()) r.Type, r.Sort, time.Now().Unix())
}
func (s *pgcCommentSrv) GetComments(tweetId int64, style cs.StyleCommentType, limit int, offset int) (res []*ms.Comment, total int64, err error) {
switch style {
case cs.StyleCommentHots:
if err = s.p.GetHotsComments.Select(&res, tweetId, limit, offset); err == nil {
err = s.q.GetCommentCount.Get(&total, tweetId)
}
case cs.StyleCommentNewest:
if err = s.q.GetNewestComments.Select(&res, tweetId, limit, offset); err == nil {
err = s.q.GetCommentCount.Get(&total, tweetId)
}
case cs.StyleCommentDefault:
fallthrough
default:
if err = s.q.GetDefaultComments.Select(&res, tweetId, limit, offset); err == nil {
err = s.q.GetCommentCount.Get(&total, tweetId)
}
}
return
} }

@ -11,10 +11,10 @@ import (
"github.com/bitbus/sqlx" "github.com/bitbus/sqlx"
"github.com/bitbus/sqlx/db" "github.com/bitbus/sqlx/db"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/core/ms" "github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/dao/sakila/auto/cc" "github.com/rocboss/paopao-ce/internal/dao/sakila/auto/cc"
"github.com/rocboss/paopao-ce/internal/dao/sakila/auto/pgc" "github.com/rocboss/paopao-ce/internal/dao/sakila/auto/pgc"
"github.com/sirupsen/logrus"
) )
var ( var (
@ -55,24 +55,40 @@ func (s *messageSrv) ReadMessage(r *ms.Message) (err error) {
return return
} }
func (s *messageSrv) GetMessages(userId int64, offset, limit int) ([]*ms.MessageFormated, error) { func (s *messageSrv) GetMessages(userId int64, style cs.MessageStyle, limit, offset int) (res []*ms.MessageFormated, total int64, err error) {
var messages []*ms.Message var messages []*ms.Message
if err := s.q.GetMessages.Select(&messages, userId, userId, limit, offset); err != nil { // 1动态2评论3回复4私信5好友申请99系统通知
return nil, err switch style {
} case cs.StyleMsgSystem:
mfs := make([]*ms.MessageFormated, 0, len(messages)) if err = s.q.CountSystemMessages.Get(&total, userId); err == nil && total > 0 {
for _, message := range messages { err = s.q.GetSystemMessages.Select(&messages, userId, limit, offset)
mf := message.Format() }
mfs = append(mfs, mf) case cs.StyleMsgWhisper:
if err = s.q.CountWhisperMessages.Get(&total, userId, userId); err == nil && total > 0 {
err = s.q.GetWhisperMessages.Select(&messages, userId, userId, limit, offset)
}
case cs.StyleMsgRequesting:
if err = s.q.CountRequestingMessages.Get(&total, userId); err == nil && total > 0 {
err = s.q.GetRequestingMessages.Select(&messages, userId, limit, offset)
}
case cs.StyleMsgUnread:
if err = s.q.CountUnreadMessages.Get(&total, userId); err == nil && total > 0 {
err = s.q.GetUnreadMessages.Select(&messages, userId, limit, offset)
}
case cs.StyleMsgAll:
fallthrough
default:
if err = s.q.CountAllMessages.Get(&total, userId, userId); err == nil && total > 0 {
err = s.q.GetAllMessages.Select(&messages, userId, userId, limit, offset)
}
} }
return mfs, nil if err == nil {
} for _, message := range messages {
res = append(res, message.Format())
func (s *messageSrv) GetMessageCount(userId int64) (res int64, err error) { }
if err = s.q.GetMessageCount.Get(&res, userId, userId); err != nil {
logrus.Errorf("get message count error: %s", err)
} }
return return
} }
func newMessageService(db *sqlx.DB) (s core.MessageService) { func newMessageService(db *sqlx.DB) (s core.MessageService) {

@ -20,17 +20,24 @@ type tweetMetricSrvA struct {
type commentMetricSrvA struct { type commentMetricSrvA struct {
*sqlxSrv *sqlxSrv
q *cc.CommentMetrics
} }
type userMetricSrvA struct { type userMetricSrvA struct {
*sqlxSrv *sqlxSrv
q *cc.UserMetrics
} }
func (s *tweetMetricSrvA) UpdateTweetMetric(metric *cs.TweetMetric) error { func (s *tweetMetricSrvA) UpdateTweetMetric(metric *cs.TweetMetric) error {
return s.db.Withx(func(tx *sqlx.Tx) error { return s.db.Withx(func(tx *sqlx.Tx) error {
var motivationFactor int var motivationFactor int
tx.Stmtx(s.q.GetMotivationFactor).Get(&motivationFactor, metric.PostId) now := time.Now().Unix()
_, err := tx.Stmtx(s.q.UpdateRankScore).Exec(metric.RankScore(motivationFactor), time.Now().Unix(), metric.PostId) err := tx.Stmtx(s.q.GetMotivationFactor).Get(&motivationFactor, metric.PostId)
if err == nil {
_, err = tx.Stmtx(s.q.UpdateRankScore).Exec(metric.RankScore(motivationFactor), now, metric.PostId)
} else {
_, err = tx.Stmtx(s.q.UpsertTweetMetric).Exec(metric.PostId, metric.RankScore(motivationFactor), now)
}
return err return err
}) })
} }
@ -46,33 +53,56 @@ func (s *tweetMetricSrvA) DeleteTweetMetric(postId int64) error {
} }
func (s *commentMetricSrvA) UpdateCommentMetric(metric *cs.CommentMetric) error { func (s *commentMetricSrvA) UpdateCommentMetric(metric *cs.CommentMetric) error {
// TDOO return s.db.Withx(func(tx *sqlx.Tx) error {
return cs.ErrNotImplemented var motivationFactor int
now := time.Now().Unix()
err := tx.Stmtx(s.q.GetMotivationFactor).Get(&motivationFactor, metric.CommentId)
if err == nil {
_, err = tx.Stmtx(s.q.UpdateRankScore).Exec(metric.RankScore(motivationFactor), now, metric.CommentId)
} else {
_, err = tx.Stmtx(s.q.UpsertCommentMetric).Exec(metric.CommentId, metric.RankScore(motivationFactor), now)
}
return err
})
} }
func (s *commentMetricSrvA) AddCommentMetric(commentId int64) (err error) { func (s *commentMetricSrvA) AddCommentMetric(commentId int64) error {
// TDOO _, err := s.q.AddCommentMetric.Exec(commentId, time.Now().Unix())
return cs.ErrNotImplemented return err
} }
func (s *commentMetricSrvA) DeleteCommentMetric(commentId int64) (err error) { func (s *commentMetricSrvA) DeleteCommentMetric(commentId int64) error {
// TDOO _, err := s.q.DeleteCommentMetric.Exec(time.Now().Unix(), commentId)
return cs.ErrNotImplemented return err
} }
func (s *userMetricSrvA) UpdateUserMetric(userId int64, action uint8) error { func (s *userMetricSrvA) UpdateUserMetric(userId int64, action uint8) (err error) {
// TODO var tweets_count int
return cs.ErrNotImplemented now := time.Now().Unix()
if err = s.q.GetTweetsCount.Get(&tweets_count, userId); err != nil {
_, err = s.q.AddUserMetric.Exec(userId, now)
return
}
switch action {
case cs.MetricActionCreateTweet:
tweets_count++
case cs.MetricActionDeleteTweet:
if tweets_count > 0 {
tweets_count--
}
}
_, err = s.q.UpdateUserMetric.Exec(userId, tweets_count)
return
} }
func (s *userMetricSrvA) AddUserMetric(userId int64) (err error) { func (s *userMetricSrvA) AddUserMetric(userId int64) error {
// TDOO _, err := s.q.AddUserMetric.Exec(userId, time.Now().Unix())
return cs.ErrNotImplemented return err
} }
func (s *userMetricSrvA) DeleteUserMetric(userId int64) (err error) { func (s *userMetricSrvA) DeleteUserMetric(userId int64) error {
// TDOO _, err := s.q.DeleteUserMetric.Exec(time.Now().Unix(), userId)
return cs.ErrNotImplemented return err
} }
func newTweetMetricServentA(db *sqlx.DB) core.TweetMetricServantA { func newTweetMetricServentA(db *sqlx.DB) core.TweetMetricServantA {
@ -85,11 +115,13 @@ func newTweetMetricServentA(db *sqlx.DB) core.TweetMetricServantA {
func newCommentMetricServentA(db *sqlx.DB) core.CommentMetricServantA { func newCommentMetricServentA(db *sqlx.DB) core.CommentMetricServantA {
return &commentMetricSrvA{ return &commentMetricSrvA{
sqlxSrv: newSqlxSrv(db), sqlxSrv: newSqlxSrv(db),
q: ccBuild(db, cc.BuildCommentMetrics),
} }
} }
func newUserMetricServentA(db *sqlx.DB) core.UserMetricServantA { func newUserMetricServentA(db *sqlx.DB) core.UserMetricServantA {
return &userMetricSrvA{ return &userMetricSrvA{
sqlxSrv: newSqlxSrv(db), sqlxSrv: newSqlxSrv(db),
q: ccBuild(db, cc.BuildUserMetrics),
} }
} }

@ -39,7 +39,9 @@ type dataSrv struct {
core.SecurityService core.SecurityService
core.AttachmentCheckService core.AttachmentCheckService
core.TweetMetricServantA core.TweetMetricServantA
core.UserMetricServantA
core.CommentMetricServantA core.CommentMetricServantA
core.TrendsManageServantA
} }
type webDataSrvA struct { type webDataSrvA struct {
@ -54,10 +56,13 @@ func NewDataService() (core.DataService, core.VersionInfo) {
pvs := security.NewPhoneVerifyService() pvs := security.NewPhoneVerifyService()
cms := newCommentMetricServentA(_db) cms := newCommentMetricServentA(_db)
tms := newTweetMetricServentA(_db) tms := newTweetMetricServentA(_db)
ums := newUserMetricServentA(_db)
cis := cache.NewEventCacheIndexSrv(tms) cis := cache.NewEventCacheIndexSrv(tms)
ds := &dataSrv{ ds := &dataSrv{
TweetMetricServantA: tms, TweetMetricServantA: tms,
CommentMetricServantA: cms, CommentMetricServantA: cms,
UserMetricServantA: ums,
TrendsManageServantA: newTrendsManageServentA(_db),
WalletService: newWalletService(_db), WalletService: newWalletService(_db),
MessageService: newMessageService(_db), MessageService: newMessageService(_db),
TopicService: newTopicService(_db), TopicService: newTopicService(_db),
@ -66,7 +71,7 @@ func NewDataService() (core.DataService, core.VersionInfo) {
TweetHelpService: newTweetHelpService(_db), TweetHelpService: newTweetHelpService(_db),
CommentService: newCommentService(_db), CommentService: newCommentService(_db),
CommentManageService: newCommentManageService(_db), CommentManageService: newCommentManageService(_db),
UserManageService: newUserManageService(_db), UserManageService: newUserManageService(_db, ums),
ContactManageService: newContactManageService(_db), ContactManageService: newContactManageService(_db),
UserRelationService: newUserRelationService(_db), UserRelationService: newUserRelationService(_db),
FollowingManageService: newFollowingManageService(_db), FollowingManageService: newFollowingManageService(_db),

@ -0,0 +1,31 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package sakila
import (
"github.com/bitbus/sqlx"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/dao/sakila/auto/cc"
)
type trendsSrvA struct {
*sqlxSrv
q *cc.TrendsManager
}
func (s *trendsSrvA) GetIndexTrends(userId int64, limit int, offset int) (res []*cs.TrendsItem, total int64, err error) {
if err = s.q.CountIndexTrends.Get(&total, userId); err == nil && total > 0 {
err = s.q.GetIndexTrends.Select(&res, userId, limit, offset)
}
return
}
func newTrendsManageServentA(db *sqlx.DB) core.TrendsManageServantA {
return &trendsSrvA{
sqlxSrv: newSqlxSrv(db),
q: ccBuild(db, cc.BuildTrendsManager),
}
}

@ -519,7 +519,7 @@ func (s *tweetSrv) getUserRelation(userId int64) (beFriendIds []int64, beFollowI
// 找到item即删数据库已经保证唯一性 // 找到item即删数据库已经保证唯一性
if beFollowIds[i] == id { if beFollowIds[i] == id {
lastIdx := len(beFollowIds) - 1 lastIdx := len(beFollowIds) - 1
beFriendIds[i] = beFriendIds[lastIdx] beFollowIds[i] = beFollowIds[lastIdx]
beFollowIds = beFollowIds[:lastIdx] beFollowIds = beFollowIds[:lastIdx]
break break
} }

@ -12,7 +12,6 @@ import (
"github.com/bitbus/sqlx" "github.com/bitbus/sqlx"
"github.com/bitbus/sqlx/db" "github.com/bitbus/sqlx/db"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/core/ms" "github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/dao/sakila/auto/cc" "github.com/rocboss/paopao-ce/internal/dao/sakila/auto/cc"
"github.com/rocboss/paopao-ce/internal/dao/sakila/auto/pgc" "github.com/rocboss/paopao-ce/internal/dao/sakila/auto/pgc"
@ -24,11 +23,13 @@ var (
type userManageSrv struct { type userManageSrv struct {
*sqlxSrv *sqlxSrv
q *cc.UserManage q *cc.UserManage
ums core.UserMetricServantA
} }
type userRelationSrv struct { type userRelationSrv struct {
*sqlxSrv *sqlxSrv
q *cc.UserRelation
} }
func (s *userManageSrv) GetUserByID(id int64) (*ms.User, error) { func (s *userManageSrv) GetUserByID(id int64) (*ms.User, error) {
@ -69,7 +70,10 @@ func (s *userManageSrv) CreateUser(r *ms.User) (*ms.User, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
r.ID, err = res.LastInsertId() if r.ID, err = res.LastInsertId(); err == nil {
// 宽松处理错误
s.ums.AddUserMetric(r.ID)
}
return r, err return r, err
} }
@ -84,29 +88,64 @@ func (s *userManageSrv) GetRegisterUserCount() (res int64, err error) {
} }
func (s *userRelationSrv) MyFriendIds(userId int64) (res []int64, err error) { func (s *userRelationSrv) MyFriendIds(userId int64) (res []int64, err error) {
// TODO err = s.q.MyFriendIds.Select(&res, userId)
return return
} }
func (s *userRelationSrv) MyFollowIds(userId int64) (res []int64, err error) { func (s *userRelationSrv) MyFollowIds(userId int64) (res []int64, err error) {
// TODO err = s.q.MyFollowIds.Select(&res, userId)
return return
} }
func (s *userRelationSrv) IsMyFriend(userId int64, friendIds ...int64) (map[int64]bool, error) { func (s *userRelationSrv) IsMyFriend(userId int64, friendIds ...int64) (map[int64]bool, error) {
// TODO size := len(friendIds)
return nil, cs.ErrNotImplemented res := make(map[int64]bool, size)
if size == 0 {
return res, nil
}
myFriendIds, err := s.MyFriendIds(userId)
if err != nil {
return nil, err
}
for _, friendId := range friendIds {
res[friendId] = false
for _, myFriendId := range myFriendIds {
if friendId == myFriendId {
res[friendId] = true
break
}
}
}
return res, nil
} }
func (s *userRelationSrv) IsMyFollow(userId int64, followIds ...int64) (map[int64]bool, error) { func (s *userRelationSrv) IsMyFollow(userId int64, followIds ...int64) (map[int64]bool, error) {
// TODO size := len(followIds)
return nil, cs.ErrNotImplemented res := make(map[int64]bool, size)
if size == 0 {
return res, nil
}
myFollowIds, err := s.MyFollowIds(userId)
if err != nil {
return nil, err
}
for _, followId := range followIds {
res[followId] = false
for _, myFollowId := range myFollowIds {
if followId == myFollowId {
res[followId] = true
break
}
}
}
return res, nil
} }
func newUserManageService(db *sqlx.DB) (s core.UserManageService) { func newUserManageService(db *sqlx.DB, userMetric core.UserMetricServantA) (s core.UserManageService) {
ums := &userManageSrv{ ums := &userManageSrv{
sqlxSrv: newSqlxSrv(db), sqlxSrv: newSqlxSrv(db),
q: ccBuild(db, cc.BuildUserManage), q: ccBuild(db, cc.BuildUserManage),
ums: userMetric,
} }
s = ums s = ums
if cfg.Any("PostgreSQL", "PgSQL", "Postgres") { if cfg.Any("PostgreSQL", "PgSQL", "Postgres") {
@ -121,5 +160,6 @@ func newUserManageService(db *sqlx.DB) (s core.UserManageService) {
func newUserRelationService(db *sqlx.DB) core.UserRelationService { func newUserRelationService(db *sqlx.DB) core.UserRelationService {
return &userRelationSrv{ return &userRelationSrv{
sqlxSrv: newSqlxSrv(db), sqlxSrv: newSqlxSrv(db),
q: ccBuild(db, cc.BuildUserRelation),
} }
} }

@ -21,10 +21,11 @@ type pgcUserManageSrv struct {
p *pgc.UserManage p *pgc.UserManage
} }
func (s *pgcUserManageSrv) CreateUser(r *ms.User) (*ms.User, error) { func (s *pgcUserManageSrv) CreateUser(r *ms.User) (res *ms.User, err error) {
r.Model = &ms.Model{CreatedOn: time.Now().Unix()} res, r.Model = r, &ms.Model{CreatedOn: time.Now().Unix()}
if err := s.p.CreateUser.Get(&r.ID, r); err != nil { if err = s.p.CreateUser.Get(&r.ID, r); err == nil {
return nil, err // 宽松处理错误
s.ums.AddUserMetric(r.ID)
} }
return r, nil return
} }

@ -25,15 +25,29 @@ SELECT status FROM @contact WHERE user_id=? AND friend_id=? AND is_del=0;
-- name: get_newest_comments@comment -- name: get_newest_comments@comment
-- prepare: stmt -- prepare: stmt
SELECT * FROM @comment WHERE post_id=? AND is_del=0 ORDER BY id DESC LIMIT ? OFFSET ?; SELECT *
FROM @comment
WHERE post_id=? AND is_del=0
ORDER BY is_essence DESC, id DESC
LIMIT ? OFFSET ?;
-- name: get_hots_comments@comment -- name: get_hots_comments@comment
-- prepare: stmt -- prepare: stmt
SELECT * FROM @comment WHERE post_id=? AND is_del=0 ORDER BY thumbs_up_count DESC, id DESC LIMIT ? OFFSET ?; SELECT c.*
FROM @comment c
LEFT JOIN @comment_metric m
ON c.id=m.comment_id
WHERE c.post_id=? AND c.is_del=0 AND m.is_del=0
ORDER BY is_essence DESC, m.rank_score DESC, id DESC
LIMIT ? OFFSET ?;
-- name: get_default_comments@comment -- name: get_default_comments@comment
-- prepare: stmt -- prepare: stmt
SELECT * FROM @comment WHERE post_id=? AND is_del=0 ORDER BY id ASC LIMIT ? OFFSET ?; SELECT *
FROM @comment
WHERE post_id=? AND is_del=0
ORDER BY is_essence DESC, id ASC
LIMIT ? OFFSET ?;
-- name: get_comment_by_id@comment -- name: get_comment_by_id@comment
-- prepare: stmt -- prepare: stmt
@ -97,6 +111,20 @@ VALUES (?, ?, ?, ?, ?);
INSERT INTO @comment_reply (comment_id, user_id, content, at_user_id, ip, ip_loc, created_on) INSERT INTO @comment_reply (comment_id, user_id, content, at_user_id, ip, ip_loc, created_on)
VALUES (?, ?, ?, ?, ?, ?, ?); VALUES (?, ?, ?, ?, ?, ?, ?);
-- name: incr_comment_reply_count@comment_manage
-- prepare: stmt
UPDATE @comment
SET reply_count=reply_count+1,
modified_on=?
WHERE id=? AND is_del=0;
-- name: decr_comment_reply_count@comment_manage
-- prepare: stmt
UPDATE @comment
SET reply_count=reply_count-1,
modified_on=?
WHERE id=? AND is_del=0;
-- name: delete_comment_reply@comment_manage -- name: delete_comment_reply@comment_manage
-- prepare: stmt -- prepare: stmt
UPDATE @comment_reply SET deleted_on=?, is_del=1 WHERE id=? AND is_del=0; UPDATE @comment_reply SET deleted_on=?, is_del=1 WHERE id=? AND is_del=0;
@ -197,6 +225,41 @@ LIMIT ? OFFSET ?;
-- prepare: stmt -- prepare: stmt
SELECT count(*) FROM @following WHERE follow_id=? AND is_del=0; SELECT count(*) FROM @following WHERE follow_id=? AND is_del=0;
--------------------------------------------------------------------------------
-- trends_manager sql dml
--------------------------------------------------------------------------------
-- name: get_index_trends@trends_manager
-- prepare: stmt
SELECT u.username username,
u.nickname nickname,
u.avatar avatar
FROM @contact c
JOIN @user u
ON c.friend_id=u.id
JOIN @user_metric m
ON c.friend_id=m.user_id
WHERE c.user_id=?
AND c.is_del=0
AND u.is_del=0
AND m.is_del=0
AND m.tweets_count>0
LIMIT ? OFFSET ?;
-- name: count_index_trends@trends_manager
-- prepare: stmt
SELECT count(*)
FROM @contact c
JOIN @user u
ON c.friend_id=u.id
JOIN @user_metric m
ON c.friend_id=m.user_id
WHERE c.user_id=?
AND c.is_del=0
AND u.is_del=0
AND m.is_del=0
AND m.tweets_count>0;
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- contact_manager sql dml -- contact_manager sql dml
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -288,17 +351,75 @@ SELECT * FROM @message WHERE id=? AND is_del=0;
-- prepare: stmt -- prepare: stmt
UPDATE @message SET is_read=1, modified_on=? WHERE id=?; UPDATE @message SET is_read=1, modified_on=? WHERE id=?;
-- name: get_messages@message -- name: get_system_messages@message
-- prepare: stmt
SELECT *
FROM @message
WHERE receiver_user_id=? AND type IN (1, 2, 3, 99) AND is_del=0
ORDER BY id DESC
LIMIT ? OFFSET ?;
-- name: count_system_messages@message
-- prepare: stmt
SELECT count(*)
FROM @message
WHERE receiver_user_id=? AND type IN (1, 2, 3, 99) AND is_del=0;
-- name: get_whisper_messages@message
-- prepare: stmt
SELECT *
FROM @message
WHERE ((receiver_user_id=? OR sender_user_id=?) AND type=4) AND is_del=0
ORDER BY id DESC
LIMIT ? OFFSET ?;
-- name: count_whisper_messages@message
-- prepare: stmt
SELECT count(*)
FROM @message
WHERE ((receiver_user_id=? OR sender_user_id=?) AND type=4) AND is_del=0;
-- name: get_requesting_messages@message
-- prepare: stmt
SELECT *
FROM @message
WHERE receiver_user_id=? AND type=5 AND is_del=0
ORDER BY id DESC
LIMIT ? OFFSET ?;
-- name: count_requesting_messages@message
-- prepare: stmt
SELECT count(*)
FROM @message
WHERE receiver_user_id=? AND type=5 AND is_del=0;
-- name: get_unread_messages@message
-- prepare: stmt
SELECT *
FROM @message
WHERE receiver_user_id=? AND is_read=0 AND is_del=0
ORDER BY id DESC
LIMIT ? OFFSET ?;
-- name: count_unread_messages@message
-- prepare: stmt
SELECT count(*)
FROM @message
WHERE receiver_user_id=? AND is_read=0 AND is_del=0;
-- name: get_all_messages@message
-- prepare: stmt -- prepare: stmt
SELECT * SELECT *
FROM @message FROM @message
WHERE (receiver_user_id=? OR (sender_user_id=? AND type=4)) AND is_del=0 WHERE (receiver_user_id=? OR (sender_user_id=? AND type=4)) AND is_del=0
ORDER BY id DESC ORDER BY id DESC
LIMIT ? OFFSET ? LIMIT ? OFFSET ?;
-- name: get_message_count@message -- name: count_all_messages@message
-- prepare: stmt -- prepare: stmt
SELECT count(*) FROM @message WHERE (receiver_user_id=? OR (sender_user_id=? AND type=4)) AND is_del=0 SELECT count(*)
FROM @message
WHERE (receiver_user_id=? OR (sender_user_id=? AND type=4)) AND is_del=0;
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- security sql dml -- security sql dml
@ -1191,6 +1312,7 @@ WHERE id IN (?) AND is_del=0;
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- tweet_metrics sql dml -- tweet_metrics sql dml
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- name: update_rank_score@tweet_metrics -- name: update_rank_score@tweet_metrics
-- prepare: stmt -- prepare: stmt
UPDATE @post_metric SET rank_score=?, modified_on=? WHERE post_id=? AND is_del=0; UPDATE @post_metric SET rank_score=?, modified_on=? WHERE post_id=? AND is_del=0;
@ -1203,10 +1325,58 @@ SELECT motivation_factor FROM @post_metric WHERE post_id=? AND is_del=0;
-- prepare: stmt -- prepare: stmt
INSERT INTO @post_metric (post_id, created_on) VALUES (?, ?); INSERT INTO @post_metric (post_id, created_on) VALUES (?, ?);
-- name: upsert_tweet_metric@tweet_metrics
-- prepare: stmt
INSERT INTO @post_metric (post_id, rank_score, created_on) VALUES (?, ?, ?);
-- name: delete_tweet_metric@tweet_metrics -- name: delete_tweet_metric@tweet_metrics
-- prepare: stmt -- prepare: stmt
UPDATE @post_metric SET is_del=1, deleted_on=? WHERE post_id=? AND is_del=0; UPDATE @post_metric SET is_del=1, deleted_on=? WHERE post_id=? AND is_del=0;
--------------------------------------------------------------------------------
-- comment_metrics sql dml
--------------------------------------------------------------------------------
-- name: update_rank_score@comment_metrics
-- prepare: stmt
UPDATE @comment_metric SET rank_score=?, modified_on=? WHERE comment_id=? AND is_del=0;
-- name: get_motivation_factor@comment_metrics
-- prepare: stmt
SELECT motivation_factor FROM @comment_metric WHERE comment_id=? AND is_del=0;
-- name: add_comment_metric@comment_metrics
-- prepare: stmt
INSERT INTO @comment_metric (comment_id, created_on) VALUES (?, ?);
-- name: upsert_comment_metric@comment_metrics
-- prepare: stmt
INSERT INTO @comment_metric (comment_id, rank_score, created_on) VALUES (?, ?, ?);
-- name: delete_comment_metric@comment_metrics
-- prepare: stmt
UPDATE @comment_metric SET is_del=1, deleted_on=? WHERE comment_id=? AND is_del=0;
--------------------------------------------------------------------------------
-- user_metrics sql dml
--------------------------------------------------------------------------------
-- name: update_user_metric@user_metrics
-- prepare: stmt
UPDATE @user_metric SET tweets_count=?, modified_on=? WHERE user_id=? AND is_del=0;
-- name: get_tweets_count@user_metrics
-- prepare: stmt
SELECT tweets_count FROM @user_metric WHERE user_id=? AND is_del=0;
-- name: add_user_metric@user_metrics
-- prepare: stmt
INSERT INTO @user_metric (user_id, created_on) VALUES (?, ?);
-- name: delete_user_metric@user_metrics
-- prepare: stmt
UPDATE @user_metric SET is_del=1, deleted_on=? WHERE user_id=? AND is_del=0;
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- user_manage sql dml -- user_manage sql dml
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -1260,6 +1430,18 @@ SET username=:username,
modified_on=:modified_on modified_on=:modified_on
WHERE id=? AND is_del=0; WHERE id=? AND is_del=0;
--------------------------------------------------------------------------------
-- user_relation sql dml
--------------------------------------------------------------------------------
-- name: my_friend_ids@user_relation
-- prepare: stmt
SELECT friend_id FROM @contact WHERE user_id=? AND is_del=0;
-- name: my_follow_ids@user_relation
-- prepare: stmt
SELECT follow_id FROM @following WHERE user_id=? AND is_del=0;
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- wallet sql dml -- wallet sql dml
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

@ -52,6 +52,20 @@ INSERT INTO @post_collection (post_id, user_id, created_on)
VALUES (?, ?, ?) VALUES (?, ?, ?)
RETURNING *; RETURNING *;
--------------------------------------------------------------------------------
-- comment sql dml
--------------------------------------------------------------------------------
-- name: get_hots_comments@comment
-- prepare: stmt
SELECT c.*
FROM @comment c
LEFT JOIN @comment_metric m
ON c.id=m.comment_id
WHERE c.post_id=? AND c.is_del=0 AND m.is_del=0
ORDER BY is_essence DESC, m.rank_score DESC NULLS LAST, id DESC
LIMIT ? OFFSET ?;
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- user_manage sql dml -- user_manage sql dml
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

@ -7,11 +7,15 @@ package web
import ( import (
"github.com/alimy/mir/v4" "github.com/alimy/mir/v4"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/model/joint"
"github.com/rocboss/paopao-ce/internal/servants/base" "github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/convert"
"github.com/rocboss/paopao-ce/pkg/xerror" "github.com/rocboss/paopao-ce/pkg/xerror"
) )
type MessageStyle = cs.MessageStyle
type ChangeAvatarReq struct { type ChangeAvatarReq struct {
BaseInfo `json:"-" binding:"-"` BaseInfo `json:"-" binding:"-"`
Avatar string `json:"avatar" form:"avatar" binding:"required"` Avatar string `json:"avatar" form:"avatar" binding:"required"`
@ -40,9 +44,15 @@ type UserInfoResp struct {
Followings int64 `json:"followings"` Followings int64 `json:"followings"`
} }
type GetMessagesReq BasePageReq type GetMessagesReq struct {
SimpleInfo `json:"-" binding:"-"`
joint.BasePageInfo
Style MessageStyle `form:"style" binding:"required"`
}
type GetMessagesResp base.PageResp type GetMessagesResp struct {
joint.CachePageResp
}
type ReadMessageReq struct { type ReadMessageReq struct {
SimpleInfo `json:"-" binding:"-"` SimpleInfo `json:"-" binding:"-"`
@ -120,10 +130,6 @@ func (r *UserInfoReq) Bind(c *gin.Context) mir.Error {
return nil return nil
} }
func (r *GetMessagesReq) Bind(c *gin.Context) mir.Error {
return (*BasePageReq)(r).Bind(c)
}
func (r *GetCollectionsReq) Bind(c *gin.Context) mir.Error { func (r *GetCollectionsReq) Bind(c *gin.Context) mir.Error {
return (*BasePageReq)(r).Bind(c) return (*BasePageReq)(r).Bind(c)
} }

@ -4,7 +4,9 @@
package web package web
import "github.com/rocboss/paopao-ce/internal/servants/base" import (
"github.com/rocboss/paopao-ce/internal/servants/base"
)
type RequestingFriendReq struct { type RequestingFriendReq struct {
BaseInfo `json:"-" binding:"-"` BaseInfo `json:"-" binding:"-"`

@ -0,0 +1,18 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package web
import (
"github.com/rocboss/paopao-ce/internal/model/joint"
)
type GetIndexTrendsReq struct {
SimpleInfo `json:"-" binding:"-"`
joint.BasePageInfo
}
type GetIndexTrendsResp struct {
joint.CachePageResp
}

@ -90,6 +90,8 @@ var (
ErrNotAllowFollowSelf = xerror.NewError(80105, "不能关注自己") ErrNotAllowFollowSelf = xerror.NewError(80105, "不能关注自己")
ErrNotAllowUnfollowSelf = xerror.NewError(80106, "不能取消关注自己") ErrNotAllowUnfollowSelf = xerror.NewError(80106, "不能取消关注自己")
ErrGetIndexTrendsFailed = xerror.NewError(802001, "获取动态条栏信息失败")
ErrFollowTopicFailed = xerror.NewError(90001, "关注话题失败") ErrFollowTopicFailed = xerror.NewError(90001, "关注话题失败")
ErrUnfollowTopicFailed = xerror.NewError(90002, "取消关注话题失败") ErrUnfollowTopicFailed = xerror.NewError(90002, "取消关注话题失败")
ErrStickTopicFailed = xerror.NewError(90003, "更行话题置顶状态失败") ErrStickTopicFailed = xerror.NewError(90003, "更行话题置顶状态失败")

@ -6,6 +6,7 @@ package web
import ( import (
"context" "context"
"fmt"
"time" "time"
"unicode/utf8" "unicode/utf8"
@ -13,8 +14,10 @@ import (
"github.com/alimy/mir/v4" "github.com/alimy/mir/v4"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
api "github.com/rocboss/paopao-ce/auto/api/v1" api "github.com/rocboss/paopao-ce/auto/api/v1"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/ms" "github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/model/joint"
"github.com/rocboss/paopao-ce/internal/model/web" "github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base" "github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain" "github.com/rocboss/paopao-ce/internal/servants/chain"
@ -35,9 +38,10 @@ var (
type coreSrv struct { type coreSrv struct {
api.UnimplementedCoreServant api.UnimplementedCoreServant
*base.DaoServant *base.DaoServant
oss core.ObjectStorageService
oss core.ObjectStorageService wc core.WebCache
wc core.WebCache messagesExpire int64
prefixMessages string
} }
func (s *coreSrv) Chain() gin.HandlersChain { func (s *coreSrv) Chain() gin.HandlersChain {
@ -84,8 +88,19 @@ func (s *coreSrv) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Erro
return resp, nil return resp, nil
} }
func (s *coreSrv) GetMessages(req *web.GetMessagesReq) (*web.GetMessagesResp, mir.Error) { func (s *coreSrv) GetMessages(req *web.GetMessagesReq) (res *web.GetMessagesResp, _ mir.Error) {
messages, err := s.Ds.GetMessages(req.UserId, (req.Page-1)*req.PageSize, req.PageSize) limit, offset := req.PageSize, (req.Page-1)*req.PageSize
// 尝试直接从缓存中获取数据
key, ok := "", false
if res, key, ok = s.messagesFromCache(req, limit, offset); ok {
// logrus.Debugf("coreSrv.GetMessages from cache key:%s", key)
return
}
messages, totalRows, err := s.Ds.GetMessages(req.Uid, req.Style, limit, offset)
if err != nil {
logrus.Errorf("Ds.GetMessages err[1]: %s", err)
return nil, web.ErrGetMessagesFailed
}
for _, mf := range messages { for _, mf := range messages {
// TODO: 优化处理这里的user获取逻辑以及错误处理 // TODO: 优化处理这里的user获取逻辑以及错误处理
if mf.SenderUserID > 0 { if mf.SenderUserID > 0 {
@ -93,7 +108,7 @@ func (s *coreSrv) GetMessages(req *web.GetMessagesReq) (*web.GetMessagesResp, mi
mf.SenderUser = user.Format() mf.SenderUser = user.Format()
} }
} }
if mf.Type == ms.MsgTypeWhisper && mf.ReceiverUserID != req.UserId { if mf.Type == ms.MsgTypeWhisper && mf.ReceiverUserID != req.Uid {
if user, err := s.Ds.GetUserByID(mf.ReceiverUserID); err == nil { if user, err := s.Ds.GetUserByID(mf.ReceiverUserID); err == nil {
mf.ReceiverUser = user.Format() mf.ReceiverUser = user.Format()
} }
@ -122,16 +137,21 @@ func (s *coreSrv) GetMessages(req *web.GetMessagesReq) (*web.GetMessagesResp, mi
} }
} }
if err != nil { if err != nil {
logrus.Errorf("Ds.GetMessages err: %v\n", err) logrus.Errorf("Ds.GetMessages err[2]: %s", err)
return nil, web.ErrGetMessagesFailed return nil, web.ErrGetMessagesFailed
} }
if err = s.PrepareMessages(req.UserId, messages); err != nil { if err = s.PrepareMessages(req.Uid, messages); err != nil {
logrus.Errorf("get messages err[2]: %v\n", err) logrus.Errorf("get messages err[3]: %s", err)
return nil, web.ErrGetMessagesFailed return nil, web.ErrGetMessagesFailed
} }
totalRows, _ := s.Ds.GetMessageCount(req.UserId) resp := joint.PageRespFrom(messages, req.Page, req.PageSize, totalRows)
resp := base.PageRespFrom(messages, req.Page, req.PageSize, totalRows) // 缓存处理
return (*web.GetMessagesResp)(resp), nil base.OnCacheRespEvent(s.wc, key, resp, s.messagesExpire)
return &web.GetMessagesResp{
CachePageResp: joint.CachePageResp{
Data: resp,
},
}, nil
} }
func (s *coreSrv) ReadMessage(req *web.ReadMessageReq) mir.Error { func (s *coreSrv) ReadMessage(req *web.ReadMessageReq) mir.Error {
@ -146,8 +166,8 @@ func (s *coreSrv) ReadMessage(req *web.ReadMessageReq) mir.Error {
logrus.Errorf("Ds.ReadMessage err: %s", err) logrus.Errorf("Ds.ReadMessage err: %s", err)
return web.ErrReadMessageFailed return web.ErrReadMessageFailed
} }
// 清除未读消息数缓存,不需要处理错误 // 缓存处理
s.wc.DelUnreadMsgCountResp(req.Uid) onMessageActionEvent(_messageActionRead, req.Uid)
return nil return nil
} }
@ -378,10 +398,25 @@ func (s *coreSrv) TweetStarStatus(req *web.TweetStarStatusReq) (*web.TweetStarSt
return resp, nil return resp, nil
} }
func (s *coreSrv) messagesFromCache(req *web.GetMessagesReq, limit int, offset int) (res *web.GetMessagesResp, key string, ok bool) {
key = fmt.Sprintf("%s%d:%s:%d:%d", s.prefixMessages, req.Uid, req.Style, limit, offset)
if data, err := s.wc.Get(key); err == nil {
ok, res = true, &web.GetMessagesResp{
CachePageResp: joint.CachePageResp{
JsonResp: data,
},
}
}
return
}
func newCoreSrv(s *base.DaoServant, oss core.ObjectStorageService, wc core.WebCache) api.Core { func newCoreSrv(s *base.DaoServant, oss core.ObjectStorageService, wc core.WebCache) api.Core {
cs := conf.CacheSetting
return &coreSrv{ return &coreSrv{
DaoServant: s, DaoServant: s,
oss: oss, oss: oss,
wc: wc, wc: wc,
messagesExpire: cs.MessagesExpire,
prefixMessages: conf.PrefixMessages,
} }
} }

@ -16,6 +16,7 @@ import (
"github.com/rocboss/paopao-ce/internal/events" "github.com/rocboss/paopao-ce/internal/events"
"github.com/rocboss/paopao-ce/internal/model/joint" "github.com/rocboss/paopao-ce/internal/model/joint"
"github.com/rocboss/paopao-ce/internal/model/web" "github.com/rocboss/paopao-ce/internal/model/web"
"github.com/sirupsen/logrus"
) )
const ( const (
@ -27,6 +28,18 @@ const (
_commentActionReplyDelete _commentActionReplyDelete
_commentActionReplyThumbsUp _commentActionReplyThumbsUp
_commentActionReplyThumbsDown _commentActionReplyThumbsDown
_commentActionHighlight
)
const (
_messageActionCreate uint8 = iota
_messageActionRead
_messageActionFollow
)
const (
_trendsActionCreateTweet uint8 = iota
_trendsActionDeleteTweet
) )
type cacheUnreadMsgEvent struct { type cacheUnreadMsgEvent struct {
@ -52,6 +65,38 @@ type commentActionEvent struct {
action uint8 action uint8
} }
type messageActionEvent struct {
event.UnimplementedEvent
wc core.WebCache
action uint8
userId []int64
}
type trendsActionEvent struct {
event.UnimplementedEvent
ac core.AppCache
ds core.DataService
action uint8
userId int64
}
func onTrendsActionEvent(action uint8, userId int64) {
events.OnEvent(&trendsActionEvent{
ac: _ac,
ds: _ds,
action: action,
userId: userId,
})
}
func onMessageActionEvent(action uint8, userIds ...int64) {
events.OnEvent(&messageActionEvent{
wc: _wc,
action: action,
userId: userIds,
})
}
func onCommentActionEvent(tweetId int64, commentId int64, action uint8) { func onCommentActionEvent(tweetId int64, commentId int64, action uint8) {
events.OnEvent(&commentActionEvent{ events.OnEvent(&commentActionEvent{
ds: _ds, ds: _ds,
@ -138,6 +183,8 @@ func (e *commentActionEvent) Action() (err error) {
case _commentActionThumbsUp, _commentActionThumbsDown: case _commentActionThumbsUp, _commentActionThumbsDown:
err = e.updateCommentMetric() err = e.updateCommentMetric()
e.expireHotsComments() e.expireHotsComments()
case _commentActionHighlight:
e.expireAllStyleComments()
default: default:
// nothing // nothing
} }
@ -166,3 +213,54 @@ func (e *commentActionEvent) updateCommentMetric() error {
}) })
return nil return nil
} }
func (e *messageActionEvent) Name() string {
return "expireMessagesEvent"
}
func (e *messageActionEvent) Action() (err error) {
for _, userId := range e.userId {
switch e.action {
case _messageActionRead:
// 清除未读消息数缓存,不需要处理错误
e.wc.DelUnreadMsgCountResp(userId)
case _messageActionCreate,
_messageActionFollow:
fallthrough
default:
// TODO
}
//清除该用户所有消息缓存
err = e.wc.DelAny(fmt.Sprintf("%s%d:*", conf.PrefixMessages, userId))
}
return
}
func (e *trendsActionEvent) Name() string {
return "trendsActionEvent"
}
func (e *trendsActionEvent) Action() (err error) {
switch e.action {
case _trendsActionCreateTweet:
logrus.Debug("trigger trendsActionEvent by create tweet ")
e.ds.UpdateUserMetric(e.userId, cs.MetricActionCreateTweet)
goto ExpireTrends
case _trendsActionDeleteTweet:
logrus.Debug("trigger trendsActionEvent by delete tweet ")
e.ds.UpdateUserMetric(e.userId, cs.MetricActionDeleteTweet)
goto ExpireTrends
default:
// nothing
goto JustReturn
}
ExpireTrends:
if friendIds, err := e.ds.MyFriendIds(e.userId); err == nil {
for _, id := range friendIds {
e.ac.DelAny(fmt.Sprintf("%s%d:*", conf.PrefixIdxTrends, id))
}
return err
}
JustReturn:
return
}

@ -86,8 +86,10 @@ func (s *followshipSrv) UnfollowUser(r *web.UnfollowUserReq) mir.Error {
return web.ErrUnfollowUserFailed return web.ErrUnfollowUserFailed
} }
// 触发缓存更新事件 // 触发缓存更新事件
// TODO: 合并成一个事件
cache.OnCacheMyFollowIdsEvent(s.Ds, r.User.ID) cache.OnCacheMyFollowIdsEvent(s.Ds, r.User.ID)
cache.OnExpireIndexTweetEvent(r.User.ID) cache.OnExpireIndexTweetEvent(r.User.ID)
onMessageActionEvent(_messageActionFollow, r.User.ID)
return nil return nil
} }
@ -102,8 +104,10 @@ func (s *followshipSrv) FollowUser(r *web.FollowUserReq) mir.Error {
return web.ErrUnfollowUserFailed return web.ErrUnfollowUserFailed
} }
// 触发缓存更新事件 // 触发缓存更新事件
// TODO: 合并成一个事件
cache.OnCacheMyFollowIdsEvent(s.Ds, r.User.ID) cache.OnCacheMyFollowIdsEvent(s.Ds, r.User.ID)
cache.OnExpireIndexTweetEvent(r.User.ID) cache.OnExpireIndexTweetEvent(r.User.ID)
onMessageActionEvent(_messageActionFollow, r.User.ID)
return nil return nil
} }

@ -313,6 +313,8 @@ func (s *privSrv) CreateTweet(req *web.CreateTweetReq) (_ *web.CreateTweetResp,
logrus.Infof("Ds.RevampPosts err: %s", err) logrus.Infof("Ds.RevampPosts err: %s", err)
return nil, web.ErrCreatePostFailed return nil, web.ErrCreatePostFailed
} }
// 缓存处理
onTrendsActionEvent(_trendsActionCreateTweet, req.User.ID)
return (*web.CreateTweetResp)(formatedPosts[0]), nil return (*web.CreateTweetResp)(formatedPosts[0]), nil
} }
@ -341,6 +343,8 @@ func (s *privSrv) DeleteTweet(req *web.DeleteTweetReq) mir.Error {
logrus.Errorf("s.DeleteSearchPost failed: %s", err) logrus.Errorf("s.DeleteSearchPost failed: %s", err)
return web.ErrDeletePostFailed return web.ErrDeletePostFailed
} }
// 缓存处理
onTrendsActionEvent(_trendsActionDeleteTweet, req.User.ID)
return nil return nil
} }
@ -484,6 +488,10 @@ func (s *privSrv) HighlightComment(req *web.HighlightCommentReq) (*web.Highlight
} else if err != nil { } else if err != nil {
return nil, web.ErrHighlightCommentFailed return nil, web.ErrHighlightCommentFailed
} }
// 缓存处理, 宽松处理错误
if comment, err := s.Ds.GetCommentByID(req.CommentId); err == nil {
onCommentActionEvent(comment.PostID, comment.ID, _commentActionHighlight)
}
return &web.HighlightCommentResp{ return &web.HighlightCommentResp{
HighlightStatus: status, HighlightStatus: status,
}, nil }, nil

@ -0,0 +1,81 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package web
import (
"fmt"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
api "github.com/rocboss/paopao-ce/auto/api/v1"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model/joint"
"github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain"
"github.com/sirupsen/logrus"
)
var (
_ api.Trends = (*trendsSrv)(nil)
)
type trendsSrv struct {
api.UnimplementedTrendsServant
*base.DaoServant
ac core.AppCache
indexTrendsExpire int64
prefixTrends string
}
func (s *trendsSrv) Chain() gin.HandlersChain {
return gin.HandlersChain{chain.JWT()}
}
func (s *trendsSrv) GetIndexTrends(req *web.GetIndexTrendsReq) (res *web.GetIndexTrendsResp, _ mir.Error) {
limit, offset := req.PageSize, (req.Page-1)*req.PageSize
// 尝试直接从缓存中获取数据
key, ok := "", false
if res, key, ok = s.trendsFromCache(req, limit, offset); ok {
// logrus.Debugf("trendsSrv.GetIndexTrends from cache key:%s", key)
return
}
trends, totalRows, err := s.Ds.GetIndexTrends(req.Uid, limit, offset)
if err != nil {
logrus.Errorf("Ds.GetIndexTrends err[1]: %s", err)
return nil, web.ErrGetIndexTrendsFailed
}
resp := joint.PageRespFrom(trends, req.Page, req.PageSize, totalRows)
// 缓存处理
base.OnCacheRespEvent(s.ac, key, resp, s.indexTrendsExpire)
return &web.GetIndexTrendsResp{
CachePageResp: joint.CachePageResp{
Data: resp,
},
}, nil
}
func (s *trendsSrv) trendsFromCache(req *web.GetIndexTrendsReq, limit int, offset int) (res *web.GetIndexTrendsResp, key string, ok bool) {
key = fmt.Sprintf("%s%d:%d:%d", s.prefixTrends, req.Uid, limit, offset)
if data, err := s.ac.Get(key); err == nil {
ok, res = true, &web.GetIndexTrendsResp{
CachePageResp: joint.CachePageResp{
JsonResp: data,
},
}
}
return
}
func newTrendsSrv(s *base.DaoServant) api.Trends {
cs := conf.CacheSetting
return &trendsSrv{
DaoServant: s,
ac: _ac,
indexTrendsExpire: cs.IndexTrendsExpire,
prefixTrends: conf.PrefixIdxTrends,
}
}

@ -38,6 +38,7 @@ func RouteWeb(e *gin.Engine) {
api.RegisterLooseServant(e, newLooseSrv(ds, _ac)) api.RegisterLooseServant(e, newLooseSrv(ds, _ac))
api.RegisterPrivServant(e, newPrivSrv(ds, _oss), newPrivChain()) api.RegisterPrivServant(e, newPrivSrv(ds, _oss), newPrivChain())
api.RegisterPubServant(e, newPubSrv(ds)) api.RegisterPubServant(e, newPubSrv(ds))
api.RegisterTrendsServant(e, newTrendsSrv(ds))
api.RegisterFollowshipServant(e, newFollowshipSrv(ds)) api.RegisterFollowshipServant(e, newFollowshipSrv(ds))
api.RegisterFriendshipServant(e, newFriendshipSrv(ds)) api.RegisterFriendshipServant(e, newFriendshipSrv(ds))
// regster servants if needed by configure // regster servants if needed by configure

@ -0,0 +1,20 @@
package v1
import (
. "github.com/alimy/mir/v4"
. "github.com/alimy/mir/v4/engine"
"github.com/rocboss/paopao-ce/internal/model/web"
)
func init() {
Entry[Trends]()
}
// Trends 动态相关 服务
type Trends struct {
Chain `mir:"-"`
Group `mir:"v1"`
// GetIndexTrends 获取广场页面动态条栏的索引item
GetIndexTrends func(Get, web.GetIndexTrendsReq) web.GetIndexTrendsResp `mir:"/trends/index"`
}

@ -1 +1 @@
import{_ as s}from"./main-nav.vue_vue_type_style_index_0_lang-93352cc4.js";import{u as i}from"./vue-router-e5a2430e.js";import{G as a,e as c,a2 as u}from"./naive-ui-defd0b2d.js";import{d as l,f as d,k as t,w as o,e as f,A as x}from"./@vue-a481fc63.js";import{_ as g}from"./index-daff1b26.js";import"./vuex-44de225f.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./@vicons-c265fba6.js";import"./seemly-76b7b838.js";import"./vueuc-39372edb.js";import"./@css-render-7124a1a5.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */const v=l({__name:"404",setup(h){const e=i(),_=()=>{e.push({path:"/"})};return(k,w)=>{const n=s,p=c,r=u,m=a;return f(),d("div",null,[t(n,{title:"404"}),t(m,{class:"main-content-wrap wrap404",bordered:""},{default:o(()=>[t(r,{status:"404",title:"404 资源不存在",description:"再看看其他的吧"},{footer:o(()=>[t(p,{onClick:_},{default:o(()=>[x("回主页")]),_:1})]),_:1})]),_:1})])}}});const O=g(v,[["__scopeId","data-v-e62daa85"]]);export{O as default}; import{_ as s}from"./main-nav.vue_vue_type_style_index_0_lang-65b365f0.js";import{u as i}from"./vue-router-e5a2430e.js";import{G as a,e as c,a2 as u}from"./naive-ui-eecf2ec3.js";import{d as l,f as d,k as t,w as o,e as f,A as x}from"./@vue-a481fc63.js";import{_ as g}from"./index-83d7d999.js";import"./vuex-44de225f.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./@vicons-f0266f88.js";import"./seemly-76b7b838.js";import"./vueuc-7c8d4b48.js";import"./@css-render-7124a1a5.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */const v=l({__name:"404",setup(h){const e=i(),_=()=>{e.push({path:"/"})};return(k,w)=>{const n=s,p=c,r=u,m=a;return f(),d("div",null,[t(n,{title:"404"}),t(m,{class:"main-content-wrap wrap404",bordered:""},{default:o(()=>[t(r,{status:"404",title:"404 资源不存在",description:"再看看其他的吧"},{footer:o(()=>[t(p,{onClick:_},{default:o(()=>[x("回主页")]),_:1})]),_:1})]),_:1})])}}});const O=g(v,[["__scopeId","data-v-e62daa85"]]);export{O as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{_ as N}from"./post-skeleton-8434d30b.js";import{_ as R}from"./main-nav.vue_vue_type_style_index_0_lang-93352cc4.js";import{u as z}from"./vuex-44de225f.js";import{b as A}from"./vue-router-e5a2430e.js";import{I as F,_ as S}from"./index-daff1b26.js";import{G as V,R as q,J as H,H as I}from"./naive-ui-defd0b2d.js";import{d as P,H as n,b as j,f as o,k as a,w as p,e as t,bf as u,Y as l,F as D,u as E,q as G,j as s,x as _,l as J}from"./@vue-a481fc63.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./@vicons-c265fba6.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */import"./seemly-76b7b838.js";import"./vueuc-39372edb.js";import"./@css-render-7124a1a5.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";const L={key:0,class:"pagination-wrap"},M={key:0,class:"skeleton-wrap"},O={key:1},T={key:0,class:"empty-wrap"},U={class:"bill-line"},Y=P({__name:"Anouncement",setup($){const d=z(),g=A(),v=n(!1),i=n([]),r=n(+g.query.p||1),f=n(20),c=n(0),h=m=>{r.value=m};return j(()=>{}),(m,K)=>{const k=R,y=q,x=N,w=H,B=I,C=V;return t(),o("div",null,[a(k,{title:"公告"}),a(C,{class:"main-content-wrap",bordered:""},{footer:p(()=>[c.value>1?(t(),o("div",L,[a(y,{page:r.value,"onUpdate:page":h,"page-slot":u(d).state.collapsedRight?5:8,"page-count":c.value},null,8,["page","page-slot","page-count"])])):l("",!0)]),default:p(()=>[v.value?(t(),o("div",M,[a(x,{num:f.value},null,8,["num"])])):(t(),o("div",O,[i.value.length===0?(t(),o("div",T,[a(w,{size:"large",description:"暂无数据"})])):l("",!0),(t(!0),o(D,null,E(i.value,e=>(t(),G(B,{key:e.id},{default:p(()=>[s("div",U,[s("div",null,"NO."+_(e.id),1),s("div",null,_(e.reason),1),s("div",{class:J({income:e.change_amount>=0,out:e.change_amount<0})},_((e.change_amount>0?"+":"")+(e.change_amount/100).toFixed(2)),3),s("div",null,_(u(F)(e.created_on)),1)])]),_:2},1024))),128))]))]),_:1})])}}});const ke=S(Y,[["__scopeId","data-v-d4d04859"]]);export{ke as default}; import{_ as N}from"./post-skeleton-63a5a4f0.js";import{_ as R}from"./main-nav.vue_vue_type_style_index_0_lang-65b365f0.js";import{u as z}from"./vuex-44de225f.js";import{b as A}from"./vue-router-e5a2430e.js";import{J as F,_ as S}from"./index-83d7d999.js";import{G as V,R as q,J as H,H as J}from"./naive-ui-eecf2ec3.js";import{d as P,H as n,b as j,f as o,k as a,w as p,e as t,bf as u,Y as l,F as D,u as E,q as G,j as s,x as _,l as I}from"./@vue-a481fc63.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./@vicons-f0266f88.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */import"./seemly-76b7b838.js";import"./vueuc-7c8d4b48.js";import"./@css-render-7124a1a5.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";const L={key:0,class:"pagination-wrap"},M={key:0,class:"skeleton-wrap"},O={key:1},T={key:0,class:"empty-wrap"},U={class:"bill-line"},Y=P({__name:"Anouncement",setup($){const d=z(),g=A(),v=n(!1),i=n([]),r=n(+g.query.p||1),f=n(20),c=n(0),h=m=>{r.value=m};return j(()=>{}),(m,K)=>{const k=R,y=q,x=N,w=H,B=J,C=V;return t(),o("div",null,[a(k,{title:"公告"}),a(C,{class:"main-content-wrap",bordered:""},{footer:p(()=>[c.value>1?(t(),o("div",L,[a(y,{page:r.value,"onUpdate:page":h,"page-slot":u(d).state.collapsedRight?5:8,"page-count":c.value},null,8,["page","page-slot","page-count"])])):l("",!0)]),default:p(()=>[v.value?(t(),o("div",M,[a(x,{num:f.value},null,8,["num"])])):(t(),o("div",O,[i.value.length===0?(t(),o("div",T,[a(w,{size:"large",description:"暂无数据"})])):l("",!0),(t(!0),o(D,null,E(i.value,e=>(t(),G(B,{key:e.id},{default:p(()=>[s("div",U,[s("div",null,"NO."+_(e.id),1),s("div",null,_(e.reason),1),s("div",{class:I({income:e.change_amount>=0,out:e.change_amount<0})},_((e.change_amount>0?"+":"")+(e.change_amount/100).toFixed(2)),3),s("div",null,_(u(F)(e.created_on)),1)])]),_:2},1024))),128))]))]),_:1})])}}});const ke=S(Y,[["__scopeId","data-v-d4d04859"]]);export{ke as default};

@ -1 +0,0 @@
import{_ as T}from"./whisper-9b4eeceb.js";import{_ as U,a as q}from"./post-item.vue_vue_type_style_index_0_lang-c2092e3d.js";import{_ as N}from"./post-skeleton-8434d30b.js";import{_ as V}from"./main-nav.vue_vue_type_style_index_0_lang-93352cc4.js";import{u as W}from"./vuex-44de225f.js";import{b as D}from"./vue-router-e5a2430e.js";import{R as E,u as G,f as J,_ as L}from"./index-daff1b26.js";import{d as Y,H as a,b as j,f as t,k as s,w as f,bf as c,Y as y,e as o,F as C,u as x,q as F}from"./@vue-a481fc63.js";import{F as K,G as Q,R as X,J as Z,H as ee}from"./naive-ui-defd0b2d.js";import"./content-64a02a2f.js";import"./@vicons-c265fba6.js";import"./paopao-video-player-2fe58954.js";import"./copy-to-clipboard-4ef7d3eb.js";import"./@babel-725317a4.js";import"./toggle-selection-93f4ad84.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */import"./seemly-76b7b838.js";import"./vueuc-39372edb.js";import"./@css-render-7124a1a5.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";const oe={key:0,class:"skeleton-wrap"},te={key:1},se={key:0,class:"empty-wrap"},ne={key:1},ae={key:2},ie={key:0,class:"pagination-wrap"},le=Y({__name:"Collection",setup(re){const i=W(),S=D(),$=K(),l=a(!1),r=a([]),u=a(+S.query.p||1),p=a(20),m=a(0),d=a(!1),g=a({id:0,avatar:"",username:"",nickname:"",is_admin:!1,is_friend:!0,is_following:!1,created_on:0,follows:0,followings:0,status:1}),v=e=>{g.value=e,d.value=!0},b=()=>{d.value=!1},w=e=>{$.success({title:"提示",content:"确定"+(e.user.is_following?"取消关注":"关注")+"该用户吗?",positiveText:"确定",negativeText:"取消",onPositiveClick:()=>{e.user.is_following?G({user_id:e.user.id}).then(_=>{window.$message.success("操作成功"),e.user.is_following=!1}).catch(_=>{}):J({user_id:e.user.id}).then(_=>{window.$message.success("关注成功"),e.user.is_following=!0}).catch(_=>{})}})},h=()=>{l.value=!0,E({page:u.value,page_size:p.value}).then(e=>{l.value=!1,r.value=e.list,m.value=Math.ceil(e.pager.total_rows/p.value),window.scrollTo(0,0)}).catch(e=>{l.value=!1})},R=e=>{u.value=e,h()};return j(()=>{h()}),(e,_)=>{const O=V,P=N,z=Z,A=U,k=ee,B=q,H=T,I=Q,M=X;return o(),t("div",null,[s(O,{title:"收藏"}),s(I,{class:"main-content-wrap",bordered:""},{default:f(()=>[l.value?(o(),t("div",oe,[s(P,{num:p.value},null,8,["num"])])):(o(),t("div",te,[r.value.length===0?(o(),t("div",se,[s(z,{size:"large",description:"暂无数据"})])):y("",!0),c(i).state.desktopModelShow?(o(),t("div",ne,[(o(!0),t(C,null,x(r.value,n=>(o(),F(k,{key:n.id},{default:f(()=>[s(A,{post:n,isOwner:c(i).state.userInfo.id==n.user_id,addFollowAction:!0,onSendWhisper:v,onHandleFollowAction:w},null,8,["post","isOwner"])]),_:2},1024))),128))])):(o(),t("div",ae,[(o(!0),t(C,null,x(r.value,n=>(o(),F(k,{key:n.id},{default:f(()=>[s(B,{post:n,isOwner:c(i).state.userInfo.id==n.user_id,addFollowAction:!0,onSendWhisper:v,onHandleFollowAction:w},null,8,["post","isOwner"])]),_:2},1024))),128))]))])),s(H,{show:d.value,user:g.value,onSuccess:b},null,8,["show","user"])]),_:1}),m.value>0?(o(),t("div",ie,[s(M,{page:u.value,"onUpdate:page":R,"page-slot":c(i).state.collapsedRight?5:8,"page-count":m.value},null,8,["page","page-slot","page-count"])])):y("",!0)])}}});const Ne=L(le,[["__scopeId","data-v-c8f8eee7"]]);export{Ne as default};

@ -1 +0,0 @@
.pagination-wrap[data-v-c8f8eee7]{padding:10px;display:flex;justify-content:center;overflow:hidden}.dark .main-content-wrap[data-v-c8f8eee7],.dark .empty-wrap[data-v-c8f8eee7],.dark .skeleton-wrap[data-v-c8f8eee7]{background-color:#101014bf}

@ -0,0 +1 @@
import{_ as j}from"./whisper-7277e566.js";import{_ as q,a as D}from"./post-item.vue_vue_type_style_index_0_lang-32efb38a.js";import{_ as R}from"./post-skeleton-63a5a4f0.js";import{_ as U}from"./main-nav.vue_vue_type_style_index_0_lang-65b365f0.js";import{u as E}from"./vuex-44de225f.js";import{b as G}from"./vue-router-e5a2430e.js";import{W as J}from"./v3-infinite-loading-2c58ec2f.js";import{S as L,u as Y,f as K,_ as Q}from"./index-83d7d999.js";import{d as X,H as s,b as Z,f as t,k as n,w as _,q as m,Y as g,e as o,bf as d,F as S,u as F,j as $,x as ee}from"./@vue-a481fc63.js";import{F as oe,G as se,a as te,J as ne,k as ae,H as ie}from"./naive-ui-eecf2ec3.js";import"./content-d0e46162.js";import"./@vicons-f0266f88.js";import"./paopao-video-player-2fe58954.js";import"./copy-to-clipboard-4ef7d3eb.js";import"./@babel-725317a4.js";import"./toggle-selection-93f4ad84.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */import"./seemly-76b7b838.js";import"./vueuc-7c8d4b48.js";import"./@css-render-7124a1a5.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";const le={key:0,class:"skeleton-wrap"},re={key:1},_e={key:0,class:"empty-wrap"},ue={key:1},ce={key:2},pe={class:"load-more-wrap"},me={class:"load-more-spinner"},de=X({__name:"Collection",setup(fe){const f=E(),b=G(),z=oe(),u=s(!1),r=s(!1),a=s([]),l=s(+b.query.p||1),v=s(20),c=s(0),w=s(!1),h=s({id:0,avatar:"",username:"",nickname:"",is_admin:!1,is_friend:!0,is_following:!1,created_on:0,follows:0,followings:0,status:1}),k=e=>{h.value=e,w.value=!0},B=()=>{w.value=!1},y=e=>{z.success({title:"提示",content:"确定"+(e.user.is_following?"取消关注":"关注")+"该用户吗?",positiveText:"确定",negativeText:"取消",onPositiveClick:()=>{e.user.is_following?Y({user_id:e.user.id}).then(p=>{window.$message.success("操作成功"),e.user.is_following=!1}).catch(p=>{}):K({user_id:e.user.id}).then(p=>{window.$message.success("关注成功"),e.user.is_following=!0}).catch(p=>{})}})},x=()=>{u.value=!0,L({page:l.value,page_size:v.value}).then(e=>{u.value=!1,e.list.length===0&&(r.value=!0),l.value>1?a.value=a.value.concat(e.list):(a.value=e.list,window.scrollTo(0,0)),c.value=Math.ceil(e.pager.total_rows/v.value)}).catch(e=>{u.value=!1,l.value>1&&l.value--})},I=()=>{l.value<c.value||c.value==0?(r.value=!1,l.value++,x()):r.value=!0};return Z(()=>{x()}),(e,p)=>{const M=U,O=R,P=ne,A=q,C=ie,H=D,N=j,T=se,V=ae,W=te;return o(),t("div",null,[n(M,{title:"收藏"}),n(T,{class:"main-content-wrap",bordered:""},{default:_(()=>[u.value&&a.value.length===0?(o(),t("div",le,[n(O,{num:v.value},null,8,["num"])])):(o(),t("div",re,[a.value.length===0?(o(),t("div",_e,[n(P,{size:"large",description:"暂无数据"})])):g("",!0),d(f).state.desktopModelShow?(o(),t("div",ue,[(o(!0),t(S,null,F(a.value,i=>(o(),m(C,{key:i.id},{default:_(()=>[n(A,{post:i,isOwner:d(f).state.userInfo.id==i.user_id,addFollowAction:!0,onSendWhisper:k,onHandleFollowAction:y},null,8,["post","isOwner"])]),_:2},1024))),128))])):(o(),t("div",ce,[(o(!0),t(S,null,F(a.value,i=>(o(),m(C,{key:i.id},{default:_(()=>[n(H,{post:i,isOwner:d(f).state.userInfo.id==i.user_id,addFollowAction:!0,onSendWhisper:k,onHandleFollowAction:y},null,8,["post","isOwner"])]),_:2},1024))),128))]))])),n(N,{show:w.value,user:h.value,onSuccess:B},null,8,["show","user"])]),_:1}),c.value>0?(o(),m(W,{key:0,justify:"center"},{default:_(()=>[n(d(J),{class:"load-more",slots:{complete:"没有更多收藏了",error:"加载出错"},onInfinite:I},{spinner:_(()=>[$("div",pe,[r.value?g("",!0):(o(),m(V,{key:0,size:14})),$("span",me,ee(r.value?"没有更多收藏了":"加载更多"),1)])]),_:1})]),_:1})):g("",!0)])}}});const Le=Q(de,[["__scopeId","data-v-02747f0a"]]);export{Le as default};

@ -0,0 +1 @@
.load-more[data-v-02747f0a]{margin:20px}.load-more .load-more-wrap[data-v-02747f0a]{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:14px}.load-more .load-more-wrap .load-more-spinner[data-v-02747f0a]{font-size:14px;opacity:.65}.dark .main-content-wrap[data-v-02747f0a],.dark .empty-wrap[data-v-02747f0a],.dark .skeleton-wrap[data-v-02747f0a]{background-color:#101014bf}

@ -0,0 +1 @@
import{_ as T}from"./whisper-7277e566.js";import{d as N,c as A,r as R,e as c,f as p,k as t,w as n,j as _,y as E,A as G,x as d,bf as h,h as x,H as l,b as J,q as $,Y as C,F as S,u as K}from"./@vue-a481fc63.js";import{K as L,_ as P,W as U}from"./index-83d7d999.js";import{k as Y,r as Q}from"./@vicons-f0266f88.js";import{j as M,o as X,e as Z,P as ee,O as te,G as ne,a as oe,J as se,k as ae,H as ce}from"./naive-ui-eecf2ec3.js";import{_ as _e}from"./post-skeleton-63a5a4f0.js";import{_ as ie}from"./main-nav.vue_vue_type_style_index_0_lang-65b365f0.js";import{W as le}from"./v3-infinite-loading-2c58ec2f.js";import{b as re}from"./vue-router-e5a2430e.js";import"./vuex-44de225f.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */import"./seemly-76b7b838.js";import"./vueuc-7c8d4b48.js";import"./evtd-b614532e.js";import"./@css-render-7124a1a5.js";import"./vooks-6d99783e.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";const ue={class:"contact-item"},pe={class:"nickname-wrap"},me={class:"username-wrap"},de={class:"user-info"},fe={class:"info-item"},ve={class:"info-item"},he={class:"item-header-extra"},ge=N({__name:"contact-item",props:{contact:{}},emits:["send-whisper"],setup(b,{emit:g}){const o=b,r=e=>()=>x(M,null,{default:()=>x(e)}),s=A(()=>[{label:"私信",key:"whisper",icon:r(Q)}]),i=e=>{switch(e){case"whisper":const a={id:o.contact.user_id,avatar:o.contact.avatar,username:o.contact.username,nickname:o.contact.nickname,is_admin:!1,is_friend:!0,is_following:!1,created_on:0,follows:0,followings:0,status:1};g("send-whisper",a);break}};return(e,a)=>{const m=X,f=R("router-link"),w=Z,k=ee,y=te;return c(),p("div",ue,[t(y,{"content-indented":""},{avatar:n(()=>[t(m,{size:54,src:e.contact.avatar},null,8,["src"])]),header:n(()=>[_("span",pe,[t(f,{onClick:a[0]||(a[0]=E(()=>{},["stop"])),class:"username-link",to:{name:"user",query:{s:e.contact.username}}},{default:n(()=>[G(d(e.contact.nickname),1)]),_:1},8,["to"])]),_("span",me," @"+d(e.contact.username),1),_("div",de,[_("span",fe," UID. "+d(e.contact.user_id),1),_("span",ve,d(h(L)(e.contact.created_on))+" 加入 ",1)])]),"header-extra":n(()=>[_("div",he,[t(k,{placement:"bottom-end",trigger:"click",size:"small",options:s.value,onSelect:i},{default:n(()=>[t(w,{quaternary:"",circle:""},{icon:n(()=>[t(h(M),null,{default:n(()=>[t(h(Y))]),_:1})]),_:1})]),_:1},8,["options"])])]),_:1})])}}});const we=P(ge,[["__scopeId","data-v-d62f19da"]]),ke={key:0,class:"skeleton-wrap"},ye={key:1},$e={key:0,class:"empty-wrap"},Ce={class:"load-more-wrap"},be={class:"load-more-spinner"},ze=N({__name:"Contacts",setup(b){const g=re(),o=l(!1),r=l(!1),s=l([]),i=l(+g.query.p||1),e=l(20),a=l(0),m=l(!1),f=l({id:0,avatar:"",username:"",nickname:"",is_admin:!1,is_friend:!0,is_following:!1,created_on:0,follows:0,followings:0,status:1}),w=v=>{f.value=v,m.value=!0},k=()=>{m.value=!1},y=()=>{i.value<a.value||a.value==0?(r.value=!1,i.value++,z()):r.value=!0};J(()=>{z()});const z=(v=!1)=>{s.value.length===0&&(o.value=!0),U({page:i.value,page_size:e.value}).then(u=>{o.value=!1,u.list.length===0&&(r.value=!0),i.value>1?s.value=s.value.concat(u.list):(s.value=u.list,v&&setTimeout(()=>{window.scrollTo(0,99999)},50)),a.value=Math.ceil(u.pager.total_rows/e.value)}).catch(u=>{o.value=!1,i.value>1&&i.value--})};return(v,u)=>{const q=ie,B=_e,V=se,W=we,j=ce,D=T,F=ne,H=ae,O=oe;return c(),p(S,null,[_("div",null,[t(q,{title:"好友"}),t(F,{class:"main-content-wrap",bordered:""},{default:n(()=>[o.value&&s.value.length===0?(c(),p("div",ke,[t(B,{num:e.value},null,8,["num"])])):(c(),p("div",ye,[s.value.length===0?(c(),p("div",$e,[t(V,{size:"large",description:"暂无数据"})])):C("",!0),(c(!0),p(S,null,K(s.value,I=>(c(),$(j,{class:"list-item",key:I.user_id},{default:n(()=>[t(W,{contact:I,onSendWhisper:w},null,8,["contact"])]),_:2},1024))),128))])),t(D,{show:m.value,user:f.value,onSuccess:k},null,8,["show","user"])]),_:1})]),a.value>0?(c(),$(O,{key:0,justify:"center"},{default:n(()=>[t(h(le),{class:"load-more",slots:{complete:"没有更多好友了",error:"加载出错"},onInfinite:y},{spinner:n(()=>[_("div",Ce,[r.value?C("",!0):(c(),$(H,{key:0,size:14})),_("span",be,d(r.value?"没有更多好友了":"加载更多"),1)])]),_:1})]),_:1})):C("",!0)],64)}}});const Xe=P(ze,[["__scopeId","data-v-69277f0c"]]);export{Xe as default};

@ -1 +0,0 @@
import{_ as O}from"./whisper-9b4eeceb.js";import{d as N,c as T,r as j,e as s,f as c,k as t,w as n,j as _,y as A,A as J,x as v,bf as g,h as S,H as a,b as U,Y as z,F as I,u as W,q as E}from"./@vue-a481fc63.js";import{J as G,_ as P,b as L}from"./index-daff1b26.js";import{k as Y,r as K}from"./@vicons-c265fba6.js";import{j as x,o as Q,e as X,P as Z,O as ee,G as te,R as ne,J as oe,H as se}from"./naive-ui-defd0b2d.js";import{_ as ae}from"./post-skeleton-8434d30b.js";import{_ as ce}from"./main-nav.vue_vue_type_style_index_0_lang-93352cc4.js";import{u as _e}from"./vuex-44de225f.js";import{b as ie}from"./vue-router-e5a2430e.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */import"./seemly-76b7b838.js";import"./vueuc-39372edb.js";import"./evtd-b614532e.js";import"./@css-render-7124a1a5.js";import"./vooks-6d99783e.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";const re={class:"contact-item"},le={class:"nickname-wrap"},pe={class:"username-wrap"},ue={class:"user-info"},me={class:"info-item"},de={class:"info-item"},fe={class:"item-header-extra"},ve=N({__name:"contact-item",props:{contact:{}},emits:["send-whisper"],setup(C,{emit:h}){const i=C,r=e=>()=>S(x,null,{default:()=>S(e)}),l=T(()=>[{label:"私信",key:"whisper",icon:r(K)}]),u=e=>{switch(e){case"whisper":const o={id:i.contact.user_id,avatar:i.contact.avatar,username:i.contact.username,nickname:i.contact.nickname,is_admin:!1,is_friend:!0,is_following:!1,created_on:0,follows:0,followings:0,status:1};h("send-whisper",o);break}};return(e,o)=>{const m=Q,d=j("router-link"),w=X,k=Z,y=ee;return s(),c("div",re,[t(y,{"content-indented":""},{avatar:n(()=>[t(m,{size:54,src:e.contact.avatar},null,8,["src"])]),header:n(()=>[_("span",le,[t(d,{onClick:o[0]||(o[0]=A(()=>{},["stop"])),class:"username-link",to:{name:"user",query:{s:e.contact.username}}},{default:n(()=>[J(v(e.contact.nickname),1)]),_:1},8,["to"])]),_("span",pe," @"+v(e.contact.username),1),_("div",ue,[_("span",me," UID. "+v(e.contact.user_id),1),_("span",de,v(g(G)(e.contact.created_on))+" 加入 ",1)])]),"header-extra":n(()=>[_("div",fe,[t(k,{placement:"bottom-end",trigger:"click",size:"small",options:l.value,onSelect:u},{default:n(()=>[t(w,{quaternary:"",circle:""},{icon:n(()=>[t(g(x),null,{default:n(()=>[t(g(Y))]),_:1})]),_:1})]),_:1},8,["options"])])]),_:1})])}}});const ge=P(ve,[["__scopeId","data-v-d62f19da"]]),he={key:0,class:"skeleton-wrap"},we={key:1},ke={key:0,class:"empty-wrap"},ye={key:0,class:"pagination-wrap"},Ce=N({__name:"Contacts",setup(C){const h=_e(),i=ie(),r=a(!1),l=a([]),u=a(+i.query.p||1),e=a(20),o=a(0),m=a(!1),d=a({id:0,avatar:"",username:"",nickname:"",is_admin:!1,is_friend:!0,is_following:!1,created_on:0,follows:0,followings:0,status:1}),w=p=>{d.value=p,m.value=!0},k=()=>{m.value=!1},y=p=>{u.value=p,$()};U(()=>{$()});const $=(p=!1)=>{l.value.length===0&&(r.value=!0),L({page:u.value,page_size:e.value}).then(f=>{r.value=!1,l.value=f.list,o.value=Math.ceil(f.pager.total_rows/e.value),p&&setTimeout(()=>{window.scrollTo(0,99999)},50)}).catch(f=>{r.value=!1})};return(p,f)=>{const q=ce,B=ae,M=oe,R=ge,V=se,D=O,F=te,H=ne;return s(),c(I,null,[_("div",null,[t(q,{title:"好友"}),t(F,{class:"main-content-wrap",bordered:""},{default:n(()=>[r.value?(s(),c("div",he,[t(B,{num:e.value},null,8,["num"])])):(s(),c("div",we,[l.value.length===0?(s(),c("div",ke,[t(M,{size:"large",description:"暂无数据"})])):z("",!0),(s(!0),c(I,null,W(l.value,b=>(s(),E(V,{class:"list-item",key:b.user_id},{default:n(()=>[t(R,{contact:b,onSendWhisper:w},null,8,["contact"])]),_:2},1024))),128))])),t(D,{show:m.value,user:d.value,onSuccess:k},null,8,["show","user"])]),_:1})]),o.value>0?(s(),c("div",ye,[t(H,{page:u.value,"onUpdate:page":y,"page-slot":g(h).state.collapsedRight?5:8,"page-count":o.value},null,8,["page","page-slot","page-count"])])):z("",!0)],64)}}});const Le=P(Ce,[["__scopeId","data-v-e20fef94"]]);export{Le as default};

@ -1 +1 @@
.contact-item[data-v-d62f19da]{width:100%;box-sizing:border-box;padding:12px 16px}.contact-item[data-v-d62f19da]:hover{background:#f7f9f9}.contact-item .nickname-wrap[data-v-d62f19da],.contact-item .username-wrap[data-v-d62f19da]{line-height:16px;font-size:16px}.contact-item .top-tag[data-v-d62f19da]{transform:scale(.75)}.contact-item .user-info .info-item[data-v-d62f19da]{font-size:14px;line-height:14px;margin-right:8px;opacity:.75}.contact-item .item-header-extra[data-v-d62f19da]{display:flex;align-items:center;opacity:.75}.dark .contact-item[data-v-d62f19da]{background-color:#101014bf}.dark .contact-item[data-v-d62f19da]:hover{background:#18181c}.pagination-wrap[data-v-e20fef94]{padding:10px;display:flex;justify-content:center;overflow:hidden}.dark .main-content-wrap[data-v-e20fef94],.dark .empty-wrap[data-v-e20fef94],.dark .skeleton-wrap[data-v-e20fef94]{background-color:#101014bf} .contact-item[data-v-d62f19da]{width:100%;box-sizing:border-box;padding:12px 16px}.contact-item[data-v-d62f19da]:hover{background:#f7f9f9}.contact-item .nickname-wrap[data-v-d62f19da],.contact-item .username-wrap[data-v-d62f19da]{line-height:16px;font-size:16px}.contact-item .top-tag[data-v-d62f19da]{transform:scale(.75)}.contact-item .user-info .info-item[data-v-d62f19da]{font-size:14px;line-height:14px;margin-right:8px;opacity:.75}.contact-item .item-header-extra[data-v-d62f19da]{display:flex;align-items:center;opacity:.75}.dark .contact-item[data-v-d62f19da]{background-color:#101014bf}.dark .contact-item[data-v-d62f19da]:hover{background:#18181c}.load-more[data-v-69277f0c]{margin:20px}.load-more .load-more-wrap[data-v-69277f0c]{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:14px}.load-more .load-more-wrap .load-more-spinner[data-v-69277f0c]{font-size:14px;opacity:.65}.dark .main-content-wrap[data-v-69277f0c],.dark .empty-wrap[data-v-69277f0c],.dark .skeleton-wrap[data-v-69277f0c]{background-color:#101014bf}

File diff suppressed because one or more lines are too long

@ -1 +1 @@
.follow-item[data-v-1fb7364a]{display:border-box;width:100%;padding:12px 16px}.follow-item[data-v-1fb7364a]:hover{background:#f7f9f9}.follow-item .nickname-wrap[data-v-1fb7364a],.follow-item .username-wrap[data-v-1fb7364a]{line-height:16px;font-size:16px}.follow-item .top-tag[data-v-1fb7364a]{transform:scale(.75)}.follow-item .user-info .info-item[data-v-1fb7364a]{font-size:14px;line-height:14px;margin-right:8px;opacity:.75}.follow-item .item-header-extra[data-v-1fb7364a]{display:flex;align-items:center;opacity:.75}.dark .follow-item[data-v-1fb7364a]{background-color:#101014bf}.dark .follow-item[data-v-1fb7364a]:hover{background:#18181c}.main-content-wrap[data-v-0a10234f]{padding:20px}.pagination-wrap[data-v-0a10234f]{padding:10px;display:flex;justify-content:center;overflow:hidden}.dark .main-content-wrap[data-v-0a10234f],.dark .empty-wrap[data-v-0a10234f],.dark .skeleton-wrap[data-v-0a10234f]{background-color:#101014bf} .follow-item[data-v-1fb7364a]{display:border-box;width:100%;padding:12px 16px}.follow-item[data-v-1fb7364a]:hover{background:#f7f9f9}.follow-item .nickname-wrap[data-v-1fb7364a],.follow-item .username-wrap[data-v-1fb7364a]{line-height:16px;font-size:16px}.follow-item .top-tag[data-v-1fb7364a]{transform:scale(.75)}.follow-item .user-info .info-item[data-v-1fb7364a]{font-size:14px;line-height:14px;margin-right:8px;opacity:.75}.follow-item .item-header-extra[data-v-1fb7364a]{display:flex;align-items:center;opacity:.75}.dark .follow-item[data-v-1fb7364a]{background-color:#101014bf}.dark .follow-item[data-v-1fb7364a]:hover{background:#18181c}.main-content-wrap[data-v-598cf32e]{padding:20px}.load-more[data-v-598cf32e]{margin:20px}.load-more .load-more-wrap[data-v-598cf32e]{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:14px}.load-more .load-more-wrap .load-more-spinner[data-v-598cf32e]{font-size:14px;opacity:.65}.dark .main-content-wrap[data-v-598cf32e],.dark .empty-wrap[data-v-598cf32e],.dark .skeleton-wrap[data-v-598cf32e]{background-color:#101014bf}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
.compose-wrap{width:100%;padding:16px;box-sizing:border-box}.compose-wrap .compose-line{display:flex;flex-direction:row}.compose-wrap .compose-line .compose-user{width:42px;height:42px;display:flex;align-items:center}.compose-wrap .compose-line.compose-options{margin-top:6px;padding-left:42px;display:flex;justify-content:space-between}.compose-wrap .compose-line.compose-options .submit-wrap{display:flex;align-items:center}.compose-wrap .compose-line.compose-options .submit-wrap .text-statistic{margin-right:8px;width:20px;height:20px;transform:rotate(180deg)}.compose-wrap .link-wrap{margin-left:42px;margin-right:42px}.compose-wrap .eye-wrap{margin-left:64px}.compose-wrap .login-only-wrap{display:flex;justify-content:center;width:100%}.compose-wrap .login-only-wrap button{margin:0 4px;width:50%}.compose-wrap .login-wrap{display:flex;justify-content:center;width:100%}.compose-wrap .login-wrap .login-banner{margin-bottom:12px;opacity:.8}.compose-wrap .login-wrap button{margin:0 4px}.attachment-list-wrap{margin-top:12px;margin-left:42px}.attachment-list-wrap .n-upload-file-info__thumbnail{overflow:hidden}.dark .compose-wrap{background-color:#101014bf}.tiny-slide-bar .tiny-slide-bar__list>div.tiny-slide-bar__select .slide-bar-item .slide-bar-item-title[data-v-c53a3615]{color:#18a058;opacity:.8}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item[data-v-c53a3615]{cursor:pointer}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-avatar[data-v-c53a3615]{color:#18a058;opacity:.8}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-title[data-v-c53a3615]{color:#18a058;opacity:.8}.tiny-slide-bar[data-v-c53a3615]{margin-top:-30px;margin-bottom:-30px}.tiny-slide-bar .slide-bar-item[data-v-c53a3615]{min-height:170px;width:64px;display:flex;flex-direction:column;justify-content:center;align-items:center;margin-top:8px}.tiny-slide-bar .slide-bar-item .slide-bar-item-title[data-v-c53a3615]{justify-content:center;font-size:12px;margin-top:4px;height:40px}.load-more[data-v-c53a3615]{margin:20px}.load-more .load-more-wrap[data-v-c53a3615]{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:14px}.load-more .load-more-wrap .load-more-spinner[data-v-c53a3615]{font-size:14px;opacity:.65}.dark .main-content-wrap[data-v-c53a3615],.dark .pagination-wrap[data-v-c53a3615],.dark .empty-wrap[data-v-c53a3615],.dark .skeleton-wrap[data-v-c53a3615]{background-color:#101014bf}.dark .tiny-slide-bar .tiny-slide-bar__list>div.tiny-slide-bar__select .slide-bar-item .slide-bar-item-title[data-v-c53a3615]{color:#63e2b7;opacity:.8}.dark .tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-title[data-v-c53a3615]{color:#63e2b7;opacity:.8} .compose-wrap{width:100%;padding:16px;box-sizing:border-box}.compose-wrap .compose-line{display:flex;flex-direction:row}.compose-wrap .compose-line .compose-user{width:42px;height:42px;display:flex;align-items:center}.compose-wrap .compose-line.compose-options{margin-top:6px;padding-left:42px;display:flex;justify-content:space-between}.compose-wrap .compose-line.compose-options .submit-wrap{display:flex;align-items:center}.compose-wrap .compose-line.compose-options .submit-wrap .text-statistic{margin-right:8px;width:20px;height:20px;transform:rotate(180deg)}.compose-wrap .link-wrap{margin-left:42px;margin-right:42px}.compose-wrap .eye-wrap{margin-left:64px}.compose-wrap .login-only-wrap{display:flex;justify-content:center;width:100%}.compose-wrap .login-only-wrap button{margin:0 4px;width:50%}.compose-wrap .login-wrap{display:flex;justify-content:center;width:100%}.compose-wrap .login-wrap .login-banner{margin-bottom:12px;opacity:.8}.compose-wrap .login-wrap button{margin:0 4px}.attachment-list-wrap{margin-top:12px;margin-left:42px}.attachment-list-wrap .n-upload-file-info__thumbnail{overflow:hidden}.dark .compose-wrap{background-color:#101014bf}.tiny-slide-bar .tiny-slide-bar__list>div.tiny-slide-bar__select .slide-bar-item .slide-bar-item-title[data-v-8d9bf027]{color:#18a058;opacity:.8}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item[data-v-8d9bf027]{cursor:pointer}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-avatar[data-v-8d9bf027]{color:#18a058;opacity:.8}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-title[data-v-8d9bf027]{color:#18a058;opacity:.8}.tiny-slide-bar[data-v-8d9bf027]{margin-top:-30px;margin-bottom:-30px}.tiny-slide-bar .slide-bar-item[data-v-8d9bf027]{min-height:170px;width:64px;display:flex;flex-direction:column;justify-content:center;align-items:center;margin-top:8px}.tiny-slide-bar .slide-bar-item .slide-bar-item-title[data-v-8d9bf027]{justify-content:center;font-size:12px;margin-top:4px;height:40px}.load-more[data-v-8d9bf027]{margin:20px}.load-more .load-more-wrap[data-v-8d9bf027]{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:14px}.load-more .load-more-wrap .load-more-spinner[data-v-8d9bf027]{font-size:14px;opacity:.65}.dark .main-content-wrap[data-v-8d9bf027],.dark .pagination-wrap[data-v-8d9bf027],.dark .empty-wrap[data-v-8d9bf027],.dark .skeleton-wrap[data-v-8d9bf027]{background-color:#101014bf}.dark .tiny-slide-bar .tiny-slide-bar__list>div.tiny-slide-bar__select .slide-bar-item .slide-bar-item-title[data-v-8d9bf027]{color:#63e2b7;opacity:.8}.dark .tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-title[data-v-8d9bf027]{color:#63e2b7;opacity:.8}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
.message-item[data-v-2507cd8e]{padding:16px}.message-item.unread[data-v-2507cd8e]{background:#fcfffc}.message-item .sender-wrap[data-v-2507cd8e]{display:flex;align-items:center}.message-item .sender-wrap .top-tag[data-v-2507cd8e]{transform:scale(.75)}.message-item .sender-wrap .username[data-v-2507cd8e]{opacity:.75;font-size:14px}.message-item .timestamp[data-v-2507cd8e]{opacity:.75;font-size:12px;display:flex;align-items:center}.message-item .timestamp .timestamp-txt[data-v-2507cd8e]{margin-left:6px}.message-item .brief-wrap[data-v-2507cd8e]{margin-top:10px}.message-item .brief-wrap .brief-content[data-v-2507cd8e],.message-item .brief-wrap .whisper-content-wrap[data-v-2507cd8e],.message-item .brief-wrap .requesting-friend-wrap[data-v-2507cd8e]{display:flex;width:100%}.message-item .view-link[data-v-2507cd8e]{margin-left:8px;display:flex;align-items:center}.message-item .status-info[data-v-2507cd8e]{margin-left:8px;align-items:center}.dark .message-item[data-v-2507cd8e]{background-color:#101014bf}.dark .message-item.unread[data-v-2507cd8e]{background:#0f180b}.dark .message-item .brief-wrap[data-v-2507cd8e]{background-color:#18181c}.skeleton-item[data-v-01d2e871]{padding:12px;display:flex}.skeleton-item .content[data-v-01d2e871]{width:100%}.dark .skeleton-item[data-v-01d2e871]{background-color:#101014bf}.load-more[data-v-7b84a068]{margin:20px}.load-more .load-more-wrap[data-v-7b84a068]{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:14px}.load-more .load-more-wrap .load-more-spinner[data-v-7b84a068]{font-size:14px;opacity:.65}.title[data-v-7b84a068]{padding-top:4px;opacity:.9}.title-action[data-v-7b84a068]{display:flex;align-items:center;margin-left:20px}.title-filter[data-v-7b84a068]{margin-right:20px}.dark .empty-wrap[data-v-7b84a068],.dark .messages-wrap[data-v-7b84a068],.dark .pagination-wrap[data-v-7b84a068]{background-color:#101014bf}

@ -1 +0,0 @@
.message-item[data-v-282eff6a]{padding:16px}.message-item.unread[data-v-282eff6a]{background:#fcfffc}.message-item .sender-wrap[data-v-282eff6a]{display:flex;align-items:center}.message-item .sender-wrap .top-tag[data-v-282eff6a]{transform:scale(.75)}.message-item .sender-wrap .username[data-v-282eff6a]{opacity:.75;font-size:14px}.message-item .timestamp[data-v-282eff6a]{opacity:.75;font-size:12px;display:flex;align-items:center}.message-item .timestamp .timestamp-txt[data-v-282eff6a]{margin-left:6px}.message-item .brief-wrap[data-v-282eff6a]{margin-top:10px}.message-item .brief-wrap .brief-content[data-v-282eff6a],.message-item .brief-wrap .whisper-content-wrap[data-v-282eff6a],.message-item .brief-wrap .requesting-friend-wrap[data-v-282eff6a]{display:flex;width:100%}.message-item .view-link[data-v-282eff6a]{margin-left:8px;display:flex;align-items:center}.message-item .status-info[data-v-282eff6a]{margin-left:8px;align-items:center}.dark .message-item[data-v-282eff6a]{background-color:#101014bf}.dark .message-item.unread[data-v-282eff6a]{background:#0f180b}.dark .message-item .brief-wrap[data-v-282eff6a]{background-color:#18181c}.skeleton-item[data-v-01d2e871]{padding:12px;display:flex}.skeleton-item .content[data-v-01d2e871]{width:100%}.dark .skeleton-item[data-v-01d2e871]{background-color:#101014bf}.pagination-wrap[data-v-eb622a78]{padding:10px;display:flex;justify-content:center;overflow:hidden}.dark .empty-wrap[data-v-eb622a78],.dark .messages-wrap[data-v-eb622a78],.dark .pagination-wrap[data-v-eb622a78]{background-color:#101014bf}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
import{E as U,F as A,G as M,H as O,I as x,_ as z}from"./index-83d7d999.js";import{D}from"./@vicons-f0266f88.js";import{d as q,H as _,c as T,b as B,r as G,e as c,f as u,k as n,w as s,q as $,A as C,x as h,Y as r,bf as w,E as H,al as j,F as P,u as Y}from"./@vue-a481fc63.js";import{o as J,M as V,j as K,e as Q,P as R,O as W,G as X,f as Z,g as ee,a as oe,k as te}from"./naive-ui-eecf2ec3.js";import{_ as ne}from"./main-nav.vue_vue_type_style_index_0_lang-65b365f0.js";import{u as se}from"./vuex-44de225f.js";import"./vue-router-e5a2430e.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */import"./seemly-76b7b838.js";import"./vueuc-7c8d4b48.js";import"./evtd-b614532e.js";import"./@css-render-7124a1a5.js";import"./vooks-6d99783e.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";const ae={key:0,class:"tag-item"},ce={key:0,class:"tag-quote"},le={key:1,class:"tag-quote tag-follow"},ie={key:0,class:"options"},_e=q({__name:"tag-item",props:{tag:{},showAction:{type:Boolean},checkFollowing:{type:Boolean}},setup(F){const o=F,m=_(!1),g=T(()=>o.tag.user?o.tag.user.avatar:U),i=T(()=>{let e=[];return o.tag.is_following===0?e.push({label:"关注",key:"follow"}):(o.tag.is_top===0?e.push({label:"置顶",key:"stick"}):e.push({label:"取消置顶",key:"unstick"}),e.push({label:"取消关注",key:"unfollow"})),e}),l=e=>{switch(e){case"follow":O({topic_id:o.tag.id}).then(t=>{o.tag.is_following=1,window.$message.success("关注成功")}).catch(t=>{console.log(t)});break;case"unfollow":M({topic_id:o.tag.id}).then(t=>{o.tag.is_following=0,window.$message.success("取消关注")}).catch(t=>{console.log(t)});break;case"stick":A({topic_id:o.tag.id}).then(t=>{o.tag.is_top=t.top_status,window.$message.success("置顶成功")}).catch(t=>{console.log(t)});break;case"unstick":A({topic_id:o.tag.id}).then(t=>{o.tag.is_top=t.top_status,window.$message.success("取消置顶")}).catch(t=>{console.log(t)});break}};return B(()=>{m.value=!1}),(e,t)=>{const d=G("router-link"),k=J,a=V,f=K,v=Q,p=R,y=W;return!e.checkFollowing||e.checkFollowing&&e.tag.is_following===1?(c(),u("div",ae,[n(y,null,{header:s(()=>[(c(),$(a,{type:"success",size:"large",round:"",key:e.tag.id},{avatar:s(()=>[n(k,{src:g.value},null,8,["src"])]),default:s(()=>[n(d,{class:"hash-link",to:{name:"home",query:{q:e.tag.tag,t:"tag"}}},{default:s(()=>[C(" #"+h(e.tag.tag),1)]),_:1},8,["to"]),e.showAction?r("",!0):(c(),u("span",ce,"("+h(e.tag.quote_num)+")",1)),e.showAction?(c(),u("span",le,"("+h(e.tag.quote_num)+")",1)):r("",!0)]),_:1}))]),"header-extra":s(()=>[e.showAction?(c(),u("div",ie,[n(p,{placement:"bottom-end",trigger:"click",size:"small",options:i.value,onSelect:l},{default:s(()=>[n(v,{type:"success",quaternary:"",circle:"",block:""},{icon:s(()=>[n(f,null,{default:s(()=>[n(w(D))]),_:1})]),_:1})]),_:1},8,["options"])])):r("",!0)]),_:1})])):r("",!0)}}});const ue=q({__name:"Topic",setup(F){const o=se(),m=_([]),g=_("hot"),i=_(!1),l=_(!1),e=_(!1);H(l,()=>{l.value||(window.$message.success("保存成功"),o.commit("refreshTopicFollow"))});const t=T({get:()=>{let a="编辑";return l.value&&(a="保存"),a},set:a=>{}}),d=()=>{i.value=!0,x({type:g.value,num:50}).then(a=>{m.value=a.topics,i.value=!1}).catch(a=>{console.log(a),i.value=!1})},k=a=>{g.value=a,a=="follow"?e.value=!0:e.value=!1,d()};return B(()=>{d()}),(a,f)=>{const v=ne,p=Z,y=V,E=ee,I=_e,L=oe,N=te,S=X;return c(),u("div",null,[n(v,{title:"话题"}),n(S,{class:"main-content-wrap tags-wrap",bordered:""},{default:s(()=>[n(E,{type:"line",animated:"","onUpdate:value":k},j({default:s(()=>[n(p,{name:"hot",tab:"热门"}),n(p,{name:"new",tab:"最新"}),w(o).state.userLogined?(c(),$(p,{key:0,name:"follow",tab:"关注"})):r("",!0)]),_:2},[w(o).state.userLogined?{name:"suffix",fn:s(()=>[n(y,{checked:l.value,"onUpdate:checked":f[0]||(f[0]=b=>l.value=b),checkable:""},{default:s(()=>[C(h(t.value),1)]),_:1},8,["checked"])]),key:"0"}:void 0]),1024),n(N,{show:i.value},{default:s(()=>[n(L,null,{default:s(()=>[(c(!0),u(P,null,Y(m.value,b=>(c(),$(I,{tag:b,showAction:w(o).state.userLogined&&l.value,checkFollowing:e.value},null,8,["tag","showAction","checkFollowing"]))),256))]),_:1})]),_:1},8,["show"])]),_:1})])}}});const Ne=z(ue,[["__scopeId","data-v-1fb31ecf"]]);export{Ne as default};

@ -1 +0,0 @@
import{E as $,F as M,G as O,H as z,_ as D}from"./index-daff1b26.js";import{D as G}from"./@vicons-c265fba6.js";import{d as F,H as i,c as q,b as A,r as H,e as c,f as _,k as n,w as s,q as b,A as B,x as f,Y as u,bf as h,E as U,al as j,F as x,u as P}from"./@vue-a481fc63.js";import{o as Y,M as C,j as J,e as K,P as Q,O as R,G as W,f as X,g as Z,a as ee,k as oe}from"./naive-ui-defd0b2d.js";import{_ as te}from"./main-nav.vue_vue_type_style_index_0_lang-93352cc4.js";import{u as ne}from"./vuex-44de225f.js";import"./vue-router-e5a2430e.js";import"./axios-4a70c6fc.js";import"./moment-2ab8298d.js";/* empty css */import"./seemly-76b7b838.js";import"./vueuc-39372edb.js";import"./evtd-b614532e.js";import"./@css-render-7124a1a5.js";import"./vooks-6d99783e.js";import"./vdirs-b0483831.js";import"./@juggle-41516555.js";import"./css-render-6a5c5852.js";import"./@emotion-8a8e73f6.js";import"./lodash-es-8412e618.js";import"./treemate-25c27bff.js";import"./async-validator-dee29e8b.js";import"./date-fns-975a2d8f.js";const se={key:0,class:"tag-item"},ae={key:0,class:"tag-quote"},ce={key:1,class:"tag-quote tag-follow"},le={key:0,class:"options"},ie=F({__name:"tag-item",props:{tag:{},showAction:{type:Boolean},checkFollowing:{type:Boolean}},setup(T){const t=T,r=i(!1),m=q(()=>{let e=[];return t.tag.is_following===0?e.push({label:"关注",key:"follow"}):(t.tag.is_top===0?e.push({label:"置顶",key:"stick"}):e.push({label:"取消置顶",key:"unstick"}),e.push({label:"取消关注",key:"unfollow"})),e}),l=e=>{switch(e){case"follow":O({topic_id:t.tag.id}).then(o=>{t.tag.is_following=1,window.$message.success("关注成功")}).catch(o=>{console.log(o)});break;case"unfollow":M({topic_id:t.tag.id}).then(o=>{t.tag.is_following=0,window.$message.success("取消关注")}).catch(o=>{console.log(o)});break;case"stick":$({topic_id:t.tag.id}).then(o=>{t.tag.is_top=o.top_status,window.$message.success("置顶成功")}).catch(o=>{console.log(o)});break;case"unstick":$({topic_id:t.tag.id}).then(o=>{t.tag.is_top=o.top_status,window.$message.success("取消置顶")}).catch(o=>{console.log(o)});break}};return A(()=>{r.value=!1}),(e,o)=>{const w=H("router-link"),g=Y,k=C,a=J,d=K,v=Q,p=R;return!e.checkFollowing||e.checkFollowing&&e.tag.is_following===1?(c(),_("div",se,[n(p,null,{header:s(()=>[(c(),b(k,{type:"success",size:"large",round:"",key:e.tag.id},{avatar:s(()=>[n(g,{src:e.tag.user.avatar},null,8,["src"])]),default:s(()=>[n(w,{class:"hash-link",to:{name:"home",query:{q:e.tag.tag,t:"tag"}}},{default:s(()=>[B(" #"+f(e.tag.tag),1)]),_:1},8,["to"]),e.showAction?u("",!0):(c(),_("span",ae,"("+f(e.tag.quote_num)+")",1)),e.showAction?(c(),_("span",ce,"("+f(e.tag.quote_num)+")",1)):u("",!0)]),_:1}))]),"header-extra":s(()=>[e.showAction?(c(),_("div",le,[n(v,{placement:"bottom-end",trigger:"click",size:"small",options:m.value,onSelect:l},{default:s(()=>[n(d,{type:"success",quaternary:"",circle:"",block:""},{icon:s(()=>[n(a,null,{default:s(()=>[n(h(G))]),_:1})]),_:1})]),_:1},8,["options"])])):u("",!0)]),_:1})])):u("",!0)}}});const _e=F({__name:"Topic",setup(T){const t=ne(),r=i([]),m=i("hot"),l=i(!1),e=i(!1),o=i(!1);U(e,()=>{e.value||(window.$message.success("保存成功"),t.commit("refreshTopicFollow"))});const w=q({get:()=>{let a="编辑";return e.value&&(a="保存"),a},set:a=>{}}),g=()=>{l.value=!0,z({type:m.value,num:50}).then(a=>{r.value=a.topics,l.value=!1}).catch(a=>{console.log(a),l.value=!1})},k=a=>{m.value=a,a=="follow"?o.value=!0:o.value=!1,g()};return A(()=>{g()}),(a,d)=>{const v=te,p=X,V=C,E=Z,L=ie,N=ee,S=oe,I=W;return c(),_("div",null,[n(v,{title:"话题"}),n(I,{class:"main-content-wrap tags-wrap",bordered:""},{default:s(()=>[n(E,{type:"line",animated:"","onUpdate:value":k},j({default:s(()=>[n(p,{name:"hot",tab:"热门"}),n(p,{name:"new",tab:"最新"}),h(t).state.userLogined?(c(),b(p,{key:0,name:"follow",tab:"关注"})):u("",!0)]),_:2},[h(t).state.userLogined?{name:"suffix",fn:s(()=>[n(V,{checked:e.value,"onUpdate:checked":d[0]||(d[0]=y=>e.value=y),checkable:""},{default:s(()=>[B(f(w.value),1)]),_:1},8,["checked"])]),key:"0"}:void 0]),1024),n(S,{show:l.value},{default:s(()=>[n(N,null,{default:s(()=>[(c(!0),_(x,null,P(r.value,y=>(c(),b(L,{tag:y,showAction:h(t).state.userLogined&&e.value,checkFollowing:o.value},null,8,["tag","showAction","checkFollowing"]))),256))]),_:1})]),_:1},8,["show"])]),_:1})])}}});const Ne=D(_e,[["__scopeId","data-v-1fb31ecf"]]);export{Ne as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
import{aa as A}from"./index-83d7d999.js";import{u as B}from"./vuex-44de225f.js";import{u as E}from"./vue-router-e5a2430e.js";import{j as z}from"./vooks-6d99783e.js";import{a3 as C,a4 as N,a5 as P,a6 as D}from"./@vicons-f0266f88.js";import{u as R,a3 as x,a4 as H,j as I,e as V,a5 as $,h as j}from"./naive-ui-eecf2ec3.js";import{d as q,H as h,b as F,e as n,f,bf as a,k as e,w as t,Y as c,j as L,q as _,A as U,x as Y,F as G}from"./@vue-a481fc63.js";const J={key:0},K={class:"navbar"},ae=q({__name:"main-nav",props:{title:{default:""},back:{type:Boolean,default:!1},theme:{type:Boolean,default:!0}},setup(w){const i=w,o=B(),m=E(),l=h(!1),g=h("left"),u=s=>{s?(localStorage.setItem("PAOPAO_THEME","dark"),o.commit("triggerTheme","dark")):(localStorage.setItem("PAOPAO_THEME","light"),o.commit("triggerTheme","light"))},k=()=>{window.history.length<=1?m.push({path:"/"}):m.go(-1)},v=()=>{l.value=!0};return F(()=>{localStorage.getItem("PAOPAO_THEME")||u(z()==="dark"),o.state.desktopModelShow||(window.$store=o,window.$message=R())}),(s,d)=>{const b=A,y=x,M=H,r=I,p=V,O=$,S=j;return n(),f(G,null,[a(o).state.drawerModelShow?(n(),f("div",J,[e(M,{show:l.value,"onUpdate:show":d[0]||(d[0]=T=>l.value=T),width:212,placement:g.value,resizable:""},{default:t(()=>[e(y,null,{default:t(()=>[e(b)]),_:1})]),_:1},8,["show","placement"])])):c("",!0),e(S,{size:"small",bordered:!0,class:"nav-title-card"},{header:t(()=>[L("div",K,[a(o).state.drawerModelShow&&!s.back?(n(),_(p,{key:0,class:"drawer-btn",onClick:v,quaternary:"",circle:"",size:"medium"},{icon:t(()=>[e(r,null,{default:t(()=>[e(a(C))]),_:1})]),_:1})):c("",!0),s.back?(n(),_(p,{key:1,class:"back-btn",onClick:k,quaternary:"",circle:"",size:"small"},{icon:t(()=>[e(r,null,{default:t(()=>[e(a(N))]),_:1})]),_:1})):c("",!0),U(" "+Y(i.title)+" ",1),i.theme?(n(),_(O,{key:2,value:a(o).state.theme==="dark","onUpdate:value":u,size:"small",class:"theme-switch-wrap"},{"checked-icon":t(()=>[e(r,{component:a(P)},null,8,["component"])]),"unchecked-icon":t(()=>[e(r,{component:a(D)},null,8,["component"])]),_:1},8,["value"])):c("",!0)])]),_:1})],64)}}});export{ae as _};

@ -1 +0,0 @@
import{a8 as A}from"./index-daff1b26.js";import{u as B}from"./vuex-44de225f.js";import{u as E}from"./vue-router-e5a2430e.js";import{j as z}from"./vooks-6d99783e.js";import{$ as C,a0 as N,a1 as P,a2 as D}from"./@vicons-c265fba6.js";import{u as R,a3 as $,a4 as x,j as H,e as I,a5 as V,h as j}from"./naive-ui-defd0b2d.js";import{d as q,H as h,b as F,e as n,f,bf as a,k as e,w as t,Y as c,j as L,q as _,A as U,x as Y,F as G}from"./@vue-a481fc63.js";const J={key:0},K={class:"navbar"},ae=q({__name:"main-nav",props:{title:{default:""},back:{type:Boolean,default:!1},theme:{type:Boolean,default:!0}},setup(w){const i=w,o=B(),m=E(),l=h(!1),g=h("left"),u=s=>{s?(localStorage.setItem("PAOPAO_THEME","dark"),o.commit("triggerTheme","dark")):(localStorage.setItem("PAOPAO_THEME","light"),o.commit("triggerTheme","light"))},k=()=>{window.history.length<=1?m.push({path:"/"}):m.go(-1)},v=()=>{l.value=!0};return F(()=>{localStorage.getItem("PAOPAO_THEME")||u(z()==="dark"),o.state.desktopModelShow||(window.$store=o,window.$message=R())}),(s,d)=>{const b=A,y=$,M=x,r=H,p=I,O=V,S=j;return n(),f(G,null,[a(o).state.drawerModelShow?(n(),f("div",J,[e(M,{show:l.value,"onUpdate:show":d[0]||(d[0]=T=>l.value=T),width:212,placement:g.value,resizable:""},{default:t(()=>[e(y,null,{default:t(()=>[e(b)]),_:1})]),_:1},8,["show","placement"])])):c("",!0),e(S,{size:"small",bordered:!0,class:"nav-title-card"},{header:t(()=>[L("div",K,[a(o).state.drawerModelShow&&!s.back?(n(),_(p,{key:0,class:"drawer-btn",onClick:v,quaternary:"",circle:"",size:"medium"},{icon:t(()=>[e(r,null,{default:t(()=>[e(a(C))]),_:1})]),_:1})):c("",!0),s.back?(n(),_(p,{key:1,class:"back-btn",onClick:k,quaternary:"",circle:"",size:"small"},{icon:t(()=>[e(r,null,{default:t(()=>[e(a(N))]),_:1})]),_:1})):c("",!0),U(" "+Y(i.title)+" ",1),i.theme?(n(),_(O,{key:2,value:a(o).state.theme==="dark","onUpdate:value":u,size:"small",class:"theme-switch-wrap"},{"checked-icon":t(()=>[e(r,{component:a(P)},null,8,["component"])]),"unchecked-icon":t(()=>[e(r,{component:a(D)},null,8,["component"])]),_:1},8,["value"])):c("",!0)])]),_:1})],64)}}});export{ae as _};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{U as r}from"./naive-ui-defd0b2d.js";import{d as c,e as s,f as n,u as p,j as o,k as t,F as l}from"./@vue-a481fc63.js";import{_ as i}from"./index-daff1b26.js";const m={class:"user"},u={class:"content"},d=c({__name:"post-skeleton",props:{num:{default:1}},setup(f){return(_,k)=>{const e=r;return s(!0),n(l,null,p(new Array(_.num),a=>(s(),n("div",{class:"skeleton-item",key:a},[o("div",m,[t(e,{circle:"",size:"small"})]),o("div",u,[t(e,{text:"",repeat:3}),t(e,{text:"",style:{width:"60%"}})])]))),128)}}});const b=i(d,[["__scopeId","data-v-ab0015b4"]]);export{b as _}; import{U as r}from"./naive-ui-eecf2ec3.js";import{d as c,e as s,f as n,u as p,j as o,k as t,F as l}from"./@vue-a481fc63.js";import{_ as i}from"./index-83d7d999.js";const m={class:"user"},u={class:"content"},d=c({__name:"post-skeleton",props:{num:{default:1}},setup(f){return(_,k)=>{const e=r;return s(!0),n(l,null,p(new Array(_.num),a=>(s(),n("div",{class:"skeleton-item",key:a},[o("div",m,[t(e,{circle:"",size:"small"})]),o("div",u,[t(e,{text:"",repeat:3}),t(e,{text:"",style:{width:"60%"}})])]))),128)}}});const b=i(d,[["__scopeId","data-v-ab0015b4"]]);export{b as _};

File diff suppressed because one or more lines are too long

@ -1 +1 @@
import{X as b,_ as k}from"./index-daff1b26.js";import{d as B,H as p,e as C,q as N,w as s,j as a,k as n,A as _,x as i}from"./@vue-a481fc63.js";import{S as U,I as V,T as z,b as I,e as R,i as S}from"./naive-ui-defd0b2d.js";const T={class:"whisper-wrap"},W={class:"whisper-line"},$={class:"whisper-line send-wrap"},j=B({__name:"whisper",props:{show:{type:Boolean,default:!1},user:{}},emits:["success"],setup(r,{emit:u}){const d=r,o=p(""),t=p(!1),c=()=>{u("success")},m=()=>{t.value=!0,b({user_id:d.user.id,content:o.value}).then(e=>{window.$message.success("发送成功"),t.value=!1,o.value="",c()}).catch(e=>{t.value=!1})};return(e,l)=>{const h=U,w=V,f=z,v=I,g=R,y=S;return C(),N(y,{show:e.show,"onUpdate:show":c,class:"whisper-card",preset:"card",size:"small",title:"私信","mask-closable":!1,bordered:!1,style:{width:"360px"}},{default:s(()=>[a("div",T,[n(f,{"show-icon":!1},{default:s(()=>[_(" 即将发送私信给: "),n(w,{style:{"max-width":"100%"}},{default:s(()=>[n(h,{type:"success"},{default:s(()=>[_(i(e.user.nickname)+"@"+i(e.user.username),1)]),_:1})]),_:1})]),_:1}),a("div",W,[n(v,{type:"textarea",placeholder:"请输入私信内容(请勿发送不和谐内容,否则将会被封号)",autosize:{minRows:5,maxRows:10},value:o.value,"onUpdate:value":l[0]||(l[0]=x=>o.value=x),maxlength:"200","show-count":""},null,8,["value"])]),a("div",$,[n(g,{strong:"",secondary:"",type:"primary",loading:t.value,onClick:m},{default:s(()=>[_(" 发送 ")]),_:1},8,["loading"])])])]),_:1},8,["show"])}}});const H=k(j,[["__scopeId","data-v-0cbfe47c"]]);export{H as _}; import{Z as b,_ as k}from"./index-83d7d999.js";import{d as B,H as p,e as C,q as N,w as s,j as a,k as n,A as _,x as i}from"./@vue-a481fc63.js";import{S as U,I as V,T as z,b as I,e as R,i as S}from"./naive-ui-eecf2ec3.js";const T={class:"whisper-wrap"},W={class:"whisper-line"},$={class:"whisper-line send-wrap"},j=B({__name:"whisper",props:{show:{type:Boolean,default:!1},user:{}},emits:["success"],setup(r,{emit:u}){const d=r,o=p(""),t=p(!1),c=()=>{u("success")},m=()=>{t.value=!0,b({user_id:d.user.id,content:o.value}).then(e=>{window.$message.success("发送成功"),t.value=!1,o.value="",c()}).catch(e=>{t.value=!1})};return(e,l)=>{const h=U,w=V,f=z,v=I,g=R,y=S;return C(),N(y,{show:e.show,"onUpdate:show":c,class:"whisper-card",preset:"card",size:"small",title:"私信","mask-closable":!1,bordered:!1,style:{width:"360px"}},{default:s(()=>[a("div",T,[n(f,{"show-icon":!1},{default:s(()=>[_(" 即将发送私信给: "),n(w,{style:{"max-width":"100%"}},{default:s(()=>[n(h,{type:"success"},{default:s(()=>[_(i(e.user.nickname)+"@"+i(e.user.username),1)]),_:1})]),_:1})]),_:1}),a("div",W,[n(v,{type:"textarea",placeholder:"请输入私信内容(请勿发送不和谐内容,否则将会被封号)",autosize:{minRows:5,maxRows:10},value:o.value,"onUpdate:value":l[0]||(l[0]=x=>o.value=x),maxlength:"200","show-count":""},null,8,["value"])]),a("div",$,[n(g,{strong:"",secondary:"",type:"primary",loading:t.value,onClick:m},{default:s(()=>[_(" 发送 ")]),_:1},8,["loading"])])])]),_:1},8,["show"])}}});const H=k(j,[["__scopeId","data-v-0cbfe47c"]]);export{H as _};

@ -1 +1 @@
import{M as b,_ as k}from"./index-daff1b26.js";import{S as B,I as A,T as C,b as F,e as N,i as V}from"./naive-ui-defd0b2d.js";import{d as W,H as i,e as q,q as z,w as s,j as a,k as n,A as _,x as r}from"./@vue-a481fc63.js";const I={class:"whisper-wrap"},M={class:"whisper-line"},R={class:"whisper-line send-wrap"},S=W({__name:"whisper-add-friend",props:{show:{type:Boolean,default:!1},user:{}},emits:["success"],setup(p,{emit:d}){const u=p,o=i(""),t=i(!1),l=()=>{d("success")},m=()=>{t.value=!0,b({user_id:u.user.id,greetings:o.value}).then(e=>{window.$message.success("发送成功"),t.value=!1,o.value="",l()}).catch(e=>{t.value=!1})};return(e,c)=>{const h=B,w=A,f=C,g=F,v=N,y=V;return q(),z(y,{show:e.show,"onUpdate:show":l,class:"whisper-card",preset:"card",size:"small",title:"申请添加朋友","mask-closable":!1,bordered:!1,style:{width:"360px"}},{default:s(()=>[a("div",I,[n(f,{"show-icon":!1},{default:s(()=>[_(" 发送添加朋友申请给: "),n(w,{style:{"max-width":"100%"}},{default:s(()=>[n(h,{type:"success"},{default:s(()=>[_(r(e.user.nickname)+"@"+r(e.user.username),1)]),_:1})]),_:1})]),_:1}),a("div",M,[n(g,{type:"textarea",placeholder:"请输入真挚的问候语",autosize:{minRows:5,maxRows:10},value:o.value,"onUpdate:value":c[0]||(c[0]=x=>o.value=x),maxlength:"120","show-count":""},null,8,["value"])]),a("div",R,[n(v,{strong:"",secondary:"",type:"primary",loading:t.value,onClick:m},{default:s(()=>[_(" 发送 ")]),_:1},8,["loading"])])])]),_:1},8,["show"])}}});const D=k(S,[["__scopeId","data-v-60be56a2"]]);export{D as W}; import{N as b,_ as k}from"./index-83d7d999.js";import{S as B,I as N,T as A,b as C,e as F,i as V}from"./naive-ui-eecf2ec3.js";import{d as W,H as i,e as q,q as z,w as s,j as a,k as n,A as _,x as r}from"./@vue-a481fc63.js";const I={class:"whisper-wrap"},R={class:"whisper-line"},S={class:"whisper-line send-wrap"},T=W({__name:"whisper-add-friend",props:{show:{type:Boolean,default:!1},user:{}},emits:["success"],setup(p,{emit:d}){const u=p,o=i(""),t=i(!1),l=()=>{d("success")},m=()=>{t.value=!0,b({user_id:u.user.id,greetings:o.value}).then(e=>{window.$message.success("发送成功"),t.value=!1,o.value="",l()}).catch(e=>{t.value=!1})};return(e,c)=>{const h=B,w=N,f=A,g=C,v=F,y=V;return q(),z(y,{show:e.show,"onUpdate:show":l,class:"whisper-card",preset:"card",size:"small",title:"申请添加朋友","mask-closable":!1,bordered:!1,style:{width:"360px"}},{default:s(()=>[a("div",I,[n(f,{"show-icon":!1},{default:s(()=>[_(" 发送添加朋友申请给: "),n(w,{style:{"max-width":"100%"}},{default:s(()=>[n(h,{type:"success"},{default:s(()=>[_(r(e.user.nickname)+"@"+r(e.user.username),1)]),_:1})]),_:1})]),_:1}),a("div",R,[n(g,{type:"textarea",placeholder:"请输入真挚的问候语",autosize:{minRows:5,maxRows:10},value:o.value,"onUpdate:value":c[0]||(c[0]=x=>o.value=x),maxlength:"120","show-count":""},null,8,["value"])]),a("div",S,[n(v,{strong:"",secondary:"",type:"primary",loading:t.value,onClick:m},{default:s(()=>[_(" 发送 ")]),_:1},8,["loading"])])])]),_:1},8,["show"])}}});const H=k(T,[["__scopeId","data-v-60be56a2"]]);export{H as W};

@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" />
<link rel="manifest" href="/manifest.json" /> <link rel="manifest" href="/manifest.json" />
<title></title> <title></title>
<script type="module" crossorigin src="/assets/index-daff1b26.js"></script> <script type="module" crossorigin src="/assets/index-83d7d999.js"></script>
<link rel="modulepreload" crossorigin href="/assets/@vue-a481fc63.js"> <link rel="modulepreload" crossorigin href="/assets/@vue-a481fc63.js">
<link rel="modulepreload" crossorigin href="/assets/vue-router-e5a2430e.js"> <link rel="modulepreload" crossorigin href="/assets/vue-router-e5a2430e.js">
<link rel="modulepreload" crossorigin href="/assets/vuex-44de225f.js"> <link rel="modulepreload" crossorigin href="/assets/vuex-44de225f.js">
@ -21,14 +21,14 @@
<link rel="modulepreload" crossorigin href="/assets/@juggle-41516555.js"> <link rel="modulepreload" crossorigin href="/assets/@juggle-41516555.js">
<link rel="modulepreload" crossorigin href="/assets/@emotion-8a8e73f6.js"> <link rel="modulepreload" crossorigin href="/assets/@emotion-8a8e73f6.js">
<link rel="modulepreload" crossorigin href="/assets/css-render-6a5c5852.js"> <link rel="modulepreload" crossorigin href="/assets/css-render-6a5c5852.js">
<link rel="modulepreload" crossorigin href="/assets/vueuc-39372edb.js"> <link rel="modulepreload" crossorigin href="/assets/vueuc-7c8d4b48.js">
<link rel="modulepreload" crossorigin href="/assets/lodash-es-8412e618.js"> <link rel="modulepreload" crossorigin href="/assets/lodash-es-8412e618.js">
<link rel="modulepreload" crossorigin href="/assets/treemate-25c27bff.js"> <link rel="modulepreload" crossorigin href="/assets/treemate-25c27bff.js">
<link rel="modulepreload" crossorigin href="/assets/async-validator-dee29e8b.js"> <link rel="modulepreload" crossorigin href="/assets/async-validator-dee29e8b.js">
<link rel="modulepreload" crossorigin href="/assets/date-fns-975a2d8f.js"> <link rel="modulepreload" crossorigin href="/assets/date-fns-975a2d8f.js">
<link rel="modulepreload" crossorigin href="/assets/naive-ui-defd0b2d.js"> <link rel="modulepreload" crossorigin href="/assets/naive-ui-eecf2ec3.js">
<link rel="modulepreload" crossorigin href="/assets/moment-2ab8298d.js"> <link rel="modulepreload" crossorigin href="/assets/moment-2ab8298d.js">
<link rel="modulepreload" crossorigin href="/assets/@vicons-c265fba6.js"> <link rel="modulepreload" crossorigin href="/assets/@vicons-f0266f88.js">
<link rel="stylesheet" href="/assets/index-c337d1db.css"> <link rel="stylesheet" href="/assets/index-c337d1db.css">
<link rel="stylesheet" href="/assets/vfonts-7afd136d.css"> <link rel="stylesheet" href="/assets/vfonts-7afd136d.css">
</head> </head>

@ -99,6 +99,17 @@ export const getContacts = (
}); });
}; };
/** 获取联系人列表 */
export const getIndexTrends = (
params: NetParams.IndexTrendsReq
): Promise<NetReq.IndexTrendsResp> => {
return request({
method: "get",
url: "/v1/trends/index",
params,
});
};
/** 发布动态 */ /** 发布动态 */
export const createPost = ( export const createPost = (
data: NetParams.PostCreatePost data: NetParams.PostCreatePost

@ -22,7 +22,7 @@
}"> }">
{{ message.sender_user.nickname }} {{ message.sender_user.nickname }}
</router-link> </router-link>
<span class="username"> <span v-if="store.state.desktopModelShow" class="username">
@{{ message.sender_user.username }} @{{ message.sender_user.username }}
</span> </span>
</span> </span>
@ -35,29 +35,11 @@
}"> }">
{{ message.receiver_user.nickname }} {{ message.receiver_user.nickname }}
</router-link> </router-link>
<span class="username"> <span v-if="store.state.desktopModelShow" class="username">
@{{ message.receiver_user.username }} @{{ message.receiver_user.username }}
</span> </span>
</span> </span>
<span class="nickname" v-else> </span> <span class="nickname" v-else> </span>
<n-tag
v-if="message.type == 4"
class="top-tag"
type="success"
size="small"
round
>
</n-tag>
<!-- <n-tag
v-if="message.type != 4"
class="top-tag"
type="info"
size="small"
round
>
</n-tag> -->
<n-tag <n-tag
v-if="isWhisperSender" v-if="isWhisperSender"
class="top-tag" class="top-tag"
@ -65,7 +47,7 @@
size="small" size="small"
round round
> >
<template #icon> <template #icon>
<n-icon :component="CheckmarkCircle" /> <n-icon :component="CheckmarkCircle" />
</template> </template>
@ -77,7 +59,7 @@
size="small" size="small"
round round
> >
<template #icon> <template #icon>
<n-icon :component="CheckmarkCircle" /> <n-icon :component="CheckmarkCircle" />
</template> </template>

@ -303,7 +303,7 @@ const whisperSuccess = () => {
}; };
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'reload'): void; (e: 'reload', post_id: number): void;
}>(); }>();
const post = computed({ const post = computed({
@ -606,7 +606,7 @@ const execLockAction = () => {
id: post.value.id, id: post.value.id,
}) })
.then((res) => { .then((res) => {
emit('reload'); emit('reload', post.value.id);
if (res.lock_status === 1) { if (res.lock_status === 1) {
window.$message.success(''); window.$message.success('');
} else { } else {
@ -622,7 +622,7 @@ const execStickAction = () => {
id: post.value.id, id: post.value.id,
}) })
.then((res) => { .then((res) => {
emit('reload'); emit('reload', post.value.id);
if (res.top_status === 1) { if (res.top_status === 1) {
window.$message.success(''); window.$message.success('');
} else { } else {
@ -658,7 +658,7 @@ const execVisibilityAction = () => {
visibility: tempVisibility.value visibility: tempVisibility.value
}) })
.then((_res) => { .then((_res) => {
emit('reload'); emit('reload', post.value.id);
window.$message.success(''); window.$message.success('');
}) })
.catch((_err) => { .catch((_err) => {

@ -23,7 +23,7 @@
<span v-if="!showAction" class="tag-quote">({{ tag.quote_num }})</span> <span v-if="!showAction" class="tag-quote">({{ tag.quote_num }})</span>
<span v-if="showAction" class="tag-quote tag-follow">({{ tag.quote_num }})</span> <span v-if="showAction" class="tag-quote tag-follow">({{ tag.quote_num }})</span>
<template #avatar> <template #avatar>
<n-avatar :src="tag.user.avatar" /> <n-avatar :src="tagUserAvatar" />
</template> </template>
</n-tag> </n-tag>
</template> </template>
@ -57,6 +57,7 @@ import { ref, onMounted, computed } from 'vue';
import { MoreVertOutlined } from '@vicons/material'; import { MoreVertOutlined } from '@vicons/material';
import type { DropdownOption } from 'naive-ui'; import type { DropdownOption } from 'naive-ui';
import { stickTopic, followTopic, unfollowTopic } from '@/api/post'; import { stickTopic, followTopic, unfollowTopic } from '@/api/post';
import defaultUserAvatar from '@/assets/img/logo.png';
const hasFollowing= ref(false); const hasFollowing= ref(false);
const props = withDefaults( const props = withDefaults(
@ -68,6 +69,15 @@ const props = withDefaults(
{} {}
); );
const tagUserAvatar = computed(() => {
if (props.tag.user) {
return props.tag.user.avatar
} else {
return defaultUserAvatar
}
})
const tagOptions = computed(() => { const tagOptions = computed(() => {
let options: DropdownOption[] = []; let options: DropdownOption[] = [];
if (props.tag.is_following === 0) { if (props.tag.is_following === 0) {

@ -142,6 +142,13 @@ declare module Item {
created_on: number; created_on: number;
} }
interface IndexTrendsItem {
nickname: string;
username: string;
avatar: string;
is_fresh: boolean;
}
/** slide bar item */ /** slide bar item */
interface SlideBarItem { interface SlideBarItem {
title: string; title: string;

@ -38,6 +38,7 @@ declare module NetParams {
interface UserGetUnreadMsgCount {} interface UserGetUnreadMsgCount {}
interface UserGetMessages { interface UserGetMessages {
style: "all" | "system" | "whisper" | "requesting" | "unread";
page: number; page: number;
page_size: number; page_size: number;
} }
@ -121,6 +122,11 @@ declare module NetParams {
page_size: number; page_size: number;
} }
interface IndexTrendsReq {
page: number;
page_size: number;
}
interface GetUserFollows { interface GetUserFollows {
username: string; username: string;
page: number; page: number;

@ -189,6 +189,11 @@ declare module NetReq {
pager: Item.PagerProps; pager: Item.PagerProps;
} }
interface IndexTrendsResp {
list: Item.IndexTrendsItem[];
pager: Item.PagerProps;
}
interface PostStickTopic { interface PostStickTopic {
/** 置顶状态0为未置顶1为置顶 */ /** 置顶状态0为未置顶1为置顶 */
top_status: 0 | 1; top_status: 0 | 1;

@ -3,7 +3,7 @@
<main-nav title="收藏" /> <main-nav title="收藏" />
<n-list class="main-content-wrap" bordered> <n-list class="main-content-wrap" bordered>
<div v-if="loading" class="skeleton-wrap"> <div v-if="loading && list.length === 0" class="skeleton-wrap">
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
@ -33,14 +33,16 @@
<!-- --> <!-- -->
<whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" /> <whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" />
</n-list> </n-list>
<n-space v-if="totalPage > 0" justify="center">
<div class="pagination-wrap" v-if="totalPage > 0"> <InfiniteLoading class="load-more" :slots="{ complete: '没有更多收藏了', error: '加载出错' }" @infinite="nextPage">
<n-pagination <template #spinner>
:page="page" <div class="load-more-wrap">
@update:page="updatePage" <n-spin :size="14" v-if="!noMore" />
:page-slot="!store.state.collapsedRight ? 8 : 5" <span class="load-more-spinner">{{ noMore ? '' : '' }}</span>
:page-count="totalPage" /> </div>
</div> </template>
</InfiniteLoading>
</n-space>
</div> </div>
</template> </template>
@ -49,6 +51,7 @@ import { ref, onMounted } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useDialog } from 'naive-ui'; import { useDialog } from 'naive-ui';
import InfiniteLoading from "v3-infinite-loading";
import { getCollections, followUser, unfollowUser } from '@/api/user'; import { getCollections, followUser, unfollowUser } from '@/api/user';
const store = useStore(); const store = useStore();
@ -56,6 +59,7 @@ const route = useRoute();
const dialog = useDialog(); const dialog = useDialog();
const loading = ref(false); const loading = ref(false);
const noMore = ref(false);
const list = ref<any[]>([]); const list = ref<any[]>([]);
const page = ref(+(route.query.p as any) || 1); const page = ref(+(route.query.p as any) || 1);
const pageSize = ref(20); const pageSize = ref(20);
@ -118,21 +122,34 @@ const loadPosts = () => {
getCollections({ getCollections({
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) }).then((res) => {
.then((rsp) => { loading.value = false;
loading.value = false; if (res.list.length === 0) {
list.value = rsp.list; noMore.value = true
totalPage.value = Math.ceil(rsp.pager.total_rows / pageSize.value); }
if (page.value > 1) {
list.value = list.value.concat(res.list);
} else {
list.value = res.list;
window.scrollTo(0, 0); window.scrollTo(0, 0);
}) }
.catch((err) => { totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
loading.value = false; })
}); .catch((_err) => {
loading.value = false;
if (page.value > 1) {
page.value--
}
});
}; };
const updatePage = (p: number) => { const nextPage = () => {
page.value = p; if (page.value < totalPage.value || totalPage.value == 0) {
loadPosts(); noMore.value = false;
page.value++;
loadPosts();
} else {
noMore.value = true;
}
}; };
onMounted(() => { onMounted(() => {
loadPosts(); loadPosts();
@ -140,11 +157,21 @@ onMounted(() => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.pagination-wrap { .load-more {
padding: 10px; margin: 20px;
display: flex;
justify-content: center; .load-more-wrap {
overflow: hidden; display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 14px;
.load-more-spinner {
font-size: 14px;
opacity: 0.65;
}
}
} }
.dark { .dark {
.main-content-wrap, .empty-wrap, .skeleton-wrap { .main-content-wrap, .empty-wrap, .skeleton-wrap {

@ -3,7 +3,7 @@
<main-nav title="好友" /> <main-nav title="好友" />
<n-list class="main-content-wrap" bordered> <n-list class="main-content-wrap" bordered>
<div v-if="loading" class="skeleton-wrap"> <div v-if="loading && list.length === 0" class="skeleton-wrap">
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
@ -19,26 +19,27 @@
<whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" /> <whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" />
</n-list> </n-list>
</div> </div>
<n-space v-if="totalPage > 0" justify="center">
<div class="pagination-wrap" v-if="totalPage > 0"> <InfiniteLoading class="load-more" :slots="{ complete: '没有更多好友了', error: '加载出错' }" @infinite="nextPage">
<n-pagination <template #spinner>
:page="page" <div class="load-more-wrap">
@update:page="updatePage" <n-spin :size="14" v-if="!noMore" />
:page-slot="!store.state.collapsedRight ? 8 : 5" <span class="load-more-spinner">{{ noMore ? '' : '' }}</span>
:page-count="totalPage" /> </div>
</div> </template>
</InfiniteLoading>
</n-space>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { getContacts } from '@/api/post'; import { getContacts } from '@/api/post';
import { useStore } from 'vuex'; import InfiniteLoading from "v3-infinite-loading";
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
const store = useStore();
const route = useRoute(); const route = useRoute();
const loading = ref(false); const loading = ref(false);
const noMore = ref(false);
const list = ref<Item.ContactItemProps[]>([]); const list = ref<Item.ContactItemProps[]>([]);
const page = ref(+(route.query.p as string) || 1); const page = ref(+(route.query.p as string) || 1);
const pageSize = ref(20); const pageSize = ref(20);
@ -67,9 +68,14 @@ const whisperSuccess = () => {
showWhisper.value = false; showWhisper.value = false;
}; };
const updatePage = (p: number) => { const nextPage = () => {
page.value = p; if (page.value < totalPage.value || totalPage.value == 0) {
loadContacts(); noMore.value = false;
page.value++;
loadContacts();
} else {
noMore.value = true;
}
}; };
onMounted(() => { onMounted(() => {
@ -83,30 +89,48 @@ const loadContacts = (scrollToBottom: boolean = false) => {
getContacts({ getContacts({
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) }).then((res) => {
.then((res) => { loading.value = false;
loading.value = false; if (res.list.length === 0) {
noMore.value = true
}
if (page.value > 1) {
list.value = list.value.concat(res.list);
} else {
list.value = res.list; list.value = res.list;
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
if (scrollToBottom) { if (scrollToBottom) {
setTimeout(() => { setTimeout(() => {
window.scrollTo(0, 99999); window.scrollTo(0, 99999);
}, 50); }, 50);
} }
}) }
.catch((err) => { totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
loading.value = false; })
}); .catch((_err) => {
}; loading.value = false;
if (page.value > 1) {
page.value--;
}
});
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.pagination-wrap { .load-more {
padding: 10px; margin: 20px;
display: flex;
justify-content: center; .load-more-wrap {
overflow: hidden; display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 14px;
.load-more-spinner {
font-size: 14px;
opacity: 0.65;
}
}
} }
.dark { .dark {
.main-content-wrap, .empty-wrap, .skeleton-wrap { .main-content-wrap, .empty-wrap, .skeleton-wrap {

@ -7,7 +7,7 @@
<n-tab-pane name="follows" tab="正在关注" /> <n-tab-pane name="follows" tab="正在关注" />
<n-tab-pane name="followings" tab="我的粉丝" /> <n-tab-pane name="followings" tab="我的粉丝" />
</n-tabs> </n-tabs>
<div v-if="loading" class="skeleton-wrap"> <div v-if="loading && list.length === 0" class="skeleton-wrap">
<post-skeleton :num="pageSize" /> <post-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
@ -23,26 +23,27 @@
<whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" /> <whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" />
</n-list> </n-list>
</div> </div>
<n-space v-if="totalPage > 0" justify="center">
<div class="pagination-wrap" v-if="totalPage > 0"> <InfiniteLoading class="load-more" :slots="{ complete: completeStr, error: '加载出错' }" @infinite="nextPage">
<n-pagination <template #spinner>
:page="page" <div class="load-more-wrap">
@update:page="updatePage" <n-spin :size="14" v-if="!noMore" />
:page-slot="!store.state.collapsedRight ? 8 : 5" <span class="load-more-spinner">{{ noMore ? completeStr : '' }}</span>
:page-count="totalPage" /> </div>
</div> </template>
</InfiniteLoading>
</n-space>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, onMounted, computed } from 'vue';
import { getUserFollows, getUserFollowings } from '@/api/user'; import { getUserFollows, getUserFollowings } from '@/api/user';
import { useStore } from 'vuex'; import InfiniteLoading from "v3-infinite-loading";
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
const store = useStore();
const route = useRoute(); const route = useRoute();
const loading = ref(false); const loading = ref(false);
const noMore = ref(false);
const list = ref<Item.ContactItemProps[]>([]); const list = ref<Item.ContactItemProps[]>([]);
const nickname= route.query.n as string || "粉丝详情"; const nickname= route.query.n as string || "粉丝详情";
const username = route.query.s as string || ""; const username = route.query.s as string || "";
@ -65,6 +66,14 @@ const whisperReceiver = ref<Item.UserInfo>({
status: 1, status: 1,
}); });
const completeStr = computed(() => {
if (tabler.value == "follows") {
return ''
} else {
return ''
}
});
const onSendWhisper = (user: Item.UserInfo) => { const onSendWhisper = (user: Item.UserInfo) => {
whisperReceiver.value = user; whisperReceiver.value = user;
showWhisper.value = true; showWhisper.value = true;
@ -74,9 +83,14 @@ const whisperSuccess = () => {
showWhisper.value = false; showWhisper.value = false;
}; };
const updatePage = (p: number) => { const nextPage = () => {
page.value = p; if (page.value < totalPage.value || totalPage.value == 0) {
loadPage(); noMore.value = false;
page.value++;
loadPage();
} else {
noMore.value = true;
}
}; };
const changeTab = (tab: "follows" | "followings") => { const changeTab = (tab: "follows" | "followings") => {
@ -100,21 +114,29 @@ const loadFollows = (username: string, scrollToBottom: boolean = false) => {
username: username, username: username,
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) }).then((res) => {
.then((res) => { loading.value = false;
loading.value = false; if (res.list.length === 0) {
list.value = res.list || []; noMore.value = true
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value); }
if (page.value > 1) {
list.value = list.value.concat(res.list);
} else {
list.value = res.list;
if (scrollToBottom) { if (scrollToBottom) {
setTimeout(() => { setTimeout(() => {
window.scrollTo(0, 99999); window.scrollTo(0, 99999);
}, 50); }, 50);
} }
}) }
.catch((err) => { totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
loading.value = false; })
}); .catch((_err) => {
loading.value = false;
if (page.value > 1) {
page.value--;
}
});
}; };
const loadFollowings = (username: string, scrollToBottom: boolean = false) => { const loadFollowings = (username: string, scrollToBottom: boolean = false) => {
@ -125,21 +147,29 @@ const loadFollowings = (username: string, scrollToBottom: boolean = false) => {
username: username, username: username,
page: page.value, page: page.value,
page_size: pageSize.value, page_size: pageSize.value,
}) }).then((res) => {
.then((res) => { loading.value = false;
loading.value = false; if (res.list.length === 0) {
list.value = res.list || []; noMore.value = true
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value); }
if (page.value > 1) {
list.value = list.value.concat(res.list);
} else {
list.value = res.list;
if (scrollToBottom) { if (scrollToBottom) {
setTimeout(() => { setTimeout(() => {
window.scrollTo(0, 99999); window.scrollTo(0, 99999);
}, 50); }, 50);
} }
}) }
.catch((err) => { totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
loading.value = false; })
}); .catch((_err) => {
loading.value = false;
if (page.value > 1) {
page.value--;
}
});
}; };
onMounted(() => { onMounted(() => {
@ -153,11 +183,21 @@ onMounted(() => {
padding: 20px; padding: 20px;
} }
.pagination-wrap { .load-more {
padding: 10px; margin: 20px;
display: flex;
justify-content: center; .load-more-wrap {
overflow: hidden; display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 14px;
.load-more-spinner {
font-size: 14px;
opacity: 0.65;
}
}
} }
.dark { .dark {

@ -84,7 +84,7 @@ import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useDialog } from 'naive-ui'; import { useDialog } from 'naive-ui';
import InfiniteLoading from "v3-infinite-loading"; import InfiniteLoading from "v3-infinite-loading";
import { getPosts, getContacts } from '@/api/post'; import { getPosts, getIndexTrends } from '@/api/post';
import { getUserPosts, deleteFriend, followUser, unfollowUser } from '@/api/user'; import { getUserPosts, deleteFriend, followUser, unfollowUser } from '@/api/user';
import SlideBar from '@opentiny/vue-slide-bar'; import SlideBar from '@opentiny/vue-slide-bar';
import allTweets from '@/assets/img/fresh-tweets.png'; import allTweets from '@/assets/img/fresh-tweets.png';
@ -289,7 +289,7 @@ const loadContacts = () => {
if (!useFriendship || !enableFriendsBar || store.state.userInfo.id === 0) { if (!useFriendship || !enableFriendsBar || store.state.userInfo.id === 0) {
return return
} }
getContacts({ getIndexTrends({
page: 1, page: 1,
page_size: 50, page_size: 50,
}).then((res) => { }).then((res) => {
@ -297,13 +297,13 @@ const loadContacts = () => {
const list = res.list || [] const list = res.list || []
let barItems: Item.SlideBarItem[] = [] let barItems: Item.SlideBarItem[] = []
for (; i < list.length; i++) { for (; i < list.length; i++) {
let item: Item.ContactItemProps = list[i]; let item: Item.IndexTrendsItem = list[i];
barItems.push({ barItems.push({
title: item.nickname, title: item.nickname,
style: 21, style: 21,
username: item.username, username: item.username,
avatar: item.avatar, avatar: item.avatar,
show: false show: item.is_fresh,
}); });
} }
if (barItems.length > 0) { if (barItems.length > 0) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save