Merge branch 'x/gorm' into x/sqlx

r/paopao-ce-plus
Michael Li 2 years ago
commit bb7884510a
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:"-"`
}

@ -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
} }

@ -19,15 +19,17 @@ 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 {

@ -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;
list.value = rsp.list; if (res.list.length === 0) {
totalPage.value = Math.ceil(rsp.pager.total_rows / pageSize.value); noMore.value = true
}
if (page.value > 1) {
list.value = list.value.concat(res.list);
} else {
list.value = res.list;
window.scrollTo(0, 0); window.scrollTo(0, 0);
}
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
}) })
.catch((err) => { .catch((_err) => {
loading.value = false; 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) {
noMore.value = false;
page.value++;
loadPosts(); 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;
.load-more-wrap {
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
overflow: hidden; 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) {
noMore.value = false;
page.value++;
loadContacts(); 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);
} }
}
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
}) })
.catch((err) => { .catch((_err) => {
loading.value = false; 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;
.load-more-wrap {
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
overflow: hidden; 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) {
noMore.value = false;
page.value++;
loadPage(); loadPage();
} else {
noMore.value = true;
}
}; };
const changeTab = (tab: "follows" | "followings") => { const changeTab = (tab: "follows" | "followings") => {
@ -100,20 +114,28 @@ 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;
list.value = res.list || []; if (res.list.length === 0) {
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value); noMore.value = true
}
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);
} }
}
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
}) })
.catch((err) => { .catch((_err) => {
loading.value = false; loading.value = false;
if (page.value > 1) {
page.value--;
}
}); });
}; };
@ -125,20 +147,28 @@ 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;
list.value = res.list || []; if (res.list.length === 0) {
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value); noMore.value = true
}
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);
} }
}
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
}) })
.catch((err) => { .catch((_err) => {
loading.value = false; loading.value = false;
if (page.value > 1) {
page.value--;
}
}); });
}; };
@ -153,11 +183,21 @@ onMounted(() => {
padding: 20px; padding: 20px;
} }
.pagination-wrap { .load-more {
padding: 10px; margin: 20px;
.load-more-wrap {
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
overflow: hidden; 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) {

@ -5,42 +5,89 @@
<n-list class="main-content-wrap messages-wrap" bordered> <n-list class="main-content-wrap messages-wrap" bordered>
<!-- --> <!-- -->
<whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" /> <whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" />
<div v-if="loading" class="skeleton-wrap"> <n-space justify="space-between">
<div class="title title-action">
<n-button text size="small" @click="handleUnreadMessage">
<template #icon>
<n-icon>
<UnreadIcon />
</n-icon>
</template>
0
</n-button>
<n-divider vertical />
<n-button text size="small" @click="handleReadAll"></n-button>
</div>
<div class="title title-filter">
<n-dropdown
placement="bottom-end"
trigger="click"
size="small"
:options="options"
@select="handleAction">
<n-button text>
<template #icon>
<n-icon>
<OptionsIcon />
</n-icon>
</template>
{{ messageStyle }}
</n-button>
</n-dropdown>
</div>
</n-space>
<div v-if="loading && list.length === 0" class="skeleton-wrap">
<message-skeleton :num="pageSize" /> <message-skeleton :num="pageSize" />
</div> </div>
<div v-else> <div v-else>
<div class="empty-wrap" v-if="list.length === 0"> <div class="empty-wrap" v-if="list.length === 0">
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
</div> </div>
<div v-else>
<n-list-item v-for="m in list" :key="m.id"> <n-list-item v-for="m in list" :key="m.id">
<message-item :message="m" @send-whisper="onSendWhisper" @reload="loadMessages" /> <message-item :message="m" @send-whisper="onSendWhisper" @reload="reloadMessages" />
</n-list-item> </n-list-item>
</div> </div>
</div>
</n-list> </n-list>
<div class="pagination-wrap" v-if="totalPage > 0"> <n-space v-if="totalPage > 0" justify="center">
<n-pagination <InfiniteLoading class="load-more" :slots="{ complete: '没有更多消息了', error: '加载出错' }" @infinite="nextPage">
:page="page" <template #spinner>
@update:page="updatePage" <div class="load-more-wrap">
:page-slot="!store.state.collapsedRight ? 8 : 5" <n-spin :size="14" v-if="!noMore" />
:page-count="totalPage" <span class="load-more-spinner">{{ noMore ? '' : '' }}</span>
/>
</div> </div>
</template>
</InfiniteLoading>
</n-space>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { h, ref, onMounted, computed } from 'vue';
import { useStore } from 'vuex'; import type { Component } from 'vue'
import { NIcon, DropdownOption } from 'naive-ui'
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import InfiniteLoading from "v3-infinite-loading";
import { getMessages } from '@/api/user'; import { getMessages } from '@/api/user';
import {
LayersOutline as AllIcon,
AtOutline as SystemIcon,
PaperPlaneOutline as WhisperIcon,
PersonAddOutline as RequestingIcon,
ChatbubbleEllipsesOutline as UnreadIcon,
OptionsOutline as OptionsIcon,
} from '@vicons/ionicons5'
const route = useRoute(); const route = useRoute();
const store = useStore();
const loading = ref(false); const loading = ref(false);
const noMore = ref(false);
const page = ref(+(route.query.p as string) || 1); const page = ref(+(route.query.p as string) || 1);
const pageSize = ref(10); const pageSize = ref(20);
const totalPage = ref(0); const totalPage = ref(0);
const list = ref<Item.MessageProps[]>([]); const list = ref<Item.MessageProps[]>([]);
const messageStyle = ref<'' | '' | '' | '' | ''>('')
const messageStyleVal = ref<'all' | 'system' | 'whisper' | 'requesting' | 'unread'>('all')
const showWhisper = ref(false); const showWhisper = ref(false);
const whisperReceiver = ref<Item.UserInfo>({ const whisperReceiver = ref<Item.UserInfo>({
id: 0, id: 0,
@ -56,31 +103,234 @@ const whisperReceiver = ref<Item.UserInfo>({
status: 1, status: 1,
}); });
const reset = () => {
noMore.value = false;
page.value = 1;
totalPage.value = 0;
list.value = [];
}
const renderIcon = (icon: Component) => {
return () => {
return h(NIcon, null, {
default: () => h(icon)
})
}
}
const options = computed(() => {
let opts: DropdownOption[];
switch (messageStyle.value) {
case '':
opts = [
{
label: '',
key: 'system',
icon: renderIcon(SystemIcon)
},
{
label: '',
key: 'whisper',
icon: renderIcon(WhisperIcon)
},
{
label: '',
key: 'requesting',
icon: renderIcon(RequestingIcon)
},
{
label: '',
key: 'unread',
icon: renderIcon(UnreadIcon)
}
]
break;
case '':
opts = [
{
label: '',
key: 'all',
icon: renderIcon(AllIcon)
},
{
label: '',
key: 'whisper',
icon: renderIcon(WhisperIcon)
},
{
label: '',
key: 'requesting',
icon: renderIcon(RequestingIcon)
},
{
label: '',
key: 'unread',
icon: renderIcon(UnreadIcon)
}
]
break;
case '':
opts = [
{
label: '',
key: 'all',
icon: renderIcon(AllIcon)
},
{
label: '',
key: 'system',
icon: renderIcon(SystemIcon)
},
{
label: '',
key: 'requesting',
icon: renderIcon(RequestingIcon)
},
{
label: '',
key: 'unread',
icon: renderIcon(UnreadIcon)
}
]
break;
case '':
opts = [
{
label: '',
key: 'all',
icon: renderIcon(AllIcon)
},
{
label: '',
key: 'system',
icon: renderIcon(SystemIcon)
},
{
label: '',
key: 'whisper',
icon: renderIcon(WhisperIcon)
},
{
label: '',
key: 'unread',
icon: renderIcon(UnreadIcon)
}
]
break;
case '':
opts = [
{
label: '',
key: 'all',
icon: renderIcon(AllIcon)
},
{
label: '',
key: 'system',
icon: renderIcon(SystemIcon)
},
{
label: '',
key: 'whisper',
icon: renderIcon(WhisperIcon)
},
{
label: '',
key: 'requesting',
icon: renderIcon(RequestingIcon)
}
]
break;
default:
opts = [];
break;
}
return opts;
});
const handleAction = (
item: 'all' | 'system' | 'whisper' | 'requesting' | 'unread'
) => {
switch (item) {
case 'all':
messageStyle.value = '';
break;
case 'system':
messageStyle.value = '';
break;
case 'whisper':
messageStyle.value = '';
break;
case 'requesting':
messageStyle.value = '';
break;
case 'unread':
messageStyle.value = '';
break;
}
messageStyleVal.value = item
reset();
loadMessages();
};
const handleUnreadMessage = () => {
handleAction('unread')
}
const handleReadAll = () => {
// TODO: 标记全部未读消息为已读
reset();
loadMessages();
}
const onSendWhisper = (user: Item.UserInfo) => { const onSendWhisper = (user: Item.UserInfo) => {
whisperReceiver.value = user; whisperReceiver.value = user;
showWhisper.value = true; showWhisper.value = true;
}; };
const whisperSuccess = () => { const whisperSuccess = () => {
showWhisper.value = false; showWhisper.value = false;
}; };
const reloadMessages = () => {
reset();
loadMessages();
};
const loadMessages = () => { const loadMessages = () => {
loading.value = true; loading.value = true;
getMessages({ getMessages({
style: messageStyleVal.value,
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;
window.scrollTo(0, 0);
}
totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value); totalPage.value = Math.ceil(res.pager.total_rows / pageSize.value);
}) })
.catch((err) => { .catch((_err) => {
loading.value = false; 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) {
noMore.value = false;
page.value++;
loadMessages(); loadMessages();
} else {
noMore.value = true;
}
}; };
onMounted(() => { onMounted(() => {
loadMessages(); loadMessages();
@ -88,11 +338,33 @@ onMounted(() => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.pagination-wrap { .load-more {
padding: 10px; margin: 20px;
.load-more-wrap {
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
overflow: hidden; align-items: center;
gap: 14px;
.load-more-spinner {
font-size: 14px;
opacity: 0.65;
}
}
}
.title {
padding-top: 4px;
opacity: 0.9;
}
.title-action {
display: flex;
align-items: center;
margin-left: 20px;
}
.title-filter {
margin-right: 20px;
} }
.dark { .dark {
.empty-wrap { .empty-wrap {

@ -6,7 +6,7 @@
<n-list-item> <n-list-item>
<n-spin :show="loading"> <n-spin :show="loading">
<div class="detail-wrap" v-if="post.id > 1"> <div class="detail-wrap" v-if="post.id > 1">
<post-detail :post="post" @reload="loadPost" /> <post-detail :post="post" @reload="reloadPost" />
</div> </div>
<div class="empty-wrap" v-else> <div class="empty-wrap" v-else>
<n-empty size="large" description="暂无数据" /> <n-empty size="large" description="暂无数据" />
@ -97,6 +97,14 @@ const commentTab = (tab: "default" | "newest") => {
loadComments(stateHandler); loadComments(stateHandler);
}; };
const reloadPost = (post_id: number) => {
getPost({
id: post_id,
}).then((res) => {
post.value = res;
}).catch((_err) => {});
};
const loadPost = () => { const loadPost = () => {
post.value = { post.value = {
id: 0, id: 0,

Loading…
Cancel
Save