add follow/unfollow user support in index page

pull/391/head
Michael Li 1 year ago
parent 56d856f50c
commit 2274d128b4
No known key found for this signature in database

@ -76,6 +76,7 @@ All notable changes to paopao-ce are documented in this file.
```sql
ALTER TABLE `p_comment` ADD COLUMN `is_essence` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '是否精选';
```
- add follow/unfollow user support in index page.
## 0.4.2

@ -4,6 +4,7 @@ go 1.20
require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/RoaringBitmap/roaring v1.5.0
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868
github.com/alimy/mir/v4 v4.0.0
github.com/alimy/tryst v0.8.3
@ -54,6 +55,7 @@ require (
require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/bits-and-blooms/bitset v1.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
@ -106,6 +108,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pyroscope-io/godeltaprof v0.1.2 // indirect

@ -112,6 +112,8 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/RoaringBitmap/roaring v1.5.0 h1:V0VCSiHjroItEYCM3guC8T83ehi5QMt3oM9EefTTOms=
github.com/RoaringBitmap/roaring v1.5.0/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 h1:uFrPOl1VBt/Abfl2z+A/DFc+AwmFLxEHR1+Yq6cXvww=
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868/go.mod h1:srphKZ1i+yGXxl/LpBS7ZIECTjCTPzZzAMtJWoG3sLo=
@ -178,6 +180,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
@ -986,6 +989,8 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P
github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY=

@ -29,6 +29,8 @@ const (
PrefixUserInfo = "paopao:userinfo:"
PrefixUserInfoById = "paopao:userinfo:id:"
PrefixUserInfoByName = "paopao:userinfo:name:"
PrefixMyFriendIds = "paopao:myfriendids:"
PrefixMyFollowIds = "paopao:myfollowids:"
KeySiteStatus = "paopao:sitestatus"
KeyHistoryMaxOnline = "history.max.online"
)
@ -42,6 +44,8 @@ var (
KeyOnlineUser cache.KeyPool[int64]
KeyUserInfoById cache.KeyPool[int64]
KeyUserInfoByName cache.KeyPool[string]
KeyMyFriendIds cache.KeyPool[int64]
KeyMyFollowIds cache.KeyPool[int64]
)
func initCacheKeyPool() {
@ -56,6 +60,8 @@ func initCacheKeyPool() {
KeyOnlineUser = intKeyPool[int64](poolSize, PrefixOnlineUser)
KeyUserInfoById = intKeyPool[int64](poolSize, PrefixUserInfoById)
KeyUserInfoByName = strKeyPool(poolSize, PrefixUserInfoById)
KeyMyFriendIds = intKeyPool[int64](poolSize, PrefixMyFriendIds)
KeyMyFollowIds = intKeyPool[int64](poolSize, PrefixMyFollowIds)
}
func strKeyPool(size int, prefix string) cache.KeyPool[string] {

@ -34,6 +34,7 @@ type DataService interface {
UserManageService
ContactManageService
FollowingManageService
UserRelationService
// 安全服务
SecurityService

@ -37,3 +37,11 @@ type FollowingManageService interface {
GetFollowCount(userId int64) (int64, int64, error)
IsFollow(userId int64, followId int64) bool
}
// UserRelationService 用户关系服务
type UserRelationService interface {
MyFriendIds(userId int64) ([]int64, error)
MyFollowIds(userId int64) ([]int64, error)
IsMyFriend(userId int64, friendIds []int64) (map[int64]bool, error)
IsMyFollow(userId int64, followIds []int64) (map[int64]bool, error)
}

@ -8,6 +8,7 @@ import (
"bytes"
"encoding/gob"
"github.com/RoaringBitmap/roaring/roaring64"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/ms"
@ -59,3 +60,47 @@ func (s *cacheDataService) GetUserByUsername(username string) (res *ms.User, err
}
return
}
func (s *cacheDataService) IsMyFriend(userId int64, friendIds []int64) (res map[int64]bool, err error) {
size := len(friendIds)
res = make(map[int64]bool, size)
if size == 0 {
return
}
// 从缓存中获取
key := conf.KeyMyFriendIds.Get(userId)
if data, xerr := s.ac.Get(key); xerr == nil {
bitmap := roaring64.New()
if err = bitmap.UnmarshalBinary(data); err == nil {
for _, friendId := range friendIds {
res[friendId] = bitmap.Contains(uint64(friendId))
}
return
}
}
// 直接查库并触发缓存更新事件
OnCacheMyFriendIdsEvent(s.DataService, userId)
return s.DataService.IsMyFriend(userId, friendIds)
}
func (s *cacheDataService) IsMyFollow(userId int64, followIds []int64) (res map[int64]bool, err error) {
size := len(followIds)
res = make(map[int64]bool, size)
if size == 0 {
return
}
// 从缓存中获取
key := conf.KeyMyFollowIds.Get(userId)
if data, xerr := s.ac.Get(key); xerr == nil {
bitmap := roaring64.New()
if err = bitmap.UnmarshalBinary(data); err == nil {
for _, followId := range followIds {
res[followId] = bitmap.Contains(uint64(followId))
}
return
}
}
// 直接查库并触发缓存更新事件
OnCacheMyFollowIdsEvent(s.DataService, userId, key)
return s.DataService.IsMyFollow(userId, followIds)
}

@ -9,23 +9,23 @@ import (
"encoding/gob"
"fmt"
"github.com/RoaringBitmap/roaring/roaring64"
"github.com/alimy/tryst/event"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/events"
"github.com/sirupsen/logrus"
)
type expireIndexTweetsEvent struct {
event.UnimplementedEvent
tweet *ms.Post
ac core.AppCache
keysPattern []string
}
type expireHotsTweetsEvent struct {
event.UnimplementedEvent
tweet *ms.Post
ac core.AppCache
keyPattern string
}
@ -46,21 +46,34 @@ type cacheUserInfoEvent struct {
expire int64
}
func onExpireIndexTweetEvent(tweet *ms.Post) {
type cacheMyFriendIdsEvent struct {
event.UnimplementedEvent
ac core.AppCache
urs core.UserRelationService
userIds []int64
}
type cacheMyFollowIdsEvent struct {
event.UnimplementedEvent
ac core.AppCache
urs core.UserRelationService
userId int64
key string
}
func OnExpireIndexTweetEvent(userId int64) {
events.OnEvent(&expireIndexTweetsEvent{
tweet: tweet,
ac: _appCache,
keysPattern: []string{
conf.PrefixIdxTweetsNewest + "*",
conf.PrefixIdxTweetsHots + "*",
fmt.Sprintf("%s%d:*", conf.PrefixUserTweets, tweet.UserID),
fmt.Sprintf("%s%d:*", conf.PrefixUserTweets, userId),
},
})
}
func onExpireHotsTweetEvent(tweet *ms.Post) {
func OnExpireHotsTweetEvent() {
events.OnEvent(&expireHotsTweetsEvent{
tweet: tweet,
ac: _appCache,
keyPattern: conf.PrefixHotsTweets + "*",
})
@ -83,6 +96,32 @@ func onCacheUserInfoEvent(key string, data *ms.User) {
})
}
func OnCacheMyFriendIdsEvent(urs core.UserRelationService, userIds ...int64) {
if len(userIds) == 0 {
return
}
events.OnEvent(&cacheMyFriendIdsEvent{
userIds: userIds,
urs: urs,
ac: _appCache,
})
}
func OnCacheMyFollowIdsEvent(urs core.UserRelationService, userId int64, key ...string) {
cacheKey := ""
if len(key) > 0 {
cacheKey = key[0]
} else {
cacheKey = conf.KeyMyFollowIds.Get(userId)
}
events.OnEvent(&cacheMyFollowIdsEvent{
userId: userId,
urs: urs,
key: cacheKey,
ac: _appCache,
})
}
func (e *expireIndexTweetsEvent) Name() string {
return "expireIndexTweetsEvent"
}
@ -127,3 +166,49 @@ func (e *cacheUserInfoEvent) Action() (err error) {
}
return
}
func (e *cacheMyFriendIdsEvent) Name() string {
return "cacheMyFriendIdsEvent"
}
func (e *cacheMyFriendIdsEvent) Action() error {
logrus.Debug("cacheMyFriendIdsEvent action runnging")
for _, userId := range e.userIds {
myFriendIds, err := e.urs.MyFriendIds(userId)
if err != nil {
return err
}
bitmap := roaring64.New()
for _, friendId := range myFriendIds {
bitmap.Add(uint64(friendId))
}
data, err := bitmap.MarshalBinary()
if err != nil {
return err
}
e.ac.Set(conf.KeyMyFriendIds.Get(userId), data, 0)
}
return nil
}
func (e *cacheMyFollowIdsEvent) Name() string {
return "cacheMyFollowIdsEvent"
}
func (e *cacheMyFollowIdsEvent) Action() (err error) {
logrus.Debug("cacheMyFollowIdsEvent action runnging")
myFollowIds, err := e.urs.MyFollowIds(e.userId)
if err != nil {
return err
}
bitmap := roaring64.New()
for _, followId := range myFollowIds {
bitmap.Add(uint64(followId))
}
data, err := bitmap.MarshalBinary()
if err != nil {
return err
}
e.ac.Set(e.key, data, 0)
return nil
}

@ -26,15 +26,15 @@ func (s *eventCacheIndexSrv) SendAction(act core.IdxAct, post *ms.Post) {
CollectionCount: post.CollectionCount,
ShareCount: post.ShareCount,
})
onExpireIndexTweetEvent(post)
OnExpireIndexTweetEvent(post.UserID)
case core.IdxActCreatePost:
err = s.tms.AddTweetMetric(post.ID)
onExpireIndexTweetEvent(post)
OnExpireIndexTweetEvent(post.UserID)
case core.IdxActDeletePost:
err = s.tms.DeleteTweetMetric(post.ID)
onExpireIndexTweetEvent(post)
OnExpireIndexTweetEvent(post.UserID)
case core.IdxActStickPost, core.IdxActVisiblePost:
onExpireIndexTweetEvent(post)
OnExpireIndexTweetEvent(post.UserID)
}
if err != nil {
logrus.Errorf("eventCacheIndexSrv.SendAction(%s) occurs error: %s", act, err)

@ -34,6 +34,8 @@ type UserFormated struct {
Status int `json:"status"`
Avatar string `json:"avatar"`
IsAdmin bool `json:"is_admin"`
IsFriend bool `json:"is_friend"`
IsFollowing bool `json:"is_following"`
}
func (u *User) Format() *UserFormated {

@ -41,6 +41,7 @@ type dataSrv struct {
core.UserManageService
core.ContactManageService
core.FollowingManageService
core.UserRelationService
core.SecurityService
core.AttachmentCheckService
}
@ -71,6 +72,7 @@ func NewDataService() (core.DataService, core.VersionInfo) {
UserManageService: newUserManageService(db),
ContactManageService: newContactManageService(db),
FollowingManageService: newFollowingManageService(db),
UserRelationService: newUserRelationService(db),
SecurityService: newSecurityService(db, pvs),
AttachmentCheckService: security.NewAttachmentCheckService(),
}

@ -21,12 +21,22 @@ type userManageSrv struct {
db *gorm.DB
}
type userRelationSrv struct {
db *gorm.DB
}
func newUserManageService(db *gorm.DB) core.UserManageService {
return &userManageSrv{
db: db,
}
}
func newUserRelationService(db *gorm.DB) core.UserRelationService {
return &userRelationSrv{
db: db,
}
}
func (s *userManageSrv) GetUserByID(id int64) (*ms.User, error) {
user := &dbr.User{
Model: &dbr.Model{
@ -83,3 +93,57 @@ func (s *userManageSrv) GetRegisterUserCount() (res int64, err error) {
err = s.db.Model(&dbr.User{}).Count(&res).Error
return
}
func (s *userRelationSrv) MyFriendIds(userId int64) (res []int64, err error) {
err = s.db.Table(_contact_).Where("user_id=?", userId).Select("friend_id").Find(&res).Error
return
}
func (s *userRelationSrv) MyFollowIds(userId int64) (res []int64, err error) {
err = s.db.Table(_following_).Where("user_id=?", userId).Select("follow_id").Find(&res).Error
return
}
func (s *userRelationSrv) IsMyFriend(userId int64, friendIds []int64) (map[int64]bool, error) {
size := len(friendIds)
res := make(map[int64]bool, size)
if size == 0 {
return res, nil
}
myFriendIds, err := s.MyFriendIds(userId)
if err != nil {
return nil, err
}
for _, friendId := range friendIds {
res[friendId] = false
for _, myFriendId := range myFriendIds {
if friendId == myFriendId {
res[friendId] = true
break
}
}
}
return res, nil
}
func (s *userRelationSrv) IsMyFollow(userId int64, followIds []int64) (map[int64]bool, error) {
size := len(followIds)
res := make(map[int64]bool, size)
if size == 0 {
return res, nil
}
myFollowIds, err := s.MyFollowIds(userId)
if err != nil {
return nil, err
}
for _, followId := range followIds {
res[followId] = false
for _, myFollowId := range myFollowIds {
if followId == myFollowId {
res[followId] = true
break
}
}
}
return res, nil
}

@ -24,6 +24,7 @@ import (
"github.com/rocboss/paopao-ce/internal/events"
"github.com/rocboss/paopao-ce/internal/model/joint"
"github.com/rocboss/paopao-ce/pkg/app"
"github.com/rocboss/paopao-ce/pkg/types"
"github.com/rocboss/paopao-ce/pkg/xerror"
)
@ -172,6 +173,36 @@ func (s *BaseServant) Render(c *gin.Context, data any, err mir.Error) {
}
}
func (s *DaoServant) PrepareTweets(userId int64, tweets []*ms.PostFormated) error {
userIdSet := make(map[int64]types.Empty, len(tweets))
for _, tweet := range tweets {
userIdSet[tweet.UserID] = types.Empty{}
// 顺便转换一下可见性的值
tweet.Visibility = ms.PostVisibleT(tweet.Visibility.ToOutValue())
}
// guest用户的userId<0
if userId < 0 {
return nil
}
userIds := make([]int64, 0, len(userIdSet))
for id := range userIdSet {
userIds = append(userIds, id)
}
// friendMap, err := s.Ds.IsMyFriend(userId, userIds)
// if err != nil {
// return err
// }
followMap, err := s.Ds.IsMyFollow(userId, userIds)
if err != nil {
return err
}
for _, tweet := range tweets {
// tweet.User.IsFriend, tweet.User.IsFollowing = friendMap[tweet.UserID], followMap[tweet.UserID]
tweet.User.IsFollowing = followMap[tweet.UserID]
}
return nil
}
func (s *DaoServant) GetTweetBy(id int64) (*ms.PostFormated, error) {
post, err := s.Ds.GetPostByID(id)
if err != nil {
@ -278,15 +309,6 @@ func (s *DaoServant) DeleteSearchPost(post *ms.Post) error {
return s.Ts.DeleteDocuments([]string{fmt.Sprintf("%d", post.ID)})
}
func (s *DaoServant) GetTweetList(conditions ms.ConditionsT, offset, limit int) ([]*ms.Post, []*ms.PostFormated, error) {
posts, err := s.Ds.GetPosts(conditions, offset, limit)
if err != nil {
return nil, nil, err
}
postFormated, err := s.Ds.MergePosts(posts)
return posts, postFormated, err
}
func (s *DaoServant) RelationTypFrom(me *ms.User, username string) (res *cs.VistUser, err error) {
res = &cs.VistUser{
RelTyp: cs.RelationSelf,

@ -8,6 +8,7 @@ import (
"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/dao/cache"
"github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain"
@ -84,6 +85,9 @@ func (s *followshipSrv) UnfollowUser(r *web.UnfollowUserReq) mir.Error {
logrus.Errorf("Ds.UnfollowUser err: %s userId: %d followId: %d", err, r.User.ID, r.UserId)
return web.ErrUnfollowUserFailed
}
// 触发缓存更新事件
cache.OnCacheMyFollowIdsEvent(s.Ds, r.User.ID)
cache.OnExpireIndexTweetEvent(r.User.ID)
return nil
}
@ -97,6 +101,9 @@ func (s *followshipSrv) FollowUser(r *web.FollowUserReq) mir.Error {
logrus.Errorf("Ds.FollowUser err: %s userId: %d followId: %d", err, r.User.ID, r.UserId)
return web.ErrUnfollowUserFailed
}
// 触发缓存更新事件
cache.OnCacheMyFollowIdsEvent(s.Ds, r.User.ID)
cache.OnExpireIndexTweetEvent(r.User.ID)
return nil
}

@ -55,6 +55,8 @@ func (s *friendshipSrv) DeleteFriend(req *web.DeleteFriendReq) mir.Error {
logrus.Errorf("Ds.DeleteFriend err: %s", err)
return web.ErrDeleteFriendFailed
}
// 触发用户关系缓存更新事件
// cache.OnCacheMyFriendIdsEvent(s.Ds, req.User.ID, req.UserId)
return nil
}
@ -89,6 +91,8 @@ func (s *friendshipSrv) AddFriend(req *web.AddFriendReq) mir.Error {
logrus.Errorf("Ds.AddFriend err: %s", err)
return web.ErrAddFriendFailed
}
// 触发用户关系缓存更新事件
// cache.OnCacheMyFriendIdsEvent(s.Ds, req.User.ID, req.UserId)
return nil
}

@ -61,8 +61,14 @@ func (s *looseSrv) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error)
logrus.Errorf("Ds.RevampPosts err: %s", err)
return nil, web.ErrGetPostsFailed
}
// TODO: 暂时处理,需要去掉这个步骤
visbleTansform(posts)
userId := int64(-1)
if req.User != nil {
userId = req.User.ID
}
if err := s.PrepareTweets(userId, posts); err != nil {
logrus.Errorf("timeline occurs error[2]: %s", err)
return nil, web.ErrGetPostsFailed
}
resp := joint.PageRespFrom(posts, req.Page, req.PageSize, res.Total)
return &web.TimelineResp{
CachePageResp: joint.CachePageResp{
@ -98,7 +104,7 @@ func (s *looseSrv) getIndexTweets(req *web.TimelineReq, limit int, offset int) (
return nil, web.ErrGetPostsUnknowStyle
}
if xerr != nil {
logrus.Errorf("getIndexTweets occurs error: %s", xerr)
logrus.Errorf("getIndexTweets occurs error[1]: %s", xerr)
return nil, web.ErrGetPostFailed
}
postsFormated, verr := s.Ds.MergePosts(posts)
@ -106,8 +112,14 @@ func (s *looseSrv) getIndexTweets(req *web.TimelineReq, limit int, offset int) (
logrus.Errorf("getIndexTweets in merge posts occurs error: %s", verr)
return nil, web.ErrGetPostFailed
}
// TODO: 暂时处理,需要去掉这个步骤
visbleTansform(postsFormated)
userId := int64(-1)
if req.User != nil {
userId = req.User.ID
}
if err := s.PrepareTweets(userId, postsFormated); err != nil {
logrus.Errorf("getIndexTweets occurs error[2]: %s", err)
return nil, web.ErrGetPostsFailed
}
resp := joint.PageRespFrom(postsFormated, req.Page, req.PageSize, total)
// 缓存处理
base.OnCacheRespEvent(s.ac, key, resp, s.idxTweetsExpire)
@ -198,7 +210,7 @@ func (s *looseSrv) userTweetsFromCache(req *web.GetUserTweetsReq, user *cs.VistU
func (s *looseSrv) getUserStarTweets(req *web.GetUserTweetsReq, user *cs.VistUser) (*web.GetUserTweetsResp, mir.Error) {
stars, totalRows, err := s.Ds.ListUserStarTweets(user, req.PageSize, (req.Page-1)*req.PageSize)
if err != nil {
logrus.Errorf("Ds.GetUserPostStars err: %s", err)
logrus.Errorf("getUserStarTweets err[1]: %s", err)
return nil, web.ErrGetStarsFailed
}
var posts []*ms.Post
@ -212,8 +224,14 @@ func (s *looseSrv) getUserStarTweets(req *web.GetUserTweetsReq, user *cs.VistUse
logrus.Errorf("Ds.MergePosts err: %s", err)
return nil, web.ErrGetStarsFailed
}
// TODO: 暂时处理,需要去掉这个步骤
visbleTansform(postsFormated)
userId := int64(-1)
if req.User != nil {
userId = req.User.ID
}
if err := s.PrepareTweets(userId, postsFormated); err != nil {
logrus.Errorf("getUserStarTweets err[2]: %s", err)
return nil, web.ErrGetPostsFailed
}
resp := joint.PageRespFrom(postsFormated, req.Page, req.PageSize, totalRows)
return &web.GetUserTweetsResp{
CachePageResp: joint.CachePageResp{
@ -233,21 +251,27 @@ func (s *looseSrv) listUserTweets(req *web.GetUserTweetsReq, user *cs.VistUser)
} else if req.Style == web.UserPostsStyleMedia {
tweets, total, err = s.Ds.ListUserMediaTweets(user, req.PageSize, (req.Page-1)*req.PageSize)
} else {
logrus.Errorf("s.listUserTweets unknow style: %s", req.Style)
logrus.Errorf("s.listUserTweets unknow style[1]: %s", req.Style)
return nil, web.ErrGetPostsFailed
}
if err != nil {
logrus.Errorf("s.listUserTweets err: %s", err)
logrus.Errorf("s.listUserTweets err[2]: %s", err)
return nil, web.ErrGetPostsFailed
}
postFormated, err := s.Ds.MergePosts(tweets)
postsFormated, err := s.Ds.MergePosts(tweets)
if err != nil {
logrus.Errorf("s.listUserTweets err: %s", err)
logrus.Errorf("s.listUserTweets err[3]: %s", err)
return nil, web.ErrGetPostsFailed
}
userId := int64(-1)
if req.User != nil {
userId = req.User.ID
}
if err := s.PrepareTweets(userId, postsFormated); err != nil {
logrus.Errorf("s.listUserTweets err[4]: %s", err)
return nil, web.ErrGetPostsFailed
}
// TODO: 暂时处理,需要去掉这个步骤
visbleTansform(postFormated)
resp := joint.PageRespFrom(postFormated, req.Page, req.PageSize, total)
resp := joint.PageRespFrom(postsFormated, req.Page, req.PageSize, total)
return &web.GetUserTweetsResp{
CachePageResp: joint.CachePageResp{
Data: resp,
@ -281,8 +305,14 @@ func (s *looseSrv) getUserPostTweets(req *web.GetUserTweetsReq, user *cs.VistUse
logrus.Errorf("s.GetTweetList error[2]: %s", err)
return nil, web.ErrGetPostsFailed
}
// TODO: 暂时处理,需要去掉这个步骤
visbleTansform(postsFormated)
userId := int64(-1)
if req.User != nil {
userId = req.User.ID
}
if err := s.PrepareTweets(userId, postsFormated); err != nil {
logrus.Errorf("s.GetTweetList error[3]: %s", err)
return nil, web.ErrGetPostsFailed
}
resp := joint.PageRespFrom(postsFormated, req.Page, req.PageSize, total)
return &web.GetUserTweetsResp{
CachePageResp: joint.CachePageResp{

@ -209,7 +209,7 @@ func checkPermision(user *ms.User, targetUserId int64) mir.Error {
}
// visbleTansform 可见性等价转换,暂时处理方式,后续需要去掉这个步骤
func visbleTansform(list []*ms.PostFormated) {
func _visbleTansform(list []*ms.PostFormated) {
for _, post := range list {
post.Visibility = ms.PostVisibleT(post.Visibility.ToOutValue())
}

@ -1 +1 @@
import{_ as s}from"./main-nav.vue_vue_type_style_index_0_lang-e2b1e404.js";import{u as i}from"./vue-router-e5a2430e.js";import{F as a,e as c,a2 as u}from"./naive-ui-609478ed.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-ac7904e2.js";import"./vuex-44de225f.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./@vicons-4ed09704.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-832ff0ed.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-537a241d.js";import"./vuex-44de225f.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./@vicons-4ed09704.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};

@ -0,0 +1 @@
import{_ as N}from"./post-skeleton-5d89319a.js";import{_ as R}from"./main-nav.vue_vue_type_style_index_0_lang-832ff0ed.js";import{u as z}from"./vuex-44de225f.js";import{b as A}from"./vue-router-e5a2430e.js";import{H as F,_ as H}from"./index-537a241d.js";import{G as S,R as V,J as q,H as P}from"./naive-ui-defd0b2d.js";import{d as j,H as n,b as D,f as o,k as a,w as p,e as t,bf as u,Y as l,F as E,u as G,q as I,j as s,x as _,l as J}from"./@vue-a481fc63.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./@vicons-4ed09704.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=j({__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 D(()=>{}),(m,K)=>{const k=R,y=V,x=N,w=q,B=P,C=S;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(E,null,G(i.value,e=>(t(),I(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=H(Y,[["__scopeId","data-v-d4d04859"]]);export{ke as default};

@ -1 +0,0 @@
import{_ as C}from"./post-skeleton-32ed3219.js";import{_ as N}from"./main-nav.vue_vue_type_style_index_0_lang-e2b1e404.js";import{u as z}from"./vuex-44de225f.js";import{b as A}from"./vue-router-e5a2430e.js";import{F as R,_ as S}from"./index-ac7904e2.js";import{F as V,Q as q,I,G as P}from"./naive-ui-609478ed.js";import{d as j,H as n,b as D,f as o,k as a,w as p,e as t,bf as u,Y as l,F as E,u as G,q as H,j as s,x as _,l as L}from"./@vue-a481fc63.js";import"./vooks-6d99783e.js";import"./evtd-b614532e.js";import"./@vicons-4ed09704.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 M={key:0,class:"pagination-wrap"},O={key:0,class:"skeleton-wrap"},Q={key:1},T={key:0,class:"empty-wrap"},U={class:"bill-line"},Y=j({__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 D(()=>{}),(m,J)=>{const k=N,y=q,x=C,w=I,F=P,B=V;return t(),o("div",null,[a(k,{title:"公告"}),a(B,{class:"main-content-wrap",bordered:""},{footer:p(()=>[c.value>1?(t(),o("div",M,[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",O,[a(x,{num:f.value},null,8,["num"])])):(t(),o("div",Q,[i.value.length===0?(t(),o("div",T,[a(w,{size:"large",description:"暂无数据"})])):l("",!0),(t(!0),o(E,null,G(i.value,e=>(t(),H(F,{key:e.id},{default:p(()=>[s("div",U,[s("div",null,"NO."+_(e.id),1),s("div",null,_(e.reason),1),s("div",{class:L({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(R)(e.created_on)),1)])]),_:2},1024))),128))]))]),_:1})])}}});const ke=S(Y,[["__scopeId","data-v-d4d04859"]]);export{ke as default};

@ -1 +1 @@
import{_ as I}from"./whisper-b4b61448.js";import{_ as N,a as V}from"./post-item.vue_vue_type_style_index_0_lang-60ae03c7.js";import{_ as W}from"./post-skeleton-32ed3219.js";import{_ as E}from"./main-nav.vue_vue_type_style_index_0_lang-e2b1e404.js";import{u as G}from"./vuex-44de225f.js";import{b as H}from"./vue-router-e5a2430e.js";import{R as L,_ as Q}from"./index-ac7904e2.js";import{d as T,H as s,b as U,f as o,k as n,w as u,bf as h,Y as w,e,F as k,u as y,q as C}from"./@vue-a481fc63.js";import{F as Y,Q as j,I as A,G as D}from"./naive-ui-609478ed.js";import"./content-3f086a36.js";import"./@vicons-4ed09704.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 J={key:0,class:"skeleton-wrap"},K={key:1},O={key:0,class:"empty-wrap"},X={key:1},Z={key:2},ee={key:0,class:"pagination-wrap"},oe=T({__name:"Collection",setup(te){const m=G(),S=H(),_=s(!1),i=s([]),l=s(+S.query.p||1),p=s(20),r=s(0),c=s(!1),d=s({id:0,avatar:"",username:"",nickname:"",is_admin:!1,is_friend:!0,is_following:!1,created_on:0,follows:0,followings:0,status:1}),f=t=>{d.value=t,c.value=!0},b=()=>{c.value=!1},v=()=>{_.value=!0,L({page:l.value,page_size:p.value}).then(t=>{_.value=!1,i.value=t.list,r.value=Math.ceil(t.pager.total_rows/p.value),window.scrollTo(0,0)}).catch(t=>{_.value=!1})},x=t=>{l.value=t,v()};return U(()=>{v()}),(t,ne)=>{const R=E,$=W,z=A,B=N,g=D,F=V,M=I,P=Y,q=j;return e(),o("div",null,[n(R,{title:"收藏"}),n(P,{class:"main-content-wrap",bordered:""},{default:u(()=>[_.value?(e(),o("div",J,[n($,{num:p.value},null,8,["num"])])):(e(),o("div",K,[i.value.length===0?(e(),o("div",O,[n(z,{size:"large",description:"暂无数据"})])):w("",!0),h(m).state.desktopModelShow?(e(),o("div",X,[(e(!0),o(k,null,y(i.value,a=>(e(),C(g,{key:a.id},{default:u(()=>[n(B,{post:a,onSendWhisper:f},null,8,["post"])]),_:2},1024))),128))])):(e(),o("div",Z,[(e(!0),o(k,null,y(i.value,a=>(e(),C(g,{key:a.id},{default:u(()=>[n(F,{post:a,onSendWhisper:f},null,8,["post"])]),_:2},1024))),128))]))])),n(M,{show:c.value,user:d.value,onSuccess:b},null,8,["show","user"])]),_:1}),r.value>0?(e(),o("div",ee,[n(q,{page:l.value,"onUpdate:page":x,"page-slot":h(m).state.collapsedRight?5:8,"page-count":r.value},null,8,["page","page-slot","page-count"])])):w("",!0)])}}});const Ne=Q(oe,[["__scopeId","data-v-760779af"]]);export{Ne as default};
import{_ as H}from"./whisper-7c8226c3.js";import{_ as N,a as V}from"./post-item.vue_vue_type_style_index_0_lang-1243f33f.js";import{_ as W}from"./post-skeleton-5d89319a.js";import{_ as E}from"./main-nav.vue_vue_type_style_index_0_lang-832ff0ed.js";import{u as G}from"./vuex-44de225f.js";import{b as I}from"./vue-router-e5a2430e.js";import{R as J,_ as L}from"./index-537a241d.js";import{d as T,H as s,b as U,f as o,k as n,w as u,bf as h,Y as w,e,F as k,u as y,q as C}from"./@vue-a481fc63.js";import{G as Y,R as j,J as A,H as D}from"./naive-ui-defd0b2d.js";import"./content-f21e8034.js";import"./@vicons-4ed09704.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 K={key:0,class:"skeleton-wrap"},O={key:1},Q={key:0,class:"empty-wrap"},X={key:1},Z={key:2},ee={key:0,class:"pagination-wrap"},oe=T({__name:"Collection",setup(te){const m=G(),S=I(),_=s(!1),i=s([]),l=s(+S.query.p||1),p=s(20),r=s(0),c=s(!1),d=s({id:0,avatar:"",username:"",nickname:"",is_admin:!1,is_friend:!0,is_following:!1,created_on:0,follows:0,followings:0,status:1}),f=t=>{d.value=t,c.value=!0},b=()=>{c.value=!1},v=()=>{_.value=!0,J({page:l.value,page_size:p.value}).then(t=>{_.value=!1,i.value=t.list,r.value=Math.ceil(t.pager.total_rows/p.value),window.scrollTo(0,0)}).catch(t=>{_.value=!1})},x=t=>{l.value=t,v()};return U(()=>{v()}),(t,ne)=>{const R=E,$=W,z=A,B=N,g=D,M=V,P=H,q=Y,F=j;return e(),o("div",null,[n(R,{title:"收藏"}),n(q,{class:"main-content-wrap",bordered:""},{default:u(()=>[_.value?(e(),o("div",K,[n($,{num:p.value},null,8,["num"])])):(e(),o("div",O,[i.value.length===0?(e(),o("div",Q,[n(z,{size:"large",description:"暂无数据"})])):w("",!0),h(m).state.desktopModelShow?(e(),o("div",X,[(e(!0),o(k,null,y(i.value,a=>(e(),C(g,{key:a.id},{default:u(()=>[n(B,{post:a,onSendWhisper:f},null,8,["post"])]),_:2},1024))),128))])):(e(),o("div",Z,[(e(!0),o(k,null,y(i.value,a=>(e(),C(g,{key:a.id},{default:u(()=>[n(M,{post:a,onSendWhisper:f},null,8,["post"])]),_:2},1024))),128))]))])),n(P,{show:c.value,user:d.value,onSuccess:b},null,8,["show","user"])]),_:1}),r.value>0?(e(),o("div",ee,[n(F,{page:l.value,"onUpdate:page":x,"page-slot":h(m).state.collapsedRight?5:8,"page-count":r.value},null,8,["page","page-slot","page-count"])])):w("",!0)])}}});const Ne=L(oe,[["__scopeId","data-v-760779af"]]);export{Ne as default};

@ -1 +1 @@
import{_ as T}from"./whisper-b4b61448.js";import{d as M,c as j,r as A,e as s,f as c,k as t,w as n,j as _,y as G,A as H,x as v,bf as g,h as I,H as a,b as U,Y as S,F as z,u as W,q as E}from"./@vue-a481fc63.js";import{G as L,_ as N,b as Q}from"./index-ac7904e2.js";import{k as Y,r as J}from"./@vicons-4ed09704.js";import{j as x,o as K,e as X,O as Z,M as ee,F as te,Q as ne,I as oe,G as se}from"./naive-ui-609478ed.js";import{_ as ae}from"./post-skeleton-32ed3219.js";import{_ as ce}from"./main-nav.vue_vue_type_style_index_0_lang-e2b1e404.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=M({__name:"contact-item",props:{contact:{}},emits:["send-whisper"],setup(C,{emit:h}){const i=C,r=e=>()=>I(x,null,{default:()=>I(e)}),l=j(()=>[{label:"私信",key:"whisper",icon:r(J)}]),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=K,d=A("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]=G(()=>{},["stop"])),class:"username-link",to:{name:"user",query:{s:e.contact.username}}},{default:n(()=>[H(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(L)(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=N(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=M({__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),Q({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,F=oe,P=ge,V=se,D=T,O=te,R=ne;return s(),c(z,null,[_("div",null,[t(q,{title:"好友"}),t(O,{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(F,{size:"large",description:"暂无数据"})])):S("",!0),(s(!0),c(z,null,W(l.value,b=>(s(),E(V,{class:"list-item",key:b.user_id},{default:n(()=>[t(P,{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(R,{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"])])):S("",!0)],64)}}});const Qe=N(Ce,[["__scopeId","data-v-e20fef94"]]);export{Qe as default};
import{_ as O}from"./whisper-7c8226c3.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 U,x as v,bf as g,h as I,H as a,b as W,Y as S,F as z,u as E,q as G}from"./@vue-a481fc63.js";import{I as J,_ as P,b as L}from"./index-537a241d.js";import{k as Y,r as K}from"./@vicons-4ed09704.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-5d89319a.js";import{_ as ce}from"./main-nav.vue_vue_type_style_index_0_lang-832ff0ed.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=>()=>I(x,null,{default:()=>I(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(()=>[U(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(J)(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,$()};W(()=>{$()});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(z,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:"暂无数据"})])):S("",!0),(s(!0),c(z,null,E(l.value,b=>(s(),G(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"])])):S("",!0)],64)}}});const Le=P(Ce,[["__scopeId","data-v-e20fef94"]]);export{Le as default};

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-b0cbbdc2]{color:#18a058;opacity:.8}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item[data-v-b0cbbdc2]{cursor:pointer}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-avatar[data-v-b0cbbdc2]{color:#18a058;opacity:.8}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-title[data-v-b0cbbdc2]{color:#18a058;opacity:.8}.tiny-slide-bar[data-v-b0cbbdc2]{margin-top:-30px;margin-bottom:-30px}.tiny-slide-bar .slide-bar-item[data-v-b0cbbdc2]{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-b0cbbdc2]{justify-content:center;font-size:12px;margin-top:4px;height:40px}.load-more[data-v-b0cbbdc2]{margin:20px}.load-more .load-more-wrap[data-v-b0cbbdc2]{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:14px}.load-more .load-more-wrap .load-more-spinner[data-v-b0cbbdc2]{font-size:14px;opacity:.65}.dark .main-content-wrap[data-v-b0cbbdc2],.dark .pagination-wrap[data-v-b0cbbdc2],.dark .empty-wrap[data-v-b0cbbdc2],.dark .skeleton-wrap[data-v-b0cbbdc2]{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-b0cbbdc2]{color:#63e2b7;opacity:.8}.dark .tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-title[data-v-b0cbbdc2]{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-aee71446]{color:#18a058;opacity:.8}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item[data-v-aee71446]{cursor:pointer}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-avatar[data-v-aee71446]{color:#18a058;opacity:.8}.tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-title[data-v-aee71446]{color:#18a058;opacity:.8}.tiny-slide-bar[data-v-aee71446]{margin-top:-30px;margin-bottom:-30px}.tiny-slide-bar .slide-bar-item[data-v-aee71446]{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-aee71446]{justify-content:center;font-size:12px;margin-top:4px;height:40px}.load-more[data-v-aee71446]{margin:20px}.load-more .load-more-wrap[data-v-aee71446]{display:flex;flex-direction:row;justify-content:center;align-items:center;gap:14px}.load-more .load-more-wrap .load-more-spinner[data-v-aee71446]{font-size:14px;opacity:.65}.dark .main-content-wrap[data-v-aee71446],.dark .pagination-wrap[data-v-aee71446],.dark .empty-wrap[data-v-aee71446],.dark .skeleton-wrap[data-v-aee71446]{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-aee71446]{color:#63e2b7;opacity:.8}.dark .tiny-slide-bar .tiny-slide-bar__list>div:hover .slide-bar-item .slide-bar-item-title[data-v-aee71446]{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

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

@ -1 +1 @@
import{B as $,C as I,D as M,E as O,_ as D}from"./index-ac7904e2.js";import{z as U}from"./@vicons-4ed09704.js";import{d as F,H as i,c as q,b as A,r as j,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 x,al as H,F as Y,u as G}from"./@vue-a481fc63.js";import{o as J,L as C,j as K,e as P,O as Q,M as R,F as W,f as X,g as Z,a as ee,k as oe}from"./naive-ui-609478ed.js";import{_ as te}from"./main-nav.vue_vue_type_style_index_0_lang-e2b1e404.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":M({topic_id:t.tag.id}).then(o=>{t.tag.is_following=1,window.$message.success("关注成功")}).catch(o=>{console.log(o)});break;case"unfollow":I({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=j("router-link"),g=J,k=C,a=K,d=P,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(U))]),_: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);x(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,O({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,L=C,V=Z,E=ie,N=ee,S=oe,z=W;return c(),_("div",null,[n(v,{title:"话题"}),n(z,{class:"main-content-wrap tags-wrap",bordered:""},{default:s(()=>[n(V,{type:"line",animated:"","onUpdate:value":k},H({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(L,{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),_(Y,null,G(r.value,y=>(c(),b(E,{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};
import{D as $,E as I,F as M,G as O,_ as D}from"./index-537a241d.js";import{z as G}from"./@vicons-4ed09704.js";import{d as F,H as i,c as q,b as A,r as U,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 j,al as x,F as H,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-832ff0ed.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":M({topic_id:t.tag.id}).then(o=>{t.tag.is_following=1,window.$message.success("关注成功")}).catch(o=>{console.log(o)});break;case"unfollow":I({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=U("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);j(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,O({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,z=W;return c(),_("div",null,[n(v,{title:"话题"}),n(z,{class:"main-content-wrap tags-wrap",bordered:""},{default:s(()=>[n(E,{type:"line",animated:"","onUpdate:value":k},x({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),_(H,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

@ -1 +1 @@
import{a8 as A}from"./index-ac7904e2.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-4ed09704.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-609478ed.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 _};
import{a8 as A}from"./index-537a241d.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-4ed09704.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

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{U as r}from"./naive-ui-609478ed.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-ac7904e2.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-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-537a241d.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 _};

@ -1 +1 @@
import{X as b,_ as k}from"./index-ac7904e2.js";import{R as B,H as C,S as N,b as R,e as U,i as V}from"./naive-ui-609478ed.js";import{d as $,H as p,e as z,q as H,w as s,j as a,k as n,A as _,x as i}from"./@vue-a481fc63.js";const S={class:"whisper-wrap"},W={class:"whisper-line"},j={class:"whisper-line send-wrap"},q=$({__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=B,w=C,f=N,v=R,g=U,y=V;return z(),H(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",S,[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",j,[n(g,{strong:"",secondary:"",type:"primary",loading:t.value,onClick:m},{default:s(()=>[_(" 发送 ")]),_:1},8,["loading"])])])]),_:1},8,["show"])}}});const M=k(q,[["__scopeId","data-v-0cbfe47c"]]);export{M as _};
import{X as b,_ as k}from"./index-537a241d.js";import{S as B,I as C,T as N,b as U,e as V,i as $}from"./naive-ui-defd0b2d.js";import{d as z,H as p,e as I,q as R,w as s,j as a,k as n,A as _,x as i}from"./@vue-a481fc63.js";const S={class:"whisper-wrap"},T={class:"whisper-line"},W={class:"whisper-line send-wrap"},j=z({__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=B,w=C,f=N,v=U,g=V,y=$;return I(),R(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",S,[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",T,[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",W,[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 _};

@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" />
<link rel="manifest" href="/manifest.json" />
<title></title>
<script type="module" crossorigin src="/assets/index-ac7904e2.js"></script>
<script type="module" crossorigin src="/assets/index-537a241d.js"></script>
<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/vuex-44de225f.js">
@ -26,7 +26,7 @@
<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/date-fns-975a2d8f.js">
<link rel="modulepreload" crossorigin href="/assets/naive-ui-609478ed.js">
<link rel="modulepreload" crossorigin href="/assets/naive-ui-defd0b2d.js">
<link rel="modulepreload" crossorigin href="/assets/moment-2ab8298d.js">
<link rel="modulepreload" crossorigin href="/assets/@vicons-4ed09704.js">
<link rel="stylesheet" href="/assets/index-c337d1db.css">

@ -145,6 +145,10 @@ import {
BookmarkOutline,
ChatboxOutline,
ShareSocialOutline,
PersonAddOutline,
PersonRemoveOutline,
BodyOutline,
WalkOutline,
} from '@vicons/ionicons5';
import { MoreHorizFilled } from '@vicons/material';
import copy from "copy-to-clipboard";
@ -153,10 +157,14 @@ const router = useRouter();
const store = useStore();
const props = withDefaults(defineProps<{
post: Item.PostProps,
isOwner: boolean,
addExtraAction: boolean,
}>(), {});
const emit = defineEmits<{
(e: 'send-whisper', user: Item.UserInfo): void;
(e: 'send-whisper', user: Item.UserInfo): void
(e: 'handle-follow-action', user: Item.PostProps): void
(e: 'handle-friend-action', user: Item.PostProps): void
}>();
const renderIcon = (icon: Component) => {
@ -182,6 +190,34 @@ const tweetOptions = computed(() => {
key: 'whisper',
icon: renderIcon(PaperPlaneOutline)
});
if (!props.isOwner && props.addExtraAction) {
if (props.post.user.is_following) {
options.push({
label: '',
key: 'unfollow',
icon: renderIcon(WalkOutline)
})
} else {
options.push({
label: '',
key: 'follow',
icon: renderIcon(BodyOutline)
})
}
// if (props.post.user.is_friend) {
// options.push({
// label: '删除好友',
// key: 'delete',
// icon: renderIcon(PersonRemoveOutline)
// });
// } else {
// options.push({
// label: '添加朋友',
// key: 'requesting',
// icon: renderIcon(PersonAddOutline)
// });
// }
}
options.push({
label: '',
key: 'copyTweetLink',
@ -191,7 +227,7 @@ const tweetOptions = computed(() => {
});
const handleTweetAction = async (
item: 'copyTweetLink' | 'whisper'
item: 'copyTweetLink' | 'whisper' | 'follow' | 'unfollow' | 'delete' | 'requesting'
) => {
switch (item) {
case 'copyTweetLink':
@ -201,6 +237,14 @@ const handleTweetAction = async (
case 'whisper':
emit('send-whisper', props.post.user);
break;
case 'delete':
case 'requesting':
emit('handle-friend-action', props.post);
break;
case 'follow':
case 'unfollow':
emit('handle-follow-action', props.post);
break;
default:
break;
}

@ -143,6 +143,10 @@ import {
BookmarkOutline,
ChatboxOutline,
ShareSocialOutline,
PersonAddOutline,
PersonRemoveOutline,
BodyOutline,
WalkOutline,
} from '@vicons/ionicons5';
import { MoreHorizFilled } from '@vicons/material';
import copy from "copy-to-clipboard";
@ -151,10 +155,14 @@ const router = useRouter();
const store = useStore();
const props = withDefaults(defineProps<{
post: Item.PostProps,
isOwner: boolean,
addExtraAction: boolean,
}>(), {});
const emit = defineEmits<{
(e: 'send-whisper', user: Item.UserInfo): void;
(e: 'send-whisper', user: Item.UserInfo): void
(e: 'handle-follow-action', user: Item.PostProps): void
(e: 'handle-friend-action', user: Item.PostProps): void
}>();
const renderIcon = (icon: Component) => {
@ -180,6 +188,34 @@ const tweetOptions = computed(() => {
key: 'whisper',
icon: renderIcon(PaperPlaneOutline)
});
if (!props.isOwner && props.addExtraAction) {
if (props.post.user.is_following) {
options.push({
label: '',
key: 'unfollow',
icon: renderIcon(WalkOutline)
})
} else {
options.push({
label: '',
key: 'follow',
icon: renderIcon(BodyOutline)
})
}
// if (props.post.user.is_friend) {
// options.push({
// label: '删除好友',
// key: 'delete',
// icon: renderIcon(PersonRemoveOutline)
// });
// } else {
// options.push({
// label: '添加朋友',
// key: 'requesting',
// icon: renderIcon(PersonAddOutline)
// });
// }
}
options.push({
label: '',
key: 'copyTweetLink',
@ -189,7 +225,7 @@ const tweetOptions = computed(() => {
});
const handleTweetAction = async (
item: 'copyTweetLink' | 'whisper'
item: 'copyTweetLink' | 'whisper' | 'follow' | 'unfollow' | 'delete' | 'requesting'
) => {
switch (item) {
case 'copyTweetLink':
@ -199,6 +235,14 @@ const handleTweetAction = async (
case 'whisper':
emit('send-whisper', props.post.user);
break;
case 'delete':
case 'requesting':
emit('handle-friend-action', props.post);
break;
case 'follow':
case 'unfollow':
emit('handle-follow-action', props.post);
break;
default:
break;
}

@ -40,17 +40,27 @@
</div>
<div v-if="store.state.desktopModelShow">
<n-list-item v-for="post in list" :key="post.id">
<post-item :post="post" @send-whisper="onSendWhisper" />
<post-item :post="post"
:isOwner="store.state.userInfo.Id === post.user_id"
:addExtraAction="true"
@send-whisper="onSendWhisper"
@handle-follow-action="onHandleFollowAction" />
</n-list-item>
</div>
<div v-else>
<n-list-item v-for="post in list" :key="post.id">
<mobile-post-item :post="post" @send-whisper="onSendWhisper" />
<mobile-post-item :post="post"
:isOwner="store.state.userInfo.Id === post.user_id"
:addExtraAction="true"
@send-whisper="onSendWhisper"
@handle-follow-action="onHandleFollowAction" />
</n-list-item>
</div>
</div>
<!-- -->
<whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" />
<!-- -->
<!-- <whisper-add-friend :show="showAddFriendWhisper" :user="user" @success="addFriendWhisperSuccess" /> -->
</n-list>
<n-space v-if="totalPage > 0" justify="center">
@ -67,12 +77,13 @@
</template>
<script setup lang="ts">
import { ref, onMounted, computed, watch } from 'vue';
import { ref, onMounted, reactive, computed, watch } from 'vue';
import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';
import { useDialog } from 'naive-ui';
import InfiniteLoading from "v3-infinite-loading";
import { getPosts, getContacts } from '@/api/post';
import { getUserPosts } from '@/api/user';
import { getUserPosts, deleteFriend, followUser, unfollowUser } from '@/api/user';
import SlideBar from '@opentiny/vue-slide-bar';
import allTweets from '@/assets/img/fresh-tweets.png';
import discoverTweets from '@/assets/img/discover-tweets.jpeg';
@ -83,6 +94,7 @@ const enableFriendsBar = (import.meta.env.VITE_ENABLE_FRIENDS_BAR.toLowerCase()
const store = useStore();
const route = useRoute();
const router = useRouter();
const dialog = useDialog();
const initBlocks = ref(9)
const wheelBlocks = ref(8)
@ -102,6 +114,20 @@ const slideBarList = ref<Item.SlideBarItem[]>([
{ title: '', style: 1, username: '', avatar: '', show: true },
{ title: '', style: 1, username: '', avatar: '', show: true }
]);
const user = reactive<Item.UserInfo>({
id: 0,
avatar: '',
username: '',
nickname: '',
is_admin: false,
is_friend: false,
is_following: false,
created_on: 0,
follows: 0,
followings: 0,
status: 1,
});
const inActionPost = ref<Item.PostProps | null>(null)
const title = ref<string>("泡泡广场")
const loading = ref(false);
@ -113,6 +139,7 @@ const page = ref(1);
const pageSize = ref(20);
const totalPage = ref(0);
const showWhisper = ref(false);
const showAddFriendWhisper = ref(false);
const whisperReceiver = ref<Item.UserInfo>({
id: 0,
avatar: '',
@ -136,6 +163,74 @@ const whisperSuccess = () => {
showWhisper.value = false;
};
const openAddFriendWhisper = () => {
showAddFriendWhisper.value = true;
};
const openDeleteFriend = (post: Item.PostProps) => {
dialog.warning({
title: '',
content: ' ' + post.user.nickname + ' / ',
positiveText: '',
negativeText: '',
onPositiveClick: () => {
deleteFriend({
user_id: user.id,
}).then((res) => {
window.$message.success('');
post.user.is_friend = false;
})
.catch((_err) => {});
},
});
};
const addFriendWhisperSuccess = () => {
showAddFriendWhisper.value = false;
inActionPost.value = null;
};
const onHandleFriendAction = (post: Item.PostProps) => {
inActionPost.value = post;
user.id = post.user.id;
user.username = post.user.username;
user.nickname = post.user.nickname;
if (post.user.is_friend) {
openDeleteFriend(post);
} else {
openAddFriendWhisper();
}
};
const onHandleFollowAction = (post: Item.PostProps) => {
dialog.success({
title: '',
content:
'' + (post.user.is_following ? '' : '') + '',
positiveText: '',
negativeText: '',
onPositiveClick: () => {
if (post.user.is_following) {
unfollowUser({
user_id: post.user.id,
}).then((_res) => {
window.$message.success('');
post.user.is_following = false;
})
.catch((_err) => {});
} else {
followUser({
user_id: post.user.id,
}).then((_res) => {
window.$message.success('');
post.user.is_following = true;
})
.catch((_err) => {});
}
},
});
};
const updateTitle = () => {
title.value = '广';
if (route.query && route.query.q) {

Loading…
Cancel
Save