From 5433eb9e8f02d313dd3e306d9274233c70b6f8ad Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 11 Nov 2022 13:45:24 +0800 Subject: [PATCH 01/65] prepare use mir --- Makefile | 5 + go.mod | 5 + internal/dao/jinzhu/dbr/attachment.go | 27 +++ internal/dao/jinzhu/dbr/captcha.go | 38 ++++ internal/dao/jinzhu/dbr/comment.go | 127 +++++++++++ internal/dao/jinzhu/dbr/comment_content.go | 59 +++++ internal/dao/jinzhu/dbr/comment_reply.go | 110 +++++++++ internal/dao/jinzhu/dbr/contact.go | 119 ++++++++++ internal/dao/jinzhu/dbr/dbr.go | 36 +++ internal/dao/jinzhu/dbr/message.go | 148 +++++++++++++ internal/dao/jinzhu/dbr/post.go | 208 ++++++++++++++++++ .../dao/jinzhu/dbr/post_attachment_bill.go | 36 +++ internal/dao/jinzhu/dbr/post_collection.go | 102 +++++++++ internal/dao/jinzhu/dbr/post_content.go | 121 ++++++++++ internal/dao/jinzhu/dbr/post_star.go | 98 +++++++++ internal/dao/jinzhu/dbr/tag.go | 97 ++++++++ internal/dao/jinzhu/dbr/user.go | 94 ++++++++ internal/dao/jinzhu/dbr/wallet_recharge.go | 34 +++ internal/dao/jinzhu/dbr/wallet_statement.go | 83 +++++++ internal/mirc/auto/api/v1/site.go | 144 ++++++++++++ internal/mirc/main.go | 24 ++ internal/mirc/routes/README.md | 1 + internal/mirc/routes/v1/localoss.go | 15 ++ internal/mirc/routes/v1/web_admin.go | 15 ++ internal/mirc/routes/v1/web_alipay.go | 15 ++ internal/mirc/routes/v1/web_core.go | 44 ++++ internal/mirc/routes/v1/web_followship.go | 15 ++ internal/mirc/routes/v1/web_friendship.go | 15 ++ internal/mirc/routes/v1/web_loose.go | 15 ++ internal/mirc/routes/v1/web_priv.go | 15 ++ internal/mirc/routes/v1/web_pub.go | 15 ++ internal/servants/chain/admin.go | 25 +++ internal/servants/chain/jwt.go | 113 ++++++++++ internal/servants/chain/priv.go | 45 ++++ internal/servants/core.go | 26 +++ internal/servants/localoss.go | 5 + internal/servants/servants.go | 12 + internal/servants/web_admin.go | 5 + internal/servants/web_alipay.go | 5 + internal/servants/web_core.go | 32 +++ internal/servants/web_followship.go | 5 + internal/servants/web_friendship.go | 5 + internal/servants/web_loose.go | 5 + internal/servants/web_priv.go | 5 + internal/servants/web_pub.go | 5 + 45 files changed, 2173 insertions(+) create mode 100644 internal/dao/jinzhu/dbr/attachment.go create mode 100644 internal/dao/jinzhu/dbr/captcha.go create mode 100644 internal/dao/jinzhu/dbr/comment.go create mode 100644 internal/dao/jinzhu/dbr/comment_content.go create mode 100644 internal/dao/jinzhu/dbr/comment_reply.go create mode 100644 internal/dao/jinzhu/dbr/contact.go create mode 100644 internal/dao/jinzhu/dbr/dbr.go create mode 100644 internal/dao/jinzhu/dbr/message.go create mode 100644 internal/dao/jinzhu/dbr/post.go create mode 100644 internal/dao/jinzhu/dbr/post_attachment_bill.go create mode 100644 internal/dao/jinzhu/dbr/post_collection.go create mode 100644 internal/dao/jinzhu/dbr/post_content.go create mode 100644 internal/dao/jinzhu/dbr/post_star.go create mode 100644 internal/dao/jinzhu/dbr/tag.go create mode 100644 internal/dao/jinzhu/dbr/user.go create mode 100644 internal/dao/jinzhu/dbr/wallet_recharge.go create mode 100644 internal/dao/jinzhu/dbr/wallet_statement.go create mode 100644 internal/mirc/auto/api/v1/site.go create mode 100644 internal/mirc/main.go create mode 100644 internal/mirc/routes/README.md create mode 100644 internal/mirc/routes/v1/localoss.go create mode 100644 internal/mirc/routes/v1/web_admin.go create mode 100644 internal/mirc/routes/v1/web_alipay.go create mode 100644 internal/mirc/routes/v1/web_core.go create mode 100644 internal/mirc/routes/v1/web_followship.go create mode 100644 internal/mirc/routes/v1/web_friendship.go create mode 100644 internal/mirc/routes/v1/web_loose.go create mode 100644 internal/mirc/routes/v1/web_priv.go create mode 100644 internal/mirc/routes/v1/web_pub.go create mode 100644 internal/servants/chain/admin.go create mode 100644 internal/servants/chain/jwt.go create mode 100644 internal/servants/chain/priv.go create mode 100644 internal/servants/core.go create mode 100644 internal/servants/localoss.go create mode 100644 internal/servants/servants.go create mode 100644 internal/servants/web_admin.go create mode 100644 internal/servants/web_alipay.go create mode 100644 internal/servants/web_core.go create mode 100644 internal/servants/web_followship.go create mode 100644 internal/servants/web_friendship.go create mode 100644 internal/servants/web_loose.go create mode 100644 internal/servants/web_priv.go create mode 100644 internal/servants/web_pub.go diff --git a/Makefile b/Makefile index 4d0b94a2..700e2d29 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,11 @@ windows-x64: @echo Build paopao-ce [windows-x64] CGO_ENABLED=$(CGO_ENABLED) @CGO_ENABLED=$(CGO_ENABLED) GOOS=windows GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/$(basename $(TARGET)).exe +.PHONY: generate +generate: + @go generate internal/mirc/main.go + @go fmt ./internal/mirc/... + clean: @go clean @find ./release -type f -exec rm -r {} + diff --git a/go.mod b/go.mod index 8f4c9435..8e3819e5 100644 --- a/go.mod +++ b/go.mod @@ -39,6 +39,7 @@ require ( gorm.io/plugin/dbresolver v1.1.0 gorm.io/plugin/soft_delete v1.1.0 modernc.org/sqlite v1.17.3 + github.com/alimy/mir/v3 v3.0.0 ) require ( @@ -131,3 +132,7 @@ require ( modernc.org/strutil v1.1.1 // indirect modernc.org/token v1.0.0 // indirect ) + +replace ( + github.com/alimy/mir/v3 => ../../alimy/mir +) \ No newline at end of file diff --git a/internal/dao/jinzhu/dbr/attachment.go b/internal/dao/jinzhu/dbr/attachment.go new file mode 100644 index 00000000..0c748b00 --- /dev/null +++ b/internal/dao/jinzhu/dbr/attachment.go @@ -0,0 +1,27 @@ +package model + +import "gorm.io/gorm" + +type AttachmentType int + +const ( + ATTACHMENT_TYPE_IMAGE AttachmentType = iota + 1 + ATTACHMENT_TYPE_VIDEO + ATTACHMENT_TYPE_OTHER +) + +type Attachment struct { + *Model + UserID int64 `json:"user_id"` + FileSize int64 `json:"file_size"` + ImgWidth int `json:"img_width"` + ImgHeight int `json:"img_height"` + Type AttachmentType `json:"type"` + Content string `json:"content"` +} + +func (a *Attachment) Create(db *gorm.DB) (*Attachment, error) { + err := db.Create(&a).Error + + return a, err +} diff --git a/internal/dao/jinzhu/dbr/captcha.go b/internal/dao/jinzhu/dbr/captcha.go new file mode 100644 index 00000000..210cc691 --- /dev/null +++ b/internal/dao/jinzhu/dbr/captcha.go @@ -0,0 +1,38 @@ +package model + +import "gorm.io/gorm" + +type Captcha struct { + *Model + Phone string `json:"phone"` + Captcha string `json:"captcha"` + UseTimes int `json:"use_times"` + ExpiredOn int64 `json:"expired_on"` +} + +func (c *Captcha) Create(db *gorm.DB) (*Captcha, error) { + err := db.Create(&c).Error + + return c, err +} + +func (c *Captcha) Update(db *gorm.DB) error { + return db.Model(&Captcha{}).Where("id = ? AND is_del = ?", c.Model.ID, 0).Save(c).Error +} + +func (c *Captcha) Get(db *gorm.DB) (*Captcha, error) { + var captcha Captcha + if c.Model != nil && c.ID > 0 { + db = db.Where("id = ? AND is_del = ?", c.ID, 0) + } + if c.Phone != "" { + db = db.Where("phone = ?", c.Phone) + } + + err := db.Last(&captcha).Error + if err != nil { + return &captcha, err + } + + return &captcha, nil +} diff --git a/internal/dao/jinzhu/dbr/comment.go b/internal/dao/jinzhu/dbr/comment.go new file mode 100644 index 00000000..72494b53 --- /dev/null +++ b/internal/dao/jinzhu/dbr/comment.go @@ -0,0 +1,127 @@ +package model + +import ( + "time" + + "gorm.io/gorm" +) + +type Comment struct { + *Model + PostID int64 `json:"post_id"` + UserID int64 `json:"user_id"` + IP string `json:"ip"` + IPLoc string `json:"ip_loc"` +} + +type CommentFormated struct { + ID int64 `json:"id"` + PostID int64 `json:"post_id"` + UserID int64 `json:"user_id"` + User *UserFormated `json:"user"` + Contents []*CommentContent `json:"contents"` + Replies []*CommentReplyFormated `json:"replies"` + IPLoc string `json:"ip_loc"` + CreatedOn int64 `json:"created_on"` + ModifiedOn int64 `json:"modified_on"` +} + +func (c *Comment) Format() *CommentFormated { + if c.Model == nil { + return &CommentFormated{} + } + return &CommentFormated{ + ID: c.Model.ID, + PostID: c.PostID, + UserID: c.UserID, + User: &UserFormated{}, + Contents: []*CommentContent{}, + Replies: []*CommentReplyFormated{}, + IPLoc: c.IPLoc, + CreatedOn: c.CreatedOn, + ModifiedOn: c.ModifiedOn, + } +} + +func (c *Comment) Get(db *gorm.DB) (*Comment, error) { + var comment Comment + if c.Model != nil && c.ID > 0 { + db = db.Where("id = ? AND is_del = ?", c.ID, 0) + } else { + return nil, gorm.ErrRecordNotFound + } + + err := db.First(&comment).Error + if err != nil { + return &comment, err + } + + return &comment, nil +} + +func (c *Comment) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*Comment, error) { + var comments []*Comment + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if c.PostID > 0 { + db = db.Where("id = ?", c.PostID) + } + + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&comments).Error; err != nil { + return nil, err + } + + return comments, nil +} + +func (c *Comment) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { + var count int64 + if c.PostID > 0 { + db = db.Where("post_id = ?", c.PostID) + } + for k, v := range *conditions { + if k != "ORDER" { + db = db.Where(k, v) + } + } + if err := db.Model(c).Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} + +func (c *Comment) Create(db *gorm.DB) (*Comment, error) { + err := db.Create(&c).Error + + return c, err +} + +func (c *Comment) Delete(db *gorm.DB) error { + return db.Model(c).Where("id = ?", c.Model.ID).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} + +func (c *Comment) CommentIdsByPostId(db *gorm.DB, postId int64) (ids []int64, err error) { + err = db.Model(c).Where("post_id = ?", postId).Select("id").Find(&ids).Error + return +} + +func (c *Comment) DeleteByPostId(db *gorm.DB, postId int64) error { + return db.Model(c).Where("post_id = ?", postId).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} diff --git a/internal/dao/jinzhu/dbr/comment_content.go b/internal/dao/jinzhu/dbr/comment_content.go new file mode 100644 index 00000000..b7d42dfd --- /dev/null +++ b/internal/dao/jinzhu/dbr/comment_content.go @@ -0,0 +1,59 @@ +package model + +import ( + "time" + + "gorm.io/gorm" +) + +type CommentContent struct { + *Model + CommentID int64 `json:"comment_id"` + UserID int64 `json:"user_id"` + Content string `json:"content"` + Type PostContentT `json:"type"` + Sort int64 `json:"sort"` +} + +func (c *CommentContent) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*CommentContent, error) { + var comments []*CommentContent + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if c.CommentID > 0 { + db = db.Where("id = ?", c.CommentID) + } + + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&comments).Error; err != nil { + return nil, err + } + + return comments, nil +} + +func (c *CommentContent) Create(db *gorm.DB) (*CommentContent, error) { + err := db.Create(&c).Error + + return c, err +} + +func (c *CommentContent) MediaContentsByCommentId(db *gorm.DB, commentIds []int64) (contents []string, err error) { + err = db.Model(c).Where("comment_id IN ? AND type = ?", commentIds, CONTENT_TYPE_IMAGE).Select("content").Find(&contents).Error + return +} + +func (c *CommentContent) DeleteByCommentIds(db *gorm.DB, commentIds []int64) error { + return db.Model(c).Where("comment_id IN ?", commentIds).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} diff --git a/internal/dao/jinzhu/dbr/comment_reply.go b/internal/dao/jinzhu/dbr/comment_reply.go new file mode 100644 index 00000000..fd22702f --- /dev/null +++ b/internal/dao/jinzhu/dbr/comment_reply.go @@ -0,0 +1,110 @@ +package model + +import ( + "time" + + "gorm.io/gorm" +) + +type CommentReply struct { + *Model + CommentID int64 `json:"comment_id"` + UserID int64 `json:"user_id"` + AtUserID int64 `json:"at_user_id"` + Content string `json:"content"` + IP string `json:"ip"` + IPLoc string `json:"ip_loc"` +} + +type CommentReplyFormated struct { + ID int64 `json:"id"` + CommentID int64 `json:"comment_id"` + UserID int64 `json:"user_id"` + User *UserFormated `json:"user"` + AtUserID int64 `json:"at_user_id"` + AtUser *UserFormated `json:"at_user"` + Content string `json:"content"` + IPLoc string `json:"ip_loc"` + CreatedOn int64 `json:"created_on"` + ModifiedOn int64 `json:"modified_on"` +} + +func (c *CommentReply) Format() *CommentReplyFormated { + if c.Model == nil { + return &CommentReplyFormated{} + } + + return &CommentReplyFormated{ + ID: c.ID, + CommentID: c.CommentID, + UserID: c.UserID, + User: &UserFormated{}, + AtUserID: c.AtUserID, + AtUser: &UserFormated{}, + Content: c.Content, + IPLoc: c.IPLoc, + CreatedOn: c.CreatedOn, + ModifiedOn: c.ModifiedOn, + } +} + +func (c *CommentReply) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*CommentReply, error) { + var comments []*CommentReply + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if c.CommentID > 0 { + db = db.Where("id = ?", c.CommentID) + } + + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&comments).Error; err != nil { + return nil, err + } + + return comments, nil +} + +func (c *CommentReply) Create(db *gorm.DB) (*CommentReply, error) { + err := db.Create(&c).Error + + return c, err +} + +func (c *CommentReply) Get(db *gorm.DB) (*CommentReply, error) { + var reply CommentReply + if c.Model != nil && c.ID > 0 { + db = db.Where("id = ? AND is_del = ?", c.ID, 0) + } else { + return nil, gorm.ErrRecordNotFound + } + + err := db.First(&reply).Error + if err != nil { + return &reply, err + } + + return &reply, nil +} + +func (c *CommentReply) Delete(db *gorm.DB) error { + return db.Model(&CommentReply{}).Where("id = ? AND is_del = ?", c.Model.ID, 0).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} + +func (c *CommentReply) DeleteByCommentIds(db *gorm.DB, commentIds []int64) error { + return db.Model(c).Where("comment_id IN ?", commentIds).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} diff --git a/internal/dao/jinzhu/dbr/contact.go b/internal/dao/jinzhu/dbr/contact.go new file mode 100644 index 00000000..14049f77 --- /dev/null +++ b/internal/dao/jinzhu/dbr/contact.go @@ -0,0 +1,119 @@ +package model + +import ( + "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +const ( + ContactStatusRequesting int8 = iota + 1 + ContactStatusAgree + ContactStatusReject + ContactStatusDeleted +) + +type Contact struct { + *Model + User *User `json:"-" gorm:"foreignKey:ID;references:FriendId"` + UserId int64 `json:"user_id"` + FriendId int64 `json:"friend_id"` + GroupId int64 `json:"group_id"` + Remark string `json:"remark"` + Status int8 `json:"status"` // 1请求好友, 2已同意好友, 3已拒绝好友, 4已删除好友 + IsTop int8 `json:"is_top"` + IsBlack int8 `json:"is_black"` + NoticeEnable int8 `json:"notice_enable"` +} + +func (c *Contact) FetchUser(db *gorm.DB) (*Contact, error) { + var contact Contact + err := db.Omit("User").Unscoped().Where("user_id = ? AND friend_id = ?", c.UserId, c.FriendId).First(&contact).Error + if err != nil { + logrus.Debugf("Contact.FetchUser fetch user error:%s", err) + return nil, err + } + return &contact, nil +} + +func (c *Contact) GetByUserFriend(db *gorm.DB) (*Contact, error) { + var contact Contact + err := db.Omit("User").Where("user_id = ? AND friend_id = ?", c.UserId, c.FriendId).First(&contact).Error + if err != nil { + return nil, err + } + return &contact, nil +} + +func (c *Contact) FetchByUserFriendAll(db *gorm.DB) ([]*Contact, error) { + var contacts []*Contact + if err := db.Omit("User"). + Where("(user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)", + c.UserId, c.FriendId, c.FriendId, c.UserId). + Find(&contacts).Error; err != nil { + return nil, err + } + return contacts, nil +} + +func (c *Contact) List(db *gorm.DB, conditions ConditionsT, offset, limit int) ([]*Contact, error) { + var contacts []*Contact + var err error + tn := db.NamingStrategy.TableName("Contact") + "." + + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + for k, v := range conditions { + if k != "ORDER" { + db = db.Where(tn+k, v) + } + } + + db.Joins("User").Order("`User`.`nickname` ASC") + if err = db.Find(&contacts).Error; err != nil { + return nil, err + } + return contacts, nil +} + +func (c *Contact) BeFriendIds(db *gorm.DB) (ids []int64, err error) { + if err = db.Model(c).Omit("User").Select("user_id").Where("friend_id = ? AND status = ?", c.FriendId, ContactStatusAgree).Find(&ids).Error; err != nil { + return nil, err + } + return +} + +func (c *Contact) MyFriendIds(db *gorm.DB) (ids []string, err error) { + if err = db.Model(c).Omit("User").Select("friend_id").Where("user_id = ? AND status = ?", c.UserId, ContactStatusAgree).Find(&ids).Error; err != nil { + return nil, err + } + return +} + +func (m *Contact) Count(db *gorm.DB, conditions ConditionsT) (int64, error) { + var count int64 + + for k, v := range conditions { + if k != "ORDER" { + db = db.Where(k, v) + } + } + if err := db.Model(m).Omit("User").Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} + +func (c *Contact) Create(db *gorm.DB) (*Contact, error) { + err := db.Omit("User").Create(&c).Error + return c, err +} + +func (c *Contact) Update(db *gorm.DB) error { + return db.Model(&Contact{}).Omit("User").Where("id = ?", c.Model.ID).Save(c).Error +} + +func (c *Contact) UpdateInUnscoped(db *gorm.DB) error { + return db.Unscoped().Omit("User").Save(c).Error +} diff --git a/internal/dao/jinzhu/dbr/dbr.go b/internal/dao/jinzhu/dbr/dbr.go new file mode 100644 index 00000000..99bc8296 --- /dev/null +++ b/internal/dao/jinzhu/dbr/dbr.go @@ -0,0 +1,36 @@ +package model + +import ( + "time" + + "gorm.io/gorm" + "gorm.io/plugin/soft_delete" +) + +// Model 公共Model +type Model struct { + ID int64 `gorm:"primary_key" json:"id"` + CreatedOn int64 `json:"created_on"` + ModifiedOn int64 `json:"modified_on"` + DeletedOn int64 `json:"deleted_on"` + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag" json:"is_del"` +} + +type ConditionsT map[string]any +type Predicates map[string][]any + +func (m *Model) BeforeCreate(tx *gorm.DB) (err error) { + nowTime := time.Now().Unix() + + tx.Statement.SetColumn("created_on", nowTime) + tx.Statement.SetColumn("modified_on", nowTime) + return +} + +func (m *Model) BeforeUpdate(tx *gorm.DB) (err error) { + if !tx.Statement.Changed("modified_on") { + tx.Statement.SetColumn("modified_on", time.Now().Unix()) + } + + return +} diff --git a/internal/dao/jinzhu/dbr/message.go b/internal/dao/jinzhu/dbr/message.go new file mode 100644 index 00000000..c1277cf7 --- /dev/null +++ b/internal/dao/jinzhu/dbr/message.go @@ -0,0 +1,148 @@ +package model + +import "gorm.io/gorm" + +type MessageT int8 + +const ( + MsgTypePost MessageT = iota + 1 + MsgtypeComment + MsgTypeReply + MsgTypeWhisper + MsgTypeRequestingFriend + MsgTypeSystem MessageT = 99 + + MsgStatusUnread = 0 + MsgStatusReaded = 1 +) + +type Message struct { + *Model + SenderUserID int64 `json:"sender_user_id"` + ReceiverUserID int64 `json:"receiver_user_id"` + Type MessageT `json:"type"` + Brief string `json:"brief"` + Content string `json:"content"` + PostID int64 `json:"post_id"` + CommentID int64 `json:"comment_id"` + ReplyID int64 `json:"reply_id"` + IsRead int8 `json:"is_read"` +} + +type MessageFormated struct { + ID int64 `json:"id"` + SenderUserID int64 `json:"sender_user_id"` + SenderUser *UserFormated `json:"sender_user"` + ReceiverUserID int64 `json:"receiver_user_id"` + Type MessageT `json:"type"` + Brief string `json:"brief"` + Content string `json:"content"` + PostID int64 `json:"post_id"` + Post *PostFormated `json:"post"` + CommentID int64 `json:"comment_id"` + Comment *Comment `json:"comment"` + ReplyID int64 `json:"reply_id"` + Reply *CommentReply `json:"reply"` + IsRead int8 `json:"is_read"` + CreatedOn int64 `json:"created_on"` + ModifiedOn int64 `json:"modified_on"` +} + +func (m *Message) Format() *MessageFormated { + if m.Model == nil || m.Model.ID == 0 { + return nil + } + mf := &MessageFormated{ + ID: m.ID, + SenderUserID: m.SenderUserID, + SenderUser: &UserFormated{}, + ReceiverUserID: m.ReceiverUserID, + Type: m.Type, + Brief: m.Brief, + Content: m.Content, + PostID: m.PostID, + Post: &PostFormated{}, + CommentID: m.CommentID, + Comment: &Comment{}, + ReplyID: m.ReplyID, + Reply: &CommentReply{}, + IsRead: m.IsRead, + CreatedOn: m.CreatedOn, + ModifiedOn: m.ModifiedOn, + } + + return mf +} + +func (m *Message) Create(db *gorm.DB) (*Message, error) { + err := db.Create(&m).Error + + return m, err +} + +func (m *Message) Update(db *gorm.DB) error { + return db.Model(&Message{}).Where("id = ? AND is_del = ?", m.Model.ID, 0).Save(m).Error +} + +func (m *Message) Get(db *gorm.DB) (*Message, error) { + var message Message + if m.Model != nil && m.ID > 0 { + db = db.Where("id = ? AND is_del = ?", m.ID, 0) + } + if m.ReceiverUserID > 0 { + db = db.Where("receiver_user_id = ?", m.ReceiverUserID) + } + if err := db.First(&message).Error; err != nil { + return nil, err + } + return &message, nil +} + +func (m *Message) FetchBy(db *gorm.DB, predicates Predicates) ([]*Message, error) { + var messages []*Message + for k, v := range predicates { + db = db.Where(k, v...) + } + db = db.Where("is_del = 0") + if err := db.Find(&messages).Error; err != nil { + return nil, err + } + return messages, nil +} + +func (c *Message) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*Message, error) { + var messages []*Message + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&messages).Error; err != nil { + return nil, err + } + + return messages, nil +} + +func (m *Message) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { + var count int64 + + for k, v := range *conditions { + if k != "ORDER" { + db = db.Where(k, v) + } + } + if err := db.Model(m).Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} diff --git a/internal/dao/jinzhu/dbr/post.go b/internal/dao/jinzhu/dbr/post.go new file mode 100644 index 00000000..ae428a9a --- /dev/null +++ b/internal/dao/jinzhu/dbr/post.go @@ -0,0 +1,208 @@ +package model + +import ( + "strings" + "time" + + "gorm.io/gorm" +) + +// PostVisibleT 可访问类型,0公开,1私密,2好友 +type PostVisibleT uint8 + +const ( + PostVisitPublic PostVisibleT = iota + PostVisitPrivate + PostVisitFriend + PostVisitInvalid +) + +type Post struct { + *Model + UserID int64 `json:"user_id"` + CommentCount int64 `json:"comment_count"` + CollectionCount int64 `json:"collection_count"` + UpvoteCount int64 `json:"upvote_count"` + Visibility PostVisibleT `json:"visibility"` + IsTop int `json:"is_top"` + IsEssence int `json:"is_essence"` + IsLock int `json:"is_lock"` + LatestRepliedOn int64 `json:"latest_replied_on"` + Tags string `json:"tags"` + AttachmentPrice int64 `json:"attachment_price"` + IP string `json:"ip"` + IPLoc string `json:"ip_loc"` +} + +type PostFormated struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + User *UserFormated `json:"user"` + Contents []*PostContentFormated `json:"contents"` + CommentCount int64 `json:"comment_count"` + CollectionCount int64 `json:"collection_count"` + UpvoteCount int64 `json:"upvote_count"` + Visibility PostVisibleT `json:"visibility"` + IsTop int `json:"is_top"` + IsEssence int `json:"is_essence"` + IsLock int `json:"is_lock"` + LatestRepliedOn int64 `json:"latest_replied_on"` + CreatedOn int64 `json:"created_on"` + ModifiedOn int64 `json:"modified_on"` + Tags map[string]int8 `json:"tags"` + AttachmentPrice int64 `json:"attachment_price"` + IPLoc string `json:"ip_loc"` +} + +func (p *Post) Format() *PostFormated { + if p.Model != nil { + tagsMap := map[string]int8{} + for _, tag := range strings.Split(p.Tags, ",") { + tagsMap[tag] = 1 + } + return &PostFormated{ + ID: p.ID, + UserID: p.UserID, + User: &UserFormated{}, + Contents: []*PostContentFormated{}, + CommentCount: p.CommentCount, + CollectionCount: p.CollectionCount, + UpvoteCount: p.UpvoteCount, + Visibility: p.Visibility, + IsTop: p.IsTop, + IsEssence: p.IsEssence, + IsLock: p.IsLock, + LatestRepliedOn: p.LatestRepliedOn, + CreatedOn: p.CreatedOn, + ModifiedOn: p.ModifiedOn, + AttachmentPrice: p.AttachmentPrice, + Tags: tagsMap, + IPLoc: p.IPLoc, + } + } + + return nil +} + +func (p *Post) Create(db *gorm.DB) (*Post, error) { + err := db.Create(&p).Error + + return p, err +} + +func (s *Post) Delete(db *gorm.DB) error { + return db.Model(s).Where("id = ?", s.Model.ID).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} + +func (p *Post) Get(db *gorm.DB) (*Post, error) { + var post Post + if p.Model != nil && p.ID > 0 { + db = db.Where("id = ? AND is_del = ?", p.ID, 0) + } else { + return nil, gorm.ErrRecordNotFound + } + + err := db.First(&post).Error + if err != nil { + return &post, err + } + + return &post, nil +} + +func (p *Post) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*Post, error) { + var posts []*Post + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if p.UserID > 0 { + db = db.Where("user_id = ?", p.UserID) + } + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&posts).Error; err != nil { + return nil, err + } + + return posts, nil +} + +func (p *Post) Fetch(db *gorm.DB, predicates Predicates, offset, limit int) ([]*Post, error) { + var posts []*Post + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if p.UserID > 0 { + db = db.Where("user_id = ?", p.UserID) + } + for query, args := range predicates { + if query == "ORDER" { + db = db.Order(args[0]) + } else { + db = db.Where(query, args...) + } + } + + if err = db.Where("is_del = ?", 0).Find(&posts).Error; err != nil { + return nil, err + } + + return posts, nil +} + +func (p *Post) CountBy(db *gorm.DB, predicates Predicates) (count int64, err error) { + for query, args := range predicates { + if query != "ORDER" { + db = db.Where(query, args...) + } + } + err = db.Model(p).Count(&count).Error + return +} + +func (p *Post) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { + var count int64 + if p.UserID > 0 { + db = db.Where("user_id = ?", p.UserID) + } + for k, v := range *conditions { + if k != "ORDER" { + db = db.Where(k, v) + } + } + if err := db.Model(p).Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} + +func (p *Post) Update(db *gorm.DB) error { + return db.Model(&Post{}).Where("id = ? AND is_del = ?", p.Model.ID, 0).Save(p).Error +} + +func (p PostVisibleT) String() string { + switch p { + case PostVisitPublic: + return "public" + case PostVisitPrivate: + return "private" + case PostVisitFriend: + return "friend" + case PostVisitInvalid: + return "invalid" + default: + return "unknow" + } +} diff --git a/internal/dao/jinzhu/dbr/post_attachment_bill.go b/internal/dao/jinzhu/dbr/post_attachment_bill.go new file mode 100644 index 00000000..8ee7aae6 --- /dev/null +++ b/internal/dao/jinzhu/dbr/post_attachment_bill.go @@ -0,0 +1,36 @@ +package model + +import "gorm.io/gorm" + +type PostAttachmentBill struct { + *Model + PostID int64 `json:"post_id"` + UserID int64 `json:"user_id"` + PaidAmount int64 `json:"paid_amount"` +} + +func (p *PostAttachmentBill) Get(db *gorm.DB) (*PostAttachmentBill, error) { + var pas PostAttachmentBill + if p.Model != nil && p.ID > 0 { + db = db.Where("id = ? AND is_del = ?", p.ID, 0) + } + if p.PostID > 0 { + db = db.Where("post_id = ?", p.PostID) + } + if p.UserID > 0 { + db = db.Where("user_id = ?", p.UserID) + } + + err := db.First(&pas).Error + if err != nil { + return &pas, err + } + + return &pas, nil +} + +func (p *PostAttachmentBill) Create(db *gorm.DB) (*PostAttachmentBill, error) { + err := db.Create(&p).Error + + return p, err +} diff --git a/internal/dao/jinzhu/dbr/post_collection.go b/internal/dao/jinzhu/dbr/post_collection.go new file mode 100644 index 00000000..0ea0cb29 --- /dev/null +++ b/internal/dao/jinzhu/dbr/post_collection.go @@ -0,0 +1,102 @@ +package model + +import ( + "time" + + "gorm.io/gorm" +) + +type PostCollection struct { + *Model + Post *Post `json:"-"` + PostID int64 `json:"post_id"` + UserID int64 `json:"user_id"` +} + +func (p *PostCollection) Get(db *gorm.DB) (*PostCollection, error) { + var star PostCollection + tn := db.NamingStrategy.TableName("PostCollection") + "." + + if p.Model != nil && p.ID > 0 { + db = db.Where(tn+"id = ? AND "+tn+"is_del = ?", p.ID, 0) + } + if p.PostID > 0 { + db = db.Where(tn+"post_id = ?", p.PostID) + } + if p.UserID > 0 { + db = db.Where(tn+"user_id = ?", p.UserID) + } + + db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate).Order("Post.id DESC") + err := db.First(&star).Error + if err != nil { + return &star, err + } + + return &star, nil +} + +func (p *PostCollection) Create(db *gorm.DB) (*PostCollection, error) { + err := db.Omit("Post").Create(&p).Error + + return p, err +} + +func (p *PostCollection) Delete(db *gorm.DB) error { + return db.Model(&PostCollection{}).Omit("Post").Where("id = ? AND is_del = ?", p.Model.ID, 0).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} + +func (p *PostCollection) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*PostCollection, error) { + var collections []*PostCollection + var err error + tn := db.NamingStrategy.TableName("PostCollection") + "." + + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if p.UserID > 0 { + db = db.Where(tn+"user_id = ?", p.UserID) + } + + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(tn+k, v) + } + } + + db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate).Order("Post.id DESC") + if err = db.Where(tn+"is_del = ?", 0).Find(&collections).Error; err != nil { + return nil, err + } + + return collections, nil +} + +func (p *PostCollection) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { + var count int64 + tn := db.NamingStrategy.TableName("PostCollection") + "." + + if p.PostID > 0 { + db = db.Where(tn+"post_id = ?", p.PostID) + } + if p.UserID > 0 { + db = db.Where(tn+"user_id = ?", p.UserID) + } + for k, v := range *conditions { + if k != "ORDER" { + db = db.Where(tn+k, v) + } + } + + db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate) + if err := db.Model(p).Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} diff --git a/internal/dao/jinzhu/dbr/post_content.go b/internal/dao/jinzhu/dbr/post_content.go new file mode 100644 index 00000000..b301de62 --- /dev/null +++ b/internal/dao/jinzhu/dbr/post_content.go @@ -0,0 +1,121 @@ +package model + +import ( + "time" + + "gorm.io/gorm" +) + +// 类型,1标题,2文字段落,3图片地址,4视频地址,5语音地址,6链接地址,7附件资源 + +type PostContentT int + +const ( + CONTENT_TYPE_TITLE PostContentT = iota + 1 + CONTENT_TYPE_TEXT + CONTENT_TYPE_IMAGE + CONTENT_TYPE_VIDEO + CONTENT_TYPE_AUDIO + CONTENT_TYPE_LINK + CONTENT_TYPE_ATTACHMENT + CONTENT_TYPE_CHARGE_ATTACHMENT +) + +var ( + mediaContentType = []PostContentT{ + CONTENT_TYPE_IMAGE, + CONTENT_TYPE_VIDEO, + CONTENT_TYPE_AUDIO, + CONTENT_TYPE_ATTACHMENT, + CONTENT_TYPE_CHARGE_ATTACHMENT, + } +) + +type PostContent struct { + *Model + PostID int64 `json:"post_id"` + UserID int64 `json:"user_id"` + Content string `json:"content"` + Type PostContentT `json:"type"` + Sort int64 `json:"sort"` +} + +type PostContentFormated struct { + ID int64 `json:"id"` + PostID int64 `json:"post_id"` + Content string `json:"content"` + Type PostContentT `json:"type"` + Sort int64 `json:"sort"` +} + +func (p *PostContent) DeleteByPostId(db *gorm.DB, postId int64) error { + return db.Model(p).Where("post_id = ?", postId).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} + +func (p *PostContent) MediaContentsByPostId(db *gorm.DB, postId int64) (contents []string, err error) { + err = db.Model(p).Where("post_id = ? AND type IN ?", postId, mediaContentType).Select("content").Find(&contents).Error + return +} + +func (p *PostContent) Create(db *gorm.DB) (*PostContent, error) { + err := db.Create(&p).Error + + return p, err +} + +func (p *PostContent) Format() *PostContentFormated { + if p.Model == nil { + return nil + } + return &PostContentFormated{ + ID: p.ID, + PostID: p.PostID, + Content: p.Content, + Type: p.Type, + Sort: p.Sort, + } +} + +func (p *PostContent) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*PostContent, error) { + var contents []*PostContent + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if p.PostID > 0 { + db = db.Where("id = ?", p.PostID) + } + + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&contents).Error; err != nil { + return nil, err + } + + return contents, nil +} + +func (p *PostContent) Get(db *gorm.DB) (*PostContent, error) { + var content PostContent + if p.Model != nil && p.ID > 0 { + db = db.Where("id = ? AND is_del = ?", p.ID, 0) + } else { + return nil, gorm.ErrRecordNotFound + } + + err := db.First(&content).Error + if err != nil { + return &content, err + } + + return &content, nil +} diff --git a/internal/dao/jinzhu/dbr/post_star.go b/internal/dao/jinzhu/dbr/post_star.go new file mode 100644 index 00000000..3846a9c2 --- /dev/null +++ b/internal/dao/jinzhu/dbr/post_star.go @@ -0,0 +1,98 @@ +package model + +import ( + "time" + + "gorm.io/gorm" +) + +type PostStar struct { + *Model + Post *Post `json:"-"` + PostID int64 `json:"post_id"` + UserID int64 `json:"user_id"` +} + +func (p *PostStar) Get(db *gorm.DB) (*PostStar, error) { + var star PostStar + tn := db.NamingStrategy.TableName("PostStar") + "." + + if p.Model != nil && p.ID > 0 { + db = db.Where(tn+"id = ? AND "+tn+"is_del = ?", p.ID, 0) + } + if p.PostID > 0 { + db = db.Where(tn+"post_id = ?", p.PostID) + } + if p.UserID > 0 { + db = db.Where(tn+"user_id = ?", p.UserID) + } + + db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate).Order("Post.id DESC") + if err := db.First(&star).Error; err != nil { + return nil, err + } + return &star, nil +} + +func (p *PostStar) Create(db *gorm.DB) (*PostStar, error) { + err := db.Omit("Post").Create(&p).Error + + return p, err +} + +func (p *PostStar) Delete(db *gorm.DB) error { + return db.Model(&PostStar{}).Omit("Post").Where("id = ? AND is_del = ?", p.Model.ID, 0).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} + +func (p *PostStar) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*PostStar, error) { + var stars []*PostStar + var err error + tn := db.NamingStrategy.TableName("PostStar") + "." + + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if p.UserID > 0 { + db = db.Where(tn+"user_id = ?", p.UserID) + } + + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(tn+k, v) + } + } + + db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate).Order("Post.id DESC") + if err = db.Find(&stars).Error; err != nil { + return nil, err + } + return stars, nil +} + +func (p *PostStar) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { + var count int64 + tn := db.NamingStrategy.TableName("PostStar") + "." + + if p.PostID > 0 { + db = db.Where(tn+"post_id = ?", p.PostID) + } + if p.UserID > 0 { + db = db.Where(tn+"user_id = ?", p.UserID) + } + for k, v := range *conditions { + if k != "ORDER" { + db = db.Where(tn+k, v) + } + } + + db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate) + if err := db.Model(p).Count(&count).Error; err != nil { + return 0, err + } + return count, nil +} diff --git a/internal/dao/jinzhu/dbr/tag.go b/internal/dao/jinzhu/dbr/tag.go new file mode 100644 index 00000000..34bb64f9 --- /dev/null +++ b/internal/dao/jinzhu/dbr/tag.go @@ -0,0 +1,97 @@ +package model + +import ( + "time" + + "gorm.io/gorm" +) + +type Tag struct { + *Model + UserID int64 `json:"user_id"` + Tag string `json:"tag"` + QuoteNum int64 `json:"quote_num"` +} +type TagFormated struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + User *UserFormated `json:"user"` + Tag string `json:"tag"` + QuoteNum int64 `json:"quote_num"` +} + +func (t *Tag) Format() *TagFormated { + if t.Model == nil { + return &TagFormated{} + } + + return &TagFormated{ + ID: t.ID, + UserID: t.UserID, + User: &UserFormated{}, + Tag: t.Tag, + QuoteNum: t.QuoteNum, + } +} + +func (t *Tag) Get(db *gorm.DB) (*Tag, error) { + var tag Tag + if t.Model != nil && t.Model.ID > 0 { + db = db.Where("id= ? AND is_del = ?", t.Model.ID, 0) + } else { + db = db.Where("tag = ? AND is_del = ?", t.Tag, 0) + } + + err := db.First(&tag).Error + if err != nil { + return &tag, err + } + + return &tag, nil +} + +func (t *Tag) Create(db *gorm.DB) (*Tag, error) { + err := db.Create(&t).Error + + return t, err +} + +func (t *Tag) Update(db *gorm.DB) error { + return db.Model(&Tag{}).Where("id = ? AND is_del = ?", t.Model.ID, 0).Save(t).Error +} + +func (t *Tag) Delete(db *gorm.DB) error { + return db.Model(t).Where("id = ?", t.Model.ID).Updates(map[string]any{ + "deleted_on": time.Now().Unix(), + "is_del": 1, + }).Error +} + +func (t *Tag) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*Tag, error) { + var tags []*Tag + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if t.UserID > 0 { + db = db.Where("user_id = ?", t.UserID) + } + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&tags).Error; err != nil { + return nil, err + } + + return tags, nil +} + +func (t *Tag) TagsFrom(db *gorm.DB, tags []string) (res []*Tag, err error) { + err = db.Where("tag IN ?", tags).Find(&res).Error + return +} diff --git a/internal/dao/jinzhu/dbr/user.go b/internal/dao/jinzhu/dbr/user.go new file mode 100644 index 00000000..39c52d79 --- /dev/null +++ b/internal/dao/jinzhu/dbr/user.go @@ -0,0 +1,94 @@ +package model + +import "gorm.io/gorm" + +const ( + UserStatusNormal int = iota + 1 + UserStatusClosed +) + +type User struct { + *Model + Nickname string `json:"nickname"` + Username string `json:"username"` + Phone string `json:"phone"` + Password string `json:"password"` + Salt string `json:"salt"` + Status int `json:"status"` + Avatar string `json:"avatar"` + Balance int64 `json:"balance"` + IsAdmin bool `json:"is_admin"` +} + +type UserFormated struct { + ID int64 `json:"id"` + Nickname string `json:"nickname"` + Username string `json:"username"` + Status int `json:"status"` + Avatar string `json:"avatar"` + IsAdmin bool `json:"is_admin"` +} + +func (u *User) Format() *UserFormated { + if u.Model != nil { + return &UserFormated{ + ID: u.ID, + Nickname: u.Nickname, + Username: u.Username, + Status: u.Status, + Avatar: u.Avatar, + IsAdmin: u.IsAdmin, + } + } + + return nil +} + +func (u *User) Get(db *gorm.DB) (*User, error) { + var user User + if u.Model != nil && u.Model.ID > 0 { + db = db.Where("id= ? AND is_del = ?", u.Model.ID, 0) + } else if u.Phone != "" { + db = db.Where("phone = ? AND is_del = ?", u.Phone, 0) + } else { + db = db.Where("username = ? AND is_del = ?", u.Username, 0) + } + + err := db.First(&user).Error + if err != nil { + return &user, err + } + + return &user, nil +} + +func (u *User) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*User, error) { + var users []*User + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&users).Error; err != nil { + return nil, err + } + + return users, nil +} + +func (u *User) Create(db *gorm.DB) (*User, error) { + err := db.Create(&u).Error + + return u, err +} + +func (u *User) Update(db *gorm.DB) error { + return db.Model(&User{}).Where("id = ? AND is_del = ?", u.Model.ID, 0).Save(u).Error +} diff --git a/internal/dao/jinzhu/dbr/wallet_recharge.go b/internal/dao/jinzhu/dbr/wallet_recharge.go new file mode 100644 index 00000000..bfb3bc6f --- /dev/null +++ b/internal/dao/jinzhu/dbr/wallet_recharge.go @@ -0,0 +1,34 @@ +package model + +import "gorm.io/gorm" + +type WalletRecharge struct { + *Model + UserID int64 `json:"user_id"` + Amount int64 `json:"amount"` + TradeNo string `json:"trade_no"` + TradeStatus string `json:"trade_status"` +} + +func (p *WalletRecharge) Get(db *gorm.DB) (*WalletRecharge, error) { + var pas WalletRecharge + if p.Model != nil && p.ID > 0 { + db = db.Where("id = ? AND is_del = ?", p.ID, 0) + } + if p.UserID > 0 { + db = db.Where("user_id = ?", p.UserID) + } + + err := db.First(&pas).Error + if err != nil { + return &pas, err + } + + return &pas, nil +} + +func (p *WalletRecharge) Create(db *gorm.DB) (*WalletRecharge, error) { + err := db.Create(&p).Error + + return p, err +} diff --git a/internal/dao/jinzhu/dbr/wallet_statement.go b/internal/dao/jinzhu/dbr/wallet_statement.go new file mode 100644 index 00000000..163e2430 --- /dev/null +++ b/internal/dao/jinzhu/dbr/wallet_statement.go @@ -0,0 +1,83 @@ +package model + +import "gorm.io/gorm" + +type WalletStatement struct { + *Model + UserID int64 `json:"user_id"` + ChangeAmount int64 `json:"change_amount"` + BalanceSnapshot int64 `json:"balance_snapshot"` + Reason string `json:"reason"` + PostID int64 `json:"post_id"` +} + +func (w *WalletStatement) Get(db *gorm.DB) (*WalletStatement, error) { + var ws WalletStatement + if w.Model != nil && w.ID > 0 { + db = db.Where("id = ? AND is_del = ?", w.ID, 0) + } + if w.PostID > 0 { + db = db.Where("post_id = ?", w.PostID) + } + if w.UserID > 0 { + db = db.Where("user_id = ?", w.UserID) + } + + err := db.First(&ws).Error + if err != nil { + return &ws, err + } + + return &ws, nil +} + +func (w *WalletStatement) Create(db *gorm.DB) (*WalletStatement, error) { + err := db.Create(&w).Error + + return w, err +} + +func (w *WalletStatement) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*WalletStatement, error) { + var records []*WalletStatement + var err error + if offset >= 0 && limit > 0 { + db = db.Offset(offset).Limit(limit) + } + if w.UserID > 0 { + db = db.Where("user_id = ?", w.UserID) + } + + for k, v := range *conditions { + if k == "ORDER" { + db = db.Order(v) + } else { + db = db.Where(k, v) + } + } + + if err = db.Where("is_del = ?", 0).Find(&records).Error; err != nil { + return nil, err + } + + return records, nil +} + +func (w *WalletStatement) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { + var count int64 + if w.PostID > 0 { + db = db.Where("post_id = ?", w.PostID) + } + if w.UserID > 0 { + db = db.Where("user_id = ?", w.UserID) + } + for k, v := range *conditions { + if k != "ORDER" { + db = db.Where(k, v) + } + } + if err := db.Model(w).Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} diff --git a/internal/mirc/auto/api/v1/site.go b/internal/mirc/auto/api/v1/site.go new file mode 100644 index 00000000..03c50281 --- /dev/null +++ b/internal/mirc/auto/api/v1/site.go @@ -0,0 +1,144 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "errors" + "net/http" + + gin "github.com/gin-gonic/gin" +) + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type WebCore interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + Index(c *gin.Context) error + Articles(c *gin.Context) error + Login(c *gin.Context, req *LoginReq) (*LoginResp, error) + Logout(c *gin.Context) error + + mustEmbedUnimplementedWebCoreServant() +} + +type WebCoreBinding interface { + BindLogin(c *gin.Context) (*LoginReq, error) + + mustEmbedUnimplementedWebCoreBinding() +} + +type WebCoreRender interface { + RenderIndex(c *gin.Context, err error) + RenderArticles(c *gin.Context, err error) + RenderLogin(c *gin.Context, data *LoginResp, err error) + RenderLogout(c *gin.Context, err error) + + mustEmbedUnimplementedWebCoreRender() +} + +// RegisterWebCoreServant register WebCore servant to gin +func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCoreRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("GET", "/index/", func(c *gin.Context) { + r.RenderIndex(c, s.Index(c)) + }) + router.Handle("GET", "/articles/:category/", func(c *gin.Context) { + r.RenderArticles(c, s.Articles(c)) + }) + router.Handle("POST", "/user/login/", func(c *gin.Context) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + } + resp, err := s.Login(c, req) + r.RenderLogin(c, resp, err) + }) + router.Handle("POST", "/user/logout/", func(c *gin.Context) { + r.RenderLogout(c, s.Logout(c)) + }) +} + +// UnimplementedWebCoreServant can be embedded to have forward compatible implementations. +type UnimplementedWebCoreServant struct{} + +// UnimplementedWebCoreBinding can be embedded to have forward compatible implementations. +type UnimplementedWebCoreBinding struct{} + +// UnimplementedWebCoreRender can be embedded to have forward compatible implementations. +type UnimplementedWebCoreRender struct{} + +func (UnimplementedWebCoreServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedWebCoreServant) Index(c *gin.Context) error { + return errors.New("method Index not implemented") +} + +func (UnimplementedWebCoreServant) Articles(c *gin.Context) error { + return errors.New("method Index not implemented") +} + +func (UnimplementedWebCoreServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, error) { + return nil, errors.New("method Login not implemented") +} + +func (UnimplementedWebCoreServant) Logout(c *gin.Context) error { + return errors.New("method Logout not implemented") +} + +func (UnimplementedWebCoreServant) mustEmbedUnimplementedWebCoreServant() {} + +func (UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, error) { + return nil, errors.New("method BindLogin not implemented") +} + +func (UnimplementedWebCoreBinding) mustEmbedUnimplementedWebCoreBinding() {} + +func (UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err error) { + c.String(http.StatusInternalServerError, "method RenderLogout not implemented") +} + +func (UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err error) { + c.String(http.StatusInternalServerError, "method RenderLogout not implemented") +} + +func (UnimplementedWebCoreRender) RenderLogin(c *gin.Context, data *LoginResp, err error) { + c.String(http.StatusInternalServerError, "method RenderLogin not implemented") +} + +func (UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err error) { + c.String(http.StatusInternalServerError, "method RenderLogout not implemented") +} + +func (UnimplementedWebCoreRender) mustEmbedUnimplementedWebCoreRender() {} diff --git a/internal/mirc/main.go b/internal/mirc/main.go new file mode 100644 index 00000000..c2e47411 --- /dev/null +++ b/internal/mirc/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "log" + + . "github.com/alimy/mir/v3/core" + . "github.com/alimy/mir/v3/engine" + + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/v1" +) + +//go:generate go run main.go +func main() { + log.Println("generate code start") + opts := Options{ + RunMode(InSerialMode), + GeneratorName(GeneratorGin), + SinkPath("auto"), + } + if err := Generate(opts); err != nil { + log.Fatal(err) + } + log.Println("generate code finish") +} diff --git a/internal/mirc/routes/README.md b/internal/mirc/routes/README.md new file mode 100644 index 00000000..0d7ac0c1 --- /dev/null +++ b/internal/mirc/routes/README.md @@ -0,0 +1 @@ +### RESTful API for paopao-ce diff --git a/internal/mirc/routes/v1/localoss.go b/internal/mirc/routes/v1/localoss.go new file mode 100644 index 00000000..bf2d09d8 --- /dev/null +++ b/internal/mirc/routes/v1/localoss.go @@ -0,0 +1,15 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(LocalOSS)) +} + +type LocalOSS struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` +} diff --git a/internal/mirc/routes/v1/web_admin.go b/internal/mirc/routes/v1/web_admin.go new file mode 100644 index 00000000..db95fc86 --- /dev/null +++ b/internal/mirc/routes/v1/web_admin.go @@ -0,0 +1,15 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(WebAdmin)) +} + +type WebAdmin struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` +} diff --git a/internal/mirc/routes/v1/web_alipay.go b/internal/mirc/routes/v1/web_alipay.go new file mode 100644 index 00000000..61de0906 --- /dev/null +++ b/internal/mirc/routes/v1/web_alipay.go @@ -0,0 +1,15 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(WebAlipay)) +} + +type WebAlipay struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` +} diff --git a/internal/mirc/routes/v1/web_core.go b/internal/mirc/routes/v1/web_core.go new file mode 100644 index 00000000..565fb04a --- /dev/null +++ b/internal/mirc/routes/v1/web_core.go @@ -0,0 +1,44 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(WebCore)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type WebCore struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + Index func(Get) `mir:"/index/"` + Articles func(Get) `mir:"/articles/:category/"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/internal/mirc/routes/v1/web_followship.go b/internal/mirc/routes/v1/web_followship.go new file mode 100644 index 00000000..1dd9de82 --- /dev/null +++ b/internal/mirc/routes/v1/web_followship.go @@ -0,0 +1,15 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(WebFollowship)) +} + +type WebFollowship struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` +} diff --git a/internal/mirc/routes/v1/web_friendship.go b/internal/mirc/routes/v1/web_friendship.go new file mode 100644 index 00000000..e1276e99 --- /dev/null +++ b/internal/mirc/routes/v1/web_friendship.go @@ -0,0 +1,15 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(WebFriendship)) +} + +type WebFriendship struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` +} diff --git a/internal/mirc/routes/v1/web_loose.go b/internal/mirc/routes/v1/web_loose.go new file mode 100644 index 00000000..7eff7d44 --- /dev/null +++ b/internal/mirc/routes/v1/web_loose.go @@ -0,0 +1,15 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(WebLoose)) +} + +type WebLoose struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` +} diff --git a/internal/mirc/routes/v1/web_priv.go b/internal/mirc/routes/v1/web_priv.go new file mode 100644 index 00000000..3d73eb1b --- /dev/null +++ b/internal/mirc/routes/v1/web_priv.go @@ -0,0 +1,15 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(WebPriv)) +} + +type WebPriv struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` +} diff --git a/internal/mirc/routes/v1/web_pub.go b/internal/mirc/routes/v1/web_pub.go new file mode 100644 index 00000000..7bfe2e3a --- /dev/null +++ b/internal/mirc/routes/v1/web_pub.go @@ -0,0 +1,15 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(WebPub)) +} + +type WebPub struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` +} diff --git a/internal/servants/chain/admin.go b/internal/servants/chain/admin.go new file mode 100644 index 00000000..846d6b68 --- /dev/null +++ b/internal/servants/chain/admin.go @@ -0,0 +1,25 @@ +package chain + +import ( + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/pkg/app" + "github.com/rocboss/paopao-ce/pkg/errcode" +) + +func Admin() gin.HandlerFunc { + return func(c *gin.Context) { + if user, exist := c.Get("USER"); exist { + if userModel, ok := user.(*model.User); ok { + if userModel.Status == model.UserStatusNormal && userModel.IsAdmin { + c.Next() + return + } + } + } + + response := app.NewResponse(c) + response.ToErrorResponse(errcode.NoAdminPermission) + c.Abort() + } +} diff --git a/internal/servants/chain/jwt.go b/internal/servants/chain/jwt.go new file mode 100644 index 00000000..75a4c9ad --- /dev/null +++ b/internal/servants/chain/jwt.go @@ -0,0 +1,113 @@ +package chain + +import ( + "strings" + + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v4" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/pkg/app" + "github.com/rocboss/paopao-ce/pkg/errcode" +) + +func JWT() gin.HandlerFunc { + // TODO: optimize get user from a simple service that provide fetch a user info interface. + db := conf.MustGormDB() + return func(c *gin.Context) { + var ( + token string + ecode = errcode.Success + ) + if s, exist := c.GetQuery("token"); exist { + token = s + } else { + token = c.GetHeader("Authorization") + + // 验证前端传过来的token格式,不为空,开头为Bearer + if token == "" || !strings.HasPrefix(token, "Bearer ") { + response := app.NewResponse(c) + response.ToErrorResponse(errcode.UnauthorizedTokenError) + c.Abort() + return + } + + // 验证通过,提取有效部分(除去Bearer) + token = token[7:] + } + if token == "" { + ecode = errcode.InvalidParams + } else { + claims, err := app.ParseToken(token) + if err != nil { + switch err.(*jwt.ValidationError).Errors { + case jwt.ValidationErrorExpired: + ecode = errcode.UnauthorizedTokenTimeout + default: + ecode = errcode.UnauthorizedTokenError + } + } else { + c.Set("UID", claims.UID) + c.Set("USERNAME", claims.Username) + + // 加载用户信息 + user := &model.User{ + Model: &model.Model{ + ID: claims.UID, + }, + } + user, _ = user.Get(db) + c.Set("USER", user) + + // 强制下线机制 + if (conf.JWTSetting.Issuer + ":" + user.Salt) != claims.Issuer { + ecode = errcode.UnauthorizedTokenTimeout + } + } + } + + if ecode != errcode.Success { + response := app.NewResponse(c) + response.ToErrorResponse(ecode) + c.Abort() + return + } + + c.Next() + } +} + +func JwtLoose() gin.HandlerFunc { + // TODO: optimize get user from a simple service that provide fetch a user info interface. + db := conf.MustGormDB() + return func(c *gin.Context) { + token, exist := c.GetQuery("token") + if !exist { + token = c.GetHeader("Authorization") + // 验证前端传过来的token格式,不为空,开头为Bearer + if strings.HasPrefix(token, "Bearer ") { + // 验证通过,提取有效部分(除去Bearer) + token = token[7:] + } else { + c.Next() + } + } + if len(token) > 0 { + if claims, err := app.ParseToken(token); err == nil { + c.Set("UID", claims.UID) + c.Set("USERNAME", claims.Username) + // 加载用户信息 + user := &model.User{ + Model: &model.Model{ + ID: claims.UID, + }, + } + user, err := user.Get(db) + if err == nil && (conf.JWTSetting.Issuer+":"+user.Salt) == claims.Issuer { + c.Set("USER", user) + } + } + } + c.Next() + } +} diff --git a/internal/servants/chain/priv.go b/internal/servants/chain/priv.go new file mode 100644 index 00000000..60409b6b --- /dev/null +++ b/internal/servants/chain/priv.go @@ -0,0 +1,45 @@ +package chain + +import ( + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/pkg/app" + "github.com/rocboss/paopao-ce/pkg/errcode" +) + +func Priv() gin.HandlerFunc { + if conf.CfgIf("PhoneBind") { + return func(c *gin.Context) { + if u, exist := c.Get("USER"); exist { + if user, ok := u.(*model.User); ok { + if user.Status == model.UserStatusNormal { + if user.Phone == "" { + response := app.NewResponse(c) + response.ToErrorResponse(errcode.AccountNoPhoneBind) + c.Abort() + return + } + c.Next() + return + } + } + } + response := app.NewResponse(c) + response.ToErrorResponse(errcode.UserHasBeenBanned) + c.Abort() + } + } else { + return func(c *gin.Context) { + if u, exist := c.Get("USER"); exist { + if user, ok := u.(*model.User); ok && user.Status == model.UserStatusNormal { + c.Next() + return + } + } + response := app.NewResponse(c) + response.ToErrorResponse(errcode.UserHasBeenBanned) + c.Abort() + } + } +} diff --git a/internal/servants/core.go b/internal/servants/core.go new file mode 100644 index 00000000..6deb274c --- /dev/null +++ b/internal/servants/core.go @@ -0,0 +1,26 @@ +package servants + +import ( + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model" +) + +type baseServant struct { + // TODO +} + +type baseBinding struct { + // TODO +} + +type baseRender struct { + // TODO +} + +func (baseServant) userFrom(c *gin.Context) (*model.User, bool) { + if u, exists := c.Get("USER"); exists { + user, ok := u.(*model.User) + return user, ok + } + return nil, false +} diff --git a/internal/servants/localoss.go b/internal/servants/localoss.go new file mode 100644 index 00000000..b99a78f0 --- /dev/null +++ b/internal/servants/localoss.go @@ -0,0 +1,5 @@ +package servants + +type localossSrv struct { + // TODO +} diff --git a/internal/servants/servants.go b/internal/servants/servants.go new file mode 100644 index 00000000..cc808cdb --- /dev/null +++ b/internal/servants/servants.go @@ -0,0 +1,12 @@ +package servants + +import ( + "github.com/gin-gonic/gin" + + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" +) + +// RegisterServants register all the servants to gin.Engine +func RegisterServants(e *gin.Engine) { + api.RegisterWebCoreServant(e, newWebCoreSrv(), newWebCoreBinding(), newWebCoreRender()) +} diff --git a/internal/servants/web_admin.go b/internal/servants/web_admin.go new file mode 100644 index 00000000..f527df8a --- /dev/null +++ b/internal/servants/web_admin.go @@ -0,0 +1,5 @@ +package servants + +type webAdminSrv struct { + // TODO +} diff --git a/internal/servants/web_alipay.go b/internal/servants/web_alipay.go new file mode 100644 index 00000000..680a3df8 --- /dev/null +++ b/internal/servants/web_alipay.go @@ -0,0 +1,5 @@ +package servants + +type webAlipaySrv struct { + // TODO +} diff --git a/internal/servants/web_core.go b/internal/servants/web_core.go new file mode 100644 index 00000000..027676b8 --- /dev/null +++ b/internal/servants/web_core.go @@ -0,0 +1,32 @@ +package servants + +import ( + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" +) + +type webCoreSrv struct { + baseServant + api.UnimplementedWebCoreServant +} + +type webCoreBinding struct { + baseBinding + api.UnimplementedWebCoreBinding +} + +type webCoreRender struct { + baseRender + api.UnimplementedWebCoreRender +} + +func newWebCoreSrv() api.WebCore { + return &webCoreSrv{} +} + +func newWebCoreBinding() api.WebCoreBinding { + return &webCoreBinding{} +} + +func newWebCoreRender() api.WebCoreRender { + return &webCoreRender{} +} diff --git a/internal/servants/web_followship.go b/internal/servants/web_followship.go new file mode 100644 index 00000000..f069d8e7 --- /dev/null +++ b/internal/servants/web_followship.go @@ -0,0 +1,5 @@ +package servants + +type webFollowshipSrv struct { + // TODO +} diff --git a/internal/servants/web_friendship.go b/internal/servants/web_friendship.go new file mode 100644 index 00000000..63bd9896 --- /dev/null +++ b/internal/servants/web_friendship.go @@ -0,0 +1,5 @@ +package servants + +type webFriendshipSrv struct { + // TODO +} diff --git a/internal/servants/web_loose.go b/internal/servants/web_loose.go new file mode 100644 index 00000000..04eaa907 --- /dev/null +++ b/internal/servants/web_loose.go @@ -0,0 +1,5 @@ +package servants + +type webLooseSrv struct { + // TODO +} diff --git a/internal/servants/web_priv.go b/internal/servants/web_priv.go new file mode 100644 index 00000000..8a0a830e --- /dev/null +++ b/internal/servants/web_priv.go @@ -0,0 +1,5 @@ +package servants + +type webPrivSrv struct { + // TODO +} diff --git a/internal/servants/web_pub.go b/internal/servants/web_pub.go new file mode 100644 index 00000000..d66a09b2 --- /dev/null +++ b/internal/servants/web_pub.go @@ -0,0 +1,5 @@ +package servants + +type webPubSrv struct { + // TODO +} From 367e0b018bd00f309e8c35de85486733846890dc Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 11 Nov 2022 14:44:57 +0800 Subject: [PATCH 02/65] optimize source code layout --- internal/mirc/README.md | 1 + internal/proto/RADME.md | 2 ++ internal/servants/{ => core}/core.go | 10 +++---- internal/servants/servants.go | 4 +-- .../servants/{web_admin.go => web/admin.go} | 2 +- .../servants/{web_alipay.go => web/alipay.go} | 2 +- .../servants/{web_core.go => web/core.go} | 27 ++++++++----------- .../{web_followship.go => web/followship.go} | 2 +- .../{web_friendship.go => web/friendship.go} | 2 +- .../servants/{web_loose.go => web/loose.go} | 2 +- .../servants/{web_priv.go => web/priv.go} | 2 +- internal/servants/{web_pub.go => web/pub.go} | 2 +- internal/servants/web/web.go | 17 ++++++++++++ internal/version/version.go | 8 ++++++ 14 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 internal/mirc/README.md create mode 100644 internal/proto/RADME.md rename internal/servants/{ => core}/core.go (60%) rename internal/servants/{web_admin.go => web/admin.go} (69%) rename internal/servants/{web_alipay.go => web/alipay.go} (69%) rename internal/servants/{web_core.go => web/core.go} (50%) rename internal/servants/{web_followship.go => web/followship.go} (71%) rename internal/servants/{web_friendship.go => web/friendship.go} (71%) rename internal/servants/{web_loose.go => web/loose.go} (69%) rename internal/servants/{web_priv.go => web/priv.go} (68%) rename internal/servants/{web_pub.go => web/pub.go} (67%) create mode 100644 internal/servants/web/web.go create mode 100644 internal/version/version.go diff --git a/internal/mirc/README.md b/internal/mirc/README.md new file mode 100644 index 00000000..5b2162a2 --- /dev/null +++ b/internal/mirc/README.md @@ -0,0 +1 @@ +### RESTful API for paopao-ce use [go-mir](https://github.com/alimy/mir) to generate service interface code automatic. diff --git a/internal/proto/RADME.md b/internal/proto/RADME.md new file mode 100644 index 00000000..05d78ece --- /dev/null +++ b/internal/proto/RADME.md @@ -0,0 +1,2 @@ +### gRPC API +This directory contain some gRPC API define files. diff --git a/internal/servants/core.go b/internal/servants/core/core.go similarity index 60% rename from internal/servants/core.go rename to internal/servants/core/core.go index 6deb274c..6bedfa92 100644 --- a/internal/servants/core.go +++ b/internal/servants/core/core.go @@ -1,23 +1,23 @@ -package servants +package core import ( "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/model" ) -type baseServant struct { +type BaseServant struct { // TODO } -type baseBinding struct { +type BaseBinding struct { // TODO } -type baseRender struct { +type BaseRender struct { // TODO } -func (baseServant) userFrom(c *gin.Context) (*model.User, bool) { +func (BaseServant) userFrom(c *gin.Context) (*model.User, bool) { if u, exists := c.Get("USER"); exists { user, ok := u.(*model.User) return user, ok diff --git a/internal/servants/servants.go b/internal/servants/servants.go index cc808cdb..9cd595c7 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -2,11 +2,11 @@ package servants import ( "github.com/gin-gonic/gin" - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/web" ) // RegisterServants register all the servants to gin.Engine func RegisterServants(e *gin.Engine) { - api.RegisterWebCoreServant(e, newWebCoreSrv(), newWebCoreBinding(), newWebCoreRender()) + api.RegisterWebCoreServant(e, web.NewWebCoreSrv(), web.NewWebCoreBinding(), web.NewWebCoreRender()) } diff --git a/internal/servants/web_admin.go b/internal/servants/web/admin.go similarity index 69% rename from internal/servants/web_admin.go rename to internal/servants/web/admin.go index f527df8a..f97832ce 100644 --- a/internal/servants/web_admin.go +++ b/internal/servants/web/admin.go @@ -1,4 +1,4 @@ -package servants +package web type webAdminSrv struct { // TODO diff --git a/internal/servants/web_alipay.go b/internal/servants/web/alipay.go similarity index 69% rename from internal/servants/web_alipay.go rename to internal/servants/web/alipay.go index 680a3df8..a4f71e9f 100644 --- a/internal/servants/web_alipay.go +++ b/internal/servants/web/alipay.go @@ -1,4 +1,4 @@ -package servants +package web type webAlipaySrv struct { // TODO diff --git a/internal/servants/web_core.go b/internal/servants/web/core.go similarity index 50% rename from internal/servants/web_core.go rename to internal/servants/web/core.go index 027676b8..579b51b4 100644 --- a/internal/servants/web_core.go +++ b/internal/servants/web/core.go @@ -1,32 +1,27 @@ -package servants +package web import ( api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/core" +) + +var ( + _ api.WebCore = (*webCoreSrv)(nil) + _ api.WebCoreBinding = (*webCoreBinding)(nil) + _ api.WebCoreRender = (*webCoreRender)(nil) ) type webCoreSrv struct { - baseServant + core.BaseServant api.UnimplementedWebCoreServant } type webCoreBinding struct { - baseBinding + core.BaseBinding api.UnimplementedWebCoreBinding } type webCoreRender struct { - baseRender + core.BaseRender api.UnimplementedWebCoreRender } - -func newWebCoreSrv() api.WebCore { - return &webCoreSrv{} -} - -func newWebCoreBinding() api.WebCoreBinding { - return &webCoreBinding{} -} - -func newWebCoreRender() api.WebCoreRender { - return &webCoreRender{} -} diff --git a/internal/servants/web_followship.go b/internal/servants/web/followship.go similarity index 71% rename from internal/servants/web_followship.go rename to internal/servants/web/followship.go index f069d8e7..6965c4a5 100644 --- a/internal/servants/web_followship.go +++ b/internal/servants/web/followship.go @@ -1,4 +1,4 @@ -package servants +package web type webFollowshipSrv struct { // TODO diff --git a/internal/servants/web_friendship.go b/internal/servants/web/friendship.go similarity index 71% rename from internal/servants/web_friendship.go rename to internal/servants/web/friendship.go index 63bd9896..87690037 100644 --- a/internal/servants/web_friendship.go +++ b/internal/servants/web/friendship.go @@ -1,4 +1,4 @@ -package servants +package web type webFriendshipSrv struct { // TODO diff --git a/internal/servants/web_loose.go b/internal/servants/web/loose.go similarity index 69% rename from internal/servants/web_loose.go rename to internal/servants/web/loose.go index 04eaa907..051a86ef 100644 --- a/internal/servants/web_loose.go +++ b/internal/servants/web/loose.go @@ -1,4 +1,4 @@ -package servants +package web type webLooseSrv struct { // TODO diff --git a/internal/servants/web_priv.go b/internal/servants/web/priv.go similarity index 68% rename from internal/servants/web_priv.go rename to internal/servants/web/priv.go index 8a0a830e..efe80d49 100644 --- a/internal/servants/web_priv.go +++ b/internal/servants/web/priv.go @@ -1,4 +1,4 @@ -package servants +package web type webPrivSrv struct { // TODO diff --git a/internal/servants/web_pub.go b/internal/servants/web/pub.go similarity index 67% rename from internal/servants/web_pub.go rename to internal/servants/web/pub.go index d66a09b2..2b55e3ac 100644 --- a/internal/servants/web_pub.go +++ b/internal/servants/web/pub.go @@ -1,4 +1,4 @@ -package servants +package web type webPubSrv struct { // TODO diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go new file mode 100644 index 00000000..5f505dc1 --- /dev/null +++ b/internal/servants/web/web.go @@ -0,0 +1,17 @@ +package web + +import ( + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" +) + +func NewWebCoreSrv() api.WebCore { + return &webCoreSrv{} +} + +func NewWebCoreBinding() api.WebCoreBinding { + return &webCoreBinding{} +} + +func NewWebCoreRender() api.WebCoreRender { + return &webCoreRender{} +} diff --git a/internal/version/version.go b/internal/version/version.go new file mode 100644 index 00000000..b3bcb903 --- /dev/null +++ b/internal/version/version.go @@ -0,0 +1,8 @@ +package version + +var ( + // GitHash Value will be set during build + GitHash = "" + // BuildTime Value will be set during build + BuildTime = "" +) From a63744479b9647ee5d5bd7a5858fdf869a2ad4cd Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 11 Nov 2022 15:41:30 +0800 Subject: [PATCH 03/65] optimize source code layout --- internal/app/app.go | 39 +++++++++++++ internal/servants/core/xerror/common.go | 26 +++++++++ internal/servants/core/xerror/xerror.go | 75 +++++++++++++++++++++++++ internal/servants/docs.go | 13 +++++ internal/servants/docs_embed.go | 17 ++++++ internal/servants/localoss.go | 5 -- internal/servants/localoss/localoss.go | 28 +++++++++ internal/servants/localoss/xerror.go | 11 ++++ internal/servants/servants.go | 15 +++-- internal/servants/statick.go | 13 +++++ internal/servants/statick_embed.go | 27 +++++++++ internal/servants/web/core.go | 12 ++++ internal/servants/web/web.go | 14 ++--- internal/servants/web/xerror.go | 73 ++++++++++++++++++++++++ 14 files changed, 349 insertions(+), 19 deletions(-) create mode 100644 internal/app/app.go create mode 100644 internal/servants/core/xerror/common.go create mode 100644 internal/servants/core/xerror/xerror.go create mode 100644 internal/servants/docs.go create mode 100644 internal/servants/docs_embed.go delete mode 100644 internal/servants/localoss.go create mode 100644 internal/servants/localoss/localoss.go create mode 100644 internal/servants/localoss/xerror.go create mode 100644 internal/servants/statick.go create mode 100644 internal/servants/statick_embed.go create mode 100644 internal/servants/web/xerror.go diff --git a/internal/app/app.go b/internal/app/app.go new file mode 100644 index 00000000..c38b473f --- /dev/null +++ b/internal/app/app.go @@ -0,0 +1,39 @@ +package app + +import ( + "net/http" + + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" +) + +func NewWebEngine() *gin.Engine { + e := gin.New() + e.HandleMethodNotAllowed = true + e.Use(gin.Logger()) + e.Use(gin.Recovery()) + + // 跨域配置 + corsConfig := cors.DefaultConfig() + corsConfig.AllowAllOrigins = true + corsConfig.AddAllowHeaders("Authorization") + e.Use(cors.New(corsConfig)) + + // 默认404 + e.NoRoute(func(c *gin.Context) { + c.JSON(http.StatusNotFound, gin.H{ + "code": 404, + "msg": "Not Found", + }) + }) + + // 默认405 + e.NoMethod(func(c *gin.Context) { + c.JSON(http.StatusMethodNotAllowed, gin.H{ + "code": 405, + "msg": "Method Not Allowed", + }) + }) + + return e +} diff --git a/internal/servants/core/xerror/common.go b/internal/servants/core/xerror/common.go new file mode 100644 index 00000000..a59c62e8 --- /dev/null +++ b/internal/servants/core/xerror/common.go @@ -0,0 +1,26 @@ +package xerror + +var ( + Success = NewError(0, "成功") + ServerError = NewError(10000, "服务内部错误") + InvalidParams = NewError(10001, "入参错误") + NotFound = NewError(10002, "找不到") + UnauthorizedAuthNotExist = NewError(10003, "账户不存在") + UnauthorizedAuthFailed = NewError(10004, "账户密码错误") + UnauthorizedTokenError = NewError(10005, "鉴权失败,Token 错误或丢失") + UnauthorizedTokenTimeout = NewError(10006, "鉴权失败,Token 超时") + UnauthorizedTokenGenerate = NewError(10007, "鉴权失败,Token 生成失败") + TooManyRequests = NewError(10008, "请求过多") + + GatewayMethodsLimit = NewError(10109, "网关仅接受GET或POST请求") + GatewayLostSign = NewError(10110, "网关请求缺少签名") + GatewayLostAppKey = NewError(10111, "网关请求缺少APP KEY") + GatewayAppKeyInvalid = NewError(10112, "网关请求无效APP KEY") + GatewayAppKeyClosed = NewError(10113, "网关请求APP KEY已停用") + GatewayParamSignError = NewError(10114, "网关请求参数签名错误") + GatewayTooManyRequests = NewError(10115, "网关请求频次超限") + + FileUploadFailed = NewError(10200, "文件上传失败") + FileInvalidExt = NewError(10201, "文件类型不合法") + FileInvalidSize = NewError(10202, "文件大小超限") +) diff --git a/internal/servants/core/xerror/xerror.go b/internal/servants/core/xerror/xerror.go new file mode 100644 index 00000000..b1b8a23a --- /dev/null +++ b/internal/servants/core/xerror/xerror.go @@ -0,0 +1,75 @@ +package xerror + +import ( + "fmt" + "net/http" +) + +type Error struct { + code int + msg string + details []string +} + +var codes = map[int]string{} + +func NewError(code int, msg string) *Error { + if _, ok := codes[code]; ok { + panic(fmt.Sprintf("错误码 %d 已经存在,请更换一个", code)) + } + codes[code] = msg + return &Error{code: code, msg: msg} +} + +func (e *Error) Error() string { + return fmt.Sprintf("错误码: %d, 错误信息: %s", e.Code(), e.Msg()) +} + +func (e *Error) Code() int { + return e.code +} + +func (e *Error) Msg() string { + return e.msg +} + +func (e *Error) Msgf(args []any) string { + return fmt.Sprintf(e.msg, args...) +} + +func (e *Error) Details() []string { + return e.details +} + +func (e *Error) WithDetails(details ...string) *Error { + newError := *e + newError.details = []string{} + newError.details = append(newError.details, details...) + + return &newError +} + +func (e *Error) StatusCode() int { + switch e.Code() { + case Success.Code(): + return http.StatusOK + case ServerError.Code(): + return http.StatusInternalServerError + case InvalidParams.Code(): + return http.StatusBadRequest + case UnauthorizedAuthNotExist.Code(): + fallthrough + case UnauthorizedAuthFailed.Code(): + fallthrough + case UnauthorizedTokenError.Code(): + fallthrough + case UnauthorizedTokenGenerate.Code(): + fallthrough + case UnauthorizedTokenTimeout.Code(): + return http.StatusUnauthorized + case TooManyRequests.Code(): + return http.StatusTooManyRequests + } + + return http.StatusInternalServerError +} diff --git a/internal/servants/docs.go b/internal/servants/docs.go new file mode 100644 index 00000000..9d53cac5 --- /dev/null +++ b/internal/servants/docs.go @@ -0,0 +1,13 @@ +//go:build !docs +// +build !docs + +package servants + +import ( + "github.com/gin-gonic/gin" +) + +// registerDocs stub function for register docs asset route +func registerDocs(e *gin.Engine) { + // empty +} diff --git a/internal/servants/docs_embed.go b/internal/servants/docs_embed.go new file mode 100644 index 00000000..aeb0b4cd --- /dev/null +++ b/internal/servants/docs_embed.go @@ -0,0 +1,17 @@ +//go:build docs +// +build docs + +package servants + +import ( + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/docs/openapi" + "github.com/rocboss/paopao-ce/internal/conf" +) + +// registerDocs register docs asset route +func registerDocs(e *gin.Engine) { + if conf.CfgIf("Docs:OpenAPI") { + e.StaticFS("/docs/openapi", openapi.NewFileSystem()) + } +} diff --git a/internal/servants/localoss.go b/internal/servants/localoss.go deleted file mode 100644 index b99a78f0..00000000 --- a/internal/servants/localoss.go +++ /dev/null @@ -1,5 +0,0 @@ -package servants - -type localossSrv struct { - // TODO -} diff --git a/internal/servants/localoss/localoss.go b/internal/servants/localoss/localoss.go new file mode 100644 index 00000000..ba37ddf8 --- /dev/null +++ b/internal/servants/localoss/localoss.go @@ -0,0 +1,28 @@ +package localoss + +import ( + "path/filepath" + + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/sirupsen/logrus" +) + +type localossSrv struct { + // TODO +} + +// RouteLocalOSS register LocalOSS route if needed +func RouteLocalOSS(e *gin.Engine) { + if !conf.CfgIf("LocalOSS") { + return + } + + savePath, err := filepath.Abs(conf.LocalOSSSetting.SavePath) + if err != nil { + logrus.Fatalf("get localOSS save path err: %v", err) + } + e.Static("/oss", savePath) + + logrus.Infof("register LocalOSS route in /oss on save path: %s", savePath) +} diff --git a/internal/servants/localoss/xerror.go b/internal/servants/localoss/xerror.go new file mode 100644 index 00000000..3014a991 --- /dev/null +++ b/internal/servants/localoss/xerror.go @@ -0,0 +1,11 @@ +package localoss + +import ( + "github.com/rocboss/paopao-ce/internal/servants/core/xerror" +) + +var ( + errFileUploadFailed = xerror.NewError(10200, "文件上传失败") + errFileInvalidExt = xerror.NewError(10201, "文件类型不合法") + errFileInvalidSize = xerror.NewError(10202, "文件大小超限") +) diff --git a/internal/servants/servants.go b/internal/servants/servants.go index 9cd595c7..fb03aff1 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -2,11 +2,18 @@ package servants import ( "github.com/gin-gonic/gin" - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/localoss" "github.com/rocboss/paopao-ce/internal/servants/web" ) -// RegisterServants register all the servants to gin.Engine -func RegisterServants(e *gin.Engine) { - api.RegisterWebCoreServant(e, web.NewWebCoreSrv(), web.NewWebCoreBinding(), web.NewWebCoreRender()) +// RegisterWebServants register all the servants to gin.Engine +func RegisterWebServants(e *gin.Engine) { + // 按需注册 docs、静态资源 + { + registerDocs(e) + registerStatick(e) + } + + web.RouteWeb(e) + localoss.RouteLocalOSS(e) } diff --git a/internal/servants/statick.go b/internal/servants/statick.go new file mode 100644 index 00000000..d711dfe3 --- /dev/null +++ b/internal/servants/statick.go @@ -0,0 +1,13 @@ +//go:build !embed +// +build !embed + +package servants + +import ( + "github.com/gin-gonic/gin" +) + +// registerStatick stub function for register static asset route +func registerStatick(e *gin.Engine) { + // empty +} diff --git a/internal/servants/statick_embed.go b/internal/servants/statick_embed.go new file mode 100644 index 00000000..de212e55 --- /dev/null +++ b/internal/servants/statick_embed.go @@ -0,0 +1,27 @@ +//go:build embed +// +build embed + +package servants + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/web" +) + +// registerStatick register static assets route +func registerStatick(e *gin.Engine) { + routeStatic(e, "/", "/index.html", "/favicon.ico", "/assets/*filepath") +} + +func routeStatic(e *gin.Engine, paths ...string) { + staticHandler := http.FileServer(web.NewFileSystem()) + handler := func(c *gin.Context) { + staticHandler.ServeHTTP(c.Writer, c.Request) + } + for _, path := range paths { + e.GET(path, handler) + e.HEAD(path, handler) + } +} diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 579b51b4..701e9fb2 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -25,3 +25,15 @@ type webCoreRender struct { core.BaseRender api.UnimplementedWebCoreRender } + +func newWebCoreSrv() api.WebCore { + return &webCoreSrv{} +} + +func newWebCoreBinding() api.WebCoreBinding { + return &webCoreBinding{} +} + +func newWebCoreRender() api.WebCoreRender { + return &webCoreRender{} +} diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index 5f505dc1..60a0aeb1 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -1,17 +1,11 @@ package web import ( + "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" ) -func NewWebCoreSrv() api.WebCore { - return &webCoreSrv{} -} - -func NewWebCoreBinding() api.WebCoreBinding { - return &webCoreBinding{} -} - -func NewWebCoreRender() api.WebCoreRender { - return &webCoreRender{} +// RouteWeb register web route +func RouteWeb(e *gin.Engine) { + api.RegisterWebCoreServant(e, newWebCoreSrv(), newWebCoreBinding(), newWebCoreRender()) } diff --git a/internal/servants/web/xerror.go b/internal/servants/web/xerror.go new file mode 100644 index 00000000..0398f648 --- /dev/null +++ b/internal/servants/web/xerror.go @@ -0,0 +1,73 @@ +package web + +import ( + "github.com/rocboss/paopao-ce/internal/servants/core/xerror" +) + +var ( + errUsernameHasExisted = xerror.NewError(20001, "用户名已存在") + errUsernameLengthLimit = xerror.NewError(20002, "用户名长度3~12") + errUsernameCharLimit = xerror.NewError(20003, "用户名只能包含字母、数字") + errPasswordLengthLimit = xerror.NewError(20004, "密码长度6~16") + errUserRegisterFailed = xerror.NewError(20005, "用户注册失败") + errUserHasBeenBanned = xerror.NewError(20006, "该账户已被封停") + errNoPermission = xerror.NewError(20007, "无权限执行该请求") + errUserHasBindOTP = xerror.NewError(20008, "当前用户已绑定二次验证") + errUserOTPInvalid = xerror.NewError(20009, "二次验证码验证失败") + errUserNoBindOTP = xerror.NewError(20010, "当前用户未绑定二次验证") + errErrorOldPassword = xerror.NewError(20011, "当前用户密码验证失败") + errErrorCaptchaPassword = xerror.NewError(20012, "图形验证码验证失败") + errAccountNoPhoneBind = xerror.NewError(20013, "拒绝操作: 账户未绑定手机号") + errTooManyLoginError = xerror.NewError(20014, "登录失败次数过多,请稍后再试") + errGetPhoneCaptchaError = xerror.NewError(20015, "短信验证码获取失败") + errTooManyPhoneCaptchaSend = xerror.NewError(20016, "短信验证码获取次数已达今日上限") + errExistedUserPhone = xerror.NewError(20017, "该手机号已被绑定") + errErrorPhoneCaptcha = xerror.NewError(20018, "手机验证码不正确") + errMaxPhoneCaptchaUseTimes = xerror.NewError(20019, "手机验证码已达最大使用次数") + errNicknameLengthLimit = xerror.NewError(20020, "昵称长度2~12") + errNoExistUsername = xerror.NewError(20021, "用户不存在") + errNoAdminPermission = xerror.NewError(20022, "无管理权限") + + errGetPostsFailed = xerror.NewError(30001, "获取动态列表失败") + errCreatePostFailed = xerror.NewError(30002, "动态发布失败") + errGetPostFailed = xerror.NewError(30003, "获取动态详情失败") + errDeletePostFailed = xerror.NewError(30004, "动态删除失败") + errLockPostFailed = xerror.NewError(30005, "动态锁定失败") + errGetPostTagsFailed = xerror.NewError(30006, "获取话题列表失败") + errInvalidDownloadReq = xerror.NewError(30007, "附件下载请求不合法") + errDownloadReqError = xerror.NewError(30008, "附件下载请求失败") + errInsuffientDownloadMoney = xerror.NewError(30009, "附件下载失败:账户资金不足") + errDownloadExecFail = xerror.NewError(30010, "附件下载失败:扣费失败") + errStickPostFailed = xerror.NewError(30011, "动态置顶失败") + errVisblePostFailed = xerror.NewError(30012, "更新可见性失败") + + errGetCommentsFailed = xerror.NewError(40001, "获取评论列表失败") + errCreateCommentFailed = xerror.NewError(40002, "评论发布失败") + errGetCommentFailed = xerror.NewError(40003, "获取评论详情失败") + errDeleteCommentFailed = xerror.NewError(40004, "评论删除失败") + errCreateReplyFailed = xerror.NewError(40005, "评论回复失败") + errGetReplyFailed = xerror.NewError(40006, "获取评论详情失败") + errMaxCommentCount = xerror.NewError(40007, "评论数已达最大限制") + + errGetMessagesFailed = xerror.NewError(50001, "获取消息列表失败") + errReadMessageFailed = xerror.NewError(50002, "标记消息已读失败") + errSendWhisperFailed = xerror.NewError(50003, "私信发送失败") + errNoWhisperToSelf = xerror.NewError(50004, "不允许给自己发送私信") + errTooManyWhisperNum = xerror.NewError(50005, "今日私信次数已达上限") + + errGetCollectionsFailed = xerror.NewError(60001, "获取收藏列表失败") + errGetStarsFailed = xerror.NewError(60002, "获取点赞列表失败") + + errRechargeReqFail = xerror.NewError(70001, "充值请求失败") + errRechargeNotifyError = xerror.NewError(70002, "充值回调失败") + errGetRechargeFailed = xerror.NewError(70003, "充值详情获取失败") + + errNoRequestingFriendToSelf = xerror.NewError(80001, "不允许添加自己为好友") + errNotExistFriendId = xerror.NewError(80002, "好友id不存在") + errSendRequestingFriendFailed = xerror.NewError(80003, "申请添加朋友请求发送失败") + errAddFriendFailed = xerror.NewError(80004, "添加好友失败") + errRejectFriendFailed = xerror.NewError(80005, "拒绝好友失败") + errDeleteFriendFailed = xerror.NewError(80006, "删除好友失败") + errGetContactsFailed = xerror.NewError(80007, "获取联系人列表失败") + errNoActionToSelf = xerror.NewError(80008, "不允许对自己操作") +) From 8e88500d8a76821f2c1f448b26471e945ca04eaa Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 11 Nov 2022 16:19:39 +0800 Subject: [PATCH 04/65] add app service start/stop common logic --- internal/app/app.go | 48 ++++++++++++++--------------------- internal/app/web.go | 62 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 29 deletions(-) create mode 100644 internal/app/web.go diff --git a/internal/app/app.go b/internal/app/app.go index c38b473f..d35fb235 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -3,37 +3,27 @@ package app import ( "net/http" - "github.com/gin-contrib/cors" - "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" ) -func NewWebEngine() *gin.Engine { - e := gin.New() - e.HandleMethodNotAllowed = true - e.Use(gin.Logger()) - e.Use(gin.Recovery()) - - // 跨域配置 - corsConfig := cors.DefaultConfig() - corsConfig.AllowAllOrigins = true - corsConfig.AddAllowHeaders("Authorization") - e.Use(cors.New(corsConfig)) - - // 默认404 - e.NoRoute(func(c *gin.Context) { - c.JSON(http.StatusNotFound, gin.H{ - "code": 404, - "msg": "Not Found", - }) - }) +type Service interface { + Start() + Stop() + Info() string +} - // 默认405 - e.NoMethod(func(c *gin.Context) { - c.JSON(http.StatusMethodNotAllowed, gin.H{ - "code": 405, - "msg": "Method Not Allowed", - }) - }) +func NewWebService() Service { + e := newWebEngine() + servants.RegisterWebServants(e) - return e + return &webService{ + server: &http.Server{ + Addr: conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort, + Handler: e, + ReadTimeout: conf.ServerSetting.ReadTimeout, + WriteTimeout: conf.ServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } } diff --git a/internal/app/web.go b/internal/app/web.go new file mode 100644 index 00000000..79d0f5a7 --- /dev/null +++ b/internal/app/web.go @@ -0,0 +1,62 @@ +package app + +import ( + "context" + "fmt" + "log" + "net/http" + + "github.com/fatih/color" + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/conf" +) + +type webService struct { + server *http.Server +} + +func (s *webService) Start() { + if err := s.server.ListenAndServe(); err != nil { + log.Fatalf("run app failed: %s", err) + } +} + +func (s *webService) Stop() { + s.server.Shutdown(context.Background()) +} + +func (s *webService) Info() string { + return fmt.Sprintf("PaoPao service listen on %s\n", color.GreenString("http://%s:%s", conf.ServerSetting.HttpIp, conf.ServerSetting.HttpPort)) +} + +func newWebEngine() *gin.Engine { + e := gin.New() + e.HandleMethodNotAllowed = true + e.Use(gin.Logger()) + e.Use(gin.Recovery()) + + // 跨域配置 + corsConfig := cors.DefaultConfig() + corsConfig.AllowAllOrigins = true + corsConfig.AddAllowHeaders("Authorization") + e.Use(cors.New(corsConfig)) + + // 默认404 + e.NoRoute(func(c *gin.Context) { + c.JSON(http.StatusNotFound, gin.H{ + "code": 404, + "msg": "Not Found", + }) + }) + + // 默认405 + e.NoMethod(func(c *gin.Context) { + c.JSON(http.StatusMethodNotAllowed, gin.H{ + "code": 405, + "msg": "Method Not Allowed", + }) + }) + + return e +} From 3c14ced54267284182e2898c824ee51909a50178 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 11 Nov 2022 22:08:10 +0800 Subject: [PATCH 05/65] optimize base code for binding/render --- internal/mirc/auto/api/v1/site.go | 35 ++++++++------ internal/servants/core/core.go | 47 +++++++++++++++++++ internal/servants/localoss/xerror.go | 2 +- internal/servants/web/core.go | 16 +++++-- internal/servants/web/xerror.go | 2 +- .../servants/core => pkg}/xerror/common.go | 0 .../servants/core => pkg}/xerror/xerror.go | 27 ++++++++++- 7 files changed, 107 insertions(+), 22 deletions(-) rename {internal/servants/core => pkg}/xerror/common.go (100%) rename {internal/servants/core => pkg}/xerror/xerror.go (78%) diff --git a/internal/mirc/auto/api/v1/site.go b/internal/mirc/auto/api/v1/site.go index 03c50281..f10eeb54 100644 --- a/internal/mirc/auto/api/v1/site.go +++ b/internal/mirc/auto/api/v1/site.go @@ -4,7 +4,6 @@ package v1 import ( "errors" - "net/http" gin "github.com/gin-gonic/gin" ) @@ -92,10 +91,14 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor type UnimplementedWebCoreServant struct{} // UnimplementedWebCoreBinding can be embedded to have forward compatible implementations. -type UnimplementedWebCoreBinding struct{} +type UnimplementedWebCoreBinding struct { + BindAny func(*gin.Context, any) error +} // UnimplementedWebCoreRender can be embedded to have forward compatible implementations. -type UnimplementedWebCoreRender struct{} +type UnimplementedWebCoreRender struct { + RenderAny func(*gin.Context, any, error) +} func (UnimplementedWebCoreServant) Chain() gin.HandlersChain { return nil @@ -119,26 +122,28 @@ func (UnimplementedWebCoreServant) Logout(c *gin.Context) error { func (UnimplementedWebCoreServant) mustEmbedUnimplementedWebCoreServant() {} -func (UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, error) { - return nil, errors.New("method BindLogin not implemented") +func (b *UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err } -func (UnimplementedWebCoreBinding) mustEmbedUnimplementedWebCoreBinding() {} +func (b *UnimplementedWebCoreBinding) mustEmbedUnimplementedWebCoreBinding() {} -func (UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err error) { - c.String(http.StatusInternalServerError, "method RenderLogout not implemented") +func (r *UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err error) { + r.RenderAny(c, nil, err) } -func (UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err error) { - c.String(http.StatusInternalServerError, "method RenderLogout not implemented") +func (r *UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err error) { + r.RenderAny(c, nil, err) } -func (UnimplementedWebCoreRender) RenderLogin(c *gin.Context, data *LoginResp, err error) { - c.String(http.StatusInternalServerError, "method RenderLogin not implemented") +func (r *UnimplementedWebCoreRender) RenderLogin(c *gin.Context, data *LoginResp, err error) { + r.RenderAny(c, data, err) } -func (UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err error) { - c.String(http.StatusInternalServerError, "method RenderLogout not implemented") +func (r *UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err error) { + r.RenderAny(c, nil, err) } -func (UnimplementedWebCoreRender) mustEmbedUnimplementedWebCoreRender() {} +func (r *UnimplementedWebCoreRender) mustEmbedUnimplementedWebCoreRender() {} diff --git a/internal/servants/core/core.go b/internal/servants/core/core.go index 6bedfa92..7e744dab 100644 --- a/internal/servants/core/core.go +++ b/internal/servants/core/core.go @@ -1,8 +1,13 @@ package core import ( + "fmt" + "net/http" + "os" + "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/pkg/xerror" ) type BaseServant struct { @@ -24,3 +29,45 @@ func (BaseServant) userFrom(c *gin.Context) (*model.User, bool) { } return nil, false } + +func BindAny(c *gin.Context, obj any) error { + var errs xerror.ValidErrors + err := c.ShouldBind(obj) + if err != nil { + return fmt.Errorf("bind errs: %w", xerror.InvalidParams.WithDetails(errs.Error())) + } + return nil +} + +func RenderAny(c *gin.Context, data any, err error) { + if err == nil { + hostname, _ := os.Hostname() + if data == nil { + data = gin.H{ + "code": 0, + "msg": "success", + "tracehost": hostname, + } + } else { + data = gin.H{ + "code": 0, + "msg": "success", + "data": data, + "tracehost": hostname, + } + } + c.JSON(http.StatusOK, data) + } else { + // TODO: error process logic + resp := gin.H{"code": http.StatusInternalServerError, "msg": err.Error()} + // xerr := &xerror.Error{} + // if errors.As(err, xerr) { + // resp["code"], resp["msg"] = xerr.Code(), xerr.Msg() + // details := xerr.Details() + // if len(details) > 0 { + // resp["details"] = details + // } + // } + c.JSON(http.StatusInternalServerError, resp) + } +} diff --git a/internal/servants/localoss/xerror.go b/internal/servants/localoss/xerror.go index 3014a991..7b656b7d 100644 --- a/internal/servants/localoss/xerror.go +++ b/internal/servants/localoss/xerror.go @@ -1,7 +1,7 @@ package localoss import ( - "github.com/rocboss/paopao-ce/internal/servants/core/xerror" + "github.com/rocboss/paopao-ce/pkg/xerror" ) var ( diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 701e9fb2..4a4ccd32 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -18,12 +18,12 @@ type webCoreSrv struct { type webCoreBinding struct { core.BaseBinding - api.UnimplementedWebCoreBinding + *api.UnimplementedWebCoreBinding } type webCoreRender struct { core.BaseRender - api.UnimplementedWebCoreRender + *api.UnimplementedWebCoreRender } func newWebCoreSrv() api.WebCore { @@ -31,9 +31,17 @@ func newWebCoreSrv() api.WebCore { } func newWebCoreBinding() api.WebCoreBinding { - return &webCoreBinding{} + return &webCoreBinding{ + UnimplementedWebCoreBinding: &api.UnimplementedWebCoreBinding{ + BindAny: core.BindAny, + }, + } } func newWebCoreRender() api.WebCoreRender { - return &webCoreRender{} + return &webCoreRender{ + UnimplementedWebCoreRender: &api.UnimplementedWebCoreRender{ + RenderAny: core.RenderAny, + }, + } } diff --git a/internal/servants/web/xerror.go b/internal/servants/web/xerror.go index 0398f648..305d1d0c 100644 --- a/internal/servants/web/xerror.go +++ b/internal/servants/web/xerror.go @@ -1,7 +1,7 @@ package web import ( - "github.com/rocboss/paopao-ce/internal/servants/core/xerror" + "github.com/rocboss/paopao-ce/pkg/xerror" ) var ( diff --git a/internal/servants/core/xerror/common.go b/pkg/xerror/common.go similarity index 100% rename from internal/servants/core/xerror/common.go rename to pkg/xerror/common.go diff --git a/internal/servants/core/xerror/xerror.go b/pkg/xerror/xerror.go similarity index 78% rename from internal/servants/core/xerror/xerror.go rename to pkg/xerror/xerror.go index b1b8a23a..5053b62f 100644 --- a/internal/servants/core/xerror/xerror.go +++ b/pkg/xerror/xerror.go @@ -3,6 +3,11 @@ package xerror import ( "fmt" "net/http" + "strings" +) + +var ( + codes = map[int]string{} ) type Error struct { @@ -11,7 +16,27 @@ type Error struct { details []string } -var codes = map[int]string{} +type ValidError struct { + Message string +} + +type ValidErrors []*ValidError + +func (v *ValidError) Error() string { + return v.Message +} + +func (v ValidErrors) Error() string { + return strings.Join(v.Errors(), ",") +} + +func (v ValidErrors) Errors() []string { + var errs []string + for _, err := range v { + errs = append(errs, err.Error()) + } + return errs +} func NewError(code int, msg string) *Error { if _, ok := codes[code]; ok { From 0eda77775fcfe1bc3048f192fd7b2c75bb1b9c74 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 12 Nov 2022 23:07:11 +0800 Subject: [PATCH 06/65] mv app's logic to service --- internal/app/app.go | 29 ----------------------------- internal/service/service.go | 24 ++++++++++++++++++++++++ internal/{app => service}/web.go | 2 +- 3 files changed, 25 insertions(+), 30 deletions(-) delete mode 100644 internal/app/app.go rename internal/{app => service}/web.go (98%) diff --git a/internal/app/app.go b/internal/app/app.go deleted file mode 100644 index d35fb235..00000000 --- a/internal/app/app.go +++ /dev/null @@ -1,29 +0,0 @@ -package app - -import ( - "net/http" - - "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/servants" -) - -type Service interface { - Start() - Stop() - Info() string -} - -func NewWebService() Service { - e := newWebEngine() - servants.RegisterWebServants(e) - - return &webService{ - server: &http.Server{ - Addr: conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort, - Handler: e, - ReadTimeout: conf.ServerSetting.ReadTimeout, - WriteTimeout: conf.ServerSetting.WriteTimeout, - MaxHeaderBytes: 1 << 20, - }, - } -} diff --git a/internal/service/service.go b/internal/service/service.go index d7afba23..b35bc541 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -1,10 +1,13 @@ package service import ( + "net/http" + "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/dao" "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/servants" "github.com/sirupsen/logrus" ) @@ -15,6 +18,27 @@ var ( DisablePhoneVerify bool ) +type Service interface { + Start() + Stop() + Info() string +} + +func NewWebService() Service { + e := newWebEngine() + servants.RegisterWebServants(e) + + return &webService{ + server: &http.Server{ + Addr: conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort, + Handler: e, + ReadTimeout: conf.ServerSetting.ReadTimeout, + WriteTimeout: conf.ServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } +} + func Initialize() { ds = dao.DataService() ts = dao.TweetSearchService() diff --git a/internal/app/web.go b/internal/service/web.go similarity index 98% rename from internal/app/web.go rename to internal/service/web.go index 79d0f5a7..458d8fa4 100644 --- a/internal/app/web.go +++ b/internal/service/web.go @@ -1,4 +1,4 @@ -package app +package service import ( "context" From 7b325e33b81a373ef7454d4b1c3621c5476d42d2 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 15 Nov 2022 15:50:24 +0800 Subject: [PATCH 07/65] optimzie error process logic adapter mir --- internal/mirc/auto/api/v1/site.go | 53 ++++++++++++++++--------------- internal/servants/core/core.go | 10 +++--- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/internal/mirc/auto/api/v1/site.go b/internal/mirc/auto/api/v1/site.go index f10eeb54..22e9e826 100644 --- a/internal/mirc/auto/api/v1/site.go +++ b/internal/mirc/auto/api/v1/site.go @@ -3,9 +3,10 @@ package v1 import ( - "errors" + "net/http" - gin "github.com/gin-gonic/gin" + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" ) type AgentInfo struct { @@ -37,25 +38,25 @@ type WebCore interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - Index(c *gin.Context) error - Articles(c *gin.Context) error - Login(c *gin.Context, req *LoginReq) (*LoginResp, error) - Logout(c *gin.Context) error + Index(c *gin.Context) mir.Error + Articles(c *gin.Context) mir.Error + Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + Logout(c *gin.Context) mir.Error mustEmbedUnimplementedWebCoreServant() } type WebCoreBinding interface { - BindLogin(c *gin.Context) (*LoginReq, error) + BindLogin(c *gin.Context) (*LoginReq, mir.Error) mustEmbedUnimplementedWebCoreBinding() } type WebCoreRender interface { - RenderIndex(c *gin.Context, err error) - RenderArticles(c *gin.Context, err error) - RenderLogin(c *gin.Context, data *LoginResp, err error) - RenderLogout(c *gin.Context, err error) + RenderIndex(c *gin.Context, err mir.Error) + RenderArticles(c *gin.Context, err mir.Error) + RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + RenderLogout(c *gin.Context, err mir.Error) mustEmbedUnimplementedWebCoreRender() } @@ -92,37 +93,37 @@ type UnimplementedWebCoreServant struct{} // UnimplementedWebCoreBinding can be embedded to have forward compatible implementations. type UnimplementedWebCoreBinding struct { - BindAny func(*gin.Context, any) error + BindAny func(*gin.Context, any) mir.Error } // UnimplementedWebCoreRender can be embedded to have forward compatible implementations. type UnimplementedWebCoreRender struct { - RenderAny func(*gin.Context, any, error) + RenderAny func(*gin.Context, any, mir.Error) } func (UnimplementedWebCoreServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebCoreServant) Index(c *gin.Context) error { - return errors.New("method Index not implemented") +func (UnimplementedWebCoreServant) Index(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Articles(c *gin.Context) error { - return errors.New("method Index not implemented") +func (UnimplementedWebCoreServant) Articles(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, error) { - return nil, errors.New("method Login not implemented") +func (UnimplementedWebCoreServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Logout(c *gin.Context) error { - return errors.New("method Logout not implemented") +func (UnimplementedWebCoreServant) Logout(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedWebCoreServant) mustEmbedUnimplementedWebCoreServant() {} -func (b *UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, error) { +func (b *UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { obj := new(LoginReq) err := b.BindAny(c, obj) return obj, err @@ -130,19 +131,19 @@ func (b *UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, erro func (b *UnimplementedWebCoreBinding) mustEmbedUnimplementedWebCoreBinding() {} -func (r *UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err error) { +func (r *UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err error) { +func (r *UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderLogin(c *gin.Context, data *LoginResp, err error) { +func (r *UnimplementedWebCoreRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err error) { +func (r *UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } diff --git a/internal/servants/core/core.go b/internal/servants/core/core.go index 7e744dab..6dad41e7 100644 --- a/internal/servants/core/core.go +++ b/internal/servants/core/core.go @@ -1,10 +1,10 @@ package core import ( - "fmt" "net/http" "os" + "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/pkg/xerror" @@ -30,16 +30,16 @@ func (BaseServant) userFrom(c *gin.Context) (*model.User, bool) { return nil, false } -func BindAny(c *gin.Context, obj any) error { +func BindAny(c *gin.Context, obj any) mir.Error { var errs xerror.ValidErrors err := c.ShouldBind(obj) if err != nil { - return fmt.Errorf("bind errs: %w", xerror.InvalidParams.WithDetails(errs.Error())) + return mir.NewError(xerror.InvalidParams.Code(), xerror.InvalidParams.WithDetails(errs.Error())) } return nil } -func RenderAny(c *gin.Context, data any, err error) { +func RenderAny(c *gin.Context, data any, err mir.Error) { if err == nil { hostname, _ := os.Hostname() if data == nil { @@ -59,7 +59,7 @@ func RenderAny(c *gin.Context, data any, err error) { c.JSON(http.StatusOK, data) } else { // TODO: error process logic - resp := gin.H{"code": http.StatusInternalServerError, "msg": err.Error()} + resp := gin.H{"code": err.StatusCode(), "msg": err.Error()} // xerr := &xerror.Error{} // if errors.As(err, xerr) { // resp["code"], resp["msg"] = xerr.Code(), xerr.Msg() From e81772005d721f6936bfaac715b31f3b04ce73a1 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Thu, 17 Nov 2022 17:49:37 +0800 Subject: [PATCH 08/65] optimize service define in pkg/service package --- internal/service/service.go | 4 +++- internal/service/web.go | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/internal/service/service.go b/internal/service/service.go index 7236fba2..4f9434f4 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -20,9 +20,11 @@ var ( ) type Service interface { + Name() string + PreStart() string + PreStop() string Start() Stop() - Info() string } func NewWebService() Service { diff --git a/internal/service/web.go b/internal/service/web.go index 458d8fa4..d346fbd8 100644 --- a/internal/service/web.go +++ b/internal/service/web.go @@ -12,10 +12,26 @@ import ( "github.com/rocboss/paopao-ce/internal/conf" ) +type baseService struct{} + type webService struct { + baseService + server *http.Server } +func (baseService) PreStart() string { + return "" +} + +func (baseService) PreStop() string { + return "" +} + +func (s *webService) Name() string { + return "WebService" +} + func (s *webService) Start() { if err := s.server.ListenAndServe(); err != nil { log.Fatalf("run app failed: %s", err) @@ -26,7 +42,7 @@ func (s *webService) Stop() { s.server.Shutdown(context.Background()) } -func (s *webService) Info() string { +func (s *webService) PreStart() string { return fmt.Sprintf("PaoPao service listen on %s\n", color.GreenString("http://%s:%s", conf.ServerSetting.HttpIp, conf.ServerSetting.HttpPort)) } From 59ef538dc3f5ba73aab8421bb445a7fca2e7eda8 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Mon, 21 Nov 2022 12:02:13 +0800 Subject: [PATCH 09/65] mir: add initial proposal document --- ...05-引入go-mir优化后端架构设计.md | 28 +++++++++++++++++++ docs/proposal/README.md | 3 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 docs/proposal/005-引入go-mir优化后端架构设计.md diff --git a/docs/proposal/005-引入go-mir优化后端架构设计.md b/docs/proposal/005-引入go-mir优化后端架构设计.md new file mode 100644 index 00000000..f446bf5d --- /dev/null +++ b/docs/proposal/005-引入go-mir优化后端架构设计.md @@ -0,0 +1,28 @@ +| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 | +| ----- | ----- | ----- | ----- | ----- | ----- | +| 005| 北野 | 2022-11-21 | 2022-11-21 | v0.0 | 提议 | + +### 引入go-mir优化后端架构设计 + 引入[github.com/alimy/mir/v3](https://github.com/alimy/mir)优化后端的架构设计,使得后端代码更具扩展型。 + +### 需求 +* 更方便添加后端功能项的实现; +* 优化代码结构,模块化、清晰化代码布局,使得更具扩展性; +* 兼容RESTful/gRPC 服务代码,RESTful API是服务于Web/Admin,gRPC API是提供给移动端(iOS/Android)的服务; + +### 方案 + +依赖库: +* [go-mir](https://github.com/alimy/mir) + +### 疑问 + +1. 为什么引入go-mir? +TODO; +1. 为什么要兼容RESTful/gRPC服务? +RESTful API是提供给Web端使用的,包括paopao-ce web端以及后期的运维端admin; gRPC API是提供给移动端(iOS/Android)使用的服务。RESTful API天然对web端浏览器友好,而gRPC生态对后端、移动端天然友好,可以根据google-protocol-buffers DSL定义服务API自动生成服务端、客户端代码,非常利于开发,特别是移动端开发,省去了编写客户端网络数据服务相关的业务逻辑,只需要专注于页面逻辑编写,后端数据获取的网络数据访问逻辑直接调用自动生成的gRPC API客户端代码即可,大大的减轻移动端开发的心智负担。后端引入gRPC主要就是考虑到移动端(iOS/Android)开发的开发效率,在减轻移动端开发网络数据获取业务逻辑的心智负担上,gRPC生态与RESTful生态相比优势明显,因此强力引入。再一个就是[go-mir](https://github.com/alimy/mir) v3为RESTful服务的开发提供类似gRPC服务的开发体验,也为后端兼容RESTful/gRPC服务创造了很好的条件,只要代码结构组织清晰,将会有很好的后端开发体验。 + >*目前移动端 iOS/Android APP还在规划中,这里后续的后端gRPC API服务也是为此做准备,敬请期待~* + +### 更新记录 +#### v0.0(2022-11-21) - 北野 +* 初始文档 \ No newline at end of file diff --git a/docs/proposal/README.md b/docs/proposal/README.md index 8301b365..42a4dda0 100644 --- a/docs/proposal/README.md +++ b/docs/proposal/README.md @@ -1,4 +1,5 @@ ## Draft * [001-关于paopao-ce的设计定位](001-关于paopao-ce的设计定位.md "关于paopao-ce的设计定位") * [002-关于Friendship功能项的设计](002-关于Friendship功能项的设计.md "关于Friendship功能项的设计") -* [003-关于Followship功能项的设计](003-关于Followship功能项的设计.md "关于Followship功能项的设计") \ No newline at end of file +* [003-关于Followship功能项的设计](003-关于Followship功能项的设计.md "关于Followship功能项的设计") +* [005-引入go-mir优化后端架构设计](005-引入go-mir优化后端架构设计.md "引入go-mir优化后端架构设计") \ No newline at end of file From df1744fc648dc9ef9b47cf61778cc1faa056811a Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 25 Nov 2022 23:57:16 +0800 Subject: [PATCH 10/65] optimize servants code layout --- internal/servants/docs.go | 13 ------------- internal/servants/docs/docs.go | 13 +++++++++++++ internal/servants/{ => docs}/docs_embed.go | 6 +++--- internal/servants/servants.go | 6 ++++-- internal/servants/statick.go | 13 ------------- internal/servants/statick/statick.go | 13 +++++++++++++ internal/servants/{ => statick}/statick_embed.go | 6 +++--- internal/version/version.go | 8 -------- 8 files changed, 36 insertions(+), 42 deletions(-) delete mode 100644 internal/servants/docs.go create mode 100644 internal/servants/docs/docs.go rename internal/servants/{ => docs}/docs_embed.go (72%) delete mode 100644 internal/servants/statick.go create mode 100644 internal/servants/statick/statick.go rename internal/servants/{ => statick}/statick_embed.go (82%) delete mode 100644 internal/version/version.go diff --git a/internal/servants/docs.go b/internal/servants/docs.go deleted file mode 100644 index 9d53cac5..00000000 --- a/internal/servants/docs.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !docs -// +build !docs - -package servants - -import ( - "github.com/gin-gonic/gin" -) - -// registerDocs stub function for register docs asset route -func registerDocs(e *gin.Engine) { - // empty -} diff --git a/internal/servants/docs/docs.go b/internal/servants/docs/docs.go new file mode 100644 index 00000000..ef062a47 --- /dev/null +++ b/internal/servants/docs/docs.go @@ -0,0 +1,13 @@ +//go:build !docs +// +build !docs + +package docs + +import ( + "github.com/gin-gonic/gin" +) + +// RegisterDocs stub function for register docs asset route +func RegisterDocs(e *gin.Engine) { + // empty +} diff --git a/internal/servants/docs_embed.go b/internal/servants/docs/docs_embed.go similarity index 72% rename from internal/servants/docs_embed.go rename to internal/servants/docs/docs_embed.go index 1d7efb0f..da457e50 100644 --- a/internal/servants/docs_embed.go +++ b/internal/servants/docs/docs_embed.go @@ -1,7 +1,7 @@ //go:build docs // +build docs -package servants +package docs import ( "github.com/gin-gonic/gin" @@ -9,8 +9,8 @@ import ( "github.com/rocboss/paopao-ce/pkg/cfg" ) -// registerDocs register docs asset route -func registerDocs(e *gin.Engine) { +// RegisterDocs register docs asset route +func RegisterDocs(e *gin.Engine) { cfg.Be("Docs:OpenAPI", func() { e.StaticFS("/docs/openapi", openapi.NewFileSystem()) }) diff --git a/internal/servants/servants.go b/internal/servants/servants.go index c61dcc82..4c36c0d6 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -2,7 +2,9 @@ package servants import ( "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/servants/docs" "github.com/rocboss/paopao-ce/internal/servants/localoss" + "github.com/rocboss/paopao-ce/internal/servants/statick" "github.com/rocboss/paopao-ce/internal/servants/web" "github.com/rocboss/paopao-ce/pkg/cfg" ) @@ -11,8 +13,8 @@ import ( func RegisterWebServants(e *gin.Engine) { // 按需注册 docs、静态资源 { - registerDocs(e) - registerStatick(e) + docs.RegisterDocs(e) + statick.RegisterStatick(e) } web.RouteWeb(e) diff --git a/internal/servants/statick.go b/internal/servants/statick.go deleted file mode 100644 index d711dfe3..00000000 --- a/internal/servants/statick.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !embed -// +build !embed - -package servants - -import ( - "github.com/gin-gonic/gin" -) - -// registerStatick stub function for register static asset route -func registerStatick(e *gin.Engine) { - // empty -} diff --git a/internal/servants/statick/statick.go b/internal/servants/statick/statick.go new file mode 100644 index 00000000..a852bdfc --- /dev/null +++ b/internal/servants/statick/statick.go @@ -0,0 +1,13 @@ +//go:build !embed +// +build !embed + +package statick + +import ( + "github.com/gin-gonic/gin" +) + +// RegisterStatick stub function for register static asset route +func RegisterStatick(e *gin.Engine) { + // empty +} diff --git a/internal/servants/statick_embed.go b/internal/servants/statick/statick_embed.go similarity index 82% rename from internal/servants/statick_embed.go rename to internal/servants/statick/statick_embed.go index de212e55..6dd4c77b 100644 --- a/internal/servants/statick_embed.go +++ b/internal/servants/statick/statick_embed.go @@ -1,7 +1,7 @@ //go:build embed // +build embed -package servants +package statick import ( "net/http" @@ -10,8 +10,8 @@ import ( "github.com/rocboss/paopao-ce/web" ) -// registerStatick register static assets route -func registerStatick(e *gin.Engine) { +// RegisterStatick register static assets route +func RegisterStatick(e *gin.Engine) { routeStatic(e, "/", "/index.html", "/favicon.ico", "/assets/*filepath") } diff --git a/internal/version/version.go b/internal/version/version.go deleted file mode 100644 index b3bcb903..00000000 --- a/internal/version/version.go +++ /dev/null @@ -1,8 +0,0 @@ -package version - -var ( - // GitHash Value will be set during build - GitHash = "" - // BuildTime Value will be set during build - BuildTime = "" -) From 7636412940d282205d3a9acfafb443d32b169039 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 2 Dec 2022 21:18:51 +0800 Subject: [PATCH 11/65] mir: optimize source code layout for import go-mir --- docs/openapi/embed.go | 4 + internal/broker/broker.go | 5 + internal/{ => broker}/migration/migration.go | 4 + .../{ => broker}/migration/migration_embed.go | 4 + internal/conf/conf.go | 4 + internal/conf/db.go | 4 + internal/conf/db_cgo.go | 4 + internal/conf/db_nocgo.go | 4 + internal/conf/logger.go | 4 + internal/conf/logger_meili.go | 4 + internal/conf/logger_zinc.go | 4 + internal/conf/settting.go | 4 + internal/core/authority.go | 39 ++-- internal/core/cache.go | 14 +- internal/core/comments.go | 36 ++- internal/core/core.go | 4 + internal/core/messages.go | 33 ++- internal/core/search.go | 47 ++-- internal/core/security.go | 14 +- internal/core/storage.go | 4 + internal/core/topics.go | 19 +- internal/core/tweets.go | 88 +++++--- internal/core/types.go | 24 ++ internal/core/user.go | 36 ++- internal/core/version.go | 4 + internal/core/wallet.go | 21 +- internal/dao/cache/bigcache.go | 22 +- internal/dao/cache/cache.go | 4 + internal/dao/cache/none.go | 10 +- internal/dao/cache/simple.go | 16 +- internal/dao/dao.go | 4 + internal/dao/jinzhu/authority.go | 18 +- internal/dao/jinzhu/comments.go | 50 +++-- internal/dao/jinzhu/contacts.go | 81 +++---- internal/dao/jinzhu/dbr/attachment.go | 12 +- internal/dao/jinzhu/dbr/captcha.go | 6 +- internal/dao/jinzhu/dbr/comment.go | 6 +- internal/dao/jinzhu/dbr/comment_content.go | 8 +- internal/dao/jinzhu/dbr/comment_reply.go | 6 +- internal/dao/jinzhu/dbr/contact.go | 6 +- internal/dao/jinzhu/dbr/dbr.go | 36 --- internal/dao/jinzhu/dbr/message.go | 6 +- internal/{model => dao/jinzhu/dbr}/model.go | 6 +- internal/dao/jinzhu/dbr/post.go | 6 +- .../dao/jinzhu/dbr/post_attachment_bill.go | 6 +- internal/dao/jinzhu/dbr/post_collection.go | 6 +- internal/dao/jinzhu/dbr/post_content.go | 33 +-- internal/dao/jinzhu/dbr/post_star.go | 6 +- internal/dao/jinzhu/dbr/tag.go | 6 +- internal/dao/jinzhu/dbr/user.go | 6 +- internal/dao/jinzhu/dbr/wallet_recharge.go | 6 +- internal/dao/jinzhu/dbr/wallet_statement.go | 6 +- internal/dao/jinzhu/index.go | 33 +-- internal/dao/jinzhu/jinzhu.go | 4 + internal/dao/jinzhu/messages.go | 30 +-- internal/dao/jinzhu/security.go | 14 +- internal/dao/jinzhu/topics.go | 22 +- internal/dao/jinzhu/tweets.go | 140 ++++++------ internal/dao/jinzhu/user.go | 46 ++-- internal/dao/jinzhu/utils.go | 18 +- internal/dao/jinzhu/wallet.go | 46 ++-- internal/dao/sakila/sakila.go | 4 + internal/dao/search/bridge.go | 7 +- internal/dao/search/filter.go | 15 +- internal/dao/search/meili.go | 47 ++-- internal/dao/search/search.go | 17 +- internal/dao/search/zinc.go | 17 +- internal/dao/security/attachment.go | 4 + internal/dao/slonik/slonik.go | 4 + internal/dao/storage/alioss.go | 4 + internal/dao/storage/cos.go | 4 + internal/dao/storage/huaweiobs.go | 4 + internal/dao/storage/localoss.go | 4 + internal/dao/storage/minio.go | 4 + internal/dao/storage/storage.go | 4 + internal/internal.go | 12 +- internal/middleware/admin.go | 25 --- internal/middleware/jwt.go | 113 ---------- internal/middleware/priv.go | 45 ---- internal/mirc/main.go | 4 + internal/model/attachment.go | 27 --- internal/model/captcha.go | 38 ---- internal/model/comment.go | 127 ----------- internal/model/comment_content.go | 59 ----- internal/model/comment_reply.go | 110 --------- internal/model/contact.go | 119 ---------- internal/model/message.go | 148 ------------- internal/model/post.go | 208 ------------------ internal/model/post_attachment_bill.go | 36 --- internal/model/post_collection.go | 102 --------- internal/model/post_content.go | 121 ---------- internal/model/post_star.go | 98 --------- internal/model/rest/contacts.go | 31 --- internal/model/rest/tweets.go | 8 - internal/model/rest/user.go | 11 - internal/model/tag.go | 97 -------- internal/model/user.go | 94 -------- internal/model/wallet_recharge.go | 34 --- internal/model/wallet_statement.go | 83 ------- internal/proto/gen.go | 5 + internal/proto/tweets.proto | 10 + .../servants/{core/core.go => base/base.go} | 12 +- internal/servants/chain/admin.go | 10 +- internal/servants/chain/jwt.go | 14 +- internal/servants/chain/priv.go | 12 +- internal/servants/docs/docs.go | 4 + internal/servants/docs/docs_embed.go | 4 + internal/servants/localoss/localoss.go | 4 + internal/servants/localoss/xerror.go | 4 + internal/servants/servants.go | 4 + internal/servants/statick/statick.go | 4 + internal/servants/statick/statick_embed.go | 4 + internal/servants/web/admin.go | 4 + internal/servants/web/alipay.go | 4 + internal/servants/web/broker/attachment.go | 13 ++ .../web/broker}/avatar.go | 6 +- internal/servants/web/broker/broker.go | 48 ++++ .../web/broker}/comment.go | 60 ++--- .../web/broker}/message.go | 16 +- .../{service => servants/web/broker}/post.go | 114 +++++----- .../{service => servants/web/broker}/sign.go | 6 +- .../{service => servants/web/broker}/user.go | 106 +++++---- .../web/broker}/wallet.go | 14 +- internal/servants/web/core.go | 16 +- internal/servants/web/followship.go | 4 + internal/servants/web/friendship.go | 4 + internal/servants/web/loose.go | 4 + internal/servants/web/priv.go | 4 + internal/servants/web/pub.go | 4 + .../{ => servants/web}/routers/api/api.go | 4 + .../web}/routers/api/assets/comic.ttf | Bin .../web}/routers/api/attachment.go | 50 +++-- .../{ => servants/web}/routers/api/comment.go | 34 +-- .../{ => servants/web}/routers/api/home.go | 16 +- .../{ => servants/web}/routers/api/message.go | 26 ++- .../{ => servants/web}/routers/api/post.go | 65 +++--- .../{ => servants/web}/routers/api/user.go | 127 +++++------ internal/{ => servants/web}/routers/docs.go | 4 + .../{ => servants/web}/routers/docs_embed.go | 4 + internal/{ => servants/web}/routers/router.go | 16 +- .../{ => servants/web}/routers/statick.go | 4 + .../web}/routers/statick_embed.go | 4 + internal/servants/web/web.go | 4 + internal/servants/web/xerror.go | 4 + internal/service/attachment.go | 7 - internal/service/service.go | 69 +----- internal/service/web.go | 31 ++- main.go | 6 +- pkg/app/app.go | 4 + pkg/app/form.go | 4 + pkg/app/jwt.go | 8 +- pkg/app/pagination.go | 4 + pkg/cfg/cfg.go | 4 + pkg/cfg/cfg_test.go | 4 + pkg/cfg/feature.go | 4 + pkg/cfg/feature_test.go | 4 + pkg/convert/convert.go | 4 + pkg/convert/convert_test.go | 4 + pkg/crypto/signature.go | 4 + pkg/debug/version.go | 4 + pkg/errcode/common_code.go | 4 + pkg/errcode/errcode.go | 4 + pkg/errcode/module_code.go | 4 + pkg/sign/sign.go | 4 + pkg/types/types.go | 4 + pkg/util/banner.go | 4 + pkg/util/ip.go | 4 + pkg/util/ip_test.go | 4 + pkg/util/iploc/iploc.go | 4 + pkg/util/iploc/iploc_test.go | 4 + pkg/util/md5.go | 4 + pkg/util/md5_test.go | 4 + pkg/util/str.go | 4 + pkg/xerror/common.go | 4 + pkg/xerror/xerror.go | 4 + pkg/zinc/zinc.go | 4 + scripts/migration/embed.go | 4 + web/embed.go | 4 + 178 files changed, 1566 insertions(+), 2603 deletions(-) create mode 100644 internal/broker/broker.go rename internal/{ => broker}/migration/migration.go (64%) rename internal/{ => broker}/migration/migration_embed.go (94%) create mode 100644 internal/core/types.go delete mode 100644 internal/dao/jinzhu/dbr/dbr.go rename internal/{model => dao/jinzhu/dbr}/model.go (83%) delete mode 100644 internal/middleware/admin.go delete mode 100644 internal/middleware/jwt.go delete mode 100644 internal/middleware/priv.go delete mode 100644 internal/model/attachment.go delete mode 100644 internal/model/captcha.go delete mode 100644 internal/model/comment.go delete mode 100644 internal/model/comment_content.go delete mode 100644 internal/model/comment_reply.go delete mode 100644 internal/model/contact.go delete mode 100644 internal/model/message.go delete mode 100644 internal/model/post.go delete mode 100644 internal/model/post_attachment_bill.go delete mode 100644 internal/model/post_collection.go delete mode 100644 internal/model/post_content.go delete mode 100644 internal/model/post_star.go delete mode 100644 internal/model/rest/contacts.go delete mode 100644 internal/model/rest/tweets.go delete mode 100644 internal/model/rest/user.go delete mode 100644 internal/model/tag.go delete mode 100644 internal/model/user.go delete mode 100644 internal/model/wallet_recharge.go delete mode 100644 internal/model/wallet_statement.go create mode 100644 internal/proto/gen.go create mode 100644 internal/proto/tweets.proto rename internal/servants/{core/core.go => base/base.go} (81%) create mode 100644 internal/servants/web/broker/attachment.go rename internal/{service => servants/web/broker}/avatar.go (95%) create mode 100644 internal/servants/web/broker/broker.go rename internal/{service => servants/web/broker}/comment.go (83%) rename internal/{service => servants/web/broker}/message.go (84%) rename internal/{service => servants/web/broker}/post.go (76%) rename internal/{service => servants/web/broker}/sign.go (79%) rename internal/{service => servants/web/broker}/user.go (76%) rename internal/{service => servants/web/broker}/wallet.go (69%) rename internal/{ => servants/web}/routers/api/api.go (89%) rename internal/{ => servants/web}/routers/api/assets/comic.ttf (100%) rename internal/{ => servants/web}/routers/api/attachment.go (79%) rename internal/{ => servants/web}/routers/api/comment.go (75%) rename internal/{ => servants/web}/routers/api/home.go (86%) rename internal/{ => servants/web}/routers/api/message.go (74%) rename internal/{ => servants/web}/routers/api/post.go (79%) rename internal/{ => servants/web}/routers/api/user.go (80%) rename internal/{ => servants/web}/routers/docs.go (57%) rename internal/{ => servants/web}/routers/docs_embed.go (69%) rename internal/{ => servants/web}/routers/router.go (92%) rename internal/{ => servants/web}/routers/statick.go (58%) rename internal/{ => servants/web}/routers/statick_embed.go (79%) delete mode 100644 internal/service/attachment.go diff --git a/docs/openapi/embed.go b/docs/openapi/embed.go index 8500ca3c..e72721fb 100644 --- a/docs/openapi/embed.go +++ b/docs/openapi/embed.go @@ -1,3 +1,7 @@ +// 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. + //go:build docs // +build docs diff --git a/internal/broker/broker.go b/internal/broker/broker.go new file mode 100644 index 00000000..a47462c1 --- /dev/null +++ b/internal/broker/broker.go @@ -0,0 +1,5 @@ +// 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 broker diff --git a/internal/migration/migration.go b/internal/broker/migration/migration.go similarity index 64% rename from internal/migration/migration.go rename to internal/broker/migration/migration.go index 44c16fb4..7437e996 100644 --- a/internal/migration/migration.go +++ b/internal/broker/migration/migration.go @@ -1,3 +1,7 @@ +// 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. + //go:build !migration // +build !migration diff --git a/internal/migration/migration_embed.go b/internal/broker/migration/migration_embed.go similarity index 94% rename from internal/migration/migration_embed.go rename to internal/broker/migration/migration_embed.go index 84952538..976b4f26 100644 --- a/internal/migration/migration_embed.go +++ b/internal/broker/migration/migration_embed.go @@ -1,3 +1,7 @@ +// 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. + //go:build migration // +build migration diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 97512264..bbc8438c 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -1,3 +1,7 @@ +// 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 conf import ( diff --git a/internal/conf/db.go b/internal/conf/db.go index ef4f7c92..7f859152 100644 --- a/internal/conf/db.go +++ b/internal/conf/db.go @@ -1,3 +1,7 @@ +// 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 conf import ( diff --git a/internal/conf/db_cgo.go b/internal/conf/db_cgo.go index 3ec8a218..218512a5 100644 --- a/internal/conf/db_cgo.go +++ b/internal/conf/db_cgo.go @@ -1,3 +1,7 @@ +// 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. + //go:build cgo // +build cgo diff --git a/internal/conf/db_nocgo.go b/internal/conf/db_nocgo.go index 37937484..977a6695 100644 --- a/internal/conf/db_nocgo.go +++ b/internal/conf/db_nocgo.go @@ -1,3 +1,7 @@ +// 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. + //go:build !cgo // +build !cgo diff --git a/internal/conf/logger.go b/internal/conf/logger.go index c65612dc..b514b375 100644 --- a/internal/conf/logger.go +++ b/internal/conf/logger.go @@ -1,3 +1,7 @@ +// 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 conf import ( diff --git a/internal/conf/logger_meili.go b/internal/conf/logger_meili.go index 756cc41f..2d3d439d 100644 --- a/internal/conf/logger_meili.go +++ b/internal/conf/logger_meili.go @@ -1,3 +1,7 @@ +// 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 conf import ( diff --git a/internal/conf/logger_zinc.go b/internal/conf/logger_zinc.go index 211270c0..4f804cf8 100644 --- a/internal/conf/logger_zinc.go +++ b/internal/conf/logger_zinc.go @@ -1,3 +1,7 @@ +// 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 conf import ( diff --git a/internal/conf/settting.go b/internal/conf/settting.go index 116fdf95..da3d97b6 100644 --- a/internal/conf/settting.go +++ b/internal/conf/settting.go @@ -1,3 +1,7 @@ +// 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 conf import ( diff --git a/internal/core/authority.go b/internal/core/authority.go index c016c840..05e3742a 100644 --- a/internal/core/authority.go +++ b/internal/core/authority.go @@ -1,7 +1,10 @@ +// 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/model" "github.com/rocboss/paopao-ce/pkg/types" ) @@ -33,23 +36,17 @@ const ( ActCreateActivationCode ) -type act uint8 - -type FriendFilter map[int64]types.Empty -type FriendSet map[string]types.Empty +type ( + act uint8 -type Action struct { - Act act - UserId int64 -} + FriendFilter map[int64]types.Empty + FriendSet map[string]types.Empty -// AuthorizationManageService 授权管理服务 -type AuthorizationManageService interface { - IsAllow(user *model.User, action *Action) bool - BeFriendFilter(userId int64) FriendFilter - BeFriendIds(userId int64) ([]int64, error) - MyFriendSet(userId int64) FriendSet -} + Action struct { + Act act + UserId int64 + } +) func (f FriendFilter) IsFriend(userId int64) bool { _, yeah := f[userId] @@ -57,7 +54,7 @@ func (f FriendFilter) IsFriend(userId int64) bool { } // IsAllow default true if user is admin -func (a act) IsAllow(user *model.User, userId int64, isFriend bool, isActivation bool) bool { +func (a act) IsAllow(user *User, userId int64, isFriend bool, isActivation bool) bool { if user.IsAdmin { return true } @@ -116,3 +113,11 @@ func (a act) IsAllow(user *model.User, userId int64, isFriend bool, isActivation return false } + +// AuthorizationManageService 授权管理服务 +type AuthorizationManageService interface { + IsAllow(user *User, action *Action) bool + BeFriendFilter(userId int64) FriendFilter + BeFriendIds(userId int64) ([]int64, error) + MyFriendSet(userId int64) FriendSet +} diff --git a/internal/core/cache.go b/internal/core/cache.go index e4cf4cd9..d8b8cd10 100644 --- a/internal/core/cache.go +++ b/internal/core/cache.go @@ -1,6 +1,12 @@ +// 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/model" +import ( + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" +) const ( IdxActNop IdxAct = iota + 1 @@ -15,7 +21,7 @@ type IdxAct uint8 type IndexAction struct { Act IdxAct - Post *model.Post + Post *dbr.Post } func (a IdxAct) String() string { @@ -37,7 +43,7 @@ func (a IdxAct) String() string { } } -func NewIndexAction(act IdxAct, post *model.Post) *IndexAction { +func NewIndexAction(act IdxAct, post *dbr.Post) *IndexAction { return &IndexAction{ Act: act, Post: post, @@ -48,5 +54,5 @@ func NewIndexAction(act IdxAct, post *model.Post) *IndexAction { type CacheIndexService interface { IndexPostsService - SendAction(act IdxAct, post *model.Post) + SendAction(act IdxAct, post *dbr.Post) } diff --git a/internal/core/comments.go b/internal/core/comments.go index 9be29ed3..c5501b4b 100644 --- a/internal/core/comments.go +++ b/internal/core/comments.go @@ -1,24 +1,36 @@ +// 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/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" +) + +type ( + Comment = dbr.Comment + CommentFormated = dbr.CommentFormated + CommentReply = dbr.CommentReply + CommentContent = dbr.CommentContent + CommentReplyFormated = dbr.CommentReplyFormated ) // CommentService 评论检索服务 type CommentService interface { - GetComments(conditions *model.ConditionsT, offset, limit int) ([]*model.Comment, error) - GetCommentByID(id int64) (*model.Comment, error) - GetCommentCount(conditions *model.ConditionsT) (int64, error) - GetCommentReplyByID(id int64) (*model.CommentReply, error) - GetCommentContentsByIDs(ids []int64) ([]*model.CommentContent, error) - GetCommentRepliesByID(ids []int64) ([]*model.CommentReplyFormated, error) + GetComments(conditions *ConditionsT, offset, limit int) ([]*Comment, error) + GetCommentByID(id int64) (*Comment, error) + GetCommentCount(conditions *ConditionsT) (int64, error) + GetCommentReplyByID(id int64) (*CommentReply, error) + GetCommentContentsByIDs(ids []int64) ([]*CommentContent, error) + GetCommentRepliesByID(ids []int64) ([]*CommentReplyFormated, error) } // CommentManageService 评论管理服务 type CommentManageService interface { - DeleteComment(comment *model.Comment) error - CreateComment(comment *model.Comment) (*model.Comment, error) - CreateCommentReply(reply *model.CommentReply) (*model.CommentReply, error) - DeleteCommentReply(reply *model.CommentReply) error - CreateCommentContent(content *model.CommentContent) (*model.CommentContent, error) + DeleteComment(comment *Comment) error + CreateComment(comment *Comment) (*Comment, error) + CreateCommentReply(reply *CommentReply) (*CommentReply, error) + DeleteCommentReply(reply *CommentReply) error + CreateCommentContent(content *CommentContent) (*CommentContent, error) } diff --git a/internal/core/core.go b/internal/core/core.go index f0c158b1..9a8eb26f 100644 --- a/internal/core/core.go +++ b/internal/core/core.go @@ -1,3 +1,7 @@ +// 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 // DataService 数据服务集成 diff --git a/internal/core/messages.go b/internal/core/messages.go index aa08a1f8..57816480 100644 --- a/internal/core/messages.go +++ b/internal/core/messages.go @@ -1,15 +1,36 @@ +// 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/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" +) + +const ( + MsgTypePost = dbr.MsgTypePost + MsgtypeComment = dbr.MsgtypeComment + MsgTypeReply = dbr.MsgTypeReply + MsgTypeWhisper = dbr.MsgTypeWhisper + MsgTypeRequestingFriend = dbr.MsgTypeRequestingFriend + MsgTypeSystem = dbr.MsgTypeSystem + + MsgStatusUnread = dbr.MsgStatusUnread + MsgStatusReaded = dbr.MsgStatusReaded +) + +type ( + Message = dbr.Message + MessageFormated = dbr.MessageFormated ) // MessageService 消息服务 type MessageService interface { - CreateMessage(msg *model.Message) (*model.Message, error) + CreateMessage(msg *Message) (*Message, error) GetUnreadCount(userID int64) (int64, error) - GetMessageByID(id int64) (*model.Message, error) - ReadMessage(message *model.Message) error - GetMessages(conditions *model.ConditionsT, offset, limit int) ([]*model.MessageFormated, error) - GetMessageCount(conditions *model.ConditionsT) (int64, error) + GetMessageByID(id int64) (*Message, error) + ReadMessage(message *Message) error + GetMessages(conditions *ConditionsT, offset, limit int) ([]*MessageFormated, error) + GetMessageCount(conditions *ConditionsT) (int64, error) } diff --git a/internal/core/search.go b/internal/core/search.go index 3ac90288..74d6e029 100644 --- a/internal/core/search.go +++ b/internal/core/search.go @@ -1,7 +1,11 @@ +// 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/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" ) const ( @@ -9,28 +13,39 @@ const ( SearchTypeTag SearchType = "tag" ) -type SearchType string +const ( + PostVisitPublic = dbr.PostVisitPublic + PostVisitPrivate = dbr.PostVisitPrivate + PostVisitFriend = dbr.PostVisitFriend + PostVisitInvalid = dbr.PostVisitInvalid +) -type QueryReq struct { - Query string - Visibility []model.PostVisibleT - Type SearchType -} +type ( + PostVisibleT = dbr.PostVisibleT -type QueryResp struct { - Items []*model.PostFormated - Total int64 -} + SearchType string -type TsDocItem struct { - Post *model.Post - Content string -} + QueryReq struct { + Query string + Visibility []PostVisibleT + Type SearchType + } + + QueryResp struct { + Items []*PostFormated + Total int64 + } + + TsDocItem struct { + Post *Post + Content string + } +) // TweetSearchService tweet search service interface type TweetSearchService interface { IndexName() string AddDocuments(data []TsDocItem, primaryKey ...string) (bool, error) DeleteDocuments(identifiers []string) error - Search(user *model.User, q *QueryReq, offset, limit int) (*QueryResp, error) + Search(user *User, q *QueryReq, offset, limit int) (*QueryResp, error) } diff --git a/internal/core/security.go b/internal/core/security.go index 63a7ac21..81a428af 100644 --- a/internal/core/security.go +++ b/internal/core/security.go @@ -1,13 +1,21 @@ +// 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/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" +) + +type ( + Captcha = dbr.Captcha ) // SecurityService 安全相关服务 type SecurityService interface { - GetLatestPhoneCaptcha(phone string) (*model.Captcha, error) - UsePhoneCaptcha(captcha *model.Captcha) error + GetLatestPhoneCaptcha(phone string) (*Captcha, error) + UsePhoneCaptcha(captcha *Captcha) error SendPhoneCaptcha(phone string) error } diff --git a/internal/core/storage.go b/internal/core/storage.go index 2a241bca..310edf29 100644 --- a/internal/core/storage.go +++ b/internal/core/storage.go @@ -1,3 +1,7 @@ +// 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 ( diff --git a/internal/core/topics.go b/internal/core/topics.go index a894f9b2..138cc151 100644 --- a/internal/core/topics.go +++ b/internal/core/topics.go @@ -1,13 +1,22 @@ +// 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/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" +) + +type ( + Tag = dbr.Tag + TagFormated = dbr.TagFormated ) // TopicService 话题服务 type TopicService interface { - CreateTag(tag *model.Tag) (*model.Tag, error) - DeleteTag(tag *model.Tag) error - GetTags(conditions *model.ConditionsT, offset, limit int) ([]*model.Tag, error) - GetTagsByKeyword(keyword string) ([]*model.Tag, error) + CreateTag(tag *Tag) (*Tag, error) + DeleteTag(tag *Tag) error + GetTags(conditions *ConditionsT, offset, limit int) ([]*Tag, error) + GetTagsByKeyword(keyword string) ([]*Tag, error) } diff --git a/internal/core/tweets.go b/internal/core/tweets.go index 1b454c6d..682cbd65 100644 --- a/internal/core/tweets.go +++ b/internal/core/tweets.go @@ -1,49 +1,83 @@ +// 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/model" - "github.com/rocboss/paopao-ce/internal/model/rest" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" +) + +const ( + AttachmentTypeImage = dbr.AttachmentTypeImage + AttachmentTypeVideo = dbr.AttachmentTypeVideo + AttachmentTypeOther = dbr.AttachmentTypeOther + + // 类型,1标题,2文字段落,3图片地址,4视频地址,5语音地址,6链接地址,7附件资源 + ContentTypeTitle = dbr.ContentTypeTitle + ContentTypeText = dbr.ContentTypeText + ContentTypeImage = dbr.ContentTypeImage + ContentTypeVideo = dbr.ContentTypeVideo + ContentTypeAudio = dbr.ContentTypeAudio + ContentTypeLink = dbr.ContentTypeLink + ContentTypeAttachment = dbr.ContentTypeAttachment + ContentTypeChargeAttachment = dbr.ContentTypeChargeAttachment +) + +type ( + PostStar = dbr.PostStar + PostCollection = dbr.PostCollection + PostAttachmentBill = dbr.PostAttachmentBill + PostContent = dbr.PostContent + Attachment = dbr.Attachment + AttachmentType = dbr.AttachmentType + PostContentT = dbr.PostContentT + + IndexTweetList struct { + Tweets []*PostFormated + Total int64 + } ) // TweetService 推文检索服务 type TweetService interface { - GetPostByID(id int64) (*model.Post, error) - GetPosts(conditions *model.ConditionsT, offset, limit int) ([]*model.Post, error) - GetPostCount(conditions *model.ConditionsT) (int64, error) - GetUserPostStar(postID, userID int64) (*model.PostStar, error) - GetUserPostStars(userID int64, offset, limit int) ([]*model.PostStar, error) + GetPostByID(id int64) (*Post, error) + GetPosts(conditions *ConditionsT, offset, limit int) ([]*Post, error) + GetPostCount(conditions *ConditionsT) (int64, error) + GetUserPostStar(postID, userID int64) (*PostStar, error) + GetUserPostStars(userID int64, offset, limit int) ([]*PostStar, error) GetUserPostStarCount(userID int64) (int64, error) - GetUserPostCollection(postID, userID int64) (*model.PostCollection, error) - GetUserPostCollections(userID int64, offset, limit int) ([]*model.PostCollection, error) + GetUserPostCollection(postID, userID int64) (*PostCollection, error) + GetUserPostCollections(userID int64, offset, limit int) ([]*PostCollection, error) GetUserPostCollectionCount(userID int64) (int64, error) - GetPostAttatchmentBill(postID, userID int64) (*model.PostAttachmentBill, error) - GetPostContentsByIDs(ids []int64) ([]*model.PostContent, error) - GetPostContentByID(id int64) (*model.PostContent, error) + GetPostAttatchmentBill(postID, userID int64) (*PostAttachmentBill, error) + GetPostContentsByIDs(ids []int64) ([]*PostContent, error) + GetPostContentByID(id int64) (*PostContent, error) } // TweetManageService 推文管理服务,包括创建/删除/更新推文 type TweetManageService interface { - CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) - CreatePost(post *model.Post) (*model.Post, error) - DeletePost(post *model.Post) ([]string, error) - LockPost(post *model.Post) error - StickPost(post *model.Post) error - VisiblePost(post *model.Post, visibility model.PostVisibleT) error - UpdatePost(post *model.Post) error - CreatePostStar(postID, userID int64) (*model.PostStar, error) - DeletePostStar(p *model.PostStar) error - CreatePostCollection(postID, userID int64) (*model.PostCollection, error) - DeletePostCollection(p *model.PostCollection) error - CreatePostContent(content *model.PostContent) (*model.PostContent, error) + CreateAttachment(attachment *Attachment) (*Attachment, error) + CreatePost(post *Post) (*Post, error) + DeletePost(post *Post) ([]string, error) + LockPost(post *Post) error + StickPost(post *Post) error + VisiblePost(post *Post, visibility PostVisibleT) error + UpdatePost(post *Post) error + CreatePostStar(postID, userID int64) (*PostStar, error) + DeletePostStar(p *PostStar) error + CreatePostCollection(postID, userID int64) (*PostCollection, error) + DeletePostCollection(p *PostCollection) error + CreatePostContent(content *PostContent) (*PostContent, error) } // TweetHelpService 推文辅助服务 type TweetHelpService interface { - RevampPosts(posts []*model.PostFormated) ([]*model.PostFormated, error) - MergePosts(posts []*model.Post) ([]*model.PostFormated, error) + RevampPosts(posts []*PostFormated) ([]*PostFormated, error) + MergePosts(posts []*Post) ([]*PostFormated, error) } // IndexPostsService 广场首页推文列表服务 type IndexPostsService interface { - IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) + IndexPosts(user *User, offset int, limit int) (*IndexTweetList, error) } diff --git a/internal/core/types.go b/internal/core/types.go new file mode 100644 index 00000000..6ca95893 --- /dev/null +++ b/internal/core/types.go @@ -0,0 +1,24 @@ +// 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/dao/jinzhu/dbr" +) + +const ( + UserStatusNormal = dbr.UserStatusNormal + UserStatusClosed = dbr.UserStatusClosed +) + +type ( + User = dbr.User + Post = dbr.Post + ConditionsT = dbr.ConditionsT + PostFormated = dbr.PostFormated + UserFormated = dbr.UserFormated + PostContentFormated = dbr.PostContentFormated + Model = dbr.Model +) diff --git a/internal/core/user.go b/internal/core/user.go index cf0ebaa8..ed132dd3 100644 --- a/internal/core/user.go +++ b/internal/core/user.go @@ -1,19 +1,33 @@ +// 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/model" - "github.com/rocboss/paopao-ce/internal/model/rest" +type ( + ContactItem struct { + UserId int64 `json:"user_id"` + UserName string `json:"username"` + Nickname string `json:"nickname"` + Avatar string `json:"avatar"` + Phone string `json:"phone"` + } + + ContactList struct { + Contacts []ContactItem `json:"contacts"` + Total int64 `json:"total"` + } ) // UserManageService 用户管理服务 type UserManageService interface { - GetUserByID(id int64) (*model.User, error) - GetUserByUsername(username string) (*model.User, error) - GetUserByPhone(phone string) (*model.User, error) - GetUsersByIDs(ids []int64) ([]*model.User, error) - GetUsersByKeyword(keyword string) ([]*model.User, error) - CreateUser(user *model.User) (*model.User, error) - UpdateUser(user *model.User) error + GetUserByID(id int64) (*User, error) + GetUserByUsername(username string) (*User, error) + GetUserByPhone(phone string) (*User, error) + GetUsersByIDs(ids []int64) ([]*User, error) + GetUsersByKeyword(keyword string) ([]*User, error) + CreateUser(user *User) (*User, error) + UpdateUser(user *User) error } // ContactManageService 联系人管理服务 @@ -22,6 +36,6 @@ type ContactManageService interface { AddFriend(userId int64, friendId int64) error RejectFriend(userId int64, friendId int64) error DeleteFriend(userId int64, friendId int64) error - GetContacts(userId int64, offset int, limit int) (*rest.ContactsResp, error) + GetContacts(userId int64, offset int, limit int) (*ContactList, error) IsFriend(userID int64, friendID int64) bool } diff --git a/internal/core/version.go b/internal/core/version.go index e603c0a5..07376c39 100644 --- a/internal/core/version.go +++ b/internal/core/version.go @@ -1,3 +1,7 @@ +// 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 ( diff --git a/internal/core/wallet.go b/internal/core/wallet.go index 5b3a3391..c4792d3b 100644 --- a/internal/core/wallet.go +++ b/internal/core/wallet.go @@ -1,15 +1,24 @@ +// 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/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" +) + +type ( + WalletStatement = dbr.WalletStatement + WalletRecharge = dbr.WalletRecharge ) // WalletService wallet service interface type WalletService interface { - GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error) + GetUserWalletBills(userID int64, offset, limit int) ([]*WalletStatement, error) GetUserWalletBillCount(userID int64) (int64, error) - GetRechargeByID(id int64) (*model.WalletRecharge, error) - CreateRecharge(userId, amount int64) (*model.WalletRecharge, error) - HandleRechargeSuccess(recharge *model.WalletRecharge, tradeNo string) error - HandlePostAttachmentBought(post *model.Post, user *model.User) error + GetRechargeByID(id int64) (*WalletRecharge, error) + CreateRecharge(userId, amount int64) (*WalletRecharge, error) + HandleRechargeSuccess(recharge *WalletRecharge, tradeNo string) error + HandlePostAttachmentBought(post *Post, user *User) error } diff --git a/internal/dao/cache/bigcache.go b/internal/dao/cache/bigcache.go index 4fce26de..8ec83c38 100644 --- a/internal/dao/cache/bigcache.go +++ b/internal/dao/cache/bigcache.go @@ -1,3 +1,7 @@ +// 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 cache import ( @@ -11,8 +15,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/allegro/bigcache/v3" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/model/rest" "github.com/rocboss/paopao-ce/pkg/types" "github.com/sirupsen/logrus" ) @@ -24,7 +26,7 @@ var ( type postsEntry struct { key string - tweets *rest.IndexTweetsResp + tweets *core.IndexTweetList } type bigCacheIndexServant struct { @@ -38,7 +40,7 @@ type bigCacheIndexServant struct { preventDuration time.Duration } -func (s *bigCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { +func (s *bigCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { key := s.keyFrom(user, offset, limit) posts, err := s.getPosts(key) if err == nil { @@ -54,7 +56,7 @@ func (s *bigCacheIndexServant) IndexPosts(user *model.User, offset int, limit in return posts, nil } -func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, error) { +func (s *bigCacheIndexServant) getPosts(key string) (*core.IndexTweetList, error) { data, err := s.cache.Get(key) if err != nil { logrus.Debugf("bigCacheIndexServant.getPosts get posts by key: %s from cache err: %v", key, err) @@ -62,7 +64,7 @@ func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, erro } buf := bytes.NewBuffer(data) dec := gob.NewDecoder(buf) - var resp rest.IndexTweetsResp + var resp core.IndexTweetList if err := dec.Decode(&resp); err != nil { logrus.Debugf("bigCacheIndexServant.getPosts get posts from cache in decode err: %v", err) return nil, err @@ -70,7 +72,7 @@ func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, erro return &resp, nil } -func (s *bigCacheIndexServant) cachePosts(key string, tweets *rest.IndexTweetsResp) { +func (s *bigCacheIndexServant) cachePosts(key string, tweets *core.IndexTweetList) { entry := &postsEntry{key: key, tweets: tweets} select { case s.cachePostsCh <- entry: @@ -96,7 +98,7 @@ func (s *bigCacheIndexServant) setPosts(entry *postsEntry) { logrus.Debugf("bigCacheIndexServant.setPosts setPosts set cache by key: %s", entry.key) } -func (s *bigCacheIndexServant) keyFrom(user *model.User, offset int, limit int) string { +func (s *bigCacheIndexServant) keyFrom(user *core.User, offset int, limit int) string { var userId int64 = -1 if user != nil { userId = user.ID @@ -104,7 +106,7 @@ func (s *bigCacheIndexServant) keyFrom(user *model.User, offset int, limit int) return fmt.Sprintf("index:%d:%d:%d", userId, offset, limit) } -func (s *bigCacheIndexServant) SendAction(act core.IdxAct, post *model.Post) { +func (s *bigCacheIndexServant) SendAction(act core.IdxAct, post *core.Post) { action := core.NewIndexAction(act, post) select { case s.indexActionCh <- action: @@ -134,7 +136,7 @@ func (s *bigCacheIndexServant) handleIndexAction(action *core.IndexAction) { // 创建/删除 私密推文特殊处理 switch act { case core.IdxActCreatePost, core.IdxActDeletePost: - if post.Visibility == model.PostVisitPrivate { + if post.Visibility == core.PostVisitPrivate { s.deleteCacheByUserId(post.UserID, true) return } diff --git a/internal/dao/cache/cache.go b/internal/dao/cache/cache.go index 1b12ad88..773c9a2f 100644 --- a/internal/dao/cache/cache.go +++ b/internal/dao/cache/cache.go @@ -1,3 +1,7 @@ +// 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 cache import ( diff --git a/internal/dao/cache/none.go b/internal/dao/cache/none.go index 79705280..ce6e1caf 100644 --- a/internal/dao/cache/none.go +++ b/internal/dao/cache/none.go @@ -1,10 +1,12 @@ +// 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 cache import ( "github.com/Masterminds/semver/v3" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/model/rest" ) var ( @@ -16,11 +18,11 @@ type noneCacheIndexServant struct { ips core.IndexPostsService } -func (s *noneCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { +func (s *noneCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { return s.ips.IndexPosts(user, offset, limit) } -func (s *noneCacheIndexServant) SendAction(_act core.IdxAct, _post *model.Post) { +func (s *noneCacheIndexServant) SendAction(_act core.IdxAct, _post *core.Post) { // empty } diff --git a/internal/dao/cache/simple.go b/internal/dao/cache/simple.go index afdea1be..ba674d1b 100644 --- a/internal/dao/cache/simple.go +++ b/internal/dao/cache/simple.go @@ -1,3 +1,7 @@ +// 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 cache import ( @@ -6,8 +10,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/model/rest" "github.com/sirupsen/logrus" ) @@ -20,21 +22,21 @@ type simpleCacheIndexServant struct { ips core.IndexPostsService indexActionCh chan core.IdxAct - indexPosts *rest.IndexTweetsResp + indexPosts *core.IndexTweetList atomicIndex atomic.Value maxIndexSize int checkTick *time.Ticker expireIndexTick *time.Ticker } -func (s *simpleCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { - cacheResp := s.atomicIndex.Load().(*rest.IndexTweetsResp) +func (s *simpleCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { + cacheResp := s.atomicIndex.Load().(*core.IndexTweetList) end := offset + limit if cacheResp != nil { size := len(cacheResp.Tweets) logrus.Debugf("simpleCacheIndexServant.IndexPosts get index posts from cache posts: %d offset:%d limit:%d start:%d, end:%d", size, offset, limit, offset, end) if size >= end { - return &rest.IndexTweetsResp{ + return &core.IndexTweetList{ Tweets: cacheResp.Tweets[offset:end], Total: cacheResp.Total, }, nil @@ -45,7 +47,7 @@ func (s *simpleCacheIndexServant) IndexPosts(user *model.User, offset int, limit return s.ips.IndexPosts(user, offset, limit) } -func (s *simpleCacheIndexServant) SendAction(act core.IdxAct, _post *model.Post) { +func (s *simpleCacheIndexServant) SendAction(act core.IdxAct, _post *core.Post) { select { case s.indexActionCh <- act: logrus.Debugf("simpleCacheIndexServant.SendAction send indexAction by chan: %s", act) diff --git a/internal/dao/dao.go b/internal/dao/dao.go index 6f4a776a..e4b2ea6a 100644 --- a/internal/dao/dao.go +++ b/internal/dao/dao.go @@ -1,3 +1,7 @@ +// 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 dao import ( diff --git a/internal/dao/jinzhu/authority.go b/internal/dao/jinzhu/authority.go index c0f59556..5932fa24 100644 --- a/internal/dao/jinzhu/authority.go +++ b/internal/dao/jinzhu/authority.go @@ -1,8 +1,12 @@ +// 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 jinzhu import ( "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "github.com/rocboss/paopao-ce/pkg/types" "gorm.io/gorm" ) @@ -21,7 +25,7 @@ func newAuthorizationManageService(db *gorm.DB) core.AuthorizationManageService } } -func (s *authorizationManageServant) IsAllow(user *model.User, action *core.Action) bool { +func (s *authorizationManageServant) IsAllow(user *core.User, action *core.Action) bool { // user is activation if had bind phone isActivation := (len(user.Phone) != 0) isFriend := s.isFriend(user.ID, action.UserId) @@ -30,7 +34,7 @@ func (s *authorizationManageServant) IsAllow(user *model.User, action *core.Acti } func (s *authorizationManageServant) MyFriendSet(userId int64) core.FriendSet { - ids, err := (&model.Contact{UserId: userId}).MyFriendIds(s.db) + ids, err := (&dbr.Contact{UserId: userId}).MyFriendIds(s.db) if err != nil { return core.FriendSet{} } @@ -43,7 +47,7 @@ func (s *authorizationManageServant) MyFriendSet(userId int64) core.FriendSet { } func (s *authorizationManageServant) BeFriendFilter(userId int64) core.FriendFilter { - ids, err := (&model.Contact{FriendId: userId}).BeFriendIds(s.db) + ids, err := (&dbr.Contact{FriendId: userId}).BeFriendIds(s.db) if err != nil { return core.FriendFilter{} } @@ -56,12 +60,12 @@ func (s *authorizationManageServant) BeFriendFilter(userId int64) core.FriendFil } func (s *authorizationManageServant) BeFriendIds(userId int64) ([]int64, error) { - return (&model.Contact{FriendId: userId}).BeFriendIds(s.db) + return (&dbr.Contact{FriendId: userId}).BeFriendIds(s.db) } func (s *authorizationManageServant) isFriend(userId int64, friendId int64) bool { - contact, err := (&model.Contact{UserId: friendId, FriendId: userId}).GetByUserFriend(s.db) - if err == nil || contact.Status == model.ContactStatusAgree { + contact, err := (&dbr.Contact{UserId: friendId, FriendId: userId}).GetByUserFriend(s.db) + if err == nil || contact.Status == dbr.ContactStatusAgree { return true } return false diff --git a/internal/dao/jinzhu/comments.go b/internal/dao/jinzhu/comments.go index c15e74f3..1af9e5ce 100644 --- a/internal/dao/jinzhu/comments.go +++ b/internal/dao/jinzhu/comments.go @@ -1,8 +1,12 @@ +// 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 jinzhu import ( "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "gorm.io/gorm" ) @@ -31,42 +35,42 @@ func newCommentManageService(db *gorm.DB) core.CommentManageService { } } -func (s *commentServant) GetComments(conditions *model.ConditionsT, offset, limit int) ([]*model.Comment, error) { - return (&model.Comment{}).List(s.db, conditions, offset, limit) +func (s *commentServant) GetComments(conditions *core.ConditionsT, offset, limit int) ([]*core.Comment, error) { + return (&dbr.Comment{}).List(s.db, conditions, offset, limit) } -func (s *commentServant) GetCommentByID(id int64) (*model.Comment, error) { - comment := &model.Comment{ - Model: &model.Model{ +func (s *commentServant) GetCommentByID(id int64) (*core.Comment, error) { + comment := &dbr.Comment{ + Model: &dbr.Model{ ID: id, }, } return comment.Get(s.db) } -func (s *commentServant) GetCommentReplyByID(id int64) (*model.CommentReply, error) { - reply := &model.CommentReply{ - Model: &model.Model{ +func (s *commentServant) GetCommentReplyByID(id int64) (*core.CommentReply, error) { + reply := &dbr.CommentReply{ + Model: &dbr.Model{ ID: id, }, } return reply.Get(s.db) } -func (s *commentServant) GetCommentCount(conditions *model.ConditionsT) (int64, error) { - return (&model.Comment{}).Count(s.db, conditions) +func (s *commentServant) GetCommentCount(conditions *core.ConditionsT) (int64, error) { + return (&dbr.Comment{}).Count(s.db, conditions) } -func (s *commentServant) GetCommentContentsByIDs(ids []int64) ([]*model.CommentContent, error) { - commentContent := &model.CommentContent{} - return commentContent.List(s.db, &model.ConditionsT{ +func (s *commentServant) GetCommentContentsByIDs(ids []int64) ([]*core.CommentContent, error) { + commentContent := &dbr.CommentContent{} + return commentContent.List(s.db, &dbr.ConditionsT{ "comment_id IN ?": ids, }, 0, 0) } -func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentReplyFormated, error) { - CommentReply := &model.CommentReply{} - replies, err := CommentReply.List(s.db, &model.ConditionsT{ +func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*core.CommentReplyFormated, error) { + CommentReply := &dbr.CommentReply{} + replies, err := CommentReply.List(s.db, &dbr.ConditionsT{ "comment_id IN ?": ids, }, 0, 0) @@ -83,7 +87,7 @@ func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentRep if err != nil { return nil, err } - repliesFormated := []*model.CommentReplyFormated{} + repliesFormated := []*core.CommentReplyFormated{} for _, reply := range replies { replyFormated := reply.Format() for _, user := range users { @@ -101,22 +105,22 @@ func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentRep return repliesFormated, nil } -func (s *commentManageServant) DeleteComment(comment *model.Comment) error { +func (s *commentManageServant) DeleteComment(comment *core.Comment) error { return comment.Delete(s.db) } -func (s *commentManageServant) CreateComment(comment *model.Comment) (*model.Comment, error) { +func (s *commentManageServant) CreateComment(comment *core.Comment) (*core.Comment, error) { return comment.Create(s.db) } -func (s *commentManageServant) CreateCommentReply(reply *model.CommentReply) (*model.CommentReply, error) { +func (s *commentManageServant) CreateCommentReply(reply *core.CommentReply) (*core.CommentReply, error) { return reply.Create(s.db) } -func (s *commentManageServant) DeleteCommentReply(reply *model.CommentReply) error { +func (s *commentManageServant) DeleteCommentReply(reply *core.CommentReply) error { return reply.Delete(s.db) } -func (s *commentManageServant) CreateCommentContent(content *model.CommentContent) (*model.CommentContent, error) { +func (s *commentManageServant) CreateCommentContent(content *core.CommentContent) (*core.CommentContent, error) { return content.Create(s.db) } diff --git a/internal/dao/jinzhu/contacts.go b/internal/dao/jinzhu/contacts.go index c55a94a0..c26ae4de 100644 --- a/internal/dao/jinzhu/contacts.go +++ b/internal/dao/jinzhu/contacts.go @@ -1,11 +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 jinzhu import ( "time" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/model/rest" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "github.com/sirupsen/logrus" "gorm.io/gorm" ) @@ -24,14 +27,14 @@ func newContactManageService(db *gorm.DB) core.ContactManageService { } } -func (s *contactManageServant) fetchOrNewContact(db *gorm.DB, userId int64, friendId int64, status int8) (*model.Contact, error) { - contact := &model.Contact{ +func (s *contactManageServant) fetchOrNewContact(db *gorm.DB, userId int64, friendId int64, status int8) (*dbr.Contact, error) { + contact := &dbr.Contact{ UserId: userId, FriendId: friendId, } contact, err := contact.FetchUser(db) if err != nil { - contact = &model.Contact{ + contact = &dbr.Contact{ UserId: userId, FriendId: friendId, Status: status, @@ -54,17 +57,17 @@ func (s *contactManageServant) RequestingFriend(userId int64, friendId int64, gr } }() - contact, e := s.fetchOrNewContact(db, userId, friendId, model.ContactStatusRequesting) + contact, e := s.fetchOrNewContact(db, userId, friendId, dbr.ContactStatusRequesting) if e != nil { err = e return } // 如果已经好友,啥也不干 - if contact.Status == model.ContactStatusAgree { + if contact.Status == dbr.ContactStatusAgree { return nil - } else if contact.Status == model.ContactStatusReject || contact.Status == model.ContactStatusDeleted { - contact.Status = model.ContactStatusRequesting + } else if contact.Status == dbr.ContactStatusReject || contact.Status == dbr.ContactStatusDeleted { + contact.Status = dbr.ContactStatusRequesting contact.IsDel = 0 // remove deleted flag if needed if err = contact.UpdateInUnscoped(db); err != nil { logrus.Errorf("contactManageServant.RequestingFriend update exsit contact err:%s", err) @@ -72,13 +75,13 @@ func (s *contactManageServant) RequestingFriend(userId int64, friendId int64, gr } } - msg := &model.Message{ + msg := &dbr.Message{ SenderUserID: userId, ReceiverUserID: friendId, - Type: model.MsgTypeRequestingFriend, + Type: dbr.MsgTypeRequestingFriend, Brief: "请求添加好友,并附言:", Content: greetings, - ReplyID: int64(model.ContactStatusRequesting), + ReplyID: int64(dbr.ContactStatusRequesting), } if _, err = msg.Create(db); err != nil { logrus.Errorf("contactManageServant.RequestingFriend create message err:%s", err) @@ -97,7 +100,7 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro } }() - contact := &model.Contact{ + contact := &dbr.Contact{ UserId: friendId, FriendId: userId, } @@ -105,23 +108,23 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro return } // 如果还不是请求好友,啥也不干 - if contact.Status != model.ContactStatusRequesting { + if contact.Status != dbr.ContactStatusRequesting { logrus.Debugf("contactManageServant.AddFriend not reuesting status now so skip") return nil } - contact.Status = model.ContactStatusAgree + contact.Status = dbr.ContactStatusAgree if err = contact.Update(db); err != nil { return err } - contact, err = s.fetchOrNewContact(db, userId, friendId, model.ContactStatusAgree) + contact, err = s.fetchOrNewContact(db, userId, friendId, dbr.ContactStatusAgree) if err != nil { return } // 如果已经好友,啥也不干 - if contact.Status != model.ContactStatusAgree { - contact.Status = model.ContactStatusAgree + if contact.Status != dbr.ContactStatusAgree { + contact.Status = dbr.ContactStatusAgree contact.IsDel = 0 // remove deleted flag if err = contact.UpdateInUnscoped(db); err != nil { logrus.Errorf("contactManageServant.AddFriend update contact err:%s", err) @@ -129,8 +132,8 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro } } - args := []any{userId, friendId, friendId, userId, model.MsgTypeRequestingFriend, model.ContactStatusRequesting} - msgs, e := (&model.Message{}).FetchBy(db, model.Predicates{ + args := []any{userId, friendId, friendId, userId, dbr.MsgTypeRequestingFriend, dbr.ContactStatusRequesting} + msgs, e := (&dbr.Message{}).FetchBy(db, dbr.Predicates{ "((sender_user_id = ? AND receiver_user_id = ?) OR (sender_user_id = ? AND receiver_user_id = ?)) AND type = ? AND reply_id = ?": args, }) if e != nil { @@ -138,7 +141,7 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro return } for _, msg := range msgs { - msg.ReplyID = int64(model.ContactStatusAgree) + msg.ReplyID = int64(dbr.ContactStatusAgree) if err = msg.Update(db); err != nil { return } @@ -156,7 +159,7 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e } }() - contact := &model.Contact{ + contact := &dbr.Contact{ UserId: friendId, FriendId: userId, } @@ -164,16 +167,16 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e return } // 如果还不是请求好友,啥也不干 - if contact.Status != model.ContactStatusRequesting { + if contact.Status != dbr.ContactStatusRequesting { return nil } - contact.Status = model.ContactStatusReject + contact.Status = dbr.ContactStatusReject if err = contact.Update(db); err != nil { return err } - args := []any{friendId, userId, model.MsgTypeRequestingFriend, model.ContactStatusRequesting} - msgs, e := (&model.Message{}).FetchBy(db, model.Predicates{ + args := []any{friendId, userId, dbr.MsgTypeRequestingFriend, dbr.ContactStatusRequesting} + msgs, e := (&dbr.Message{}).FetchBy(db, dbr.Predicates{ "sender_user_id = ? AND receiver_user_id = ? AND type = ? AND reply_id = ?": args, }) if e != nil { @@ -181,7 +184,7 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e return } for _, msg := range msgs { - msg.ReplyID = int64(model.ContactStatusReject) + msg.ReplyID = int64(dbr.ContactStatusReject) if err = msg.Update(db); err != nil { return } @@ -199,7 +202,7 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e } }() - contact := &model.Contact{ + contact := &dbr.Contact{ UserId: userId, FriendId: friendId, } @@ -210,10 +213,10 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e for _, contact := range contacts { // 如果还不是好友,啥也不干 - if contact.Status != model.ContactStatusAgree { + if contact.Status != dbr.ContactStatusAgree { continue } - contact.Status = model.ContactStatusDeleted + contact.Status = dbr.ContactStatusDeleted contact.DeletedOn = time.Now().Unix() contact.IsDel = 1 if err = contact.Update(db); err != nil { @@ -223,11 +226,11 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e return nil } -func (s *contactManageServant) GetContacts(userId int64, offset int, limit int) (*rest.ContactsResp, error) { - contact := &model.Contact{} - condition := model.ConditionsT{ +func (s *contactManageServant) GetContacts(userId int64, offset int, limit int) (*core.ContactList, error) { + contact := &dbr.Contact{} + condition := dbr.ConditionsT{ "user_id": userId, - "status": model.ContactStatusAgree, + "status": dbr.ContactStatusAgree, } contacts, err := contact.List(s.db, condition, offset, limit) if err != nil { @@ -237,13 +240,13 @@ func (s *contactManageServant) GetContacts(userId int64, offset int, limit int) if err != nil { return nil, err } - resp := &rest.ContactsResp{ - Contacts: make([]rest.ContactItem, 0, len(contacts)), + resp := &core.ContactList{ + Contacts: make([]core.ContactItem, 0, len(contacts)), Total: total, } for _, c := range contacts { if c.User != nil { - resp.Contacts = append(resp.Contacts, rest.ContactItem{ + resp.Contacts = append(resp.Contacts, core.ContactItem{ UserId: c.FriendId, UserName: c.User.Username, Nickname: c.User.Nickname, @@ -256,12 +259,12 @@ func (s *contactManageServant) GetContacts(userId int64, offset int, limit int) } func (s *contactManageServant) IsFriend(userId int64, friendId int64) bool { - contact := &model.Contact{ + contact := &dbr.Contact{ UserId: friendId, FriendId: userId, } contact, err := contact.GetByUserFriend(s.db) - if err == nil && contact.Status == model.ContactStatusAgree { + if err == nil && contact.Status == dbr.ContactStatusAgree { return true } return false diff --git a/internal/dao/jinzhu/dbr/attachment.go b/internal/dao/jinzhu/dbr/attachment.go index 0c748b00..b62a5d8b 100644 --- a/internal/dao/jinzhu/dbr/attachment.go +++ b/internal/dao/jinzhu/dbr/attachment.go @@ -1,13 +1,17 @@ -package model +// 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 dbr import "gorm.io/gorm" type AttachmentType int const ( - ATTACHMENT_TYPE_IMAGE AttachmentType = iota + 1 - ATTACHMENT_TYPE_VIDEO - ATTACHMENT_TYPE_OTHER + AttachmentTypeImage AttachmentType = iota + 1 + AttachmentTypeVideo + AttachmentTypeOther ) type Attachment struct { diff --git a/internal/dao/jinzhu/dbr/captcha.go b/internal/dao/jinzhu/dbr/captcha.go index 210cc691..4567d4b3 100644 --- a/internal/dao/jinzhu/dbr/captcha.go +++ b/internal/dao/jinzhu/dbr/captcha.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import "gorm.io/gorm" diff --git a/internal/dao/jinzhu/dbr/comment.go b/internal/dao/jinzhu/dbr/comment.go index 72494b53..80192df7 100644 --- a/internal/dao/jinzhu/dbr/comment.go +++ b/internal/dao/jinzhu/dbr/comment.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "time" diff --git a/internal/dao/jinzhu/dbr/comment_content.go b/internal/dao/jinzhu/dbr/comment_content.go index b7d42dfd..778f113a 100644 --- a/internal/dao/jinzhu/dbr/comment_content.go +++ b/internal/dao/jinzhu/dbr/comment_content.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "time" @@ -47,7 +51,7 @@ func (c *CommentContent) Create(db *gorm.DB) (*CommentContent, error) { } func (c *CommentContent) MediaContentsByCommentId(db *gorm.DB, commentIds []int64) (contents []string, err error) { - err = db.Model(c).Where("comment_id IN ? AND type = ?", commentIds, CONTENT_TYPE_IMAGE).Select("content").Find(&contents).Error + err = db.Model(c).Where("comment_id IN ? AND type = ?", commentIds, ContentTypeImage).Select("content").Find(&contents).Error return } diff --git a/internal/dao/jinzhu/dbr/comment_reply.go b/internal/dao/jinzhu/dbr/comment_reply.go index fd22702f..fe527be5 100644 --- a/internal/dao/jinzhu/dbr/comment_reply.go +++ b/internal/dao/jinzhu/dbr/comment_reply.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "time" diff --git a/internal/dao/jinzhu/dbr/contact.go b/internal/dao/jinzhu/dbr/contact.go index 14049f77..e8c12bd0 100644 --- a/internal/dao/jinzhu/dbr/contact.go +++ b/internal/dao/jinzhu/dbr/contact.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "github.com/sirupsen/logrus" diff --git a/internal/dao/jinzhu/dbr/dbr.go b/internal/dao/jinzhu/dbr/dbr.go deleted file mode 100644 index 99bc8296..00000000 --- a/internal/dao/jinzhu/dbr/dbr.go +++ /dev/null @@ -1,36 +0,0 @@ -package model - -import ( - "time" - - "gorm.io/gorm" - "gorm.io/plugin/soft_delete" -) - -// Model 公共Model -type Model struct { - ID int64 `gorm:"primary_key" json:"id"` - CreatedOn int64 `json:"created_on"` - ModifiedOn int64 `json:"modified_on"` - DeletedOn int64 `json:"deleted_on"` - IsDel soft_delete.DeletedAt `gorm:"softDelete:flag" json:"is_del"` -} - -type ConditionsT map[string]any -type Predicates map[string][]any - -func (m *Model) BeforeCreate(tx *gorm.DB) (err error) { - nowTime := time.Now().Unix() - - tx.Statement.SetColumn("created_on", nowTime) - tx.Statement.SetColumn("modified_on", nowTime) - return -} - -func (m *Model) BeforeUpdate(tx *gorm.DB) (err error) { - if !tx.Statement.Changed("modified_on") { - tx.Statement.SetColumn("modified_on", time.Now().Unix()) - } - - return -} diff --git a/internal/dao/jinzhu/dbr/message.go b/internal/dao/jinzhu/dbr/message.go index c1277cf7..6c952bae 100644 --- a/internal/dao/jinzhu/dbr/message.go +++ b/internal/dao/jinzhu/dbr/message.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import "gorm.io/gorm" diff --git a/internal/model/model.go b/internal/dao/jinzhu/dbr/model.go similarity index 83% rename from internal/model/model.go rename to internal/dao/jinzhu/dbr/model.go index 99bc8296..75e66561 100644 --- a/internal/model/model.go +++ b/internal/dao/jinzhu/dbr/model.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "time" diff --git a/internal/dao/jinzhu/dbr/post.go b/internal/dao/jinzhu/dbr/post.go index ae428a9a..a47dedfc 100644 --- a/internal/dao/jinzhu/dbr/post.go +++ b/internal/dao/jinzhu/dbr/post.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "strings" diff --git a/internal/dao/jinzhu/dbr/post_attachment_bill.go b/internal/dao/jinzhu/dbr/post_attachment_bill.go index 8ee7aae6..7bdd812f 100644 --- a/internal/dao/jinzhu/dbr/post_attachment_bill.go +++ b/internal/dao/jinzhu/dbr/post_attachment_bill.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import "gorm.io/gorm" diff --git a/internal/dao/jinzhu/dbr/post_collection.go b/internal/dao/jinzhu/dbr/post_collection.go index 0ea0cb29..04ca2647 100644 --- a/internal/dao/jinzhu/dbr/post_collection.go +++ b/internal/dao/jinzhu/dbr/post_collection.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "time" diff --git a/internal/dao/jinzhu/dbr/post_content.go b/internal/dao/jinzhu/dbr/post_content.go index b301de62..672cc57e 100644 --- a/internal/dao/jinzhu/dbr/post_content.go +++ b/internal/dao/jinzhu/dbr/post_content.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "time" @@ -7,27 +11,26 @@ import ( ) // 类型,1标题,2文字段落,3图片地址,4视频地址,5语音地址,6链接地址,7附件资源 - type PostContentT int const ( - CONTENT_TYPE_TITLE PostContentT = iota + 1 - CONTENT_TYPE_TEXT - CONTENT_TYPE_IMAGE - CONTENT_TYPE_VIDEO - CONTENT_TYPE_AUDIO - CONTENT_TYPE_LINK - CONTENT_TYPE_ATTACHMENT - CONTENT_TYPE_CHARGE_ATTACHMENT + ContentTypeTitle PostContentT = iota + 1 + ContentTypeText + ContentTypeImage + ContentTypeVideo + ContentTypeAudio + ContentTypeLink + ContentTypeAttachment + ContentTypeChargeAttachment ) var ( mediaContentType = []PostContentT{ - CONTENT_TYPE_IMAGE, - CONTENT_TYPE_VIDEO, - CONTENT_TYPE_AUDIO, - CONTENT_TYPE_ATTACHMENT, - CONTENT_TYPE_CHARGE_ATTACHMENT, + ContentTypeImage, + ContentTypeVideo, + ContentTypeAudio, + ContentTypeAttachment, + ContentTypeChargeAttachment, } ) diff --git a/internal/dao/jinzhu/dbr/post_star.go b/internal/dao/jinzhu/dbr/post_star.go index 3846a9c2..45c48f45 100644 --- a/internal/dao/jinzhu/dbr/post_star.go +++ b/internal/dao/jinzhu/dbr/post_star.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "time" diff --git a/internal/dao/jinzhu/dbr/tag.go b/internal/dao/jinzhu/dbr/tag.go index 34bb64f9..5193df26 100644 --- a/internal/dao/jinzhu/dbr/tag.go +++ b/internal/dao/jinzhu/dbr/tag.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import ( "time" diff --git a/internal/dao/jinzhu/dbr/user.go b/internal/dao/jinzhu/dbr/user.go index 39c52d79..a10d5432 100644 --- a/internal/dao/jinzhu/dbr/user.go +++ b/internal/dao/jinzhu/dbr/user.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import "gorm.io/gorm" diff --git a/internal/dao/jinzhu/dbr/wallet_recharge.go b/internal/dao/jinzhu/dbr/wallet_recharge.go index bfb3bc6f..14601cb0 100644 --- a/internal/dao/jinzhu/dbr/wallet_recharge.go +++ b/internal/dao/jinzhu/dbr/wallet_recharge.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import "gorm.io/gorm" diff --git a/internal/dao/jinzhu/dbr/wallet_statement.go b/internal/dao/jinzhu/dbr/wallet_statement.go index 163e2430..890e34ec 100644 --- a/internal/dao/jinzhu/dbr/wallet_statement.go +++ b/internal/dao/jinzhu/dbr/wallet_statement.go @@ -1,4 +1,8 @@ -package model +// 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 dbr import "gorm.io/gorm" diff --git a/internal/dao/jinzhu/index.go b/internal/dao/jinzhu/index.go index 31712c61..7548de49 100644 --- a/internal/dao/jinzhu/index.go +++ b/internal/dao/jinzhu/index.go @@ -1,9 +1,12 @@ +// 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 jinzhu import ( "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/model/rest" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "github.com/sirupsen/logrus" "gorm.io/gorm" ) @@ -40,20 +43,20 @@ func newSimpleIndexPostsService(db *gorm.DB) core.IndexPostsService { } // IndexPosts 根据userId查询广场推文列表,简单做到不同用户的主页都是不同的; -func (s *indexPostsServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { - predicates := model.Predicates{ +func (s *indexPostsServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { + predicates := dbr.Predicates{ "ORDER": []any{"is_top DESC, latest_replied_on DESC"}, } if user == nil { - predicates["visibility = ?"] = []any{model.PostVisitPublic} + predicates["visibility = ?"] = []any{dbr.PostVisitPublic} } else if !user.IsAdmin { friendIds, _ := s.ams.BeFriendIds(user.ID) friendIds = append(friendIds, user.ID) - args := []any{model.PostVisitPublic, model.PostVisitPrivate, user.ID, model.PostVisitFriend, friendIds} + args := []any{dbr.PostVisitPublic, dbr.PostVisitPrivate, user.ID, dbr.PostVisitFriend, friendIds} predicates["visibility = ? OR (visibility = ? AND user_id = ?) OR (visibility = ? AND user_id IN ?)"] = args } - posts, err := (&model.Post{}).Fetch(s.db, predicates, offset, limit) + posts, err := (&dbr.Post{}).Fetch(s.db, predicates, offset, limit) if err != nil { logrus.Debugf("gormIndexPostsServant.IndexPosts err: %v", err) return nil, err @@ -63,25 +66,25 @@ func (s *indexPostsServant) IndexPosts(user *model.User, offset int, limit int) return nil, err } - total, err := (&model.Post{}).CountBy(s.db, predicates) + total, err := (&dbr.Post{}).CountBy(s.db, predicates) if err != nil { return nil, err } - return &rest.IndexTweetsResp{ + return &core.IndexTweetList{ Tweets: formatPosts, Total: total, }, nil } // simpleCacheIndexGetPosts simpleCacheIndex 专属获取广场推文列表函数 -func (s *simpleIndexPostsServant) IndexPosts(_user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { - predicates := model.Predicates{ - "visibility = ?": []any{model.PostVisitPublic}, +func (s *simpleIndexPostsServant) IndexPosts(_user *core.User, offset int, limit int) (*core.IndexTweetList, error) { + predicates := dbr.Predicates{ + "visibility = ?": []any{dbr.PostVisitPublic}, "ORDER": []any{"is_top DESC, latest_replied_on DESC"}, } - posts, err := (&model.Post{}).Fetch(s.db, predicates, offset, limit) + posts, err := (&dbr.Post{}).Fetch(s.db, predicates, offset, limit) if err != nil { logrus.Debugf("gormSimpleIndexPostsServant.IndexPosts err: %v", err) return nil, err @@ -92,12 +95,12 @@ func (s *simpleIndexPostsServant) IndexPosts(_user *model.User, offset int, limi return nil, err } - total, err := (&model.Post{}).CountBy(s.db, predicates) + total, err := (&dbr.Post{}).CountBy(s.db, predicates) if err != nil { return nil, err } - return &rest.IndexTweetsResp{ + return &core.IndexTweetList{ Tweets: formatPosts, Total: total, }, nil diff --git a/internal/dao/jinzhu/jinzhu.go b/internal/dao/jinzhu/jinzhu.go index 9f5e1c66..753bb639 100644 --- a/internal/dao/jinzhu/jinzhu.go +++ b/internal/dao/jinzhu/jinzhu.go @@ -1,3 +1,7 @@ +// 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. + // Core service implement base gorm+mysql/postgresql/sqlite3. // Jinzhu is the primary developer of gorm so use his name as // package name as a saluter. diff --git a/internal/dao/jinzhu/messages.go b/internal/dao/jinzhu/messages.go index 3e282776..32edaac2 100644 --- a/internal/dao/jinzhu/messages.go +++ b/internal/dao/jinzhu/messages.go @@ -1,8 +1,12 @@ +// 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 jinzhu import ( "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "gorm.io/gorm" ) @@ -20,37 +24,37 @@ func newMessageService(db *gorm.DB) core.MessageService { } } -func (d *messageServant) CreateMessage(msg *model.Message) (*model.Message, error) { +func (d *messageServant) CreateMessage(msg *core.Message) (*core.Message, error) { return msg.Create(d.db) } func (d *messageServant) GetUnreadCount(userID int64) (int64, error) { - return (&model.Message{}).Count(d.db, &model.ConditionsT{ + return (&dbr.Message{}).Count(d.db, &dbr.ConditionsT{ "receiver_user_id": userID, - "is_read": model.MsgStatusUnread, + "is_read": dbr.MsgStatusUnread, }) } -func (d *messageServant) GetMessageByID(id int64) (*model.Message, error) { - return (&model.Message{ - Model: &model.Model{ +func (d *messageServant) GetMessageByID(id int64) (*core.Message, error) { + return (&dbr.Message{ + Model: &dbr.Model{ ID: id, }, }).Get(d.db) } -func (d *messageServant) ReadMessage(message *model.Message) error { +func (d *messageServant) ReadMessage(message *core.Message) error { message.IsRead = 1 return message.Update(d.db) } -func (d *messageServant) GetMessages(conditions *model.ConditionsT, offset, limit int) ([]*model.MessageFormated, error) { - messages, err := (&model.Message{}).List(d.db, conditions, offset, limit) +func (d *messageServant) GetMessages(conditions *core.ConditionsT, offset, limit int) ([]*core.MessageFormated, error) { + messages, err := (&dbr.Message{}).List(d.db, conditions, offset, limit) if err != nil { return nil, err } - mfs := []*model.MessageFormated{} + mfs := []*dbr.MessageFormated{} for _, message := range messages { mf := message.Format() mfs = append(mfs, mf) @@ -59,6 +63,6 @@ func (d *messageServant) GetMessages(conditions *model.ConditionsT, offset, limi return mfs, nil } -func (d *messageServant) GetMessageCount(conditions *model.ConditionsT) (int64, error) { - return (&model.Message{}).Count(d.db, conditions) +func (d *messageServant) GetMessageCount(conditions *core.ConditionsT) (int64, error) { + return (&dbr.Message{}).Count(d.db, conditions) } diff --git a/internal/dao/jinzhu/security.go b/internal/dao/jinzhu/security.go index dfbe2c74..49f66074 100644 --- a/internal/dao/jinzhu/security.go +++ b/internal/dao/jinzhu/security.go @@ -1,3 +1,7 @@ +// 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 jinzhu import ( @@ -10,7 +14,7 @@ import ( "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "github.com/rocboss/paopao-ce/pkg/json" "gopkg.in/resty.v1" "gorm.io/gorm" @@ -36,14 +40,14 @@ type juhePhoneCaptchaRsp struct { } // 获取最新短信验证码 -func (s *securityServant) GetLatestPhoneCaptcha(phone string) (*model.Captcha, error) { - return (&model.Captcha{ +func (s *securityServant) GetLatestPhoneCaptcha(phone string) (*core.Captcha, error) { + return (&dbr.Captcha{ Phone: phone, }).Get(s.db) } // 更新短信验证码 -func (s *securityServant) UsePhoneCaptcha(captcha *model.Captcha) error { +func (s *securityServant) UsePhoneCaptcha(captcha *core.Captcha) error { captcha.UseTimes++ return captcha.Update(s.db) } @@ -82,7 +86,7 @@ func (s *securityServant) SendPhoneCaptcha(phone string) error { } // 写入表 - captchaModel := &model.Captcha{ + captchaModel := &dbr.Captcha{ Phone: phone, Captcha: strconv.Itoa(captcha), ExpiredOn: time.Now().Add(time.Minute * time.Duration(m)).Unix(), diff --git a/internal/dao/jinzhu/topics.go b/internal/dao/jinzhu/topics.go index 0524b71b..d5ce70a9 100644 --- a/internal/dao/jinzhu/topics.go +++ b/internal/dao/jinzhu/topics.go @@ -1,10 +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 jinzhu import ( "strings" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "gorm.io/gorm" ) @@ -22,28 +26,28 @@ func newTopicService(db *gorm.DB) core.TopicService { } } -func (s *topicServant) CreateTag(tag *model.Tag) (*model.Tag, error) { +func (s *topicServant) CreateTag(tag *core.Tag) (*core.Tag, error) { return createTag(s.db, tag) } -func (s *topicServant) DeleteTag(tag *model.Tag) error { +func (s *topicServant) DeleteTag(tag *core.Tag) error { return deleteTag(s.db, tag) } -func (s *topicServant) GetTags(conditions *model.ConditionsT, offset, limit int) ([]*model.Tag, error) { - return (&model.Tag{}).List(s.db, conditions, offset, limit) +func (s *topicServant) GetTags(conditions *core.ConditionsT, offset, limit int) ([]*core.Tag, error) { + return (&dbr.Tag{}).List(s.db, conditions, offset, limit) } -func (s *topicServant) GetTagsByKeyword(keyword string) ([]*model.Tag, error) { - tag := &model.Tag{} +func (s *topicServant) GetTagsByKeyword(keyword string) ([]*core.Tag, error) { + tag := &dbr.Tag{} keyword = "%" + strings.Trim(keyword, " ") + "%" if keyword == "%%" { - return tag.List(s.db, &model.ConditionsT{ + return tag.List(s.db, &dbr.ConditionsT{ "ORDER": "quote_num DESC", }, 0, 6) } else { - return tag.List(s.db, &model.ConditionsT{ + return tag.List(s.db, &dbr.ConditionsT{ "tag LIKE ?": keyword, "ORDER": "quote_num DESC", }, 0, 6) diff --git a/internal/dao/jinzhu/tweets.go b/internal/dao/jinzhu/tweets.go index 12e6f21c..186b7280 100644 --- a/internal/dao/jinzhu/tweets.go +++ b/internal/dao/jinzhu/tweets.go @@ -1,3 +1,7 @@ +// 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 jinzhu import ( @@ -5,7 +9,7 @@ import ( "time" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "gorm.io/gorm" ) @@ -48,7 +52,7 @@ func newTweetHelpService(db *gorm.DB) core.TweetHelpService { } // MergePosts post数据整合 -func (s *tweetHelpServant) MergePosts(posts []*model.Post) ([]*model.PostFormated, error) { +func (s *tweetHelpServant) MergePosts(posts []*core.Post) ([]*core.PostFormated, error) { postIds := make([]int64, 0, len(posts)) userIds := make([]int64, 0, len(posts)) for _, post := range posts { @@ -66,18 +70,18 @@ func (s *tweetHelpServant) MergePosts(posts []*model.Post) ([]*model.PostFormate return nil, err } - userMap := make(map[int64]*model.UserFormated, len(users)) + userMap := make(map[int64]*dbr.UserFormated, len(users)) for _, user := range users { userMap[user.ID] = user.Format() } - contentMap := make(map[int64][]*model.PostContentFormated, len(postContents)) + contentMap := make(map[int64][]*dbr.PostContentFormated, len(postContents)) for _, content := range postContents { contentMap[content.PostID] = append(contentMap[content.PostID], content.Format()) } // 数据整合 - postsFormated := make([]*model.PostFormated, 0, len(posts)) + postsFormated := make([]*dbr.PostFormated, 0, len(posts)) for _, post := range posts { postFormated := post.Format() postFormated.User = userMap[post.UserID] @@ -88,7 +92,7 @@ func (s *tweetHelpServant) MergePosts(posts []*model.Post) ([]*model.PostFormate } // RevampPosts post数据整形修复 -func (s *tweetHelpServant) RevampPosts(posts []*model.PostFormated) ([]*model.PostFormated, error) { +func (s *tweetHelpServant) RevampPosts(posts []*core.PostFormated) ([]*core.PostFormated, error) { postIds := make([]int64, 0, len(posts)) userIds := make([]int64, 0, len(posts)) for _, post := range posts { @@ -106,12 +110,12 @@ func (s *tweetHelpServant) RevampPosts(posts []*model.PostFormated) ([]*model.Po return nil, err } - userMap := make(map[int64]*model.UserFormated, len(users)) + userMap := make(map[int64]*dbr.UserFormated, len(users)) for _, user := range users { userMap[user.ID] = user.Format() } - contentMap := make(map[int64][]*model.PostContentFormated, len(postContents)) + contentMap := make(map[int64][]*dbr.PostContentFormated, len(postContents)) for _, content := range postContents { contentMap[content.PostID] = append(contentMap[content.PostID], content.Format()) } @@ -124,23 +128,23 @@ func (s *tweetHelpServant) RevampPosts(posts []*model.PostFormated) ([]*model.Po return posts, nil } -func (s *tweetHelpServant) getPostContentsByIDs(ids []int64) ([]*model.PostContent, error) { - return (&model.PostContent{}).List(s.db, &model.ConditionsT{ +func (s *tweetHelpServant) getPostContentsByIDs(ids []int64) ([]*dbr.PostContent, error) { + return (&dbr.PostContent{}).List(s.db, &dbr.ConditionsT{ "post_id IN ?": ids, "ORDER": "sort ASC", }, 0, 0) } -func (s *tweetHelpServant) getUsersByIDs(ids []int64) ([]*model.User, error) { - user := &model.User{} +func (s *tweetHelpServant) getUsersByIDs(ids []int64) ([]*dbr.User, error) { + user := &dbr.User{} - return user.List(s.db, &model.ConditionsT{ + return user.List(s.db, &dbr.ConditionsT{ "id IN ?": ids, }, 0, 0) } -func (s *tweetManageServant) CreatePostCollection(postID, userID int64) (*model.PostCollection, error) { - collection := &model.PostCollection{ +func (s *tweetManageServant) CreatePostCollection(postID, userID int64) (*core.PostCollection, error) { + collection := &dbr.PostCollection{ PostID: postID, UserID: userID, } @@ -148,19 +152,19 @@ func (s *tweetManageServant) CreatePostCollection(postID, userID int64) (*model. return collection.Create(s.db) } -func (s *tweetManageServant) DeletePostCollection(p *model.PostCollection) error { +func (s *tweetManageServant) DeletePostCollection(p *core.PostCollection) error { return p.Delete(s.db) } -func (s *tweetManageServant) CreatePostContent(content *model.PostContent) (*model.PostContent, error) { +func (s *tweetManageServant) CreatePostContent(content *core.PostContent) (*core.PostContent, error) { return content.Create(s.db) } -func (s *tweetManageServant) CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) { +func (s *tweetManageServant) CreateAttachment(attachment *core.Attachment) (*core.Attachment, error) { return attachment.Create(s.db) } -func (s *tweetManageServant) CreatePost(post *model.Post) (*model.Post, error) { +func (s *tweetManageServant) CreatePost(post *core.Post) (*core.Post, error) { post.LatestRepliedOn = time.Now().Unix() p, err := post.Create(s.db) if err != nil { @@ -170,11 +174,11 @@ func (s *tweetManageServant) CreatePost(post *model.Post) (*model.Post, error) { return p, nil } -func (s *tweetManageServant) DeletePost(post *model.Post) ([]string, error) { +func (s *tweetManageServant) DeletePost(post *core.Post) ([]string, error) { var mediaContents []string postId := post.ID - postContent := &model.PostContent{} + postContent := &dbr.PostContent{} err := s.db.Transaction( func(tx *gorm.DB) error { if contents, err := postContent.MediaContentsByPostId(tx, postId); err == nil { @@ -218,8 +222,8 @@ func (s *tweetManageServant) DeletePost(post *model.Post) ([]string, error) { } func (s *tweetManageServant) deleteCommentByPostId(db *gorm.DB, postId int64) ([]string, error) { - comment := &model.Comment{} - commentContent := &model.CommentContent{} + comment := &dbr.Comment{} + commentContent := &dbr.CommentContent{} // 获取推文的所有评论id commentIds, err := comment.CommentIdsByPostId(db, postId) @@ -244,19 +248,19 @@ func (s *tweetManageServant) deleteCommentByPostId(db *gorm.DB, postId int64) ([ } // 删评论的评论 - if err = (&model.CommentReply{}).DeleteByCommentIds(db, commentIds); err != nil { + if err = (&dbr.CommentReply{}).DeleteByCommentIds(db, commentIds); err != nil { return nil, err } return mediaContents, nil } -func (s *tweetManageServant) LockPost(post *model.Post) error { +func (s *tweetManageServant) LockPost(post *core.Post) error { post.IsLock = 1 - post.IsLock return post.Update(s.db) } -func (s *tweetManageServant) StickPost(post *model.Post) error { +func (s *tweetManageServant) StickPost(post *core.Post) error { post.IsTop = 1 - post.IsTop if err := post.Update(s.db); err != nil { return err @@ -265,7 +269,7 @@ func (s *tweetManageServant) StickPost(post *model.Post) error { return nil } -func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.PostVisibleT) error { +func (s *tweetManageServant) VisiblePost(post *core.Post, visibility core.PostVisibleT) error { oldVisibility := post.Visibility post.Visibility = visibility // TODO: 这个判断是否可以不要呢 @@ -273,7 +277,7 @@ func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.Post return nil } // 私密推文 特殊处理 - if visibility == model.PostVisitPrivate { + if visibility == dbr.PostVisitPrivate { // 强制取消置顶 // TODO: 置顶推文用户是否有权设置成私密? 后续完善 post.IsTop = 0 @@ -288,14 +292,14 @@ func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.Post // tag处理 tags := strings.Split(post.Tags, ",") for _, t := range tags { - tag := &model.Tag{ + tag := &dbr.Tag{ Tag: t, } // TODO: 暂时宽松不处理错误,这里或许可以有优化,后续完善 - if oldVisibility == model.PostVisitPrivate { + if oldVisibility == dbr.PostVisitPrivate { // 从私密转为非私密才需要重新创建tag createTag(db, tag) - } else if visibility == model.PostVisitPrivate { + } else if visibility == dbr.PostVisitPrivate { // 从非私密转为私密才需要删除tag deleteTag(db, tag) } @@ -305,7 +309,7 @@ func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.Post return nil } -func (s *tweetManageServant) UpdatePost(post *model.Post) error { +func (s *tweetManageServant) UpdatePost(post *core.Post) error { if err := post.Update(s.db); err != nil { return err } @@ -313,104 +317,104 @@ func (s *tweetManageServant) UpdatePost(post *model.Post) error { return nil } -func (s *tweetManageServant) CreatePostStar(postID, userID int64) (*model.PostStar, error) { - star := &model.PostStar{ +func (s *tweetManageServant) CreatePostStar(postID, userID int64) (*core.PostStar, error) { + star := &dbr.PostStar{ PostID: postID, UserID: userID, } return star.Create(s.db) } -func (s *tweetManageServant) DeletePostStar(p *model.PostStar) error { +func (s *tweetManageServant) DeletePostStar(p *core.PostStar) error { return p.Delete(s.db) } -func (s *tweetServant) GetPostByID(id int64) (*model.Post, error) { - post := &model.Post{ - Model: &model.Model{ +func (s *tweetServant) GetPostByID(id int64) (*core.Post, error) { + post := &dbr.Post{ + Model: &dbr.Model{ ID: id, }, } return post.Get(s.db) } -func (s *tweetServant) GetPosts(conditions *model.ConditionsT, offset, limit int) ([]*model.Post, error) { - return (&model.Post{}).List(s.db, conditions, offset, limit) +func (s *tweetServant) GetPosts(conditions *core.ConditionsT, offset, limit int) ([]*core.Post, error) { + return (&dbr.Post{}).List(s.db, conditions, offset, limit) } -func (s *tweetServant) GetPostCount(conditions *model.ConditionsT) (int64, error) { - return (&model.Post{}).Count(s.db, conditions) +func (s *tweetServant) GetPostCount(conditions *core.ConditionsT) (int64, error) { + return (&dbr.Post{}).Count(s.db, conditions) } -func (s *tweetServant) GetUserPostStar(postID, userID int64) (*model.PostStar, error) { - star := &model.PostStar{ +func (s *tweetServant) GetUserPostStar(postID, userID int64) (*core.PostStar, error) { + star := &dbr.PostStar{ PostID: postID, UserID: userID, } return star.Get(s.db) } -func (s *tweetServant) GetUserPostStars(userID int64, offset, limit int) ([]*model.PostStar, error) { - star := &model.PostStar{ +func (s *tweetServant) GetUserPostStars(userID int64, offset, limit int) ([]*core.PostStar, error) { + star := &dbr.PostStar{ UserID: userID, } - return star.List(s.db, &model.ConditionsT{ + return star.List(s.db, &dbr.ConditionsT{ "ORDER": s.db.NamingStrategy.TableName("PostStar") + ".id DESC", }, offset, limit) } func (s *tweetServant) GetUserPostStarCount(userID int64) (int64, error) { - star := &model.PostStar{ + star := &dbr.PostStar{ UserID: userID, } - return star.Count(s.db, &model.ConditionsT{}) + return star.Count(s.db, &dbr.ConditionsT{}) } -func (s *tweetServant) GetUserPostCollection(postID, userID int64) (*model.PostCollection, error) { - star := &model.PostCollection{ +func (s *tweetServant) GetUserPostCollection(postID, userID int64) (*core.PostCollection, error) { + star := &dbr.PostCollection{ PostID: postID, UserID: userID, } return star.Get(s.db) } -func (s *tweetServant) GetUserPostCollections(userID int64, offset, limit int) ([]*model.PostCollection, error) { - collection := &model.PostCollection{ +func (s *tweetServant) GetUserPostCollections(userID int64, offset, limit int) ([]*core.PostCollection, error) { + collection := &dbr.PostCollection{ UserID: userID, } - return collection.List(s.db, &model.ConditionsT{ + return collection.List(s.db, &dbr.ConditionsT{ "ORDER": s.db.NamingStrategy.TableName("PostCollection") + ".id DESC", }, offset, limit) } func (s *tweetServant) GetUserPostCollectionCount(userID int64) (int64, error) { - collection := &model.PostCollection{ + collection := &dbr.PostCollection{ UserID: userID, } - return collection.Count(s.db, &model.ConditionsT{}) + return collection.Count(s.db, &dbr.ConditionsT{}) } -func (s *tweetServant) GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error) { - statement := &model.WalletStatement{ +func (s *tweetServant) GetUserWalletBills(userID int64, offset, limit int) ([]*core.WalletStatement, error) { + statement := &dbr.WalletStatement{ UserID: userID, } - return statement.List(s.db, &model.ConditionsT{ + return statement.List(s.db, &dbr.ConditionsT{ "ORDER": "id DESC", }, offset, limit) } func (s *tweetServant) GetUserWalletBillCount(userID int64) (int64, error) { - statement := &model.WalletStatement{ + statement := &dbr.WalletStatement{ UserID: userID, } - return statement.Count(s.db, &model.ConditionsT{}) + return statement.Count(s.db, &dbr.ConditionsT{}) } -func (s *tweetServant) GetPostAttatchmentBill(postID, userID int64) (*model.PostAttachmentBill, error) { - bill := &model.PostAttachmentBill{ +func (s *tweetServant) GetPostAttatchmentBill(postID, userID int64) (*core.PostAttachmentBill, error) { + bill := &dbr.PostAttachmentBill{ PostID: postID, UserID: userID, } @@ -418,16 +422,16 @@ func (s *tweetServant) GetPostAttatchmentBill(postID, userID int64) (*model.Post return bill.Get(s.db) } -func (s *tweetServant) GetPostContentsByIDs(ids []int64) ([]*model.PostContent, error) { - return (&model.PostContent{}).List(s.db, &model.ConditionsT{ +func (s *tweetServant) GetPostContentsByIDs(ids []int64) ([]*core.PostContent, error) { + return (&dbr.PostContent{}).List(s.db, &dbr.ConditionsT{ "post_id IN ?": ids, "ORDER": "sort ASC", }, 0, 0) } -func (s *tweetServant) GetPostContentByID(id int64) (*model.PostContent, error) { - return (&model.PostContent{ - Model: &model.Model{ +func (s *tweetServant) GetPostContentByID(id int64) (*core.PostContent, error) { + return (&dbr.PostContent{ + Model: &dbr.Model{ ID: id, }, }).Get(s.db) diff --git a/internal/dao/jinzhu/user.go b/internal/dao/jinzhu/user.go index e1380f00..96d09fc1 100644 --- a/internal/dao/jinzhu/user.go +++ b/internal/dao/jinzhu/user.go @@ -1,10 +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 jinzhu import ( "strings" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "gorm.io/gorm" ) @@ -22,69 +26,69 @@ func newUserManageService(db *gorm.DB) core.UserManageService { } } -func (s *userManageServant) GetUserByID(id int64) (*model.User, error) { - user := &model.User{ - Model: &model.Model{ +func (s *userManageServant) GetUserByID(id int64) (*core.User, error) { + user := &dbr.User{ + Model: &dbr.Model{ ID: id, }, } return user.Get(s.db) } -func (s *userManageServant) GetUserByUsername(username string) (*model.User, error) { - user := &model.User{ +func (s *userManageServant) GetUserByUsername(username string) (*core.User, error) { + user := &dbr.User{ Username: username, } return user.Get(s.db) } -func (s *userManageServant) GetUserByPhone(phone string) (*model.User, error) { - user := &model.User{ +func (s *userManageServant) GetUserByPhone(phone string) (*core.User, error) { + user := &dbr.User{ Phone: phone, } return user.Get(s.db) } -func (s *userManageServant) GetUsersByIDs(ids []int64) ([]*model.User, error) { - user := &model.User{} - return user.List(s.db, &model.ConditionsT{ +func (s *userManageServant) GetUsersByIDs(ids []int64) ([]*core.User, error) { + user := &dbr.User{} + return user.List(s.db, &dbr.ConditionsT{ "id IN ?": ids, }, 0, 0) } -func (s *userManageServant) GetUsersByKeyword(keyword string) ([]*model.User, error) { - user := &model.User{} +func (s *userManageServant) GetUsersByKeyword(keyword string) ([]*core.User, error) { + user := &dbr.User{} keyword = strings.Trim(keyword, " ") + "%" if keyword == "%" { - return user.List(s.db, &model.ConditionsT{ + return user.List(s.db, &dbr.ConditionsT{ "ORDER": "id ASC", }, 0, 6) } else { - return user.List(s.db, &model.ConditionsT{ + return user.List(s.db, &dbr.ConditionsT{ "username LIKE ?": keyword, }, 0, 6) } } -func (s *userManageServant) GetTagsByKeyword(keyword string) ([]*model.Tag, error) { - tag := &model.Tag{} +func (s *userManageServant) GetTagsByKeyword(keyword string) ([]*core.Tag, error) { + tag := &dbr.Tag{} keyword = "%" + strings.Trim(keyword, " ") + "%" if keyword == "%%" { - return tag.List(s.db, &model.ConditionsT{ + return tag.List(s.db, &dbr.ConditionsT{ "ORDER": "quote_num DESC", }, 0, 6) } else { - return tag.List(s.db, &model.ConditionsT{ + return tag.List(s.db, &dbr.ConditionsT{ "tag LIKE ?": keyword, "ORDER": "quote_num DESC", }, 0, 6) } } -func (s *userManageServant) CreateUser(user *model.User) (*model.User, error) { +func (s *userManageServant) CreateUser(user *dbr.User) (*core.User, error) { return user.Create(s.db) } -func (s *userManageServant) UpdateUser(user *model.User) error { +func (s *userManageServant) UpdateUser(user *core.User) error { return user.Update(s.db) } diff --git a/internal/dao/jinzhu/utils.go b/internal/dao/jinzhu/utils.go index 8c866027..27766397 100644 --- a/internal/dao/jinzhu/utils.go +++ b/internal/dao/jinzhu/utils.go @@ -1,11 +1,15 @@ +// 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 jinzhu import ( - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "gorm.io/gorm" ) -func createTag(db *gorm.DB, tag *model.Tag) (*model.Tag, error) { +func createTag(db *gorm.DB, tag *dbr.Tag) (*dbr.Tag, error) { t, err := tag.Get(db) if err != nil { tag.QuoteNum = 1 @@ -23,7 +27,7 @@ func createTag(db *gorm.DB, tag *model.Tag) (*model.Tag, error) { return t, nil } -func deleteTag(db *gorm.DB, tag *model.Tag) error { +func deleteTag(db *gorm.DB, tag *dbr.Tag) error { tag, err := tag.Get(db) if err != nil { return err @@ -33,7 +37,7 @@ func deleteTag(db *gorm.DB, tag *model.Tag) error { } func deleteTags(db *gorm.DB, tags []string) error { - allTags, err := (&model.Tag{}).TagsFrom(db, tags) + allTags, err := (&dbr.Tag{}).TagsFrom(db, tags) if err != nil { return err } @@ -51,9 +55,9 @@ func deleteTags(db *gorm.DB, tags []string) error { } // 根据IDs获取用户列表 -func getUsersByIDs(db *gorm.DB, ids []int64) ([]*model.User, error) { - user := &model.User{} - return user.List(db, &model.ConditionsT{ +func getUsersByIDs(db *gorm.DB, ids []int64) ([]*dbr.User, error) { + user := &dbr.User{} + return user.List(db, &dbr.ConditionsT{ "id IN ?": ids, }, 0, 0) } diff --git a/internal/dao/jinzhu/wallet.go b/internal/dao/jinzhu/wallet.go index 3b4f9ea1..7b2023d7 100644 --- a/internal/dao/jinzhu/wallet.go +++ b/internal/dao/jinzhu/wallet.go @@ -1,9 +1,13 @@ +// 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 jinzhu import ( "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" "gorm.io/gorm" ) @@ -21,17 +25,17 @@ func newWalletService(db *gorm.DB) core.WalletService { } } -func (d *walletServant) GetRechargeByID(id int64) (*model.WalletRecharge, error) { - recharge := &model.WalletRecharge{ - Model: &model.Model{ +func (d *walletServant) GetRechargeByID(id int64) (*core.WalletRecharge, error) { + recharge := &dbr.WalletRecharge{ + Model: &dbr.Model{ ID: id, }, } return recharge.Get(d.db) } -func (d *walletServant) CreateRecharge(userId, amount int64) (*model.WalletRecharge, error) { - recharge := &model.WalletRecharge{ +func (d *walletServant) CreateRecharge(userId, amount int64) (*core.WalletRecharge, error) { + recharge := &dbr.WalletRecharge{ UserID: userId, Amount: amount, } @@ -39,26 +43,26 @@ func (d *walletServant) CreateRecharge(userId, amount int64) (*model.WalletRecha return recharge.Create(d.db) } -func (d *walletServant) GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error) { - statement := &model.WalletStatement{ +func (d *walletServant) GetUserWalletBills(userID int64, offset, limit int) ([]*core.WalletStatement, error) { + statement := &dbr.WalletStatement{ UserID: userID, } - return statement.List(d.db, &model.ConditionsT{ + return statement.List(d.db, &dbr.ConditionsT{ "ORDER": "id DESC", }, offset, limit) } func (d *walletServant) GetUserWalletBillCount(userID int64) (int64, error) { - statement := &model.WalletStatement{ + statement := &dbr.WalletStatement{ UserID: userID, } - return statement.Count(d.db, &model.ConditionsT{}) + return statement.Count(d.db, &dbr.ConditionsT{}) } -func (d *walletServant) HandleRechargeSuccess(recharge *model.WalletRecharge, tradeNo string) error { - user, _ := (&model.User{ - Model: &model.Model{ +func (d *walletServant) HandleRechargeSuccess(recharge *core.WalletRecharge, tradeNo string) error { + user, _ := (&dbr.User{ + Model: &dbr.Model{ ID: recharge.UserID, }, }).Get(d.db) @@ -71,7 +75,7 @@ func (d *walletServant) HandleRechargeSuccess(recharge *model.WalletRecharge, tr } // 新增账单 - if err := tx.Create(&model.WalletStatement{ + if err := tx.Create(&dbr.WalletStatement{ UserID: user.ID, ChangeAmount: recharge.Amount, BalanceSnapshot: user.Balance + recharge.Amount, @@ -93,7 +97,7 @@ func (d *walletServant) HandleRechargeSuccess(recharge *model.WalletRecharge, tr }) } -func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model.User) error { +func (d *walletServant) HandlePostAttachmentBought(post *core.Post, user *core.User) error { return d.db.Transaction(func(tx *gorm.DB) error { // 扣除金额 if err := tx.Model(user).Update("balance", gorm.Expr("balance - ?", post.AttachmentPrice)).Error; err != nil { @@ -102,7 +106,7 @@ func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model } // 新增账单 - if err := tx.Create(&model.WalletStatement{ + if err := tx.Create(&dbr.WalletStatement{ PostID: post.ID, UserID: user.ID, ChangeAmount: -post.AttachmentPrice, @@ -113,7 +117,7 @@ func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model } // 新增附件购买记录 - if err := tx.Create(&model.PostAttachmentBill{ + if err := tx.Create(&dbr.PostAttachmentBill{ PostID: post.ID, UserID: user.ID, PaidAmount: post.AttachmentPrice, @@ -124,8 +128,8 @@ func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model // 对附件主新增账单 income := int64(float64(post.AttachmentPrice) * conf.AppSetting.AttachmentIncomeRate) if income > 0 { - master := &model.User{ - Model: &model.Model{ + master := &dbr.User{ + Model: &dbr.Model{ ID: post.UserID, }, } @@ -137,7 +141,7 @@ func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model } // 新增账单 - if err := tx.Create(&model.WalletStatement{ + if err := tx.Create(&dbr.WalletStatement{ PostID: post.ID, UserID: master.ID, ChangeAmount: income, diff --git a/internal/dao/sakila/sakila.go b/internal/dao/sakila/sakila.go index 6efdffa6..d82a0d23 100644 --- a/internal/dao/sakila/sakila.go +++ b/internal/dao/sakila/sakila.go @@ -1,3 +1,7 @@ +// 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. + // Core service implement base sqlx+mysql. All sub-service // will declare here and provide initial function. diff --git a/internal/dao/search/bridge.go b/internal/dao/search/bridge.go index 84f469a5..f23aaa25 100644 --- a/internal/dao/search/bridge.go +++ b/internal/dao/search/bridge.go @@ -1,10 +1,13 @@ +// 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 search import ( "time" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" "github.com/sirupsen/logrus" ) @@ -43,7 +46,7 @@ func (s *bridgeTweetSearchServant) DeleteDocuments(identifiers []string) error { return nil } -func (s *bridgeTweetSearchServant) Search(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { +func (s *bridgeTweetSearchServant) Search(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { return s.ts.Search(user, q, offset, limit) } diff --git a/internal/dao/search/filter.go b/internal/dao/search/filter.go index 229f2482..5840e189 100644 --- a/internal/dao/search/filter.go +++ b/internal/dao/search/filter.go @@ -1,8 +1,11 @@ +// 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 search import ( "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/pkg/types" ) @@ -10,19 +13,19 @@ type tweetSearchFilter struct { ams core.AuthorizationManageService } -func (s *tweetSearchFilter) filterResp(user *model.User, resp *core.QueryResp) { +func (s *tweetSearchFilter) filterResp(user *core.User, resp *core.QueryResp) { // 管理员不过滤 if user != nil && user.IsAdmin { return } - var item *model.PostFormated + var item *core.PostFormated items := resp.Items latestIndex := len(items) - 1 if user == nil { for i := 0; i <= latestIndex; i++ { item = items[i] - if item.Visibility != model.PostVisitPublic { + if item.Visibility != core.PostVisitPublic { items[i] = items[latestIndex] items = items[:latestIndex] resp.Total-- @@ -36,8 +39,8 @@ func (s *tweetSearchFilter) filterResp(user *model.User, resp *core.QueryResp) { friendFilter[user.ID] = types.Empty{} for i := 0; i <= latestIndex; i++ { item = items[i] - cutFriend = (item.Visibility == model.PostVisitFriend && !friendFilter.IsFriend(item.UserID)) - cutPrivate = (item.Visibility == model.PostVisitPrivate && user.ID != item.UserID) + cutFriend = (item.Visibility == core.PostVisitFriend && !friendFilter.IsFriend(item.UserID)) + cutPrivate = (item.Visibility == core.PostVisitPrivate && user.ID != item.UserID) if cutFriend || cutPrivate { items[i] = items[latestIndex] items = items[:latestIndex] diff --git a/internal/dao/search/meili.go b/internal/dao/search/meili.go index 321953ee..b2ee4d16 100644 --- a/internal/dao/search/meili.go +++ b/internal/dao/search/meili.go @@ -1,3 +1,7 @@ +// 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 search import ( @@ -7,7 +11,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/meilisearch/meilisearch-go" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/pkg/json" "github.com/sirupsen/logrus" ) @@ -28,20 +31,20 @@ type meiliTweetSearchServant struct { } type postInfo struct { - ID int64 `json:"id"` - UserID int64 `json:"user_id"` - CommentCount int64 `json:"comment_count"` - CollectionCount int64 `json:"collection_count"` - UpvoteCount int64 `json:"upvote_count"` - Visibility model.PostVisibleT `json:"visibility"` - IsTop int `json:"is_top"` - IsEssence int `json:"is_essence"` - IsLock int `json:"is_lock"` - LatestRepliedOn int64 `json:"latest_replied_on"` - CreatedOn int64 `json:"created_on"` - ModifiedOn int64 `json:"modified_on"` - AttachmentPrice int64 `json:"attachment_price"` - IPLoc string `json:"ip_loc"` + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + CommentCount int64 `json:"comment_count"` + CollectionCount int64 `json:"collection_count"` + UpvoteCount int64 `json:"upvote_count"` + Visibility core.PostVisibleT `json:"visibility"` + IsTop int `json:"is_top"` + IsEssence int `json:"is_essence"` + IsLock int `json:"is_lock"` + LatestRepliedOn int64 `json:"latest_replied_on"` + CreatedOn int64 `json:"created_on"` + ModifiedOn int64 `json:"modified_on"` + AttachmentPrice int64 `json:"attachment_price"` + IPLoc string `json:"ip_loc"` } func (s *meiliTweetSearchServant) Name() string { @@ -78,7 +81,7 @@ func (s *meiliTweetSearchServant) DeleteDocuments(identifiers []string) error { return nil } -func (s *meiliTweetSearchServant) Search(user *model.User, q *core.QueryReq, offset, limit int) (resp *core.QueryResp, err error) { +func (s *meiliTweetSearchServant) Search(user *core.User, q *core.QueryReq, offset, limit int) (resp *core.QueryResp, err error) { if q.Type == core.SearchTypeDefault && q.Query != "" { resp, err = s.queryByContent(user, q, offset, limit) } else if q.Type == core.SearchTypeTag && q.Query != "" { @@ -96,7 +99,7 @@ func (s *meiliTweetSearchServant) Search(user *model.User, q *core.QueryReq, off return } -func (s *meiliTweetSearchServant) queryByContent(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { +func (s *meiliTweetSearchServant) queryByContent(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { request := &meilisearch.SearchRequest{ Offset: int64(offset), Limit: int64(limit), @@ -117,7 +120,7 @@ func (s *meiliTweetSearchServant) queryByContent(user *model.User, q *core.Query return s.postsFrom(resp) } -func (s *meiliTweetSearchServant) queryByTag(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { +func (s *meiliTweetSearchServant) queryByTag(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { request := &meilisearch.SearchRequest{ Offset: int64(offset), Limit: int64(limit), @@ -141,7 +144,7 @@ func (s *meiliTweetSearchServant) queryByTag(user *model.User, q *core.QueryReq, return s.postsFrom(resp) } -func (s *meiliTweetSearchServant) queryAny(user *model.User, offset, limit int) (*core.QueryResp, error) { +func (s *meiliTweetSearchServant) queryAny(user *core.User, offset, limit int) (*core.QueryResp, error) { request := &meilisearch.SearchRequest{ Offset: int64(offset), Limit: int64(limit), @@ -161,7 +164,7 @@ func (s *meiliTweetSearchServant) queryAny(user *model.User, offset, limit int) return s.postsFrom(resp) } -func (s *meiliTweetSearchServant) filterList(user *model.User) string { +func (s *meiliTweetSearchServant) filterList(user *core.User) string { if user == nil { return s.publicFilter } @@ -174,7 +177,7 @@ func (s *meiliTweetSearchServant) filterList(user *model.User) string { } func (s *meiliTweetSearchServant) postsFrom(resp *meilisearch.SearchResponse) (*core.QueryResp, error) { - posts := make([]*model.PostFormated, 0, len(resp.Hits)) + posts := make([]*core.PostFormated, 0, len(resp.Hits)) for _, hit := range resp.Hits { raw, err := json.Marshal(hit) if err != nil { @@ -184,7 +187,7 @@ func (s *meiliTweetSearchServant) postsFrom(resp *meilisearch.SearchResponse) (* if err = json.Unmarshal(raw, p); err != nil { return nil, err } - posts = append(posts, &model.PostFormated{ + posts = append(posts, &core.PostFormated{ ID: p.ID, UserID: p.UserID, CommentCount: p.CommentCount, diff --git a/internal/dao/search/search.go b/internal/dao/search/search.go index 1dda80ef..baf0923b 100644 --- a/internal/dao/search/search.go +++ b/internal/dao/search/search.go @@ -1,3 +1,7 @@ +// 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 search import ( @@ -6,7 +10,6 @@ import ( "github.com/meilisearch/meilisearch-go" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/pkg/zinc" "github.com/sirupsen/logrus" ) @@ -40,9 +43,9 @@ func NewMeiliTweetSearchService(ams core.AuthorizationManageService) (core.Tweet }, client: client, index: client.Index(s.Index), - publicFilter: fmt.Sprintf("visibility=%d", model.PostVisitPublic), - privateFilter: fmt.Sprintf("visibility=%d AND user_id=", model.PostVisitPrivate), - friendFilter: fmt.Sprintf("visibility=%d", model.PostVisitFriend), + publicFilter: fmt.Sprintf("visibility=%d", core.PostVisitPublic), + privateFilter: fmt.Sprintf("visibility=%d AND user_id=", core.PostVisitPrivate), + friendFilter: fmt.Sprintf("visibility=%d", core.PostVisitFriend), } return mts, mts } @@ -55,9 +58,9 @@ func NewZincTweetSearchService(ams core.AuthorizationManageService) (core.TweetS }, indexName: s.Index, client: zinc.NewClient(s), - publicFilter: fmt.Sprintf("visibility:%d", model.PostVisitPublic), - privateFilter: fmt.Sprintf("visibility:%d AND user_id:%%d", model.PostVisitPrivate), - friendFilter: fmt.Sprintf("visibility:%d", model.PostVisitFriend), + publicFilter: fmt.Sprintf("visibility:%d", core.PostVisitPublic), + privateFilter: fmt.Sprintf("visibility:%d AND user_id:%%d", core.PostVisitPrivate), + friendFilter: fmt.Sprintf("visibility:%d", core.PostVisitFriend), } zts.createIndex() diff --git a/internal/dao/search/zinc.go b/internal/dao/search/zinc.go index c038cb90..ea9a7fa5 100644 --- a/internal/dao/search/zinc.go +++ b/internal/dao/search/zinc.go @@ -1,3 +1,7 @@ +// 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 search import ( @@ -5,7 +9,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/pkg/json" "github.com/rocboss/paopao-ce/pkg/zinc" "github.com/sirupsen/logrus" @@ -73,7 +76,7 @@ func (s *zincTweetSearchServant) DeleteDocuments(identifiers []string) error { return nil } -func (s *zincTweetSearchServant) Search(user *model.User, q *core.QueryReq, offset, limit int) (resp *core.QueryResp, err error) { +func (s *zincTweetSearchServant) Search(user *core.User, q *core.QueryReq, offset, limit int) (resp *core.QueryResp, err error) { if q.Type == core.SearchTypeDefault && q.Query != "" { resp, err = s.queryByContent(user, q, offset, limit) } else if q.Type == core.SearchTypeTag && q.Query != "" { @@ -91,7 +94,7 @@ func (s *zincTweetSearchServant) Search(user *model.User, q *core.QueryReq, offs return } -func (s *zincTweetSearchServant) queryByContent(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { +func (s *zincTweetSearchServant) queryByContent(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { resp, err := s.client.EsQuery(s.indexName, map[string]any{ "query": map[string]any{ "match_phrase": map[string]any{ @@ -108,7 +111,7 @@ func (s *zincTweetSearchServant) queryByContent(user *model.User, q *core.QueryR return s.postsFrom(resp) } -func (s *zincTweetSearchServant) queryByTag(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { +func (s *zincTweetSearchServant) queryByTag(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { resp, err := s.client.ApiQuery(s.indexName, map[string]any{ "search_type": "querystring", "query": map[string]any{ @@ -124,7 +127,7 @@ func (s *zincTweetSearchServant) queryByTag(user *model.User, q *core.QueryReq, return s.postsFrom(resp) } -func (s *zincTweetSearchServant) queryAny(user *model.User, offset, limit int) (*core.QueryResp, error) { +func (s *zincTweetSearchServant) queryAny(user *core.User, offset, limit int) (*core.QueryResp, error) { queryMap := map[string]any{ "query": map[string]any{ "match_all": map[string]string{}, @@ -141,9 +144,9 @@ func (s *zincTweetSearchServant) queryAny(user *model.User, offset, limit int) ( } func (s *zincTweetSearchServant) postsFrom(resp *zinc.QueryResultT) (*core.QueryResp, error) { - posts := make([]*model.PostFormated, 0, len(resp.Hits.Hits)) + posts := make([]*core.PostFormated, 0, len(resp.Hits.Hits)) for _, hit := range resp.Hits.Hits { - item := &model.PostFormated{} + item := &core.PostFormated{} raw, err := json.Marshal(hit.Source) if err != nil { return nil, err diff --git a/internal/dao/security/attachment.go b/internal/dao/security/attachment.go index 3bd79461..706621ac 100644 --- a/internal/dao/security/attachment.go +++ b/internal/dao/security/attachment.go @@ -1,3 +1,7 @@ +// 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 security import ( diff --git a/internal/dao/slonik/slonik.go b/internal/dao/slonik/slonik.go index 8cfb49c3..bb8f82ad 100644 --- a/internal/dao/slonik/slonik.go +++ b/internal/dao/slonik/slonik.go @@ -1,3 +1,7 @@ +// 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. + // Core service implement base sqlx+postgresql. All sub-service // will declare here and provide initial function. diff --git a/internal/dao/storage/alioss.go b/internal/dao/storage/alioss.go index 3519cba5..e72fa44c 100644 --- a/internal/dao/storage/alioss.go +++ b/internal/dao/storage/alioss.go @@ -1,3 +1,7 @@ +// 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 storage import ( diff --git a/internal/dao/storage/cos.go b/internal/dao/storage/cos.go index f7a7ebad..3c2ea65f 100644 --- a/internal/dao/storage/cos.go +++ b/internal/dao/storage/cos.go @@ -1,3 +1,7 @@ +// 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 storage import ( diff --git a/internal/dao/storage/huaweiobs.go b/internal/dao/storage/huaweiobs.go index 31656e6c..7db9818b 100644 --- a/internal/dao/storage/huaweiobs.go +++ b/internal/dao/storage/huaweiobs.go @@ -1,3 +1,7 @@ +// 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 storage import ( diff --git a/internal/dao/storage/localoss.go b/internal/dao/storage/localoss.go index f2ba55ab..584fea91 100644 --- a/internal/dao/storage/localoss.go +++ b/internal/dao/storage/localoss.go @@ -1,3 +1,7 @@ +// 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 storage import ( diff --git a/internal/dao/storage/minio.go b/internal/dao/storage/minio.go index b4da9fed..3859a5b7 100644 --- a/internal/dao/storage/minio.go +++ b/internal/dao/storage/minio.go @@ -1,3 +1,7 @@ +// 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 storage import ( diff --git a/internal/dao/storage/storage.go b/internal/dao/storage/storage.go index 8e124047..fff9d13f 100644 --- a/internal/dao/storage/storage.go +++ b/internal/dao/storage/storage.go @@ -1,3 +1,7 @@ +// 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 storage import ( diff --git a/internal/internal.go b/internal/internal.go index 8d51c97a..e359af0d 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -1,9 +1,13 @@ +// 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 internal import ( - "github.com/rocboss/paopao-ce/internal/migration" - "github.com/rocboss/paopao-ce/internal/routers/api" - "github.com/rocboss/paopao-ce/internal/service" + "github.com/rocboss/paopao-ce/internal/broker/migration" + wb "github.com/rocboss/paopao-ce/internal/servants/web/broker" + "github.com/rocboss/paopao-ce/internal/servants/web/routers/api" ) func Initialize() { @@ -11,6 +15,6 @@ func Initialize() { migration.Run() // initialize service - service.Initialize() + wb.Initialize() api.Initialize() } diff --git a/internal/middleware/admin.go b/internal/middleware/admin.go deleted file mode 100644 index f81b00ee..00000000 --- a/internal/middleware/admin.go +++ /dev/null @@ -1,25 +0,0 @@ -package middleware - -import ( - "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/pkg/app" - "github.com/rocboss/paopao-ce/pkg/errcode" -) - -func Admin() gin.HandlerFunc { - return func(c *gin.Context) { - if user, exist := c.Get("USER"); exist { - if userModel, ok := user.(*model.User); ok { - if userModel.Status == model.UserStatusNormal && userModel.IsAdmin { - c.Next() - return - } - } - } - - response := app.NewResponse(c) - response.ToErrorResponse(errcode.NoAdminPermission) - c.Abort() - } -} diff --git a/internal/middleware/jwt.go b/internal/middleware/jwt.go deleted file mode 100644 index 3fab7679..00000000 --- a/internal/middleware/jwt.go +++ /dev/null @@ -1,113 +0,0 @@ -package middleware - -import ( - "strings" - - "github.com/gin-gonic/gin" - "github.com/golang-jwt/jwt/v4" - "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/pkg/app" - "github.com/rocboss/paopao-ce/pkg/errcode" -) - -func JWT() gin.HandlerFunc { - // TODO: optimize get user from a simple service that provide fetch a user info interface. - db := conf.MustGormDB() - return func(c *gin.Context) { - var ( - token string - ecode = errcode.Success - ) - if s, exist := c.GetQuery("token"); exist { - token = s - } else { - token = c.GetHeader("Authorization") - - // 验证前端传过来的token格式,不为空,开头为Bearer - if token == "" || !strings.HasPrefix(token, "Bearer ") { - response := app.NewResponse(c) - response.ToErrorResponse(errcode.UnauthorizedTokenError) - c.Abort() - return - } - - // 验证通过,提取有效部分(除去Bearer) - token = token[7:] - } - if token == "" { - ecode = errcode.InvalidParams - } else { - claims, err := app.ParseToken(token) - if err != nil { - switch err.(*jwt.ValidationError).Errors { - case jwt.ValidationErrorExpired: - ecode = errcode.UnauthorizedTokenTimeout - default: - ecode = errcode.UnauthorizedTokenError - } - } else { - c.Set("UID", claims.UID) - c.Set("USERNAME", claims.Username) - - // 加载用户信息 - user := &model.User{ - Model: &model.Model{ - ID: claims.UID, - }, - } - user, _ = user.Get(db) - c.Set("USER", user) - - // 强制下线机制 - if (conf.JWTSetting.Issuer + ":" + user.Salt) != claims.Issuer { - ecode = errcode.UnauthorizedTokenTimeout - } - } - } - - if ecode != errcode.Success { - response := app.NewResponse(c) - response.ToErrorResponse(ecode) - c.Abort() - return - } - - c.Next() - } -} - -func JwtLoose() gin.HandlerFunc { - // TODO: optimize get user from a simple service that provide fetch a user info interface. - db := conf.MustGormDB() - return func(c *gin.Context) { - token, exist := c.GetQuery("token") - if !exist { - token = c.GetHeader("Authorization") - // 验证前端传过来的token格式,不为空,开头为Bearer - if strings.HasPrefix(token, "Bearer ") { - // 验证通过,提取有效部分(除去Bearer) - token = token[7:] - } else { - c.Next() - } - } - if len(token) > 0 { - if claims, err := app.ParseToken(token); err == nil { - c.Set("UID", claims.UID) - c.Set("USERNAME", claims.Username) - // 加载用户信息 - user := &model.User{ - Model: &model.Model{ - ID: claims.UID, - }, - } - user, err := user.Get(db) - if err == nil && (conf.JWTSetting.Issuer+":"+user.Salt) == claims.Issuer { - c.Set("USER", user) - } - } - } - c.Next() - } -} diff --git a/internal/middleware/priv.go b/internal/middleware/priv.go deleted file mode 100644 index fe31b008..00000000 --- a/internal/middleware/priv.go +++ /dev/null @@ -1,45 +0,0 @@ -package middleware - -import ( - "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/pkg/app" - "github.com/rocboss/paopao-ce/pkg/cfg" - "github.com/rocboss/paopao-ce/pkg/errcode" -) - -func Priv() gin.HandlerFunc { - if cfg.If("PhoneBind") { - return func(c *gin.Context) { - if u, exist := c.Get("USER"); exist { - if user, ok := u.(*model.User); ok { - if user.Status == model.UserStatusNormal { - if user.Phone == "" { - response := app.NewResponse(c) - response.ToErrorResponse(errcode.AccountNoPhoneBind) - c.Abort() - return - } - c.Next() - return - } - } - } - response := app.NewResponse(c) - response.ToErrorResponse(errcode.UserHasBeenBanned) - c.Abort() - } - } else { - return func(c *gin.Context) { - if u, exist := c.Get("USER"); exist { - if user, ok := u.(*model.User); ok && user.Status == model.UserStatusNormal { - c.Next() - return - } - } - response := app.NewResponse(c) - response.ToErrorResponse(errcode.UserHasBeenBanned) - c.Abort() - } - } -} diff --git a/internal/mirc/main.go b/internal/mirc/main.go index c2e47411..46de42d1 100644 --- a/internal/mirc/main.go +++ b/internal/mirc/main.go @@ -1,3 +1,7 @@ +// 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 main import ( diff --git a/internal/model/attachment.go b/internal/model/attachment.go deleted file mode 100644 index 0c748b00..00000000 --- a/internal/model/attachment.go +++ /dev/null @@ -1,27 +0,0 @@ -package model - -import "gorm.io/gorm" - -type AttachmentType int - -const ( - ATTACHMENT_TYPE_IMAGE AttachmentType = iota + 1 - ATTACHMENT_TYPE_VIDEO - ATTACHMENT_TYPE_OTHER -) - -type Attachment struct { - *Model - UserID int64 `json:"user_id"` - FileSize int64 `json:"file_size"` - ImgWidth int `json:"img_width"` - ImgHeight int `json:"img_height"` - Type AttachmentType `json:"type"` - Content string `json:"content"` -} - -func (a *Attachment) Create(db *gorm.DB) (*Attachment, error) { - err := db.Create(&a).Error - - return a, err -} diff --git a/internal/model/captcha.go b/internal/model/captcha.go deleted file mode 100644 index 210cc691..00000000 --- a/internal/model/captcha.go +++ /dev/null @@ -1,38 +0,0 @@ -package model - -import "gorm.io/gorm" - -type Captcha struct { - *Model - Phone string `json:"phone"` - Captcha string `json:"captcha"` - UseTimes int `json:"use_times"` - ExpiredOn int64 `json:"expired_on"` -} - -func (c *Captcha) Create(db *gorm.DB) (*Captcha, error) { - err := db.Create(&c).Error - - return c, err -} - -func (c *Captcha) Update(db *gorm.DB) error { - return db.Model(&Captcha{}).Where("id = ? AND is_del = ?", c.Model.ID, 0).Save(c).Error -} - -func (c *Captcha) Get(db *gorm.DB) (*Captcha, error) { - var captcha Captcha - if c.Model != nil && c.ID > 0 { - db = db.Where("id = ? AND is_del = ?", c.ID, 0) - } - if c.Phone != "" { - db = db.Where("phone = ?", c.Phone) - } - - err := db.Last(&captcha).Error - if err != nil { - return &captcha, err - } - - return &captcha, nil -} diff --git a/internal/model/comment.go b/internal/model/comment.go deleted file mode 100644 index 72494b53..00000000 --- a/internal/model/comment.go +++ /dev/null @@ -1,127 +0,0 @@ -package model - -import ( - "time" - - "gorm.io/gorm" -) - -type Comment struct { - *Model - PostID int64 `json:"post_id"` - UserID int64 `json:"user_id"` - IP string `json:"ip"` - IPLoc string `json:"ip_loc"` -} - -type CommentFormated struct { - ID int64 `json:"id"` - PostID int64 `json:"post_id"` - UserID int64 `json:"user_id"` - User *UserFormated `json:"user"` - Contents []*CommentContent `json:"contents"` - Replies []*CommentReplyFormated `json:"replies"` - IPLoc string `json:"ip_loc"` - CreatedOn int64 `json:"created_on"` - ModifiedOn int64 `json:"modified_on"` -} - -func (c *Comment) Format() *CommentFormated { - if c.Model == nil { - return &CommentFormated{} - } - return &CommentFormated{ - ID: c.Model.ID, - PostID: c.PostID, - UserID: c.UserID, - User: &UserFormated{}, - Contents: []*CommentContent{}, - Replies: []*CommentReplyFormated{}, - IPLoc: c.IPLoc, - CreatedOn: c.CreatedOn, - ModifiedOn: c.ModifiedOn, - } -} - -func (c *Comment) Get(db *gorm.DB) (*Comment, error) { - var comment Comment - if c.Model != nil && c.ID > 0 { - db = db.Where("id = ? AND is_del = ?", c.ID, 0) - } else { - return nil, gorm.ErrRecordNotFound - } - - err := db.First(&comment).Error - if err != nil { - return &comment, err - } - - return &comment, nil -} - -func (c *Comment) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*Comment, error) { - var comments []*Comment - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if c.PostID > 0 { - db = db.Where("id = ?", c.PostID) - } - - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&comments).Error; err != nil { - return nil, err - } - - return comments, nil -} - -func (c *Comment) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { - var count int64 - if c.PostID > 0 { - db = db.Where("post_id = ?", c.PostID) - } - for k, v := range *conditions { - if k != "ORDER" { - db = db.Where(k, v) - } - } - if err := db.Model(c).Count(&count).Error; err != nil { - return 0, err - } - - return count, nil -} - -func (c *Comment) Create(db *gorm.DB) (*Comment, error) { - err := db.Create(&c).Error - - return c, err -} - -func (c *Comment) Delete(db *gorm.DB) error { - return db.Model(c).Where("id = ?", c.Model.ID).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} - -func (c *Comment) CommentIdsByPostId(db *gorm.DB, postId int64) (ids []int64, err error) { - err = db.Model(c).Where("post_id = ?", postId).Select("id").Find(&ids).Error - return -} - -func (c *Comment) DeleteByPostId(db *gorm.DB, postId int64) error { - return db.Model(c).Where("post_id = ?", postId).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} diff --git a/internal/model/comment_content.go b/internal/model/comment_content.go deleted file mode 100644 index b7d42dfd..00000000 --- a/internal/model/comment_content.go +++ /dev/null @@ -1,59 +0,0 @@ -package model - -import ( - "time" - - "gorm.io/gorm" -) - -type CommentContent struct { - *Model - CommentID int64 `json:"comment_id"` - UserID int64 `json:"user_id"` - Content string `json:"content"` - Type PostContentT `json:"type"` - Sort int64 `json:"sort"` -} - -func (c *CommentContent) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*CommentContent, error) { - var comments []*CommentContent - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if c.CommentID > 0 { - db = db.Where("id = ?", c.CommentID) - } - - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&comments).Error; err != nil { - return nil, err - } - - return comments, nil -} - -func (c *CommentContent) Create(db *gorm.DB) (*CommentContent, error) { - err := db.Create(&c).Error - - return c, err -} - -func (c *CommentContent) MediaContentsByCommentId(db *gorm.DB, commentIds []int64) (contents []string, err error) { - err = db.Model(c).Where("comment_id IN ? AND type = ?", commentIds, CONTENT_TYPE_IMAGE).Select("content").Find(&contents).Error - return -} - -func (c *CommentContent) DeleteByCommentIds(db *gorm.DB, commentIds []int64) error { - return db.Model(c).Where("comment_id IN ?", commentIds).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} diff --git a/internal/model/comment_reply.go b/internal/model/comment_reply.go deleted file mode 100644 index fd22702f..00000000 --- a/internal/model/comment_reply.go +++ /dev/null @@ -1,110 +0,0 @@ -package model - -import ( - "time" - - "gorm.io/gorm" -) - -type CommentReply struct { - *Model - CommentID int64 `json:"comment_id"` - UserID int64 `json:"user_id"` - AtUserID int64 `json:"at_user_id"` - Content string `json:"content"` - IP string `json:"ip"` - IPLoc string `json:"ip_loc"` -} - -type CommentReplyFormated struct { - ID int64 `json:"id"` - CommentID int64 `json:"comment_id"` - UserID int64 `json:"user_id"` - User *UserFormated `json:"user"` - AtUserID int64 `json:"at_user_id"` - AtUser *UserFormated `json:"at_user"` - Content string `json:"content"` - IPLoc string `json:"ip_loc"` - CreatedOn int64 `json:"created_on"` - ModifiedOn int64 `json:"modified_on"` -} - -func (c *CommentReply) Format() *CommentReplyFormated { - if c.Model == nil { - return &CommentReplyFormated{} - } - - return &CommentReplyFormated{ - ID: c.ID, - CommentID: c.CommentID, - UserID: c.UserID, - User: &UserFormated{}, - AtUserID: c.AtUserID, - AtUser: &UserFormated{}, - Content: c.Content, - IPLoc: c.IPLoc, - CreatedOn: c.CreatedOn, - ModifiedOn: c.ModifiedOn, - } -} - -func (c *CommentReply) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*CommentReply, error) { - var comments []*CommentReply - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if c.CommentID > 0 { - db = db.Where("id = ?", c.CommentID) - } - - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&comments).Error; err != nil { - return nil, err - } - - return comments, nil -} - -func (c *CommentReply) Create(db *gorm.DB) (*CommentReply, error) { - err := db.Create(&c).Error - - return c, err -} - -func (c *CommentReply) Get(db *gorm.DB) (*CommentReply, error) { - var reply CommentReply - if c.Model != nil && c.ID > 0 { - db = db.Where("id = ? AND is_del = ?", c.ID, 0) - } else { - return nil, gorm.ErrRecordNotFound - } - - err := db.First(&reply).Error - if err != nil { - return &reply, err - } - - return &reply, nil -} - -func (c *CommentReply) Delete(db *gorm.DB) error { - return db.Model(&CommentReply{}).Where("id = ? AND is_del = ?", c.Model.ID, 0).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} - -func (c *CommentReply) DeleteByCommentIds(db *gorm.DB, commentIds []int64) error { - return db.Model(c).Where("comment_id IN ?", commentIds).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} diff --git a/internal/model/contact.go b/internal/model/contact.go deleted file mode 100644 index 14049f77..00000000 --- a/internal/model/contact.go +++ /dev/null @@ -1,119 +0,0 @@ -package model - -import ( - "github.com/sirupsen/logrus" - "gorm.io/gorm" -) - -const ( - ContactStatusRequesting int8 = iota + 1 - ContactStatusAgree - ContactStatusReject - ContactStatusDeleted -) - -type Contact struct { - *Model - User *User `json:"-" gorm:"foreignKey:ID;references:FriendId"` - UserId int64 `json:"user_id"` - FriendId int64 `json:"friend_id"` - GroupId int64 `json:"group_id"` - Remark string `json:"remark"` - Status int8 `json:"status"` // 1请求好友, 2已同意好友, 3已拒绝好友, 4已删除好友 - IsTop int8 `json:"is_top"` - IsBlack int8 `json:"is_black"` - NoticeEnable int8 `json:"notice_enable"` -} - -func (c *Contact) FetchUser(db *gorm.DB) (*Contact, error) { - var contact Contact - err := db.Omit("User").Unscoped().Where("user_id = ? AND friend_id = ?", c.UserId, c.FriendId).First(&contact).Error - if err != nil { - logrus.Debugf("Contact.FetchUser fetch user error:%s", err) - return nil, err - } - return &contact, nil -} - -func (c *Contact) GetByUserFriend(db *gorm.DB) (*Contact, error) { - var contact Contact - err := db.Omit("User").Where("user_id = ? AND friend_id = ?", c.UserId, c.FriendId).First(&contact).Error - if err != nil { - return nil, err - } - return &contact, nil -} - -func (c *Contact) FetchByUserFriendAll(db *gorm.DB) ([]*Contact, error) { - var contacts []*Contact - if err := db.Omit("User"). - Where("(user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)", - c.UserId, c.FriendId, c.FriendId, c.UserId). - Find(&contacts).Error; err != nil { - return nil, err - } - return contacts, nil -} - -func (c *Contact) List(db *gorm.DB, conditions ConditionsT, offset, limit int) ([]*Contact, error) { - var contacts []*Contact - var err error - tn := db.NamingStrategy.TableName("Contact") + "." - - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - for k, v := range conditions { - if k != "ORDER" { - db = db.Where(tn+k, v) - } - } - - db.Joins("User").Order("`User`.`nickname` ASC") - if err = db.Find(&contacts).Error; err != nil { - return nil, err - } - return contacts, nil -} - -func (c *Contact) BeFriendIds(db *gorm.DB) (ids []int64, err error) { - if err = db.Model(c).Omit("User").Select("user_id").Where("friend_id = ? AND status = ?", c.FriendId, ContactStatusAgree).Find(&ids).Error; err != nil { - return nil, err - } - return -} - -func (c *Contact) MyFriendIds(db *gorm.DB) (ids []string, err error) { - if err = db.Model(c).Omit("User").Select("friend_id").Where("user_id = ? AND status = ?", c.UserId, ContactStatusAgree).Find(&ids).Error; err != nil { - return nil, err - } - return -} - -func (m *Contact) Count(db *gorm.DB, conditions ConditionsT) (int64, error) { - var count int64 - - for k, v := range conditions { - if k != "ORDER" { - db = db.Where(k, v) - } - } - if err := db.Model(m).Omit("User").Count(&count).Error; err != nil { - return 0, err - } - - return count, nil -} - -func (c *Contact) Create(db *gorm.DB) (*Contact, error) { - err := db.Omit("User").Create(&c).Error - return c, err -} - -func (c *Contact) Update(db *gorm.DB) error { - return db.Model(&Contact{}).Omit("User").Where("id = ?", c.Model.ID).Save(c).Error -} - -func (c *Contact) UpdateInUnscoped(db *gorm.DB) error { - return db.Unscoped().Omit("User").Save(c).Error -} diff --git a/internal/model/message.go b/internal/model/message.go deleted file mode 100644 index c1277cf7..00000000 --- a/internal/model/message.go +++ /dev/null @@ -1,148 +0,0 @@ -package model - -import "gorm.io/gorm" - -type MessageT int8 - -const ( - MsgTypePost MessageT = iota + 1 - MsgtypeComment - MsgTypeReply - MsgTypeWhisper - MsgTypeRequestingFriend - MsgTypeSystem MessageT = 99 - - MsgStatusUnread = 0 - MsgStatusReaded = 1 -) - -type Message struct { - *Model - SenderUserID int64 `json:"sender_user_id"` - ReceiverUserID int64 `json:"receiver_user_id"` - Type MessageT `json:"type"` - Brief string `json:"brief"` - Content string `json:"content"` - PostID int64 `json:"post_id"` - CommentID int64 `json:"comment_id"` - ReplyID int64 `json:"reply_id"` - IsRead int8 `json:"is_read"` -} - -type MessageFormated struct { - ID int64 `json:"id"` - SenderUserID int64 `json:"sender_user_id"` - SenderUser *UserFormated `json:"sender_user"` - ReceiverUserID int64 `json:"receiver_user_id"` - Type MessageT `json:"type"` - Brief string `json:"brief"` - Content string `json:"content"` - PostID int64 `json:"post_id"` - Post *PostFormated `json:"post"` - CommentID int64 `json:"comment_id"` - Comment *Comment `json:"comment"` - ReplyID int64 `json:"reply_id"` - Reply *CommentReply `json:"reply"` - IsRead int8 `json:"is_read"` - CreatedOn int64 `json:"created_on"` - ModifiedOn int64 `json:"modified_on"` -} - -func (m *Message) Format() *MessageFormated { - if m.Model == nil || m.Model.ID == 0 { - return nil - } - mf := &MessageFormated{ - ID: m.ID, - SenderUserID: m.SenderUserID, - SenderUser: &UserFormated{}, - ReceiverUserID: m.ReceiverUserID, - Type: m.Type, - Brief: m.Brief, - Content: m.Content, - PostID: m.PostID, - Post: &PostFormated{}, - CommentID: m.CommentID, - Comment: &Comment{}, - ReplyID: m.ReplyID, - Reply: &CommentReply{}, - IsRead: m.IsRead, - CreatedOn: m.CreatedOn, - ModifiedOn: m.ModifiedOn, - } - - return mf -} - -func (m *Message) Create(db *gorm.DB) (*Message, error) { - err := db.Create(&m).Error - - return m, err -} - -func (m *Message) Update(db *gorm.DB) error { - return db.Model(&Message{}).Where("id = ? AND is_del = ?", m.Model.ID, 0).Save(m).Error -} - -func (m *Message) Get(db *gorm.DB) (*Message, error) { - var message Message - if m.Model != nil && m.ID > 0 { - db = db.Where("id = ? AND is_del = ?", m.ID, 0) - } - if m.ReceiverUserID > 0 { - db = db.Where("receiver_user_id = ?", m.ReceiverUserID) - } - if err := db.First(&message).Error; err != nil { - return nil, err - } - return &message, nil -} - -func (m *Message) FetchBy(db *gorm.DB, predicates Predicates) ([]*Message, error) { - var messages []*Message - for k, v := range predicates { - db = db.Where(k, v...) - } - db = db.Where("is_del = 0") - if err := db.Find(&messages).Error; err != nil { - return nil, err - } - return messages, nil -} - -func (c *Message) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*Message, error) { - var messages []*Message - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&messages).Error; err != nil { - return nil, err - } - - return messages, nil -} - -func (m *Message) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { - var count int64 - - for k, v := range *conditions { - if k != "ORDER" { - db = db.Where(k, v) - } - } - if err := db.Model(m).Count(&count).Error; err != nil { - return 0, err - } - - return count, nil -} diff --git a/internal/model/post.go b/internal/model/post.go deleted file mode 100644 index ae428a9a..00000000 --- a/internal/model/post.go +++ /dev/null @@ -1,208 +0,0 @@ -package model - -import ( - "strings" - "time" - - "gorm.io/gorm" -) - -// PostVisibleT 可访问类型,0公开,1私密,2好友 -type PostVisibleT uint8 - -const ( - PostVisitPublic PostVisibleT = iota - PostVisitPrivate - PostVisitFriend - PostVisitInvalid -) - -type Post struct { - *Model - UserID int64 `json:"user_id"` - CommentCount int64 `json:"comment_count"` - CollectionCount int64 `json:"collection_count"` - UpvoteCount int64 `json:"upvote_count"` - Visibility PostVisibleT `json:"visibility"` - IsTop int `json:"is_top"` - IsEssence int `json:"is_essence"` - IsLock int `json:"is_lock"` - LatestRepliedOn int64 `json:"latest_replied_on"` - Tags string `json:"tags"` - AttachmentPrice int64 `json:"attachment_price"` - IP string `json:"ip"` - IPLoc string `json:"ip_loc"` -} - -type PostFormated struct { - ID int64 `json:"id"` - UserID int64 `json:"user_id"` - User *UserFormated `json:"user"` - Contents []*PostContentFormated `json:"contents"` - CommentCount int64 `json:"comment_count"` - CollectionCount int64 `json:"collection_count"` - UpvoteCount int64 `json:"upvote_count"` - Visibility PostVisibleT `json:"visibility"` - IsTop int `json:"is_top"` - IsEssence int `json:"is_essence"` - IsLock int `json:"is_lock"` - LatestRepliedOn int64 `json:"latest_replied_on"` - CreatedOn int64 `json:"created_on"` - ModifiedOn int64 `json:"modified_on"` - Tags map[string]int8 `json:"tags"` - AttachmentPrice int64 `json:"attachment_price"` - IPLoc string `json:"ip_loc"` -} - -func (p *Post) Format() *PostFormated { - if p.Model != nil { - tagsMap := map[string]int8{} - for _, tag := range strings.Split(p.Tags, ",") { - tagsMap[tag] = 1 - } - return &PostFormated{ - ID: p.ID, - UserID: p.UserID, - User: &UserFormated{}, - Contents: []*PostContentFormated{}, - CommentCount: p.CommentCount, - CollectionCount: p.CollectionCount, - UpvoteCount: p.UpvoteCount, - Visibility: p.Visibility, - IsTop: p.IsTop, - IsEssence: p.IsEssence, - IsLock: p.IsLock, - LatestRepliedOn: p.LatestRepliedOn, - CreatedOn: p.CreatedOn, - ModifiedOn: p.ModifiedOn, - AttachmentPrice: p.AttachmentPrice, - Tags: tagsMap, - IPLoc: p.IPLoc, - } - } - - return nil -} - -func (p *Post) Create(db *gorm.DB) (*Post, error) { - err := db.Create(&p).Error - - return p, err -} - -func (s *Post) Delete(db *gorm.DB) error { - return db.Model(s).Where("id = ?", s.Model.ID).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} - -func (p *Post) Get(db *gorm.DB) (*Post, error) { - var post Post - if p.Model != nil && p.ID > 0 { - db = db.Where("id = ? AND is_del = ?", p.ID, 0) - } else { - return nil, gorm.ErrRecordNotFound - } - - err := db.First(&post).Error - if err != nil { - return &post, err - } - - return &post, nil -} - -func (p *Post) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*Post, error) { - var posts []*Post - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if p.UserID > 0 { - db = db.Where("user_id = ?", p.UserID) - } - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&posts).Error; err != nil { - return nil, err - } - - return posts, nil -} - -func (p *Post) Fetch(db *gorm.DB, predicates Predicates, offset, limit int) ([]*Post, error) { - var posts []*Post - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if p.UserID > 0 { - db = db.Where("user_id = ?", p.UserID) - } - for query, args := range predicates { - if query == "ORDER" { - db = db.Order(args[0]) - } else { - db = db.Where(query, args...) - } - } - - if err = db.Where("is_del = ?", 0).Find(&posts).Error; err != nil { - return nil, err - } - - return posts, nil -} - -func (p *Post) CountBy(db *gorm.DB, predicates Predicates) (count int64, err error) { - for query, args := range predicates { - if query != "ORDER" { - db = db.Where(query, args...) - } - } - err = db.Model(p).Count(&count).Error - return -} - -func (p *Post) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { - var count int64 - if p.UserID > 0 { - db = db.Where("user_id = ?", p.UserID) - } - for k, v := range *conditions { - if k != "ORDER" { - db = db.Where(k, v) - } - } - if err := db.Model(p).Count(&count).Error; err != nil { - return 0, err - } - - return count, nil -} - -func (p *Post) Update(db *gorm.DB) error { - return db.Model(&Post{}).Where("id = ? AND is_del = ?", p.Model.ID, 0).Save(p).Error -} - -func (p PostVisibleT) String() string { - switch p { - case PostVisitPublic: - return "public" - case PostVisitPrivate: - return "private" - case PostVisitFriend: - return "friend" - case PostVisitInvalid: - return "invalid" - default: - return "unknow" - } -} diff --git a/internal/model/post_attachment_bill.go b/internal/model/post_attachment_bill.go deleted file mode 100644 index 8ee7aae6..00000000 --- a/internal/model/post_attachment_bill.go +++ /dev/null @@ -1,36 +0,0 @@ -package model - -import "gorm.io/gorm" - -type PostAttachmentBill struct { - *Model - PostID int64 `json:"post_id"` - UserID int64 `json:"user_id"` - PaidAmount int64 `json:"paid_amount"` -} - -func (p *PostAttachmentBill) Get(db *gorm.DB) (*PostAttachmentBill, error) { - var pas PostAttachmentBill - if p.Model != nil && p.ID > 0 { - db = db.Where("id = ? AND is_del = ?", p.ID, 0) - } - if p.PostID > 0 { - db = db.Where("post_id = ?", p.PostID) - } - if p.UserID > 0 { - db = db.Where("user_id = ?", p.UserID) - } - - err := db.First(&pas).Error - if err != nil { - return &pas, err - } - - return &pas, nil -} - -func (p *PostAttachmentBill) Create(db *gorm.DB) (*PostAttachmentBill, error) { - err := db.Create(&p).Error - - return p, err -} diff --git a/internal/model/post_collection.go b/internal/model/post_collection.go deleted file mode 100644 index 0ea0cb29..00000000 --- a/internal/model/post_collection.go +++ /dev/null @@ -1,102 +0,0 @@ -package model - -import ( - "time" - - "gorm.io/gorm" -) - -type PostCollection struct { - *Model - Post *Post `json:"-"` - PostID int64 `json:"post_id"` - UserID int64 `json:"user_id"` -} - -func (p *PostCollection) Get(db *gorm.DB) (*PostCollection, error) { - var star PostCollection - tn := db.NamingStrategy.TableName("PostCollection") + "." - - if p.Model != nil && p.ID > 0 { - db = db.Where(tn+"id = ? AND "+tn+"is_del = ?", p.ID, 0) - } - if p.PostID > 0 { - db = db.Where(tn+"post_id = ?", p.PostID) - } - if p.UserID > 0 { - db = db.Where(tn+"user_id = ?", p.UserID) - } - - db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate).Order("Post.id DESC") - err := db.First(&star).Error - if err != nil { - return &star, err - } - - return &star, nil -} - -func (p *PostCollection) Create(db *gorm.DB) (*PostCollection, error) { - err := db.Omit("Post").Create(&p).Error - - return p, err -} - -func (p *PostCollection) Delete(db *gorm.DB) error { - return db.Model(&PostCollection{}).Omit("Post").Where("id = ? AND is_del = ?", p.Model.ID, 0).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} - -func (p *PostCollection) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*PostCollection, error) { - var collections []*PostCollection - var err error - tn := db.NamingStrategy.TableName("PostCollection") + "." - - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if p.UserID > 0 { - db = db.Where(tn+"user_id = ?", p.UserID) - } - - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(tn+k, v) - } - } - - db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate).Order("Post.id DESC") - if err = db.Where(tn+"is_del = ?", 0).Find(&collections).Error; err != nil { - return nil, err - } - - return collections, nil -} - -func (p *PostCollection) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { - var count int64 - tn := db.NamingStrategy.TableName("PostCollection") + "." - - if p.PostID > 0 { - db = db.Where(tn+"post_id = ?", p.PostID) - } - if p.UserID > 0 { - db = db.Where(tn+"user_id = ?", p.UserID) - } - for k, v := range *conditions { - if k != "ORDER" { - db = db.Where(tn+k, v) - } - } - - db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate) - if err := db.Model(p).Count(&count).Error; err != nil { - return 0, err - } - - return count, nil -} diff --git a/internal/model/post_content.go b/internal/model/post_content.go deleted file mode 100644 index b301de62..00000000 --- a/internal/model/post_content.go +++ /dev/null @@ -1,121 +0,0 @@ -package model - -import ( - "time" - - "gorm.io/gorm" -) - -// 类型,1标题,2文字段落,3图片地址,4视频地址,5语音地址,6链接地址,7附件资源 - -type PostContentT int - -const ( - CONTENT_TYPE_TITLE PostContentT = iota + 1 - CONTENT_TYPE_TEXT - CONTENT_TYPE_IMAGE - CONTENT_TYPE_VIDEO - CONTENT_TYPE_AUDIO - CONTENT_TYPE_LINK - CONTENT_TYPE_ATTACHMENT - CONTENT_TYPE_CHARGE_ATTACHMENT -) - -var ( - mediaContentType = []PostContentT{ - CONTENT_TYPE_IMAGE, - CONTENT_TYPE_VIDEO, - CONTENT_TYPE_AUDIO, - CONTENT_TYPE_ATTACHMENT, - CONTENT_TYPE_CHARGE_ATTACHMENT, - } -) - -type PostContent struct { - *Model - PostID int64 `json:"post_id"` - UserID int64 `json:"user_id"` - Content string `json:"content"` - Type PostContentT `json:"type"` - Sort int64 `json:"sort"` -} - -type PostContentFormated struct { - ID int64 `json:"id"` - PostID int64 `json:"post_id"` - Content string `json:"content"` - Type PostContentT `json:"type"` - Sort int64 `json:"sort"` -} - -func (p *PostContent) DeleteByPostId(db *gorm.DB, postId int64) error { - return db.Model(p).Where("post_id = ?", postId).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} - -func (p *PostContent) MediaContentsByPostId(db *gorm.DB, postId int64) (contents []string, err error) { - err = db.Model(p).Where("post_id = ? AND type IN ?", postId, mediaContentType).Select("content").Find(&contents).Error - return -} - -func (p *PostContent) Create(db *gorm.DB) (*PostContent, error) { - err := db.Create(&p).Error - - return p, err -} - -func (p *PostContent) Format() *PostContentFormated { - if p.Model == nil { - return nil - } - return &PostContentFormated{ - ID: p.ID, - PostID: p.PostID, - Content: p.Content, - Type: p.Type, - Sort: p.Sort, - } -} - -func (p *PostContent) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*PostContent, error) { - var contents []*PostContent - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if p.PostID > 0 { - db = db.Where("id = ?", p.PostID) - } - - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&contents).Error; err != nil { - return nil, err - } - - return contents, nil -} - -func (p *PostContent) Get(db *gorm.DB) (*PostContent, error) { - var content PostContent - if p.Model != nil && p.ID > 0 { - db = db.Where("id = ? AND is_del = ?", p.ID, 0) - } else { - return nil, gorm.ErrRecordNotFound - } - - err := db.First(&content).Error - if err != nil { - return &content, err - } - - return &content, nil -} diff --git a/internal/model/post_star.go b/internal/model/post_star.go deleted file mode 100644 index 3846a9c2..00000000 --- a/internal/model/post_star.go +++ /dev/null @@ -1,98 +0,0 @@ -package model - -import ( - "time" - - "gorm.io/gorm" -) - -type PostStar struct { - *Model - Post *Post `json:"-"` - PostID int64 `json:"post_id"` - UserID int64 `json:"user_id"` -} - -func (p *PostStar) Get(db *gorm.DB) (*PostStar, error) { - var star PostStar - tn := db.NamingStrategy.TableName("PostStar") + "." - - if p.Model != nil && p.ID > 0 { - db = db.Where(tn+"id = ? AND "+tn+"is_del = ?", p.ID, 0) - } - if p.PostID > 0 { - db = db.Where(tn+"post_id = ?", p.PostID) - } - if p.UserID > 0 { - db = db.Where(tn+"user_id = ?", p.UserID) - } - - db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate).Order("Post.id DESC") - if err := db.First(&star).Error; err != nil { - return nil, err - } - return &star, nil -} - -func (p *PostStar) Create(db *gorm.DB) (*PostStar, error) { - err := db.Omit("Post").Create(&p).Error - - return p, err -} - -func (p *PostStar) Delete(db *gorm.DB) error { - return db.Model(&PostStar{}).Omit("Post").Where("id = ? AND is_del = ?", p.Model.ID, 0).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} - -func (p *PostStar) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*PostStar, error) { - var stars []*PostStar - var err error - tn := db.NamingStrategy.TableName("PostStar") + "." - - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if p.UserID > 0 { - db = db.Where(tn+"user_id = ?", p.UserID) - } - - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(tn+k, v) - } - } - - db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate).Order("Post.id DESC") - if err = db.Find(&stars).Error; err != nil { - return nil, err - } - return stars, nil -} - -func (p *PostStar) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { - var count int64 - tn := db.NamingStrategy.TableName("PostStar") + "." - - if p.PostID > 0 { - db = db.Where(tn+"post_id = ?", p.PostID) - } - if p.UserID > 0 { - db = db.Where(tn+"user_id = ?", p.UserID) - } - for k, v := range *conditions { - if k != "ORDER" { - db = db.Where(tn+k, v) - } - } - - db = db.Joins("Post").Where("Post.visibility <> ?", PostVisitPrivate) - if err := db.Model(p).Count(&count).Error; err != nil { - return 0, err - } - return count, nil -} diff --git a/internal/model/rest/contacts.go b/internal/model/rest/contacts.go deleted file mode 100644 index bbf31e42..00000000 --- a/internal/model/rest/contacts.go +++ /dev/null @@ -1,31 +0,0 @@ -package rest - -type RequestingFriendReq struct { - UserId int64 `json:"user_id" binding:"required"` - Greetings string `json:"greetings" binding:"required"` -} - -type AddFriendReq struct { - UserId int64 `json:"user_id" binding:"required"` -} - -type RejectFriendReq struct { - UserId int64 `json:"user_id" binding:"required"` -} - -type DeleteFriendReq struct { - UserId int64 `json:"user_id"` -} - -type ContactItem struct { - UserId int64 `json:"user_id"` - UserName string `json:"username"` - Nickname string `json:"nickname"` - Avatar string `json:"avatar"` - Phone string `json:"phone"` -} - -type ContactsResp struct { - Contacts []ContactItem `json:"contacts"` - Total int64 `json:"total"` -} diff --git a/internal/model/rest/tweets.go b/internal/model/rest/tweets.go deleted file mode 100644 index de85e179..00000000 --- a/internal/model/rest/tweets.go +++ /dev/null @@ -1,8 +0,0 @@ -package rest - -import "github.com/rocboss/paopao-ce/internal/model" - -type IndexTweetsResp struct { - Tweets []*model.PostFormated - Total int64 -} diff --git a/internal/model/rest/user.go b/internal/model/rest/user.go deleted file mode 100644 index 60ff467d..00000000 --- a/internal/model/rest/user.go +++ /dev/null @@ -1,11 +0,0 @@ -package rest - -type UserProfileResp struct { - ID int64 `json:"id"` - Nickname string `json:"nickname"` - Username string `json:"username"` - Status int `json:"status"` - Avatar string `json:"avatar"` - IsAdmin bool `json:"is_admin"` - IsFriend bool `json:"is_friend"` -} diff --git a/internal/model/tag.go b/internal/model/tag.go deleted file mode 100644 index 34bb64f9..00000000 --- a/internal/model/tag.go +++ /dev/null @@ -1,97 +0,0 @@ -package model - -import ( - "time" - - "gorm.io/gorm" -) - -type Tag struct { - *Model - UserID int64 `json:"user_id"` - Tag string `json:"tag"` - QuoteNum int64 `json:"quote_num"` -} -type TagFormated struct { - ID int64 `json:"id"` - UserID int64 `json:"user_id"` - User *UserFormated `json:"user"` - Tag string `json:"tag"` - QuoteNum int64 `json:"quote_num"` -} - -func (t *Tag) Format() *TagFormated { - if t.Model == nil { - return &TagFormated{} - } - - return &TagFormated{ - ID: t.ID, - UserID: t.UserID, - User: &UserFormated{}, - Tag: t.Tag, - QuoteNum: t.QuoteNum, - } -} - -func (t *Tag) Get(db *gorm.DB) (*Tag, error) { - var tag Tag - if t.Model != nil && t.Model.ID > 0 { - db = db.Where("id= ? AND is_del = ?", t.Model.ID, 0) - } else { - db = db.Where("tag = ? AND is_del = ?", t.Tag, 0) - } - - err := db.First(&tag).Error - if err != nil { - return &tag, err - } - - return &tag, nil -} - -func (t *Tag) Create(db *gorm.DB) (*Tag, error) { - err := db.Create(&t).Error - - return t, err -} - -func (t *Tag) Update(db *gorm.DB) error { - return db.Model(&Tag{}).Where("id = ? AND is_del = ?", t.Model.ID, 0).Save(t).Error -} - -func (t *Tag) Delete(db *gorm.DB) error { - return db.Model(t).Where("id = ?", t.Model.ID).Updates(map[string]any{ - "deleted_on": time.Now().Unix(), - "is_del": 1, - }).Error -} - -func (t *Tag) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*Tag, error) { - var tags []*Tag - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if t.UserID > 0 { - db = db.Where("user_id = ?", t.UserID) - } - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&tags).Error; err != nil { - return nil, err - } - - return tags, nil -} - -func (t *Tag) TagsFrom(db *gorm.DB, tags []string) (res []*Tag, err error) { - err = db.Where("tag IN ?", tags).Find(&res).Error - return -} diff --git a/internal/model/user.go b/internal/model/user.go deleted file mode 100644 index 39c52d79..00000000 --- a/internal/model/user.go +++ /dev/null @@ -1,94 +0,0 @@ -package model - -import "gorm.io/gorm" - -const ( - UserStatusNormal int = iota + 1 - UserStatusClosed -) - -type User struct { - *Model - Nickname string `json:"nickname"` - Username string `json:"username"` - Phone string `json:"phone"` - Password string `json:"password"` - Salt string `json:"salt"` - Status int `json:"status"` - Avatar string `json:"avatar"` - Balance int64 `json:"balance"` - IsAdmin bool `json:"is_admin"` -} - -type UserFormated struct { - ID int64 `json:"id"` - Nickname string `json:"nickname"` - Username string `json:"username"` - Status int `json:"status"` - Avatar string `json:"avatar"` - IsAdmin bool `json:"is_admin"` -} - -func (u *User) Format() *UserFormated { - if u.Model != nil { - return &UserFormated{ - ID: u.ID, - Nickname: u.Nickname, - Username: u.Username, - Status: u.Status, - Avatar: u.Avatar, - IsAdmin: u.IsAdmin, - } - } - - return nil -} - -func (u *User) Get(db *gorm.DB) (*User, error) { - var user User - if u.Model != nil && u.Model.ID > 0 { - db = db.Where("id= ? AND is_del = ?", u.Model.ID, 0) - } else if u.Phone != "" { - db = db.Where("phone = ? AND is_del = ?", u.Phone, 0) - } else { - db = db.Where("username = ? AND is_del = ?", u.Username, 0) - } - - err := db.First(&user).Error - if err != nil { - return &user, err - } - - return &user, nil -} - -func (u *User) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*User, error) { - var users []*User - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&users).Error; err != nil { - return nil, err - } - - return users, nil -} - -func (u *User) Create(db *gorm.DB) (*User, error) { - err := db.Create(&u).Error - - return u, err -} - -func (u *User) Update(db *gorm.DB) error { - return db.Model(&User{}).Where("id = ? AND is_del = ?", u.Model.ID, 0).Save(u).Error -} diff --git a/internal/model/wallet_recharge.go b/internal/model/wallet_recharge.go deleted file mode 100644 index bfb3bc6f..00000000 --- a/internal/model/wallet_recharge.go +++ /dev/null @@ -1,34 +0,0 @@ -package model - -import "gorm.io/gorm" - -type WalletRecharge struct { - *Model - UserID int64 `json:"user_id"` - Amount int64 `json:"amount"` - TradeNo string `json:"trade_no"` - TradeStatus string `json:"trade_status"` -} - -func (p *WalletRecharge) Get(db *gorm.DB) (*WalletRecharge, error) { - var pas WalletRecharge - if p.Model != nil && p.ID > 0 { - db = db.Where("id = ? AND is_del = ?", p.ID, 0) - } - if p.UserID > 0 { - db = db.Where("user_id = ?", p.UserID) - } - - err := db.First(&pas).Error - if err != nil { - return &pas, err - } - - return &pas, nil -} - -func (p *WalletRecharge) Create(db *gorm.DB) (*WalletRecharge, error) { - err := db.Create(&p).Error - - return p, err -} diff --git a/internal/model/wallet_statement.go b/internal/model/wallet_statement.go deleted file mode 100644 index 163e2430..00000000 --- a/internal/model/wallet_statement.go +++ /dev/null @@ -1,83 +0,0 @@ -package model - -import "gorm.io/gorm" - -type WalletStatement struct { - *Model - UserID int64 `json:"user_id"` - ChangeAmount int64 `json:"change_amount"` - BalanceSnapshot int64 `json:"balance_snapshot"` - Reason string `json:"reason"` - PostID int64 `json:"post_id"` -} - -func (w *WalletStatement) Get(db *gorm.DB) (*WalletStatement, error) { - var ws WalletStatement - if w.Model != nil && w.ID > 0 { - db = db.Where("id = ? AND is_del = ?", w.ID, 0) - } - if w.PostID > 0 { - db = db.Where("post_id = ?", w.PostID) - } - if w.UserID > 0 { - db = db.Where("user_id = ?", w.UserID) - } - - err := db.First(&ws).Error - if err != nil { - return &ws, err - } - - return &ws, nil -} - -func (w *WalletStatement) Create(db *gorm.DB) (*WalletStatement, error) { - err := db.Create(&w).Error - - return w, err -} - -func (w *WalletStatement) List(db *gorm.DB, conditions *ConditionsT, offset, limit int) ([]*WalletStatement, error) { - var records []*WalletStatement - var err error - if offset >= 0 && limit > 0 { - db = db.Offset(offset).Limit(limit) - } - if w.UserID > 0 { - db = db.Where("user_id = ?", w.UserID) - } - - for k, v := range *conditions { - if k == "ORDER" { - db = db.Order(v) - } else { - db = db.Where(k, v) - } - } - - if err = db.Where("is_del = ?", 0).Find(&records).Error; err != nil { - return nil, err - } - - return records, nil -} - -func (w *WalletStatement) Count(db *gorm.DB, conditions *ConditionsT) (int64, error) { - var count int64 - if w.PostID > 0 { - db = db.Where("post_id = ?", w.PostID) - } - if w.UserID > 0 { - db = db.Where("user_id = ?", w.UserID) - } - for k, v := range *conditions { - if k != "ORDER" { - db = db.Where(k, v) - } - } - if err := db.Model(w).Count(&count).Error; err != nil { - return 0, err - } - - return count, nil -} diff --git a/internal/proto/gen.go b/internal/proto/gen.go new file mode 100644 index 00000000..adb9c8db --- /dev/null +++ b/internal/proto/gen.go @@ -0,0 +1,5 @@ +// 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 proto diff --git a/internal/proto/tweets.proto b/internal/proto/tweets.proto new file mode 100644 index 00000000..1fcc9364 --- /dev/null +++ b/internal/proto/tweets.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package paopao; + +option go_package = "proto"; + +message Tag { + string name = 1; + int32 type = 2; +} diff --git a/internal/servants/core/core.go b/internal/servants/base/base.go similarity index 81% rename from internal/servants/core/core.go rename to internal/servants/base/base.go index 6dad41e7..6c204e7e 100644 --- a/internal/servants/core/core.go +++ b/internal/servants/base/base.go @@ -1,4 +1,8 @@ -package core +// 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 base import ( "net/http" @@ -6,7 +10,7 @@ import ( "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/pkg/xerror" ) @@ -22,9 +26,9 @@ type BaseRender struct { // TODO } -func (BaseServant) userFrom(c *gin.Context) (*model.User, bool) { +func (BaseServant) userFrom(c *gin.Context) (*core.User, bool) { if u, exists := c.Get("USER"); exists { - user, ok := u.(*model.User) + user, ok := u.(*core.User) return user, ok } return nil, false diff --git a/internal/servants/chain/admin.go b/internal/servants/chain/admin.go index 846d6b68..35a0fbc3 100644 --- a/internal/servants/chain/admin.go +++ b/internal/servants/chain/admin.go @@ -1,8 +1,12 @@ +// 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 chain import ( "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/errcode" ) @@ -10,8 +14,8 @@ import ( func Admin() gin.HandlerFunc { return func(c *gin.Context) { if user, exist := c.Get("USER"); exist { - if userModel, ok := user.(*model.User); ok { - if userModel.Status == model.UserStatusNormal && userModel.IsAdmin { + if userModel, ok := user.(*core.User); ok { + if userModel.Status == core.UserStatusNormal && userModel.IsAdmin { c.Next() return } diff --git a/internal/servants/chain/jwt.go b/internal/servants/chain/jwt.go index 75a4c9ad..a0396630 100644 --- a/internal/servants/chain/jwt.go +++ b/internal/servants/chain/jwt.go @@ -1,3 +1,7 @@ +// 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 chain import ( @@ -6,7 +10,7 @@ import ( "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v4" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/errcode" ) @@ -51,8 +55,8 @@ func JWT() gin.HandlerFunc { c.Set("USERNAME", claims.Username) // 加载用户信息 - user := &model.User{ - Model: &model.Model{ + user := &core.User{ + Model: &core.Model{ ID: claims.UID, }, } @@ -97,8 +101,8 @@ func JwtLoose() gin.HandlerFunc { c.Set("UID", claims.UID) c.Set("USERNAME", claims.Username) // 加载用户信息 - user := &model.User{ - Model: &model.Model{ + user := &core.User{ + Model: &core.Model{ ID: claims.UID, }, } diff --git a/internal/servants/chain/priv.go b/internal/servants/chain/priv.go index a60ebe41..f03c14b7 100644 --- a/internal/servants/chain/priv.go +++ b/internal/servants/chain/priv.go @@ -1,8 +1,12 @@ +// 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 chain import ( "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/rocboss/paopao-ce/pkg/errcode" @@ -12,8 +16,8 @@ func Priv() gin.HandlerFunc { if cfg.If("PhoneBind") { return func(c *gin.Context) { if u, exist := c.Get("USER"); exist { - if user, ok := u.(*model.User); ok { - if user.Status == model.UserStatusNormal { + if user, ok := u.(*core.User); ok { + if user.Status == core.UserStatusNormal { if user.Phone == "" { response := app.NewResponse(c) response.ToErrorResponse(errcode.AccountNoPhoneBind) @@ -32,7 +36,7 @@ func Priv() gin.HandlerFunc { } else { return func(c *gin.Context) { if u, exist := c.Get("USER"); exist { - if user, ok := u.(*model.User); ok && user.Status == model.UserStatusNormal { + if user, ok := u.(*core.User); ok && user.Status == core.UserStatusNormal { c.Next() return } diff --git a/internal/servants/docs/docs.go b/internal/servants/docs/docs.go index ef062a47..7b6c9d36 100644 --- a/internal/servants/docs/docs.go +++ b/internal/servants/docs/docs.go @@ -1,3 +1,7 @@ +// 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. + //go:build !docs // +build !docs diff --git a/internal/servants/docs/docs_embed.go b/internal/servants/docs/docs_embed.go index da457e50..653e1c07 100644 --- a/internal/servants/docs/docs_embed.go +++ b/internal/servants/docs/docs_embed.go @@ -1,3 +1,7 @@ +// 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. + //go:build docs // +build docs diff --git a/internal/servants/localoss/localoss.go b/internal/servants/localoss/localoss.go index 1435e300..828b3be2 100644 --- a/internal/servants/localoss/localoss.go +++ b/internal/servants/localoss/localoss.go @@ -1,3 +1,7 @@ +// 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 localoss import ( diff --git a/internal/servants/localoss/xerror.go b/internal/servants/localoss/xerror.go index 7b656b7d..38132d24 100644 --- a/internal/servants/localoss/xerror.go +++ b/internal/servants/localoss/xerror.go @@ -1,3 +1,7 @@ +// 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 localoss import ( diff --git a/internal/servants/servants.go b/internal/servants/servants.go index 4c36c0d6..4f1f0bcd 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -1,3 +1,7 @@ +// 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 servants import ( diff --git a/internal/servants/statick/statick.go b/internal/servants/statick/statick.go index a852bdfc..d4c2bfdc 100644 --- a/internal/servants/statick/statick.go +++ b/internal/servants/statick/statick.go @@ -1,3 +1,7 @@ +// 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. + //go:build !embed // +build !embed diff --git a/internal/servants/statick/statick_embed.go b/internal/servants/statick/statick_embed.go index 6dd4c77b..32da717f 100644 --- a/internal/servants/statick/statick_embed.go +++ b/internal/servants/statick/statick_embed.go @@ -1,3 +1,7 @@ +// 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. + //go:build embed // +build embed diff --git a/internal/servants/web/admin.go b/internal/servants/web/admin.go index f97832ce..e4f2ef6e 100644 --- a/internal/servants/web/admin.go +++ b/internal/servants/web/admin.go @@ -1,3 +1,7 @@ +// 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 type webAdminSrv struct { diff --git a/internal/servants/web/alipay.go b/internal/servants/web/alipay.go index a4f71e9f..80cfd7b7 100644 --- a/internal/servants/web/alipay.go +++ b/internal/servants/web/alipay.go @@ -1,3 +1,7 @@ +// 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 type webAlipaySrv struct { diff --git a/internal/servants/web/broker/attachment.go b/internal/servants/web/broker/attachment.go new file mode 100644 index 00000000..e8c69447 --- /dev/null +++ b/internal/servants/web/broker/attachment.go @@ -0,0 +1,13 @@ +// 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 broker + +import ( + "github.com/rocboss/paopao-ce/internal/core" +) + +func CreateAttachment(attachment *core.Attachment) (*core.Attachment, error) { + return ds.CreateAttachment(attachment) +} diff --git a/internal/service/avatar.go b/internal/servants/web/broker/avatar.go similarity index 95% rename from internal/service/avatar.go rename to internal/servants/web/broker/avatar.go index 3ac302e0..04e183f4 100644 --- a/internal/service/avatar.go +++ b/internal/servants/web/broker/avatar.go @@ -1,4 +1,8 @@ -package service +// 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 broker import ( "math/rand" diff --git a/internal/servants/web/broker/broker.go b/internal/servants/web/broker/broker.go new file mode 100644 index 00000000..79423901 --- /dev/null +++ b/internal/servants/web/broker/broker.go @@ -0,0 +1,48 @@ +// 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 broker + +import ( + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/dao" + "github.com/rocboss/paopao-ce/pkg/cfg" + "github.com/sirupsen/logrus" +) + +var ( + ds core.DataService + ts core.TweetSearchService + oss core.ObjectStorageService + DisablePhoneVerify bool +) + +func Initialize() { + ds = dao.DataService() + ts = dao.TweetSearchService() + oss = dao.ObjectStorageService() + DisablePhoneVerify = !cfg.If("Sms") +} + +// persistMediaContents 获取媒体内容并持久化 +func persistMediaContents(contents []*PostContentItem) (items []string, err error) { + items = make([]string, 0, len(contents)) + for _, item := range contents { + switch item.Type { + case core.ContentTypeImage, + core.ContentTypeVideo, + core.ContentTypeAudio, + core.ContentTypeAttachment, + core.ContentTypeChargeAttachment: + items = append(items, item.Content) + if err != nil { + continue + } + if err = oss.PersistObject(oss.ObjectKey(item.Content)); err != nil { + logrus.Errorf("service.persistMediaContents failed: %s", err) + } + } + } + return +} diff --git a/internal/service/comment.go b/internal/servants/web/broker/comment.go similarity index 83% rename from internal/service/comment.go rename to internal/servants/web/broker/comment.go index f5165d71..7f9389dc 100644 --- a/internal/service/comment.go +++ b/internal/servants/web/broker/comment.go @@ -1,11 +1,15 @@ -package service +// 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 broker import ( + "github.com/rocboss/paopao-ce/internal/core" "time" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/pkg/errcode" "github.com/rocboss/paopao-ce/pkg/util" ) @@ -28,8 +32,8 @@ type ReplyDelReq struct { ID int64 `json:"id" binding:"required"` } -func GetPostComments(postID int64, sort string, offset, limit int) ([]*model.CommentFormated, int64, error) { - conditions := &model.ConditionsT{ +func GetPostComments(postID int64, sort string, offset, limit int) ([]*core.CommentFormated, int64, error) { + conditions := &core.ConditionsT{ "post_id": postID, "ORDER": sort, } @@ -61,7 +65,7 @@ func GetPostComments(postID int64, sort string, offset, limit int) ([]*model.Com return nil, 0, err } - commentsFormated := []*model.CommentFormated{} + commentsFormated := []*core.CommentFormated{} for _, comment := range comments { commentFormated := comment.Format() for _, content := range contents { @@ -89,7 +93,7 @@ func GetPostComments(postID int64, sort string, offset, limit int) ([]*model.Com return commentsFormated, totalRows, nil } -func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) (comment *model.Comment, err error) { +func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) (comment *core.Comment, err error) { var mediaContents []string defer func() { @@ -113,7 +117,7 @@ func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) return nil, errcode.MaxCommentCount } ip := ctx.ClientIP() - comment = &model.Comment{ + comment = &core.Comment{ PostID: post.ID, UserID: userID, IP: ip, @@ -126,13 +130,13 @@ func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) for _, item := range param.Contents { // 检查附件是否是本站资源 - if item.Type == model.CONTENT_TYPE_IMAGE || item.Type == model.CONTENT_TYPE_VIDEO || item.Type == model.CONTENT_TYPE_ATTACHMENT { + if item.Type == core.ContentTypeImage || item.Type == core.ContentTypeVideo || item.Type == core.ContentTypeAttachment { if err := ds.CheckAttachment(item.Content); err != nil { continue } } - postContent := &model.CommentContent{ + postContent := &core.CommentContent{ CommentID: comment.ID, UserID: userID, Content: item.Content, @@ -153,10 +157,10 @@ func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) // 创建用户消息提醒 postMaster, err := ds.GetUserByID(post.UserID) if err == nil && postMaster.ID != userID { - go ds.CreateMessage(&model.Message{ + go ds.CreateMessage(&core.Message{ SenderUserID: userID, ReceiverUserID: postMaster.ID, - Type: model.MsgtypeComment, + Type: core.MsgtypeComment, Brief: "在泡泡中评论了你", PostID: post.ID, CommentID: comment.ID, @@ -169,10 +173,10 @@ func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) } // 创建消息提醒 - go ds.CreateMessage(&model.Message{ + go ds.CreateMessage(&core.Message{ SenderUserID: userID, ReceiverUserID: user.ID, - Type: model.MsgtypeComment, + Type: core.MsgtypeComment, Brief: "在泡泡评论中@了你", PostID: post.ID, CommentID: comment.ID, @@ -182,11 +186,11 @@ func CreatePostComment(ctx *gin.Context, userID int64, param CommentCreationReq) return comment, nil } -func GetPostComment(id int64) (*model.Comment, error) { +func GetPostComment(id int64) (*core.Comment, error) { return ds.GetCommentByID(id) } -func DeletePostComment(comment *model.Comment) error { +func DeletePostComment(comment *core.Comment) error { // 加载post post, err := ds.GetPostByID(comment.PostID) if err == nil { @@ -198,7 +202,7 @@ func DeletePostComment(comment *model.Comment) error { return ds.DeleteComment(comment) } -func createPostPreHandler(commentID int64, userID, atUserID int64) (*model.Post, *model.Comment, int64, +func createPostPreHandler(commentID int64, userID, atUserID int64) (*core.Post, *core.Comment, int64, error) { // 加载Comment comment, err := ds.GetCommentByID(commentID) @@ -231,10 +235,10 @@ func createPostPreHandler(commentID int64, userID, atUserID int64) (*model.Post, return post, comment, atUserID, nil } -func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, userID, atUserID int64) (*model.CommentReply, error) { +func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, userID, atUserID int64) (*core.CommentReply, error) { var ( - post *model.Post - comment *model.Comment + post *core.Post + comment *core.Comment err error ) if post, comment, atUserID, err = createPostPreHandler(commentID, userID, atUserID); err != nil { @@ -243,7 +247,7 @@ func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, u // 创建评论 ip := ctx.ClientIP() - reply := &model.CommentReply{ + reply := &core.CommentReply{ CommentID: commentID, UserID: userID, Content: content, @@ -268,10 +272,10 @@ func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, u // 创建用户消息提醒 commentMaster, err := ds.GetUserByID(comment.UserID) if err == nil && commentMaster.ID != userID { - go ds.CreateMessage(&model.Message{ + go ds.CreateMessage(&core.Message{ SenderUserID: userID, ReceiverUserID: commentMaster.ID, - Type: model.MsgTypeReply, + Type: core.MsgTypeReply, Brief: "在泡泡评论下回复了你", PostID: post.ID, CommentID: comment.ID, @@ -280,10 +284,10 @@ func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, u } postMaster, err := ds.GetUserByID(post.UserID) if err == nil && postMaster.ID != userID && commentMaster.ID != postMaster.ID { - go ds.CreateMessage(&model.Message{ + go ds.CreateMessage(&core.Message{ SenderUserID: userID, ReceiverUserID: postMaster.ID, - Type: model.MsgTypeReply, + Type: core.MsgTypeReply, Brief: "在泡泡评论下发布了新回复", PostID: post.ID, CommentID: comment.ID, @@ -294,10 +298,10 @@ func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, u user, err := ds.GetUserByID(atUserID) if err == nil && user.ID != userID && commentMaster.ID != user.ID && postMaster.ID != user.ID { // 创建消息提醒 - go ds.CreateMessage(&model.Message{ + go ds.CreateMessage(&core.Message{ SenderUserID: userID, ReceiverUserID: user.ID, - Type: model.MsgTypeReply, + Type: core.MsgTypeReply, Brief: "在泡泡评论的回复中@了你", PostID: post.ID, CommentID: comment.ID, @@ -309,11 +313,11 @@ func CreatePostCommentReply(ctx *gin.Context, commentID int64, content string, u return reply, nil } -func GetPostCommentReply(id int64) (*model.CommentReply, error) { +func GetPostCommentReply(id int64) (*core.CommentReply, error) { return ds.GetCommentReplyByID(id) } -func DeletePostCommentReply(reply *model.CommentReply) error { +func DeletePostCommentReply(reply *core.CommentReply) error { err := ds.DeleteCommentReply(reply) if err != nil { return err diff --git a/internal/service/message.go b/internal/servants/web/broker/message.go similarity index 84% rename from internal/service/message.go rename to internal/servants/web/broker/message.go index a025a849..6e5dd1a1 100644 --- a/internal/service/message.go +++ b/internal/servants/web/broker/message.go @@ -1,4 +1,8 @@ -package service +// 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 broker import ( "fmt" @@ -6,7 +10,7 @@ import ( "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/errcode" ) @@ -23,7 +27,7 @@ type WhisperReq struct { } // CreateWhisper 创建私信 -func CreateWhisper(c *gin.Context, msg *model.Message) (*model.Message, error) { +func CreateWhisper(c *gin.Context, msg *core.Message) (*core.Message, error) { whisperKey := fmt.Sprintf("WhisperTimes:%d", msg.SenderUserID) // 今日频次限制 @@ -65,8 +69,8 @@ func ReadMessage(id, userID int64) error { return ds.ReadMessage(message) } -func GetMessages(userID int64, offset, limit int) ([]*model.MessageFormated, int64, error) { - conditions := &model.ConditionsT{ +func GetMessages(userID int64, offset, limit int) ([]*core.MessageFormated, int64, error) { + conditions := &core.ConditionsT{ "receiver_user_id": userID, "ORDER": "id DESC", } @@ -83,7 +87,7 @@ func GetMessages(userID int64, offset, limit int) ([]*model.MessageFormated, int } // 好友申请消息不需要获取其他信息 - if mf.Type == model.MsgTypeRequestingFriend { + if mf.Type == core.MsgTypeRequestingFriend { continue } diff --git a/internal/service/post.go b/internal/servants/web/broker/post.go similarity index 76% rename from internal/service/post.go rename to internal/servants/web/broker/post.go index c8bda6b8..9a73528b 100644 --- a/internal/service/post.go +++ b/internal/servants/web/broker/post.go @@ -1,4 +1,8 @@ -package service +// 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 broker import ( "errors" @@ -10,8 +14,6 @@ import ( "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/model/rest" "github.com/rocboss/paopao-ce/pkg/errcode" "github.com/rocboss/paopao-ce/pkg/util" "github.com/sirupsen/logrus" @@ -23,7 +25,7 @@ const TagTypeHot TagType = "hot" const TagTypeNew TagType = "new" type PostListReq struct { - Conditions *model.ConditionsT + Conditions *core.ConditionsT Offset int Limit int } @@ -37,7 +39,7 @@ type PostCreationReq struct { Tags []string `json:"tags" binding:"required"` Users []string `json:"users" binding:"required"` AttachmentPrice int64 `json:"attachment_price"` - Visibility model.PostVisibleT `json:"visibility"` + Visibility core.PostVisibleT `json:"visibility"` } type PostDelReq struct { @@ -53,8 +55,8 @@ type PostStickReq struct { } type PostVisibilityReq struct { - ID int64 `json:"id" binding:"required"` - Visibility model.PostVisibleT `json:"visibility"` + ID int64 `json:"id" binding:"required"` + Visibility core.PostVisibleT `json:"visibility"` } type PostStarReq struct { @@ -66,27 +68,25 @@ type PostCollectionReq struct { } type PostContentItem struct { - Content string `json:"content" binding:"required"` - Type model.PostContentT `json:"type" binding:"required"` - Sort int64 `json:"sort" binding:"required"` + Content string `json:"content" binding:"required"` + Type core.PostContentT `json:"type" binding:"required"` + Sort int64 `json:"sort" binding:"required"` } // Check 检查PostContentItem属性 func (p *PostContentItem) Check() error { // 检查附件是否是本站资源 - if p.Type == model.CONTENT_TYPE_IMAGE || p.Type == model.CONTENT_TYPE_VIDEO || p.Type == model. - CONTENT_TYPE_ATTACHMENT { + if p.Type == core.ContentTypeImage || p.Type == core.ContentTypeVideo || p.Type == core.ContentTypeAttachment { if err := ds.CheckAttachment(p.Content); err != nil { return err } } // 检查链接是否合法 - if p.Type == model.CONTENT_TYPE_LINK { + if p.Type == core.ContentTypeLink { if strings.Index(p.Content, "http://") != 0 && strings.Index(p.Content, "https://") != 0 { return fmt.Errorf("链接不合法") } } - return nil } @@ -103,7 +103,7 @@ func tagsFrom(originTags []string) []string { // CreatePost 创建文章 // TODO: 推文+推文内容需要在一个事务中添加,后续优化 -func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (_ *model.PostFormated, err error) { +func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (_ *core.PostFormated, err error) { var mediaContents []string defer func() { @@ -118,7 +118,7 @@ func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (_ *model.P ip := c.ClientIP() tags := tagsFrom(param.Tags) - post := &model.Post{ + post := &core.Post{ UserID: userID, Tags: strings.Join(tags, ","), IP: ip, @@ -138,11 +138,11 @@ func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (_ *model.P continue } - if item.Type == model.CONTENT_TYPE_ATTACHMENT && param.AttachmentPrice > 0 { - item.Type = model.CONTENT_TYPE_CHARGE_ATTACHMENT + if item.Type == core.ContentTypeAttachment && param.AttachmentPrice > 0 { + item.Type = core.ContentTypeChargeAttachment } - postContent := &model.PostContent{ + postContent := &core.PostContent{ PostID: post.ID, UserID: userID, Content: item.Content, @@ -155,10 +155,10 @@ func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (_ *model.P } // 私密推文不创建标签与用户提醒 - if post.Visibility != model.PostVisitPrivate { + if post.Visibility != core.PostVisitPrivate { // 创建标签 for _, t := range tags { - tag := &model.Tag{ + tag := &core.Tag{ UserID: userID, Tag: t, } @@ -174,10 +174,10 @@ func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (_ *model.P // 创建消息提醒 // TODO: 优化消息提醒处理机制 - go ds.CreateMessage(&model.Message{ + go ds.CreateMessage(&core.Message{ SenderUserID: userID, ReceiverUserID: user.ID, - Type: model.MsgTypePost, + Type: core.MsgTypePost, Brief: "在新发布的泡泡动态中@了你", PostID: post.ID, }) @@ -187,14 +187,14 @@ func CreatePost(c *gin.Context, userID int64, param PostCreationReq) (_ *model.P // 推送Search PushPostToSearch(post) - formatedPosts, err := ds.RevampPosts([]*model.PostFormated{post.Format()}) + formatedPosts, err := ds.RevampPosts([]*core.PostFormated{post.Format()}) if err != nil { return nil, err } return formatedPosts[0], nil } -func DeletePost(user *model.User, id int64) *errcode.Error { +func DeletePost(user *core.User, id int64) *errcode.Error { if user == nil { return errcode.NoPermission } @@ -261,8 +261,8 @@ func StickPost(id int64) error { return nil } -func VisiblePost(user *model.User, postId int64, visibility model.PostVisibleT) *errcode.Error { - if visibility >= model.PostVisitInvalid { +func VisiblePost(user *core.User, postId int64, visibility core.PostVisibleT) *errcode.Error { + if visibility >= core.PostVisitInvalid { return errcode.InvalidParams } @@ -287,11 +287,11 @@ func VisiblePost(user *model.User, postId int64, visibility model.PostVisibleT) return nil } -func GetPostStar(postID, userID int64) (*model.PostStar, error) { +func GetPostStar(postID, userID int64) (*core.PostStar, error) { return ds.GetUserPostStar(postID, userID) } -func CreatePostStar(postID, userID int64) (*model.PostStar, error) { +func CreatePostStar(postID, userID int64) (*core.PostStar, error) { // 加载Post post, err := ds.GetPostByID(postID) if err != nil { @@ -299,7 +299,7 @@ func CreatePostStar(postID, userID int64) (*model.PostStar, error) { } // 私密post不可操作 - if post.Visibility == model.PostVisitPrivate { + if post.Visibility == core.PostVisitPrivate { return nil, errors.New("no permision") } @@ -318,7 +318,7 @@ func CreatePostStar(postID, userID int64) (*model.PostStar, error) { return star, nil } -func DeletePostStar(star *model.PostStar) error { +func DeletePostStar(star *core.PostStar) error { err := ds.DeletePostStar(star) if err != nil { return err @@ -330,7 +330,7 @@ func DeletePostStar(star *model.PostStar) error { } // 私密post不可操作 - if post.Visibility == model.PostVisitPrivate { + if post.Visibility == core.PostVisitPrivate { return errors.New("no permision") } @@ -344,11 +344,11 @@ func DeletePostStar(star *model.PostStar) error { return nil } -func GetPostCollection(postID, userID int64) (*model.PostCollection, error) { +func GetPostCollection(postID, userID int64) (*core.PostCollection, error) { return ds.GetUserPostCollection(postID, userID) } -func CreatePostCollection(postID, userID int64) (*model.PostCollection, error) { +func CreatePostCollection(postID, userID int64) (*core.PostCollection, error) { // 加载Post post, err := ds.GetPostByID(postID) if err != nil { @@ -356,7 +356,7 @@ func CreatePostCollection(postID, userID int64) (*model.PostCollection, error) { } // 私密post不可操作 - if post.Visibility == model.PostVisitPrivate { + if post.Visibility == core.PostVisitPrivate { return nil, errors.New("no permision") } @@ -375,7 +375,7 @@ func CreatePostCollection(postID, userID int64) (*model.PostCollection, error) { return collection, nil } -func DeletePostCollection(collection *model.PostCollection) error { +func DeletePostCollection(collection *core.PostCollection) error { err := ds.DeletePostCollection(collection) if err != nil { return err @@ -387,7 +387,7 @@ func DeletePostCollection(collection *model.PostCollection) error { } // 私密post不可操作 - if post.Visibility == model.PostVisitPrivate { + if post.Visibility == core.PostVisitPrivate { return errors.New("no permision") } @@ -401,7 +401,7 @@ func DeletePostCollection(collection *model.PostCollection) error { return nil } -func GetPost(id int64) (*model.PostFormated, error) { +func GetPost(id int64) (*core.PostFormated, error) { post, err := ds.GetPostByID(id) if err != nil { @@ -431,15 +431,15 @@ func GetPost(id int64) (*model.PostFormated, error) { return postFormated, nil } -func GetPostContentByID(id int64) (*model.PostContent, error) { +func GetPostContentByID(id int64) (*core.PostContent, error) { return ds.GetPostContentByID(id) } -func GetIndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { +func GetIndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { return ds.IndexPosts(user, offset, limit) } -func GetPostList(req *PostListReq) ([]*model.Post, []*model.PostFormated, error) { +func GetPostList(req *PostListReq) ([]*core.Post, []*core.PostFormated, error) { posts, err := ds.GetPosts(req.Conditions, req.Offset, req.Limit) if err != nil { return nil, nil, err @@ -448,11 +448,11 @@ func GetPostList(req *PostListReq) ([]*model.Post, []*model.PostFormated, error) return posts, postFormated, err } -func GetPostCount(conditions *model.ConditionsT) (int64, error) { +func GetPostCount(conditions *core.ConditionsT) (int64, error) { return ds.GetPostCount(conditions) } -func GetPostListFromSearch(user *model.User, q *core.QueryReq, offset, limit int) ([]*model.PostFormated, int64, error) { +func GetPostListFromSearch(user *core.User, q *core.QueryReq, offset, limit int) ([]*core.PostFormated, int64, error) { resp, err := ts.Search(user, q, offset, limit) if err != nil { return nil, 0, err @@ -464,7 +464,7 @@ func GetPostListFromSearch(user *model.User, q *core.QueryReq, offset, limit int return posts, resp.Total, nil } -func GetPostListFromSearchByQuery(user *model.User, query string, offset, limit int) ([]*model.PostFormated, int64, error) { +func GetPostListFromSearchByQuery(user *core.User, query string, offset, limit int) ([]*core.PostFormated, int64, error) { q := &core.QueryReq{ Query: query, Type: "search", @@ -472,9 +472,9 @@ func GetPostListFromSearchByQuery(user *model.User, query string, offset, limit return GetPostListFromSearch(user, q, offset, limit) } -func PushPostToSearch(post *model.Post) { +func PushPostToSearch(post *core.Post) { postFormated := post.Format() - postFormated.User = &model.UserFormated{ + postFormated.User = &core.UserFormated{ ID: post.UserID, } contents, _ := ds.GetPostContentsByIDs([]int64{post.ID}) @@ -484,7 +484,7 @@ func PushPostToSearch(post *model.Post) { contentFormated := "" for _, content := range postFormated.Contents { - if content.Type == model.CONTENT_TYPE_TEXT || content.Type == model.CONTENT_TYPE_TITLE { + if content.Type == core.ContentTypeText || content.Type == core.ContentTypeTitle { contentFormated = contentFormated + content.Content + "\n" } } @@ -496,7 +496,7 @@ func PushPostToSearch(post *model.Post) { ts.AddDocuments(docs, fmt.Sprintf("%d", post.ID)) } -func DeleteSearchPost(post *model.Post) error { +func DeleteSearchPost(post *core.Post) error { return ts.DeleteDocuments([]string{fmt.Sprintf("%d", post.ID)}) } @@ -505,8 +505,8 @@ func PushPostsToSearch(c *gin.Context) { defer conf.Redis.Del(c, "JOB_PUSH_TO_SEARCH") splitNum := 1000 - totalRows, _ := GetPostCount(&model.ConditionsT{ - "visibility IN ?": []model.PostVisibleT{model.PostVisitPublic, model.PostVisitFriend}, + totalRows, _ := GetPostCount(&core.ConditionsT{ + "visibility IN ?": []core.PostVisibleT{core.PostVisitPublic, core.PostVisitFriend}, }) pages := math.Ceil(float64(totalRows) / float64(splitNum)) @@ -514,7 +514,7 @@ func PushPostsToSearch(c *gin.Context) { for i := 0; i < nums; i++ { posts, postsFormated, err := GetPostList(&PostListReq{ - Conditions: &model.ConditionsT{}, + Conditions: &core.ConditionsT{}, Offset: i * splitNum, Limit: splitNum, }) @@ -524,7 +524,7 @@ func PushPostsToSearch(c *gin.Context) { for i, pf := range postsFormated { contentFormated := "" for _, content := range pf.Contents { - if content.Type == model.CONTENT_TYPE_TEXT || content.Type == model.CONTENT_TYPE_TITLE { + if content.Type == core.ContentTypeText || content.Type == core.ContentTypeTitle { contentFormated = contentFormated + content.Content + "\n" } } @@ -538,22 +538,22 @@ func PushPostsToSearch(c *gin.Context) { } } -func GetPostTags(param *PostTagsReq) ([]*model.TagFormated, error) { +func GetPostTags(param *PostTagsReq) ([]*core.TagFormated, error) { num := param.Num if num > conf.AppSetting.MaxPageSize { num = conf.AppSetting.MaxPageSize } - conditions := &model.ConditionsT{} + conditions := &core.ConditionsT{} if param.Type == TagTypeHot { // 热门标签 - conditions = &model.ConditionsT{ + conditions = &core.ConditionsT{ "ORDER": "quote_num DESC", } } if param.Type == TagTypeNew { // 热门标签 - conditions = &model.ConditionsT{ + conditions = &core.ConditionsT{ "ORDER": "id DESC", } } @@ -571,7 +571,7 @@ func GetPostTags(param *PostTagsReq) ([]*model.TagFormated, error) { users, _ := ds.GetUsersByIDs(userIds) - tagsFormated := []*model.TagFormated{} + tagsFormated := []*core.TagFormated{} for _, tag := range tags { tagFormated := tag.Format() for _, user := range users { diff --git a/internal/service/sign.go b/internal/servants/web/broker/sign.go similarity index 79% rename from internal/service/sign.go rename to internal/servants/web/broker/sign.go index d3ec373a..c8883638 100644 --- a/internal/service/sign.go +++ b/internal/servants/web/broker/sign.go @@ -1,4 +1,8 @@ -package service +// 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 broker import ( "fmt" diff --git a/internal/service/user.go b/internal/servants/web/broker/user.go similarity index 76% rename from internal/service/user.go rename to internal/servants/web/broker/user.go index 7289c067..66919a99 100644 --- a/internal/service/user.go +++ b/internal/servants/web/broker/user.go @@ -1,4 +1,8 @@ -package service +// 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 broker import ( "fmt" @@ -10,15 +14,14 @@ import ( "github.com/gin-gonic/gin" "github.com/gofrs/uuid" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/model/rest" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/errcode" "github.com/rocboss/paopao-ce/pkg/util" "github.com/sirupsen/logrus" ) -const MAX_CAPTCHA_TIMES = 2 +const _MaxCaptchaTimes = 2 type PhoneCaptchaReq struct { Phone string `json:"phone" form:"phone" binding:"required"` @@ -59,19 +62,48 @@ type ChangeUserStatusReq struct { Status int `json:"status" form:"status" binding:"required"` } -const LOGIN_ERR_KEY = "PaoPaoUserLoginErr" -const MAX_LOGIN_ERR_TIMES = 10 +type RequestingFriendReq struct { + UserId int64 `json:"user_id" binding:"required"` + Greetings string `json:"greetings" binding:"required"` +} + +type AddFriendReq struct { + UserId int64 `json:"user_id" binding:"required"` +} + +type RejectFriendReq struct { + UserId int64 `json:"user_id" binding:"required"` +} + +type DeleteFriendReq struct { + UserId int64 `json:"user_id"` +} + +type UserProfileResp struct { + ID int64 `json:"id"` + Nickname string `json:"nickname"` + Username string `json:"username"` + Status int `json:"status"` + Avatar string `json:"avatar"` + IsAdmin bool `json:"is_admin"` + IsFriend bool `json:"is_friend"` +} + +const ( + _LoginErrKey = "PaoPaoUserLoginErr" + _MaxLoginErrTimes = 10 +) // DoLogin 用户认证 -func DoLogin(ctx *gin.Context, param *AuthRequest) (*model.User, error) { +func DoLogin(ctx *gin.Context, param *AuthRequest) (*core.User, error) { user, err := ds.GetUserByUsername(param.Username) if err != nil { return nil, errcode.UnauthorizedAuthNotExist } if user.Model != nil && user.ID > 0 { - if errTimes, err := conf.Redis.Get(ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID)).Result(); err == nil { - if convert.StrTo(errTimes).MustInt() >= MAX_LOGIN_ERR_TIMES { + if errTimes, err := conf.Redis.Get(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result(); err == nil { + if convert.StrTo(errTimes).MustInt() >= _MaxLoginErrTimes { return nil, errcode.TooManyLoginError } } @@ -79,19 +111,19 @@ func DoLogin(ctx *gin.Context, param *AuthRequest) (*model.User, error) { // 对比密码是否正确 if ValidPassword(user.Password, param.Password, user.Salt) { - if user.Status == model.UserStatusClosed { + if user.Status == core.UserStatusClosed { return nil, errcode.UserHasBeenBanned } // 清空登录计数 - conf.Redis.Del(ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID)) + conf.Redis.Del(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)) return user, nil } // 登录错误计数 - _, err = conf.Redis.Incr(ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID)).Result() + _, err = conf.Redis.Incr(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result() if err == nil { - conf.Redis.Expire(ctx, fmt.Sprintf("%s:%d", LOGIN_ERR_KEY, user.ID), time.Hour).Result() + conf.Redis.Expire(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID), time.Hour).Result() } return nil, errcode.UnauthorizedAuthFailed @@ -106,8 +138,8 @@ func ValidPassword(dbPassword, password, salt string) bool { } // CheckStatus 检测用户权限 -func CheckStatus(user *model.User) bool { - return user.Status == model.UserStatusNormal +func CheckStatus(user *core.User) bool { + return user.Status == core.UserStatusNormal } // ValidUsername 验证用户 @@ -161,7 +193,7 @@ func CheckPhoneCaptcha(phone, captcha string) *errcode.Error { return errcode.ErrorPhoneCaptcha } - if c.UseTimes >= MAX_CAPTCHA_TIMES { + if c.UseTimes >= _MaxCaptchaTimes { return errcode.MaxPhoneCaptchaUseTimes } @@ -198,16 +230,16 @@ func EncryptPasswordAndSalt(password string) (string, string) { } // Register 用户注册 -func Register(username, password string) (*model.User, error) { +func Register(username, password string) (*core.User, error) { password, salt := EncryptPasswordAndSalt(password) - user := &model.User{ + user := &core.User{ Nickname: username, Username: username, Password: password, Avatar: GetRandomAvatar(), Salt: salt, - Status: model.UserStatusNormal, + Status: core.UserStatusNormal, } user, err := ds.CreateUser(user) @@ -218,40 +250,40 @@ func Register(username, password string) (*model.User, error) { return user, nil } -func RequestingFriend(user *model.User, param *rest.RequestingFriendReq) error { +func RequestingFriend(user *core.User, param *RequestingFriendReq) error { if _, err := ds.GetUserByID(param.UserId); err != nil { return errcode.NotExistFriendId } return ds.RequestingFriend(user.ID, param.UserId, param.Greetings) } -func AddFriend(user *model.User, param *rest.AddFriendReq) error { +func AddFriend(user *core.User, param *AddFriendReq) error { if _, err := ds.GetUserByID(param.UserId); err != nil { return errcode.NotExistFriendId } return ds.AddFriend(user.ID, param.UserId) } -func RejectFriend(user *model.User, param *rest.RejectFriendReq) error { +func RejectFriend(user *core.User, param *RejectFriendReq) error { if _, err := ds.GetUserByID(param.UserId); err != nil { return errcode.NotExistFriendId } return ds.RejectFriend(user.ID, param.UserId) } -func DeleteFriend(user *model.User, param *rest.DeleteFriendReq) error { +func DeleteFriend(user *core.User, param *DeleteFriendReq) error { if _, err := ds.GetUserByID(param.UserId); err != nil { return errcode.NotExistFriendId } return ds.DeleteFriend(user.ID, param.UserId) } -func GetContacts(user *model.User, offset int, limit int) (*rest.ContactsResp, error) { +func GetContacts(user *core.User, offset int, limit int) (*core.ContactList, error) { return ds.GetContacts(user.ID, offset, limit) } // GetUserInfo 获取用户信息 -func GetUserInfo(param *AuthRequest) (*model.User, error) { +func GetUserInfo(param *AuthRequest) (*core.User, error) { user, err := ds.GetUserByUsername(param.Username) if err != nil { @@ -265,7 +297,7 @@ func GetUserInfo(param *AuthRequest) (*model.User, error) { return nil, errcode.UnauthorizedAuthNotExist } -func GetUserByID(id int64) (*model.User, error) { +func GetUserByID(id int64) (*core.User, error) { user, err := ds.GetUserByID(id) if err != nil { @@ -279,15 +311,15 @@ func GetUserByID(id int64) (*model.User, error) { return nil, errcode.NoExistUsername } -func GetUserByUsername(user *model.User, username string) (*rest.UserProfileResp, error) { +func GetUserByUsername(user *core.User, username string) (*UserProfileResp, error) { other, err := ds.GetUserByUsername(username) if err != nil { return nil, err } - var resp *rest.UserProfileResp + var resp *UserProfileResp if other.Model != nil && other.ID > 0 { - resp = &rest.UserProfileResp{ + resp = &UserProfileResp{ ID: other.ID, Nickname: other.Nickname, Username: other.Username, @@ -307,14 +339,14 @@ func GetUserByUsername(user *model.User, username string) (*rest.UserProfileResp } // UpdateUserInfo 更新用户信息 -func UpdateUserInfo(user *model.User) *errcode.Error { +func UpdateUserInfo(user *core.User) *errcode.Error { if err := ds.UpdateUser(user); err != nil { return errcode.ServerError } return nil } -func ChangeUserAvatar(user *model.User, avatar string) (err *errcode.Error) { +func ChangeUserAvatar(user *core.User, avatar string) (err *errcode.Error) { defer func() { if err != nil { deleteOssObjects([]string{avatar}) @@ -336,7 +368,7 @@ func ChangeUserAvatar(user *model.User, avatar string) (err *errcode.Error) { } // GetUserCollections 获取用户收藏列表 -func GetUserCollections(userID int64, offset, limit int) ([]*model.PostFormated, int64, error) { +func GetUserCollections(userID int64, offset, limit int) ([]*core.PostFormated, int64, error) { collections, err := ds.GetUserPostCollections(userID, offset, limit) if err != nil { return nil, 0, err @@ -345,7 +377,7 @@ func GetUserCollections(userID int64, offset, limit int) ([]*model.PostFormated, if err != nil { return nil, 0, err } - var posts []*model.Post + var posts []*core.Post for _, collection := range collections { posts = append(posts, collection.Post) } @@ -358,7 +390,7 @@ func GetUserCollections(userID int64, offset, limit int) ([]*model.PostFormated, } // GetUserStars 获取用户点赞列表 -func GetUserStars(userID int64, offset, limit int) ([]*model.PostFormated, int64, error) { +func GetUserStars(userID int64, offset, limit int) ([]*core.PostFormated, int64, error) { stars, err := ds.GetUserPostStars(userID, offset, limit) if err != nil { return nil, 0, err @@ -368,7 +400,7 @@ func GetUserStars(userID int64, offset, limit int) ([]*model.PostFormated, int64 return nil, 0, err } - var posts []*model.Post + var posts []*core.Post for _, star := range stars { posts = append(posts, star.Post) } @@ -381,7 +413,7 @@ func GetUserStars(userID int64, offset, limit int) ([]*model.PostFormated, int64 } // GetUserWalletBills 获取用户账单列表 -func GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, int64, error) { +func GetUserWalletBills(userID int64, offset, limit int) ([]*core.WalletStatement, int64, error) { bills, err := ds.GetUserWalletBills(userID, offset, limit) if err != nil { return nil, 0, err @@ -448,7 +480,7 @@ func IsFriend(userId, friendId int64) bool { } // checkPermision 检查是否拥有者或管理员 -func checkPermision(user *model.User, targetUserId int64) *errcode.Error { +func checkPermision(user *core.User, targetUserId int64) *errcode.Error { if user == nil || (user.ID != targetUserId && !user.IsAdmin) { return errcode.NoPermission } diff --git a/internal/service/wallet.go b/internal/servants/web/broker/wallet.go similarity index 69% rename from internal/service/wallet.go rename to internal/servants/web/broker/wallet.go index 0f22b23f..6f89edf8 100644 --- a/internal/service/wallet.go +++ b/internal/servants/web/broker/wallet.go @@ -1,11 +1,15 @@ -package service +// 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 broker import ( + "github.com/rocboss/paopao-ce/internal/core" "time" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/pkg/errcode" ) @@ -13,11 +17,11 @@ type RechargeReq struct { Amount int64 `json:"amount" form:"amount" binding:"required"` } -func GetRechargeByID(id int64) (*model.WalletRecharge, error) { +func GetRechargeByID(id int64) (*core.WalletRecharge, error) { return ds.GetRechargeByID(id) } -func CreateRecharge(userID, amount int64) (*model.WalletRecharge, error) { +func CreateRecharge(userID, amount int64) (*core.WalletRecharge, error) { return ds.CreateRecharge(userID, amount) } @@ -44,7 +48,7 @@ func FinishRecharge(ctx *gin.Context, id int64, tradeNo string) error { return nil } -func BuyPostAttachment(post *model.Post, user *model.User) error { +func BuyPostAttachment(post *core.Post, user *core.User) error { if user.Balance < post.AttachmentPrice { return errcode.InsuffientDownloadMoney } diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 4a4ccd32..085e5bcf 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -1,8 +1,12 @@ +// 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 ( api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" - "github.com/rocboss/paopao-ce/internal/servants/core" + "github.com/rocboss/paopao-ce/internal/servants/base" ) var ( @@ -12,17 +16,17 @@ var ( ) type webCoreSrv struct { - core.BaseServant + base.BaseServant api.UnimplementedWebCoreServant } type webCoreBinding struct { - core.BaseBinding + base.BaseBinding *api.UnimplementedWebCoreBinding } type webCoreRender struct { - core.BaseRender + base.BaseRender *api.UnimplementedWebCoreRender } @@ -33,7 +37,7 @@ func newWebCoreSrv() api.WebCore { func newWebCoreBinding() api.WebCoreBinding { return &webCoreBinding{ UnimplementedWebCoreBinding: &api.UnimplementedWebCoreBinding{ - BindAny: core.BindAny, + BindAny: base.BindAny, }, } } @@ -41,7 +45,7 @@ func newWebCoreBinding() api.WebCoreBinding { func newWebCoreRender() api.WebCoreRender { return &webCoreRender{ UnimplementedWebCoreRender: &api.UnimplementedWebCoreRender{ - RenderAny: core.RenderAny, + RenderAny: base.RenderAny, }, } } diff --git a/internal/servants/web/followship.go b/internal/servants/web/followship.go index 6965c4a5..4158de39 100644 --- a/internal/servants/web/followship.go +++ b/internal/servants/web/followship.go @@ -1,3 +1,7 @@ +// 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 type webFollowshipSrv struct { diff --git a/internal/servants/web/friendship.go b/internal/servants/web/friendship.go index 87690037..a4fb3d59 100644 --- a/internal/servants/web/friendship.go +++ b/internal/servants/web/friendship.go @@ -1,3 +1,7 @@ +// 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 type webFriendshipSrv struct { diff --git a/internal/servants/web/loose.go b/internal/servants/web/loose.go index 051a86ef..51a309a1 100644 --- a/internal/servants/web/loose.go +++ b/internal/servants/web/loose.go @@ -1,3 +1,7 @@ +// 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 type webLooseSrv struct { diff --git a/internal/servants/web/priv.go b/internal/servants/web/priv.go index efe80d49..51f0f486 100644 --- a/internal/servants/web/priv.go +++ b/internal/servants/web/priv.go @@ -1,3 +1,7 @@ +// 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 type webPrivSrv struct { diff --git a/internal/servants/web/pub.go b/internal/servants/web/pub.go index 2b55e3ac..d7c68ec5 100644 --- a/internal/servants/web/pub.go +++ b/internal/servants/web/pub.go @@ -1,3 +1,7 @@ +// 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 type webPubSrv struct { diff --git a/internal/routers/api/api.go b/internal/servants/web/routers/api/api.go similarity index 89% rename from internal/routers/api/api.go rename to internal/servants/web/routers/api/api.go index c722ac88..39e748ab 100644 --- a/internal/routers/api/api.go +++ b/internal/servants/web/routers/api/api.go @@ -1,3 +1,7 @@ +// 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 api import ( diff --git a/internal/routers/api/assets/comic.ttf b/internal/servants/web/routers/api/assets/comic.ttf similarity index 100% rename from internal/routers/api/assets/comic.ttf rename to internal/servants/web/routers/api/assets/comic.ttf diff --git a/internal/routers/api/attachment.go b/internal/servants/web/routers/api/attachment.go similarity index 79% rename from internal/routers/api/attachment.go rename to internal/servants/web/routers/api/attachment.go index 905b2c03..143c0c12 100644 --- a/internal/routers/api/attachment.go +++ b/internal/servants/web/routers/api/attachment.go @@ -1,3 +1,7 @@ +// 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 api import ( @@ -6,19 +10,19 @@ import ( "github.com/disintegration/imaging" "github.com/gin-gonic/gin" "github.com/gofrs/uuid" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/service" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/web/broker" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/errcode" "github.com/sirupsen/logrus" ) -var uploadAttachmentTypeMap = map[string]model.AttachmentType{ - "public/image": model.ATTACHMENT_TYPE_IMAGE, - "public/avatar": model.ATTACHMENT_TYPE_IMAGE, - "public/video": model.ATTACHMENT_TYPE_VIDEO, - "attachment": model.ATTACHMENT_TYPE_OTHER, +var uploadAttachmentTypeMap = map[string]core.AttachmentType{ + "public/image": core.AttachmentTypeImage, + "public/avatar": core.AttachmentTypeImage, + "public/video": core.AttachmentTypeVideo, + "attachment": core.AttachmentTypeOther, } func GeneratePath(s string) string { @@ -110,7 +114,7 @@ func UploadAttachment(c *gin.Context) { } // 构造附件Model - attachment := &model.Attachment{ + attachment := &core.Attachment{ FileSize: fileHeader.Size, Content: objectUrl, } @@ -120,7 +124,7 @@ func UploadAttachment(c *gin.Context) { } attachment.Type = uploadAttachmentTypeMap[uploadType] - if attachment.Type == model.ATTACHMENT_TYPE_IMAGE { + if attachment.Type == core.AttachmentTypeImage { var src image.Image src, err = imaging.Decode(file) if err == nil { @@ -128,7 +132,7 @@ func UploadAttachment(c *gin.Context) { } } - attachment, err = service.CreateAttachment(attachment) + attachment, err = broker.CreateAttachment(attachment) if err != nil { logrus.Errorf("service.CreateAttachment err: %v", err) response.ToErrorResponse(errcode.FileUploadFailed) @@ -142,15 +146,15 @@ func DownloadAttachmentPrecheck(c *gin.Context) { contentID := convert.StrTo(c.Query("id")).MustInt64() // 加载content - content, err := service.GetPostContentByID(contentID) + content, err := broker.GetPostContentByID(contentID) if err != nil { logrus.Errorf("service.GetPostContentByID err: %v", err) response.ToErrorResponse(errcode.InvalidDownloadReq) } user, _ := c.Get("USER") - if content.Type == model.CONTENT_TYPE_CHARGE_ATTACHMENT { + if content.Type == core.ContentTypeChargeAttachment { // 加载post - post, err := service.GetPost(content.PostID) + post, err := broker.GetPost(content.PostID) if err != nil { logrus.Errorf("service.GetPost err: %v", err) response.ToResponse(gin.H{ @@ -160,7 +164,7 @@ func DownloadAttachmentPrecheck(c *gin.Context) { } // 发布者或管理员免费下载 - if post.UserID == user.(*model.User).ID || user.(*model.User).IsAdmin { + if post.UserID == user.(*core.User).ID || user.(*core.User).IsAdmin { response.ToResponse(gin.H{ "paid": true, }) @@ -169,7 +173,7 @@ func DownloadAttachmentPrecheck(c *gin.Context) { // 检测是否有购买记录 response.ToResponse(gin.H{ - "paid": service.CheckPostAttachmentIsPaid(post.ID, user.(*model.User).ID), + "paid": broker.CheckPostAttachmentIsPaid(post.ID, user.(*core.User).ID), }) return } @@ -184,18 +188,18 @@ func DownloadAttachment(c *gin.Context) { contentID := convert.StrTo(c.Query("id")).MustInt64() // 加载content - content, err := service.GetPostContentByID(contentID) + content, err := broker.GetPostContentByID(contentID) if err != nil { logrus.Errorf("service.GetPostContentByID err: %v", err) response.ToErrorResponse(errcode.InvalidDownloadReq) } // 收费附件 - if content.Type == model.CONTENT_TYPE_CHARGE_ATTACHMENT { + if content.Type == core.ContentTypeChargeAttachment { user, _ := c.Get("USER") // 加载post - post, err := service.GetPost(content.PostID) + post, err := broker.GetPost(content.PostID) if err != nil { logrus.Errorf("service.GetPost err: %v", err) response.ToResponse(gin.H{ @@ -207,24 +211,24 @@ func DownloadAttachment(c *gin.Context) { paidFlag := false // 发布者或管理员免费下载 - if post.UserID == user.(*model.User).ID || user.(*model.User).IsAdmin { + if post.UserID == user.(*core.User).ID || user.(*core.User).IsAdmin { paidFlag = true } // 检测是否有购买记录 - if service.CheckPostAttachmentIsPaid(post.ID, user.(*model.User).ID) { + if broker.CheckPostAttachmentIsPaid(post.ID, user.(*core.User).ID) { paidFlag = true } if !paidFlag { // 未购买,则尝试购买 - err := service.BuyPostAttachment(&model.Post{ - Model: &model.Model{ + err := broker.BuyPostAttachment(&core.Post{ + Model: &core.Model{ ID: post.ID, }, UserID: post.UserID, AttachmentPrice: post.AttachmentPrice, - }, user.(*model.User)) + }, user.(*core.User)) if err != nil { logrus.Errorf("service.BuyPostAttachment err: %v", err) if err == errcode.InsuffientDownloadMoney { diff --git a/internal/routers/api/comment.go b/internal/servants/web/routers/api/comment.go similarity index 75% rename from internal/routers/api/comment.go rename to internal/servants/web/routers/api/comment.go index 4b1fca36..0779eabb 100644 --- a/internal/routers/api/comment.go +++ b/internal/servants/web/routers/api/comment.go @@ -1,9 +1,13 @@ +// 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 api import ( "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/service" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/web/broker" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/errcode" @@ -14,7 +18,7 @@ func GetPostComments(c *gin.Context) { postID := convert.StrTo(c.Query("id")).MustInt64() response := app.NewResponse(c) - contents, totalRows, err := service.GetPostComments(postID, "id ASC", 0, 0) + contents, totalRows, err := broker.GetPostComments(postID, "id ASC", 0, 0) if err != nil { logrus.Errorf("service.GetPostComments err: %v\n", err) @@ -26,7 +30,7 @@ func GetPostComments(c *gin.Context) { } func CreatePostComment(c *gin.Context) { - param := service.CommentCreationReq{} + param := broker.CommentCreationReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -36,7 +40,7 @@ func CreatePostComment(c *gin.Context) { } userID, _ := c.Get("UID") - comment, err := service.CreatePostComment(c, userID.(int64), param) + comment, err := broker.CreatePostComment(c, userID.(int64), param) if err != nil { if err == errcode.MaxCommentCount { @@ -52,7 +56,7 @@ func CreatePostComment(c *gin.Context) { } func DeletePostComment(c *gin.Context) { - param := service.CommentDelReq{} + param := broker.CommentDelReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -62,20 +66,20 @@ func DeletePostComment(c *gin.Context) { } user, _ := c.Get("USER") - comment, err := service.GetPostComment(param.ID) + comment, err := broker.GetPostComment(param.ID) if err != nil { logrus.Errorf("service.GetPostComment err: %v\n", err) response.ToErrorResponse(errcode.GetCommentFailed) return } - if user.(*model.User).ID != comment.UserID && !user.(*model.User).IsAdmin { + if user.(*core.User).ID != comment.UserID && !user.(*core.User).IsAdmin { response.ToErrorResponse(errcode.NoPermission) return } // 执行删除 - err = service.DeletePostComment(comment) + err = broker.DeletePostComment(comment) if err != nil { logrus.Errorf("service.DeletePostComment err: %v\n", err) response.ToErrorResponse(errcode.DeleteCommentFailed) @@ -86,7 +90,7 @@ func DeletePostComment(c *gin.Context) { } func CreatePostCommentReply(c *gin.Context) { - param := service.CommentReplyCreationReq{} + param := broker.CommentReplyCreationReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -96,7 +100,7 @@ func CreatePostCommentReply(c *gin.Context) { } user, _ := c.Get("USER") - comment, err := service.CreatePostCommentReply(c, param.CommentID, param.Content, user.(*model.User).ID, param.AtUserID) + comment, err := broker.CreatePostCommentReply(c, param.CommentID, param.Content, user.(*core.User).ID, param.AtUserID) if err != nil { logrus.Errorf("service.CreatePostCommentReply err: %v\n", err) response.ToErrorResponse(errcode.CreateReplyFailed) @@ -107,7 +111,7 @@ func CreatePostCommentReply(c *gin.Context) { } func DeletePostCommentReply(c *gin.Context) { - param := service.ReplyDelReq{} + param := broker.ReplyDelReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -118,20 +122,20 @@ func DeletePostCommentReply(c *gin.Context) { user, _ := c.Get("USER") - reply, err := service.GetPostCommentReply(param.ID) + reply, err := broker.GetPostCommentReply(param.ID) if err != nil { logrus.Errorf("service.GetPostCommentReply err: %v\n", err) response.ToErrorResponse(errcode.GetReplyFailed) return } - if user.(*model.User).ID != reply.UserID && !user.(*model.User).IsAdmin { + if user.(*core.User).ID != reply.UserID && !user.(*core.User).IsAdmin { response.ToErrorResponse(errcode.NoPermission) return } // 执行删除 - err = service.DeletePostCommentReply(reply) + err = broker.DeletePostCommentReply(reply) if err != nil { logrus.Errorf("service.DeletePostCommentReply err: %v\n", err) response.ToErrorResponse(errcode.DeleteCommentFailed) diff --git a/internal/routers/api/home.go b/internal/servants/web/routers/api/home.go similarity index 86% rename from internal/routers/api/home.go rename to internal/servants/web/routers/api/home.go index 80489978..b863b712 100644 --- a/internal/routers/api/home.go +++ b/internal/servants/web/routers/api/home.go @@ -1,3 +1,7 @@ +// 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 api import ( @@ -12,8 +16,8 @@ import ( "github.com/gin-gonic/gin" "github.com/gofrs/uuid" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/service" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/web/broker" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/debug" @@ -39,8 +43,8 @@ func SyncSearchIndex(c *gin.Context) { user, _ := c.Get("USER") - if user.(*model.User).IsAdmin { - go service.PushPostsToSearch(c) + if user.(*core.User).IsAdmin { + go broker.PushPostsToSearch(c) } response.ToResponse(nil) @@ -74,7 +78,7 @@ func GetCaptcha(c *gin.Context) { } func PostCaptcha(c *gin.Context) { - param := service.PhoneCaptchaReq{} + param := broker.PhoneCaptchaReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -96,7 +100,7 @@ func PostCaptcha(c *gin.Context) { return } - err := service.SendPhoneCaptcha(c, param.Phone) + err := broker.SendPhoneCaptcha(c, param.Phone) if err != nil { logrus.Errorf("app.SendPhoneCaptcha errs: %v", errs) response.ToErrorResponse(errcode.GetPhoneCaptchaError) diff --git a/internal/routers/api/message.go b/internal/servants/web/routers/api/message.go similarity index 74% rename from internal/routers/api/message.go rename to internal/servants/web/routers/api/message.go index 8c24cbd2..9cc72ffd 100644 --- a/internal/routers/api/message.go +++ b/internal/servants/web/routers/api/message.go @@ -1,9 +1,13 @@ +// 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 api import ( "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/service" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/web/broker" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/errcode" "github.com/sirupsen/logrus" @@ -12,12 +16,12 @@ import ( func GetUnreadMsgCount(c *gin.Context) { response := app.NewResponse(c) - user := &model.User{} + user := &core.User{} if u, exists := c.Get("USER"); exists { - user = u.(*model.User) + user = u.(*core.User) } - count, _ := service.GetUnreadCount(user.ID) + count, _ := broker.GetUnreadCount(user.ID) response.ToResponse(gin.H{ "count": count, @@ -28,7 +32,7 @@ func GetMessages(c *gin.Context) { response := app.NewResponse(c) userID, _ := c.Get("UID") - messages, totalRows, err := service.GetMessages(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c)) + messages, totalRows, err := broker.GetMessages(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c)) if err != nil { logrus.Errorf("service.GetMessages err: %v\n", err) @@ -40,7 +44,7 @@ func GetMessages(c *gin.Context) { } func ReadMessage(c *gin.Context) { - param := service.ReadMessageReq{} + param := broker.ReadMessageReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -50,7 +54,7 @@ func ReadMessage(c *gin.Context) { } userID, _ := c.Get("UID") - err := service.ReadMessage(param.ID, userID.(int64)) + err := broker.ReadMessage(param.ID, userID.(int64)) if err != nil { logrus.Errorf("service.ReadMessage err: %v\n", err) response.ToErrorResponse(errcode.ReadMessageFailed) @@ -61,7 +65,7 @@ func ReadMessage(c *gin.Context) { } func SendUserWhisper(c *gin.Context) { - param := service.WhisperReq{} + param := broker.WhisperReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -78,10 +82,10 @@ func SendUserWhisper(c *gin.Context) { return } - _, err := service.CreateWhisper(c, &model.Message{ + _, err := broker.CreateWhisper(c, &core.Message{ SenderUserID: userID.(int64), ReceiverUserID: param.UserID, - Type: model.MsgTypeWhisper, + Type: core.MsgTypeWhisper, Brief: "给你发送新私信了", Content: param.Content, }) diff --git a/internal/routers/api/post.go b/internal/servants/web/routers/api/post.go similarity index 79% rename from internal/routers/api/post.go rename to internal/servants/web/routers/api/post.go index f580428f..9ca19f3f 100644 --- a/internal/routers/api/post.go +++ b/internal/servants/web/routers/api/post.go @@ -1,10 +1,13 @@ +// 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 api import ( "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/service" + "github.com/rocboss/paopao-ce/internal/servants/web/broker" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/errcode" @@ -25,7 +28,7 @@ func GetPostList(c *gin.Context) { user, _ := userFrom(c) offset, limit := app.GetPageOffset(c) if q.Query == "" && q.Type == "search" { - resp, err := service.GetIndexPosts(user, offset, limit) + resp, err := broker.GetIndexPosts(user, offset, limit) if err != nil { logrus.Errorf("service.GetPostList err: %v\n", err) response.ToErrorResponse(errcode.GetPostsFailed) @@ -34,7 +37,7 @@ func GetPostList(c *gin.Context) { response.ToResponseList(resp.Tweets, resp.Total) } else { - posts, totalRows, err := service.GetPostListFromSearch(user, q, offset, limit) + posts, totalRows, err := broker.GetPostListFromSearch(user, q, offset, limit) if err != nil { logrus.Errorf("service.GetPostListFromSearch err: %v\n", err) @@ -49,7 +52,7 @@ func GetPost(c *gin.Context) { postID := convert.StrTo(c.Query("id")).MustInt64() response := app.NewResponse(c) - postFormated, err := service.GetPost(postID) + postFormated, err := broker.GetPost(postID) if err != nil { logrus.Errorf("service.GetPost err: %v\n", err) @@ -61,7 +64,7 @@ func GetPost(c *gin.Context) { } func CreatePost(c *gin.Context) { - param := service.PostCreationReq{} + param := broker.PostCreationReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -71,7 +74,7 @@ func CreatePost(c *gin.Context) { } userID, _ := c.Get("UID") - post, err := service.CreatePost(c, userID.(int64), param) + post, err := broker.CreatePost(c, userID.(int64), param) if err != nil { logrus.Errorf("service.CreatePost err: %v\n", err) @@ -83,7 +86,7 @@ func CreatePost(c *gin.Context) { } func DeletePost(c *gin.Context) { - param := service.PostDelReq{} + param := broker.PostDelReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -98,7 +101,7 @@ func DeletePost(c *gin.Context) { return } - err := service.DeletePost(user, param.ID) + err := broker.DeletePost(user, param.ID) if err != nil { logrus.Errorf("service.DeletePost err: %v\n", err) response.ToErrorResponse(err) @@ -114,7 +117,7 @@ func GetPostStar(c *gin.Context) { userID, _ := c.Get("UID") - _, err := service.GetPostStar(postID, userID.(int64)) + _, err := broker.GetPostStar(postID, userID.(int64)) if err != nil { response.ToResponse(gin.H{ "status": false, @@ -129,7 +132,7 @@ func GetPostStar(c *gin.Context) { } func PostStar(c *gin.Context) { - param := service.PostStarReq{} + param := broker.PostStarReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -141,14 +144,14 @@ func PostStar(c *gin.Context) { userID, _ := c.Get("UID") status := false - star, err := service.GetPostStar(param.ID, userID.(int64)) + star, err := broker.GetPostStar(param.ID, userID.(int64)) if err != nil { // 创建Star - _, err = service.CreatePostStar(param.ID, userID.(int64)) + _, err = broker.CreatePostStar(param.ID, userID.(int64)) status = true } else { // 取消Star - err = service.DeletePostStar(star) + err = broker.DeletePostStar(star) } if err != nil { @@ -167,7 +170,7 @@ func GetPostCollection(c *gin.Context) { userID, _ := c.Get("UID") - _, err := service.GetPostCollection(postID, userID.(int64)) + _, err := broker.GetPostCollection(postID, userID.(int64)) if err != nil { response.ToResponse(gin.H{ "status": false, @@ -182,7 +185,7 @@ func GetPostCollection(c *gin.Context) { } func PostCollection(c *gin.Context) { - param := service.PostCollectionReq{} + param := broker.PostCollectionReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -194,14 +197,14 @@ func PostCollection(c *gin.Context) { userID, _ := c.Get("UID") status := false - collection, err := service.GetPostCollection(param.ID, userID.(int64)) + collection, err := broker.GetPostCollection(param.ID, userID.(int64)) if err != nil { // 创建collection - _, err = service.CreatePostCollection(param.ID, userID.(int64)) + _, err = broker.CreatePostCollection(param.ID, userID.(int64)) status = true } else { // 取消Star - err = service.DeletePostCollection(collection) + err = broker.DeletePostCollection(collection) } if err != nil { @@ -215,7 +218,7 @@ func PostCollection(c *gin.Context) { } func LockPost(c *gin.Context) { - param := service.PostLockReq{} + param := broker.PostLockReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -227,18 +230,18 @@ func LockPost(c *gin.Context) { user, _ := c.Get("USER") // 获取Post - postFormated, err := service.GetPost(param.ID) + postFormated, err := broker.GetPost(param.ID) if err != nil { logrus.Errorf("service.GetPost err: %v\n", err) response.ToErrorResponse(errcode.GetPostFailed) return } - if postFormated.UserID != user.(*model.User).ID && !user.(*model.User).IsAdmin { + if postFormated.UserID != user.(*core.User).ID && !user.(*core.User).IsAdmin { response.ToErrorResponse(errcode.NoPermission) return } - err = service.LockPost(param.ID) + err = broker.LockPost(param.ID) if err != nil { logrus.Errorf("service.LockPost err: %v\n", err) response.ToErrorResponse(errcode.LockPostFailed) @@ -251,7 +254,7 @@ func LockPost(c *gin.Context) { } func StickPost(c *gin.Context) { - param := service.PostStickReq{} + param := broker.PostStickReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -263,18 +266,18 @@ func StickPost(c *gin.Context) { user, _ := c.Get("USER") // 获取Post - postFormated, err := service.GetPost(param.ID) + postFormated, err := broker.GetPost(param.ID) if err != nil { logrus.Errorf("service.GetPost err: %v\n", err) response.ToErrorResponse(errcode.GetPostFailed) return } - if !user.(*model.User).IsAdmin { + if !user.(*core.User).IsAdmin { response.ToErrorResponse(errcode.NoPermission) return } - err = service.StickPost(param.ID) + err = broker.StickPost(param.ID) if err != nil { logrus.Errorf("service.StickPost err: %v\n", err) response.ToErrorResponse(errcode.LockPostFailed) @@ -287,7 +290,7 @@ func StickPost(c *gin.Context) { } func VisiblePost(c *gin.Context) { - param := service.PostVisibilityReq{} + param := broker.PostVisibilityReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -297,7 +300,7 @@ func VisiblePost(c *gin.Context) { } user, _ := userFrom(c) - if err := service.VisiblePost(user, param.ID, param.Visibility); err != nil { + if err := broker.VisiblePost(user, param.ID, param.Visibility); err != nil { logrus.Errorf("service.VisiblePost err: %v\n", err) response.ToErrorResponse(err) return @@ -309,7 +312,7 @@ func VisiblePost(c *gin.Context) { } func GetPostTags(c *gin.Context) { - param := service.PostTagsReq{} + param := broker.PostTagsReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -318,7 +321,7 @@ func GetPostTags(c *gin.Context) { return } - tags, err := service.GetPostTags(¶m) + tags, err := broker.GetPostTags(¶m) if err != nil { logrus.Errorf("service.GetPostTags err: %v\n", err) response.ToErrorResponse(errcode.GetPostTagsFailed) diff --git a/internal/routers/api/user.go b/internal/servants/web/routers/api/user.go similarity index 80% rename from internal/routers/api/user.go rename to internal/servants/web/routers/api/user.go index 7541c54b..f45ff8ce 100644 --- a/internal/routers/api/user.go +++ b/internal/servants/web/routers/api/user.go @@ -1,3 +1,7 @@ +// 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 api import ( @@ -6,9 +10,8 @@ import ( "unicode/utf8" "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/model/rest" - "github.com/rocboss/paopao-ce/internal/service" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/web/broker" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/errcode" @@ -18,7 +21,7 @@ import ( // Login 用户登录 func Login(c *gin.Context) { - param := service.AuthRequest{} + param := broker.AuthRequest{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -27,7 +30,7 @@ func Login(c *gin.Context) { return } - user, err := service.DoLogin(c, ¶m) + user, err := broker.DoLogin(c, ¶m) if err != nil { logrus.Errorf("service.DoLogin err: %v", err) response.ToErrorResponse(err.(*errcode.Error)) @@ -49,7 +52,7 @@ func Login(c *gin.Context) { // Register 用户注册 func Register(c *gin.Context) { - param := service.RegisterRequest{} + param := broker.RegisterRequest{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -59,7 +62,7 @@ func Register(c *gin.Context) { } // 用户名检查 - err := service.ValidUsername(param.Username) + err := broker.ValidUsername(param.Username) if err != nil { logrus.Errorf("service.Register err: %v", err) response.ToErrorResponse(err.(*errcode.Error)) @@ -67,14 +70,14 @@ func Register(c *gin.Context) { } // 密码检查 - err = service.CheckPassword(param.Password) + err = broker.CheckPassword(param.Password) if err != nil { logrus.Errorf("service.Register err: %v", err) response.ToErrorResponse(err.(*errcode.Error)) return } - user, err := service.Register( + user, err := broker.Register( param.Username, param.Password, ) @@ -92,7 +95,7 @@ func Register(c *gin.Context) { } func RequestingFriend(c *gin.Context) { - param := rest.RequestingFriendReq{} + param := broker.RequestingFriendReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -110,7 +113,7 @@ func RequestingFriend(c *gin.Context) { return } - if err := service.RequestingFriend(user, ¶m); err != nil { + if err := broker.RequestingFriend(user, ¶m); err != nil { logrus.Errorf("service.RequestingFriend err: %v", err) response.ToErrorResponse(errcode.SendRequestingFriendFailed) return @@ -120,7 +123,7 @@ func RequestingFriend(c *gin.Context) { } func AddFriend(c *gin.Context) { - param := rest.AddFriendReq{} + param := broker.AddFriendReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -137,7 +140,7 @@ func AddFriend(c *gin.Context) { return } - if err := service.AddFriend(user, ¶m); err != nil { + if err := broker.AddFriend(user, ¶m); err != nil { logrus.Errorf("service.AddFriend err: %v", err) response.ToErrorResponse(errcode.AddFriendFailed) return @@ -147,7 +150,7 @@ func AddFriend(c *gin.Context) { } func RejectFriend(c *gin.Context) { - param := rest.RejectFriendReq{} + param := broker.RejectFriendReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -164,7 +167,7 @@ func RejectFriend(c *gin.Context) { return } - if err := service.RejectFriend(user, ¶m); err != nil { + if err := broker.RejectFriend(user, ¶m); err != nil { logrus.Errorf("service.RejectFriend err: %v", err) response.ToErrorResponse(errcode.RejectFriendFailed) return @@ -174,7 +177,7 @@ func RejectFriend(c *gin.Context) { } func DeleteFriend(c *gin.Context) { - param := rest.DeleteFriendReq{} + param := broker.DeleteFriendReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -191,7 +194,7 @@ func DeleteFriend(c *gin.Context) { return } - if err := service.DeleteFriend(user, ¶m); err != nil { + if err := broker.DeleteFriend(user, ¶m); err != nil { logrus.Errorf("service.DeleteFriend err: %v", err) response.ToErrorResponse(errcode.DeleteFriendFailed) return @@ -208,7 +211,7 @@ func GetContacts(c *gin.Context) { } offset, limit := app.GetPageOffset(c) - resp, err := service.GetContacts(user, offset, limit) + resp, err := broker.GetContacts(user, offset, limit) if err != nil { logrus.Errorf("service.DeleteFriend err: %v", err) response.ToErrorResponse(errcode.GetContactsFailed) @@ -219,14 +222,14 @@ func GetContacts(c *gin.Context) { // 获取用户基本信息 func GetUserInfo(c *gin.Context) { - param := service.AuthRequest{} + param := broker.AuthRequest{} response := app.NewResponse(c) if username, exists := c.Get("USERNAME"); exists { param.Username = username.(string) } - user, err := service.GetUserInfo(¶m) + user, err := broker.GetUserInfo(¶m) if err != nil { response.ToErrorResponse(errcode.UnauthorizedAuthNotExist) @@ -251,7 +254,7 @@ func GetUserInfo(c *gin.Context) { // 修改密码 func ChangeUserPassword(c *gin.Context) { - param := service.ChangePasswordReq{} + param := broker.ChangePasswordReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -260,13 +263,13 @@ func ChangeUserPassword(c *gin.Context) { return } - user := &model.User{} + user := &core.User{} if u, exists := c.Get("USER"); exists { - user = u.(*model.User) + user = u.(*core.User) } // 密码检查 - err := service.CheckPassword(param.Password) + err := broker.CheckPassword(param.Password) if err != nil { logrus.Errorf("service.Register err: %v", err) response.ToErrorResponse(err.(*errcode.Error)) @@ -274,21 +277,21 @@ func ChangeUserPassword(c *gin.Context) { } // 旧密码校验 - if !service.ValidPassword(user.Password, param.OldPassword, user.Salt) { + if !broker.ValidPassword(user.Password, param.OldPassword, user.Salt) { response.ToErrorResponse(errcode.ErrorOldPassword) return } // 更新入库 - user.Password, user.Salt = service.EncryptPasswordAndSalt(param.Password) - service.UpdateUserInfo(user) + user.Password, user.Salt = broker.EncryptPasswordAndSalt(param.Password) + broker.UpdateUserInfo(user) response.ToResponse(nil) } // 修改昵称 func ChangeNickname(c *gin.Context) { - param := service.ChangeNicknameReq{} + param := broker.ChangeNicknameReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -297,9 +300,9 @@ func ChangeNickname(c *gin.Context) { return } - user := &model.User{} + user := &core.User{} if u, exists := c.Get("USER"); exists { - user = u.(*model.User) + user = u.(*core.User) } if utf8.RuneCountInString(param.Nickname) < 2 || utf8.RuneCountInString(param.Nickname) > 12 { @@ -309,14 +312,14 @@ func ChangeNickname(c *gin.Context) { // 执行绑定 user.Nickname = param.Nickname - service.UpdateUserInfo(user) + broker.UpdateUserInfo(user) response.ToResponse(nil) } // 修改头像 func ChangeAvatar(c *gin.Context) { - param := service.ChangeAvatarReq{} + param := broker.ChangeAvatarReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -331,7 +334,7 @@ func ChangeAvatar(c *gin.Context) { return } - if err := service.ChangeUserAvatar(user, param.Avatar); err != nil { + if err := broker.ChangeUserAvatar(user, param.Avatar); err != nil { response.ToErrorResponse(err) return } @@ -340,7 +343,7 @@ func ChangeAvatar(c *gin.Context) { // 用户绑定手机号 func BindUserPhone(c *gin.Context) { - param := service.UserPhoneBindReq{} + param := broker.UserPhoneBindReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -349,18 +352,18 @@ func BindUserPhone(c *gin.Context) { return } - user := &model.User{} + user := &core.User{} if u, exists := c.Get("USER"); exists { - user = u.(*model.User) + user = u.(*core.User) } // 手机重复性检查 - if service.CheckPhoneExist(user.ID, param.Phone) { + if broker.CheckPhoneExist(user.ID, param.Phone) { response.ToErrorResponse(errcode.ExistedUserPhone) return } - if err := service.CheckPhoneCaptcha(param.Phone, param.Captcha); err != nil { + if err := broker.CheckPhoneCaptcha(param.Phone, param.Captcha); err != nil { logrus.Errorf("service.CheckPhoneCaptcha err: %v\n", err) response.ToErrorResponse(err) return @@ -368,7 +371,7 @@ func BindUserPhone(c *gin.Context) { // 执行绑定 user.Phone = param.Phone - if err := service.UpdateUserInfo(user); err != nil { + if err := broker.UpdateUserInfo(user); err != nil { response.ToErrorResponse(err) return } @@ -378,7 +381,7 @@ func BindUserPhone(c *gin.Context) { // 修改用户状态 func ChangeUserStatus(c *gin.Context) { - param := service.ChangeUserStatusReq{} + param := broker.ChangeUserStatusReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -387,12 +390,12 @@ func ChangeUserStatus(c *gin.Context) { return } - if param.Status != model.UserStatusNormal && param.Status != model.UserStatusClosed { + if param.Status != core.UserStatusNormal && param.Status != core.UserStatusClosed { response.ToErrorResponse(errcode.InvalidParams) return } - user, err := service.GetUserByID(param.ID) + user, err := broker.GetUserByID(param.ID) if err != nil { logrus.Errorf("service.GetUserByID err: %v\n", err) response.ToErrorResponse(errcode.NoExistUsername) @@ -401,7 +404,7 @@ func ChangeUserStatus(c *gin.Context) { // 执行更新 user.Status = param.Status - service.UpdateUserInfo(user) + broker.UpdateUserInfo(user) response.ToResponse(nil) } @@ -411,7 +414,7 @@ func GetUserProfile(c *gin.Context) { username := c.Query("username") user, _ := userFrom(c) - resp, err := service.GetUserByUsername(user, username) + resp, err := broker.GetUserByUsername(user, username) if err != nil { logrus.Errorf("service.GetUserByUsername err: %v\n", err) response.ToErrorResponse(errcode.NoExistUsername) @@ -426,28 +429,28 @@ func GetUserPosts(c *gin.Context) { username := c.Query("username") user, exists := userFrom(c) - other, err := service.GetUserByUsername(user, username) + other, err := broker.GetUserByUsername(user, username) if err != nil { logrus.Errorf("service.GetUserByUsername err: %v\n", err) response.ToErrorResponse(errcode.NoExistUsername) return } - visibilities := []model.PostVisibleT{model.PostVisitPublic} + visibilities := []core.PostVisibleT{core.PostVisitPublic} if exists { if user.ID == other.ID || user.IsAdmin { - visibilities = append(visibilities, model.PostVisitPrivate, model.PostVisitFriend) + visibilities = append(visibilities, core.PostVisitPrivate, core.PostVisitFriend) } else if other.IsFriend { - visibilities = append(visibilities, model.PostVisitFriend) + visibilities = append(visibilities, core.PostVisitFriend) } } - conditions := model.ConditionsT{ + conditions := core.ConditionsT{ "user_id": other.ID, "visibility IN ?": visibilities, "ORDER": "latest_replied_on DESC", } - _, posts, err := service.GetPostList(&service.PostListReq{ + _, posts, err := broker.GetPostList(&broker.PostListReq{ Conditions: &conditions, Offset: (app.GetPage(c) - 1) * app.GetPageSize(c), Limit: app.GetPageSize(c), @@ -457,7 +460,7 @@ func GetUserPosts(c *gin.Context) { response.ToErrorResponse(errcode.GetPostsFailed) return } - totalRows, _ := service.GetPostCount(&conditions) + totalRows, _ := broker.GetPostCount(&conditions) response.ToResponseList(posts, totalRows) } @@ -466,7 +469,7 @@ func GetUserCollections(c *gin.Context) { response := app.NewResponse(c) userID, _ := c.Get("UID") - posts, totalRows, err := service.GetUserCollections(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c)) + posts, totalRows, err := broker.GetUserCollections(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c)) if err != nil { logrus.Errorf("service.GetUserCollections err: %v\n", err) @@ -481,7 +484,7 @@ func GetUserStars(c *gin.Context) { response := app.NewResponse(c) userID, _ := c.Get("UID") - posts, totalRows, err := service.GetUserStars(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c)) + posts, totalRows, err := broker.GetUserStars(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c)) if err != nil { logrus.Errorf("service.GetUserStars err: %v\n", err) response.ToErrorResponse(errcode.GetCollectionsFailed) @@ -495,7 +498,7 @@ func GetSuggestUsers(c *gin.Context) { keyword := c.Query("k") response := app.NewResponse(c) - usernames, err := service.GetSuggestUsers(keyword) + usernames, err := broker.GetSuggestUsers(keyword) if err != nil { logrus.Errorf("service.GetSuggestUsers err: %v\n", err) response.ToErrorResponse(errcode.GetCollectionsFailed) @@ -509,7 +512,7 @@ func GetSuggestTags(c *gin.Context) { keyword := c.Query("k") response := app.NewResponse(c) - tags, err := service.GetSuggestTags(keyword) + tags, err := broker.GetSuggestTags(keyword) if err != nil { logrus.Errorf("service.GetSuggestTags err: %v\n", err) response.ToErrorResponse(errcode.GetCollectionsFailed) @@ -520,7 +523,7 @@ func GetSuggestTags(c *gin.Context) { } func GetUserRechargeLink(c *gin.Context) { - param := service.RechargeReq{} + param := broker.RechargeReq{} response := app.NewResponse(c) valid, errs := app.BindAndValid(c, ¶m) if !valid { @@ -531,7 +534,7 @@ func GetUserRechargeLink(c *gin.Context) { // 下单 userID, _ := c.Get("UID") - recharge, err := service.CreateRecharge(userID.(int64), param.Amount) + recharge, err := broker.CreateRecharge(userID.(int64), param.Amount) if err != nil { logrus.Errorf("service.CreateRecharge err: %v\n", err) response.ToErrorResponse(errcode.RechargeReqFail) @@ -567,7 +570,7 @@ func GetUserRechargeResult(c *gin.Context) { id := c.Query("id") userID, _ := c.Get("UID") - recharge, err := service.GetRechargeByID(convert.StrTo(id).MustInt64()) + recharge, err := broker.GetRechargeByID(convert.StrTo(id).MustInt64()) if err != nil { response.ToErrorResponse(errcode.GetRechargeFailed) return @@ -601,7 +604,7 @@ func AlipayNotify(c *gin.Context) { tradeStatus := c.Request.Form.Get("trade_status") if tradeStatus == "TRADE_SUCCESS" { // 交易支付成功 - err = service.FinishRecharge(c, convert.StrTo(id).MustInt64(), tradeNo) + err = broker.FinishRecharge(c, convert.StrTo(id).MustInt64(), tradeNo) if err != nil { logrus.Errorf("service.FinishRecharge err: %v\n", err) response.ToErrorResponse(errcode.RechargeNotifyError) @@ -615,7 +618,7 @@ func GetUserWalletBills(c *gin.Context) { response := app.NewResponse(c) userID, _ := c.Get("UID") - bills, totalRows, err := service.GetUserWalletBills(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c)) + bills, totalRows, err := broker.GetUserWalletBills(userID.(int64), (app.GetPage(c)-1)*app.GetPageSize(c), app.GetPageSize(c)) if err != nil { logrus.Errorf("service.GetUserWalletBills err: %v\n", err) @@ -626,9 +629,9 @@ func GetUserWalletBills(c *gin.Context) { response.ToResponseList(bills, totalRows) } -func userFrom(c *gin.Context) (*model.User, bool) { +func userFrom(c *gin.Context) (*core.User, bool) { if u, exists := c.Get("USER"); exists { - user, ok := u.(*model.User) + user, ok := u.(*core.User) return user, ok } return nil, false diff --git a/internal/routers/docs.go b/internal/servants/web/routers/docs.go similarity index 57% rename from internal/routers/docs.go rename to internal/servants/web/routers/docs.go index fc054b08..bf5e0488 100644 --- a/internal/routers/docs.go +++ b/internal/servants/web/routers/docs.go @@ -1,3 +1,7 @@ +// 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. + //go:build !docs // +build !docs diff --git a/internal/routers/docs_embed.go b/internal/servants/web/routers/docs_embed.go similarity index 69% rename from internal/routers/docs_embed.go rename to internal/servants/web/routers/docs_embed.go index e9c0d17d..a636e487 100644 --- a/internal/routers/docs_embed.go +++ b/internal/servants/web/routers/docs_embed.go @@ -1,3 +1,7 @@ +// 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. + //go:build docs // +build docs diff --git a/internal/routers/router.go b/internal/servants/web/routers/router.go similarity index 92% rename from internal/routers/router.go rename to internal/servants/web/routers/router.go index 1a2b57f6..c020cec3 100644 --- a/internal/routers/router.go +++ b/internal/servants/web/routers/router.go @@ -1,3 +1,7 @@ +// 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 routers import ( @@ -7,8 +11,8 @@ import ( "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/middleware" - "github.com/rocboss/paopao-ce/internal/routers/api" + "github.com/rocboss/paopao-ce/internal/servants/chain" + "github.com/rocboss/paopao-ce/internal/servants/web/routers/api" "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/sirupsen/logrus" ) @@ -67,7 +71,7 @@ func NewRouter() *gin.Engine { } // 宽松鉴权路由组 - looseApi := r.Group("/").Use(middleware.JwtLoose()) + looseApi := r.Group("/").Use(chain.JwtLoose()) { // 获取广场流 looseApi.GET("/posts", api.GetPostList) @@ -80,9 +84,9 @@ func NewRouter() *gin.Engine { } // 鉴权路由组 - authApi := r.Group("/").Use(middleware.JWT()) - privApi := r.Group("/").Use(middleware.JWT()).Use(middleware.Priv()) - adminApi := r.Group("/").Use(middleware.JWT()).Use(middleware.Admin()) + authApi := r.Group("/").Use(chain.JWT()) + privApi := r.Group("/").Use(chain.JWT()).Use(chain.Priv()) + adminApi := r.Group("/").Use(chain.JWT()).Use(chain.Admin()) // 核心路由注册 routeCore(authApi, privApi, adminApi) diff --git a/internal/routers/statick.go b/internal/servants/web/routers/statick.go similarity index 58% rename from internal/routers/statick.go rename to internal/servants/web/routers/statick.go index c20d5059..c1f2d1cb 100644 --- a/internal/routers/statick.go +++ b/internal/servants/web/routers/statick.go @@ -1,3 +1,7 @@ +// 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. + //go:build !embed // +build !embed diff --git a/internal/routers/statick_embed.go b/internal/servants/web/routers/statick_embed.go similarity index 79% rename from internal/routers/statick_embed.go rename to internal/servants/web/routers/statick_embed.go index 2ea56171..dfc729f5 100644 --- a/internal/routers/statick_embed.go +++ b/internal/servants/web/routers/statick_embed.go @@ -1,3 +1,7 @@ +// 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. + //go:build embed // +build embed diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index 60a0aeb1..76ac9dd3 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -1,3 +1,7 @@ +// 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 ( diff --git a/internal/servants/web/xerror.go b/internal/servants/web/xerror.go index 305d1d0c..ecc0355e 100644 --- a/internal/servants/web/xerror.go +++ b/internal/servants/web/xerror.go @@ -1,3 +1,7 @@ +// 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 ( diff --git a/internal/service/attachment.go b/internal/service/attachment.go deleted file mode 100644 index 432a1a2f..00000000 --- a/internal/service/attachment.go +++ /dev/null @@ -1,7 +0,0 @@ -package service - -import "github.com/rocboss/paopao-ce/internal/model" - -func CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) { - return ds.CreateAttachment(attachment) -} diff --git a/internal/service/service.go b/internal/service/service.go index 4f9434f4..84c9ec7a 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -1,72 +1,17 @@ -package service - -import ( - "net/http" +// 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. - "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/dao" - "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/internal/servants" - "github.com/rocboss/paopao-ce/pkg/cfg" - "github.com/sirupsen/logrus" -) - -var ( - ds core.DataService - ts core.TweetSearchService - oss core.ObjectStorageService - DisablePhoneVerify bool -) +package service type Service interface { Name() string - PreStart() string - PreStop() string Start() Stop() } -func NewWebService() Service { - e := newWebEngine() - servants.RegisterWebServants(e) - - return &webService{ - server: &http.Server{ - Addr: conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort, - Handler: e, - ReadTimeout: conf.ServerSetting.ReadTimeout, - WriteTimeout: conf.ServerSetting.WriteTimeout, - MaxHeaderBytes: 1 << 20, - }, - } -} - -func Initialize() { - ds = dao.DataService() - ts = dao.TweetSearchService() - oss = dao.ObjectStorageService() - DisablePhoneVerify = !cfg.If("Sms") -} +type baseService struct{} -// persistMediaContents 获取媒体内容并持久化 -func persistMediaContents(contents []*PostContentItem) (items []string, err error) { - items = make([]string, 0, len(contents)) - for _, item := range contents { - switch item.Type { - case model.CONTENT_TYPE_IMAGE, - model.CONTENT_TYPE_VIDEO, - model.CONTENT_TYPE_AUDIO, - model.CONTENT_TYPE_ATTACHMENT, - model.CONTENT_TYPE_CHARGE_ATTACHMENT: - items = append(items, item.Content) - if err != nil { - continue - } - if err = oss.PersistObject(oss.ObjectKey(item.Content)); err != nil { - logrus.Errorf("service.persistMediaContents failed: %s", err) - } - } - } - return +func (baseService) String() string { + return "" } diff --git a/internal/service/web.go b/internal/service/web.go index d346fbd8..a64a6f73 100644 --- a/internal/service/web.go +++ b/internal/service/web.go @@ -1,3 +1,7 @@ +// 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 service import ( @@ -10,24 +14,15 @@ import ( "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" ) -type baseService struct{} - type webService struct { baseService server *http.Server } -func (baseService) PreStart() string { - return "" -} - -func (baseService) PreStop() string { - return "" -} - func (s *webService) Name() string { return "WebService" } @@ -42,7 +37,7 @@ func (s *webService) Stop() { s.server.Shutdown(context.Background()) } -func (s *webService) PreStart() string { +func (s *webService) String() string { return fmt.Sprintf("PaoPao service listen on %s\n", color.GreenString("http://%s:%s", conf.ServerSetting.HttpIp, conf.ServerSetting.HttpPort)) } @@ -76,3 +71,17 @@ func newWebEngine() *gin.Engine { return e } + +func NewWebService() Service { + e := newWebEngine() + servants.RegisterWebServants(e) + return &webService{ + server: &http.Server{ + Addr: conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort, + Handler: e, + ReadTimeout: conf.ServerSetting.ReadTimeout, + WriteTimeout: conf.ServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } +} diff --git a/main.go b/main.go index 1046e97d..0d28b464 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,7 @@ +// 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 main import ( @@ -11,7 +15,7 @@ import ( "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/routers" + "github.com/rocboss/paopao-ce/internal/servants/web/routers" "github.com/rocboss/paopao-ce/pkg/debug" "github.com/rocboss/paopao-ce/pkg/util" ) diff --git a/pkg/app/app.go b/pkg/app/app.go index fc860d27..a98a49a2 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -1,3 +1,7 @@ +// 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 app import ( diff --git a/pkg/app/form.go b/pkg/app/form.go index 7e376104..91b116a2 100644 --- a/pkg/app/form.go +++ b/pkg/app/form.go @@ -1,3 +1,7 @@ +// 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 app import ( diff --git a/pkg/app/jwt.go b/pkg/app/jwt.go index 8033296f..b9759e07 100644 --- a/pkg/app/jwt.go +++ b/pkg/app/jwt.go @@ -1,3 +1,7 @@ +// 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 app import ( @@ -5,7 +9,7 @@ import ( "github.com/golang-jwt/jwt/v4" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/model" + "github.com/rocboss/paopao-ce/internal/core" ) type Claims struct { @@ -18,7 +22,7 @@ func GetJWTSecret() []byte { return []byte(conf.JWTSetting.Secret) } -func GenerateToken(User *model.User) (string, error) { +func GenerateToken(User *core.User) (string, error) { expireTime := time.Now().Add(conf.JWTSetting.Expire) claims := Claims{ UID: User.ID, diff --git a/pkg/app/pagination.go b/pkg/app/pagination.go index 1888efb9..699d1dd2 100644 --- a/pkg/app/pagination.go +++ b/pkg/app/pagination.go @@ -1,3 +1,7 @@ +// 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 app import ( diff --git a/pkg/cfg/cfg.go b/pkg/cfg/cfg.go index 019deba9..f04dc297 100644 --- a/pkg/cfg/cfg.go +++ b/pkg/cfg/cfg.go @@ -1,3 +1,7 @@ +// 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 cfg var ( diff --git a/pkg/cfg/cfg_test.go b/pkg/cfg/cfg_test.go index 0fccbce2..68a3ce74 100644 --- a/pkg/cfg/cfg_test.go +++ b/pkg/cfg/cfg_test.go @@ -1,3 +1,7 @@ +// 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 cfg import ( diff --git a/pkg/cfg/feature.go b/pkg/cfg/feature.go index a04d07ca..32810b47 100644 --- a/pkg/cfg/feature.go +++ b/pkg/cfg/feature.go @@ -1,3 +1,7 @@ +// 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 cfg import ( diff --git a/pkg/cfg/feature_test.go b/pkg/cfg/feature_test.go index 98e01ec7..21c44c72 100644 --- a/pkg/cfg/feature_test.go +++ b/pkg/cfg/feature_test.go @@ -1,3 +1,7 @@ +// 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 cfg import ( diff --git a/pkg/convert/convert.go b/pkg/convert/convert.go index 60dacf9b..ff3be5e5 100644 --- a/pkg/convert/convert.go +++ b/pkg/convert/convert.go @@ -1,3 +1,7 @@ +// 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 convert import "strconv" diff --git a/pkg/convert/convert_test.go b/pkg/convert/convert_test.go index a746e3e7..a31d13e6 100644 --- a/pkg/convert/convert_test.go +++ b/pkg/convert/convert_test.go @@ -1,3 +1,7 @@ +// 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 convert import ( diff --git a/pkg/crypto/signature.go b/pkg/crypto/signature.go index 7f18959a..20a6deaa 100644 --- a/pkg/crypto/signature.go +++ b/pkg/crypto/signature.go @@ -1,3 +1,7 @@ +// 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 crypto import ( diff --git a/pkg/debug/version.go b/pkg/debug/version.go index 485e8046..68236f05 100644 --- a/pkg/debug/version.go +++ b/pkg/debug/version.go @@ -1,3 +1,7 @@ +// 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 debug import ( diff --git a/pkg/errcode/common_code.go b/pkg/errcode/common_code.go index 75b220ee..1f15f8c5 100644 --- a/pkg/errcode/common_code.go +++ b/pkg/errcode/common_code.go @@ -1,3 +1,7 @@ +// 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 errcode var ( diff --git a/pkg/errcode/errcode.go b/pkg/errcode/errcode.go index 50f04868..5143aabb 100644 --- a/pkg/errcode/errcode.go +++ b/pkg/errcode/errcode.go @@ -1,3 +1,7 @@ +// 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 errcode import ( diff --git a/pkg/errcode/module_code.go b/pkg/errcode/module_code.go index 1c5b7215..9543624b 100644 --- a/pkg/errcode/module_code.go +++ b/pkg/errcode/module_code.go @@ -1,3 +1,7 @@ +// 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 errcode var ( diff --git a/pkg/sign/sign.go b/pkg/sign/sign.go index 717b8e54..fc7c10e9 100644 --- a/pkg/sign/sign.go +++ b/pkg/sign/sign.go @@ -1,3 +1,7 @@ +// 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 sign import ( diff --git a/pkg/types/types.go b/pkg/types/types.go index 2696f8b9..830c56c6 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -1,3 +1,7 @@ +// 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 types // Empty empty alias type diff --git a/pkg/util/banner.go b/pkg/util/banner.go index d41b5ae1..31e25ba9 100644 --- a/pkg/util/banner.go +++ b/pkg/util/banner.go @@ -1,3 +1,7 @@ +// 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 util import "fmt" diff --git a/pkg/util/ip.go b/pkg/util/ip.go index 3aaa13c1..4561d8a6 100644 --- a/pkg/util/ip.go +++ b/pkg/util/ip.go @@ -1,3 +1,7 @@ +// 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 util import "github.com/rocboss/paopao-ce/pkg/util/iploc" diff --git a/pkg/util/ip_test.go b/pkg/util/ip_test.go index 82976be8..0740ffd5 100644 --- a/pkg/util/ip_test.go +++ b/pkg/util/ip_test.go @@ -1,3 +1,7 @@ +// 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 util import "testing" diff --git a/pkg/util/iploc/iploc.go b/pkg/util/iploc/iploc.go index a05f8d7e..449e52a9 100644 --- a/pkg/util/iploc/iploc.go +++ b/pkg/util/iploc/iploc.go @@ -1,3 +1,7 @@ +// 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 iploc import ( diff --git a/pkg/util/iploc/iploc_test.go b/pkg/util/iploc/iploc_test.go index 4754e86d..a38bb106 100644 --- a/pkg/util/iploc/iploc_test.go +++ b/pkg/util/iploc/iploc_test.go @@ -1,3 +1,7 @@ +// 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 iploc import ( diff --git a/pkg/util/md5.go b/pkg/util/md5.go index 8a00f545..477cd5ff 100644 --- a/pkg/util/md5.go +++ b/pkg/util/md5.go @@ -1,3 +1,7 @@ +// 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 util import ( diff --git a/pkg/util/md5_test.go b/pkg/util/md5_test.go index 0bab593f..12c14c86 100644 --- a/pkg/util/md5_test.go +++ b/pkg/util/md5_test.go @@ -1,3 +1,7 @@ +// 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 util import "testing" diff --git a/pkg/util/str.go b/pkg/util/str.go index 35e034ab..8b62217d 100644 --- a/pkg/util/str.go +++ b/pkg/util/str.go @@ -1,3 +1,7 @@ +// 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 util import ( diff --git a/pkg/xerror/common.go b/pkg/xerror/common.go index a59c62e8..b502840b 100644 --- a/pkg/xerror/common.go +++ b/pkg/xerror/common.go @@ -1,3 +1,7 @@ +// 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 xerror var ( diff --git a/pkg/xerror/xerror.go b/pkg/xerror/xerror.go index 5053b62f..f614d18e 100644 --- a/pkg/xerror/xerror.go +++ b/pkg/xerror/xerror.go @@ -1,3 +1,7 @@ +// 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 xerror import ( diff --git a/pkg/zinc/zinc.go b/pkg/zinc/zinc.go index ba1fb270..cc200a55 100644 --- a/pkg/zinc/zinc.go +++ b/pkg/zinc/zinc.go @@ -1,3 +1,7 @@ +// 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 zinc import ( diff --git a/scripts/migration/embed.go b/scripts/migration/embed.go index 88e633c8..3f1eacda 100644 --- a/scripts/migration/embed.go +++ b/scripts/migration/embed.go @@ -1,3 +1,7 @@ +// 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. + //go:build migration // +build migration diff --git a/web/embed.go b/web/embed.go index 4866a53a..a16df24a 100644 --- a/web/embed.go +++ b/web/embed.go @@ -1,3 +1,7 @@ +// 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. + //go:build embed // +build embed From 1125487bbcc6070dcaa341cf8bbbcbd79ae55cf7 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 3 Dec 2022 00:30:17 +0800 Subject: [PATCH 12/65] mir: move mirgration module to internal pkg --- internal/broker/broker.go | 5 ----- internal/internal.go | 6 +++--- internal/{broker => }/migration/migration.go | 0 internal/{broker => }/migration/migration_embed.go | 0 4 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 internal/broker/broker.go rename internal/{broker => }/migration/migration.go (100%) rename internal/{broker => }/migration/migration_embed.go (100%) diff --git a/internal/broker/broker.go b/internal/broker/broker.go deleted file mode 100644 index a47462c1..00000000 --- a/internal/broker/broker.go +++ /dev/null @@ -1,5 +0,0 @@ -// 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 broker diff --git a/internal/internal.go b/internal/internal.go index e359af0d..a8c0934f 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -5,8 +5,8 @@ package internal import ( - "github.com/rocboss/paopao-ce/internal/broker/migration" - wb "github.com/rocboss/paopao-ce/internal/servants/web/broker" + "github.com/rocboss/paopao-ce/internal/migration" + "github.com/rocboss/paopao-ce/internal/servants/web/broker" "github.com/rocboss/paopao-ce/internal/servants/web/routers/api" ) @@ -15,6 +15,6 @@ func Initialize() { migration.Run() // initialize service - wb.Initialize() + broker.Initialize() api.Initialize() } diff --git a/internal/broker/migration/migration.go b/internal/migration/migration.go similarity index 100% rename from internal/broker/migration/migration.go rename to internal/migration/migration.go diff --git a/internal/broker/migration/migration_embed.go b/internal/migration/migration_embed.go similarity index 100% rename from internal/broker/migration/migration_embed.go rename to internal/migration/migration_embed.go From 6570286a4ef40e1e3200d5f711c9cbb1a56f0a21 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 9 Dec 2022 19:27:28 +0800 Subject: [PATCH 13/65] add internal/service base logic --- .../mirc/auto/api/v1/{site.go => web_core.go} | 115 ++++++++++-------- internal/mirc/main.go | 2 +- internal/mirc/routes/v1/web_core.go | 2 +- internal/servants/servants.go | 16 +-- internal/service/http_server.go | 83 +++++++++++++ internal/service/http_service.go | 49 ++++++++ internal/service/service.go | 28 ++++- internal/service/web.go | 42 +++---- 8 files changed, 246 insertions(+), 91 deletions(-) rename internal/mirc/auto/api/v1/{site.go => web_core.go} (93%) create mode 100644 internal/service/http_server.go create mode 100644 internal/service/http_service.go diff --git a/internal/mirc/auto/api/v1/site.go b/internal/mirc/auto/api/v1/web_core.go similarity index 93% rename from internal/mirc/auto/api/v1/site.go rename to internal/mirc/auto/api/v1/web_core.go index 22e9e826..5887e010 100644 --- a/internal/mirc/auto/api/v1/site.go +++ b/internal/mirc/auto/api/v1/web_core.go @@ -6,14 +6,26 @@ import ( "net/http" "github.com/alimy/mir/v3" - "github.com/gin-gonic/gin" + gin "github.com/gin-gonic/gin" ) +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + type AgentInfo struct { Platform string `json:"platform"` UserAgent string `json:"user_agent"` } +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + type ServerInfo struct { ApiVer string `json:"api_ver"` } @@ -22,26 +34,14 @@ type UserInfo struct { Name string `json:"name"` } -type LoginReq struct { - AgentInfo AgentInfo `json:"agent_info"` - Name string `json:"name"` - Passwd string `json:"passwd"` -} - -type LoginResp struct { - UserInfo - ServerInfo ServerInfo `json:"server_info"` - JwtToken string `json:"jwt_token"` -} - type WebCore interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - Index(c *gin.Context) mir.Error - Articles(c *gin.Context) mir.Error - Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) Logout(c *gin.Context) mir.Error + Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + Articles(c *gin.Context) mir.Error + Index(c *gin.Context) mir.Error mustEmbedUnimplementedWebCoreServant() } @@ -53,10 +53,10 @@ type WebCoreBinding interface { } type WebCoreRender interface { - RenderIndex(c *gin.Context, err mir.Error) - RenderArticles(c *gin.Context, err mir.Error) - RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) RenderLogout(c *gin.Context, err mir.Error) + RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + RenderArticles(c *gin.Context, err mir.Error) + RenderIndex(c *gin.Context, err mir.Error) mustEmbedUnimplementedWebCoreRender() } @@ -69,12 +69,10 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor router.Use(middlewares...) // register routes info to router - router.Handle("GET", "/index/", func(c *gin.Context) { - r.RenderIndex(c, s.Index(c)) - }) - router.Handle("GET", "/articles/:category/", func(c *gin.Context) { - r.RenderArticles(c, s.Articles(c)) + router.Handle("POST", "/user/logout/", func(c *gin.Context) { + r.RenderLogout(c, s.Logout(c)) }) + router.Handle("POST", "/user/login/", func(c *gin.Context) { req, err := b.BindLogin(c) if err != nil { @@ -83,33 +81,30 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor resp, err := s.Login(c, req) r.RenderLogin(c, resp, err) }) - router.Handle("POST", "/user/logout/", func(c *gin.Context) { - r.RenderLogout(c, s.Logout(c)) - }) -} -// UnimplementedWebCoreServant can be embedded to have forward compatible implementations. -type UnimplementedWebCoreServant struct{} + { + h := func(c *gin.Context) { + r.RenderArticles(c, s.Articles(c)) + } + router.Handle("HEAD", "/articles/:category/", h) + router.Handle("GET", "/articles/:category/", h) + } + + router.Handle("GET", "/index/", func(c *gin.Context) { + r.RenderIndex(c, s.Index(c)) + }) -// UnimplementedWebCoreBinding can be embedded to have forward compatible implementations. -type UnimplementedWebCoreBinding struct { - BindAny func(*gin.Context, any) mir.Error } -// UnimplementedWebCoreRender can be embedded to have forward compatible implementations. -type UnimplementedWebCoreRender struct { - RenderAny func(*gin.Context, any, mir.Error) +// UnimplementedWebCoreServant can be embedded to have forward compatible implementations. +type UnimplementedWebCoreServant struct { } func (UnimplementedWebCoreServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebCoreServant) Index(c *gin.Context) mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) -} - -func (UnimplementedWebCoreServant) Articles(c *gin.Context) mir.Error { +func (UnimplementedWebCoreServant) Logout(c *gin.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -117,25 +112,22 @@ func (UnimplementedWebCoreServant) Login(c *gin.Context, req *LoginReq) (*LoginR return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Logout(c *gin.Context) mir.Error { +func (UnimplementedWebCoreServant) Articles(c *gin.Context) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) mustEmbedUnimplementedWebCoreServant() {} - -func (b *UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { - obj := new(LoginReq) - err := b.BindAny(c, obj) - return obj, err +func (UnimplementedWebCoreServant) Index(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (b *UnimplementedWebCoreBinding) mustEmbedUnimplementedWebCoreBinding() {} +func (UnimplementedWebCoreServant) mustEmbedUnimplementedWebCoreServant() {} -func (r *UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +// UnimplementedWebCoreRender can be embedded to have forward compatible implementations. +type UnimplementedWebCoreRender struct { + RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err mir.Error) { +func (r *UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } @@ -143,8 +135,25 @@ func (r *UnimplementedWebCoreRender) RenderLogin(c *gin.Context, data *LoginResp r.RenderAny(c, data, err) } -func (r *UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err mir.Error) { +func (r *UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } func (r *UnimplementedWebCoreRender) mustEmbedUnimplementedWebCoreRender() {} + +// UnimplementedWebCoreBinding can be embedded to have forward compatible implementations. +type UnimplementedWebCoreBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebCoreBinding) mustEmbedUnimplementedWebCoreBinding() {} diff --git a/internal/mirc/main.go b/internal/mirc/main.go index 46de42d1..bf45791f 100644 --- a/internal/mirc/main.go +++ b/internal/mirc/main.go @@ -17,7 +17,7 @@ import ( func main() { log.Println("generate code start") opts := Options{ - RunMode(InSerialMode), + RunMode(InSerialDebugMode), GeneratorName(GeneratorGin), SinkPath("auto"), } diff --git a/internal/mirc/routes/v1/web_core.go b/internal/mirc/routes/v1/web_core.go index 565fb04a..83193986 100644 --- a/internal/mirc/routes/v1/web_core.go +++ b/internal/mirc/routes/v1/web_core.go @@ -38,7 +38,7 @@ type WebCore struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` Index func(Get) `mir:"/index/"` - Articles func(Get) `mir:"/articles/:category/"` + Articles func(Get, Head) `mir:"/articles/:category/"` Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` Logout func(Post) `mir:"/user/logout/"` } diff --git a/internal/servants/servants.go b/internal/servants/servants.go index 4f1f0bcd..9ae3d0a7 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -15,16 +15,12 @@ import ( // RegisterWebServants register all the servants to gin.Engine func RegisterWebServants(e *gin.Engine) { - // 按需注册 docs、静态资源 - { - docs.RegisterDocs(e) - statick.RegisterStatick(e) - } + docs.RegisterDocs(e) + statick.RegisterStatick(e) + + cfg.Be("LocalOSS", func() { + localoss.RouteLocalOSS(e) + }) web.RouteWeb(e) - { - cfg.Be("LocalOSS", func() { - localoss.RouteLocalOSS(e) - }) - } } diff --git a/internal/service/http_server.go b/internal/service/http_server.go new file mode 100644 index 00000000..4a8fdf3b --- /dev/null +++ b/internal/service/http_server.go @@ -0,0 +1,83 @@ +// 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 service + +import ( + "context" + "net/http" + "sync" + + "github.com/gin-gonic/gin" +) + +var ( + httpServers = make(map[string]*httpServer) +) + +const ( + httpServerInitilized uint8 = iota + 1 + httpServerStarted + httpServerStoped +) + +// httpServer wraper for gin.engine and http.Server +type httpServer struct { + sync.RWMutex + + e *gin.Engine + server *http.Server + serverStatus uint8 +} + +func (s *httpServer) status() uint8 { + s.RLock() + defer s.RUnlock() + + return s.serverStatus +} + +func (s *httpServer) start() error { + s.Lock() + if s.serverStatus == httpServerStarted || s.serverStatus == httpServerStoped { + return nil + } + oldStatus := s.serverStatus + s.serverStatus = httpServerStarted + s.Unlock() + + if err := s.server.ListenAndServe(); err != nil { + s.Lock() + s.serverStatus = oldStatus + s.Unlock() + + return err + } + return nil +} + +func (s *httpServer) stop() error { + s.Lock() + defer s.Unlock() + + if s.serverStatus == httpServerStoped || s.serverStatus == httpServerInitilized { + return nil + } + if err := s.server.Shutdown(context.Background()); err != nil { + return err + } + s.serverStatus = httpServerStoped + return nil +} + +func httpServerFrom(addr string, newServer func() *httpServer) *httpServer { + s, exist := httpServers[addr] + if exist { + return s + } + s = newServer() + s.serverStatus = httpServerInitilized + httpServers[addr] = s + return s +} diff --git a/internal/service/http_service.go b/internal/service/http_service.go new file mode 100644 index 00000000..11ec1b98 --- /dev/null +++ b/internal/service/http_service.go @@ -0,0 +1,49 @@ +// 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 service + +import ( + "github.com/gin-gonic/gin" +) + +type httpService interface { + Service + + registerRoute(e *gin.Engine) +} + +type baseHttpService struct { + baseService + + server *httpServer +} + +func (s *baseHttpService) Init() error { + if s.server.status() != httpServerStarted { + s.registerRoute(s.server.e) + } + return nil +} + +func (s *baseHttpService) Start() error { + if err := s.server.start(); err != nil { + return err + } + return nil +} + +func (s *baseHttpService) Stop() error { + return s.server.stop() +} + +func (s *baseHttpService) registerRoute(e *gin.Engine) { + // default empty +} + +func newBaseHttpService(s *httpServer) httpService { + return &baseHttpService{ + server: s, + } +} diff --git a/internal/service/service.go b/internal/service/service.go index 84c9ec7a..31efbae0 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -4,14 +4,36 @@ package service +import ( + "log" + + "github.com/rocboss/paopao-ce/pkg/types" +) + type Service interface { Name() string - Start() - Stop() + Init() error + Start() error + Stop() error } -type baseService struct{} +type baseService types.Empty + +func (baseService) Name() string { + return "" +} func (baseService) String() string { return "" } + +func InitService() (ss []Service) { + ss = append(ss, newWebService()) + + for _, s := range ss { + if err := s.Init(); err != nil { + log.Fatalf("initial %s service error: %s", s.Name(), err) + } + } + return +} diff --git a/internal/service/web.go b/internal/service/web.go index a64a6f73..6ded25d3 100644 --- a/internal/service/web.go +++ b/internal/service/web.go @@ -5,9 +5,7 @@ package service import ( - "context" "fmt" - "log" "net/http" "github.com/fatih/color" @@ -18,23 +16,15 @@ import ( ) type webService struct { - baseService - - server *http.Server + httpService } func (s *webService) Name() string { return "WebService" } -func (s *webService) Start() { - if err := s.server.ListenAndServe(); err != nil { - log.Fatalf("run app failed: %s", err) - } -} - -func (s *webService) Stop() { - s.server.Shutdown(context.Background()) +func (s *webService) registerRoute(e *gin.Engine) { + servants.RegisterWebServants(e) } func (s *webService) String() string { @@ -72,16 +62,22 @@ func newWebEngine() *gin.Engine { return e } -func NewWebService() Service { - e := newWebEngine() - servants.RegisterWebServants(e) +func newWebService() Service { + addr := conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort + server := httpServerFrom(addr, func() *httpServer { + engine := newWebEngine() + return &httpServer{ + e: engine, + server: &http.Server{ + Addr: addr, + Handler: engine, + ReadTimeout: conf.ServerSetting.ReadTimeout, + WriteTimeout: conf.ServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } + }) return &webService{ - server: &http.Server{ - Addr: conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort, - Handler: e, - ReadTimeout: conf.ServerSetting.ReadTimeout, - WriteTimeout: conf.ServerSetting.WriteTimeout, - MaxHeaderBytes: 1 << 20, - }, + httpService: newBaseHttpService(server), } } From 3c47f48c429d92a6e00eccb45de7c8bc45e1d57d Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 9 Dec 2022 23:37:23 +0800 Subject: [PATCH 14/65] optimize main initial logic for new service init --- config.yaml.sample | 12 +++++ go.mod | 6 +-- go.sum | 2 + internal/conf/conf.go | 11 ++++ internal/conf/settting.go | 1 + internal/servants/web/routers/router.go | 72 +++++++++++++++++++++++++ internal/service/http_service.go | 21 +------- internal/service/service.go | 2 +- internal/service/web.go | 19 ++++--- internal/service/web_old.go | 53 ++++++++++++++++++ main.go | 53 ++++++++++++------ pkg/xerror/common.go | 4 -- 12 files changed, 202 insertions(+), 54 deletions(-) create mode 100644 internal/service/web_old.go diff --git a/config.yaml.sample b/config.yaml.sample index d776769b..1126bcec 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -1,4 +1,5 @@ App: # APP基础设置项 + RunMode: debug AttachmentIncomeRate: 0.8 MaxCommentCount: 10 DefaultContextTimeout: 60 @@ -17,8 +18,19 @@ Features: Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile", "OSS:TempDir"] Base: ["Redis", "PhoneBind"] Docs: ["Docs:OpenAPI"] + Deprecated: ["Deprecated:OldWeb"] Option: ["SimpleCacheIndex"] Sms: "SmsJuhe" +WebServer: # Web服务 + HttpIp: 0.0.0.0 + HttpPort: 8010 + ReadTimeout: 60 + WriteTimeout: 60 +DocsServer: # 开发文档服务 + HttpIp: 0.0.0.0 + HttpPort: 8011 + ReadTimeout: 60 + WriteTimeout: 60 SmsJuhe: Gateway: https://v.juhe.cn/sms/send Key: diff --git a/go.mod b/go.mod index 8e3819e5..83348535 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 + github.com/alimy/mir/v3 v3.0.0-alpha.3 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 @@ -39,7 +40,6 @@ require ( gorm.io/plugin/dbresolver v1.1.0 gorm.io/plugin/soft_delete v1.1.0 modernc.org/sqlite v1.17.3 - github.com/alimy/mir/v3 v3.0.0 ) require ( @@ -132,7 +132,3 @@ require ( modernc.org/strutil v1.1.1 // indirect modernc.org/token v1.0.0 // indirect ) - -replace ( - github.com/alimy/mir/v3 => ../../alimy/mir -) \ No newline at end of file diff --git a/go.sum b/go.sum index 9221a97a..84ae8631 100644 --- a/go.sum +++ b/go.sum @@ -142,6 +142,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= +github.com/alimy/mir/v3 v3.0.0-alpha.3 h1:/GyBC0G041NIP3W62im8DtAwxRPSfSaivSQK6MV9fFc= +github.com/alimy/mir/v3 v3.0.0-alpha.3/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/conf/conf.go b/internal/conf/conf.go index bbc8438c..1cffa824 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -24,6 +24,8 @@ var ( PostgresSetting *PostgresSettingS Sqlite3Setting *Sqlite3SettingS ServerSetting *ServerSettingS + WebServerSetting *ServerSettingS + DocsServerSetting *ServerSettingS AppSetting *AppSettingS CacheIndexSetting *CacheIndexSettingS SimpleCacheIndexSetting *SimpleCacheIndexSettingS @@ -60,6 +62,8 @@ func setupSetting(suite []string, noDefault bool) error { objects := map[string]any{ "App": &AppSetting, "Server": &ServerSetting, + "WebServer": &WebServerSetting, + "DocsServer": &DocsServerSetting, "CacheIndex": &CacheIndexSetting, "SimpleCacheIndex": &SimpleCacheIndexSetting, "BigCacheIndex": &BigCacheIndexSetting, @@ -138,3 +142,10 @@ func GetOssDomain() string { } return uri + AliOSSSetting.Domain + "/" } + +func RunMode() string { + if !cfg.If("Deprecated:OldWeb") { + return ServerSetting.RunMode + } + return AppSetting.RunMode +} diff --git a/internal/conf/settting.go b/internal/conf/settting.go index da3d97b6..e5841c51 100644 --- a/internal/conf/settting.go +++ b/internal/conf/settting.go @@ -54,6 +54,7 @@ type ServerSettingS struct { } type AppSettingS struct { + RunMode string MaxCommentCount int64 AttachmentIncomeRate float64 DefaultContextTimeout time.Duration diff --git a/internal/servants/web/routers/router.go b/internal/servants/web/routers/router.go index c020cec3..e46b533b 100644 --- a/internal/servants/web/routers/router.go +++ b/internal/servants/web/routers/router.go @@ -118,6 +118,78 @@ func NewRouter() *gin.Engine { return e } +func RegisterRoute(e *gin.Engine) { + // 按需注册 docs、静态资源、LocalOSS 路由 + { + registerDocs(e) + registerStatick(e) + + cfg.Be("LocalOSS", func() { + routeLocalOSS(e) + }) + } + + // v1 group api + r := e.Group("/v1") + + // 获取version + r.GET("/", api.Version) + + // 用户登录 + r.POST("/auth/login", api.Login) + + // 用户注册 + r.POST("/auth/register", api.Register) + + // 获取验证码 + r.GET("/captcha", api.GetCaptcha) + + // 发送验证码 + r.POST("/captcha", api.PostCaptcha) + + // 无鉴权路由组 + noAuthApi := r.Group("/") + { + // 获取动态详情 + noAuthApi.GET("/post", api.GetPost) + + // 获取动态评论 + noAuthApi.GET("/post/comments", api.GetPostComments) + + // 获取话题列表 + noAuthApi.GET("/tags", api.GetPostTags) + } + + // 宽松鉴权路由组 + looseApi := r.Group("/").Use(chain.JwtLoose()) + { + // 获取广场流 + looseApi.GET("/posts", api.GetPostList) + + // 获取用户动态列表 + looseApi.GET("/user/posts", api.GetUserPosts) + + // 获取用户基本信息 + looseApi.GET("/user/profile", api.GetUserProfile) + } + + // 鉴权路由组 + authApi := r.Group("/").Use(chain.JWT()) + privApi := r.Group("/").Use(chain.JWT()).Use(chain.Priv()) + adminApi := r.Group("/").Use(chain.JWT()).Use(chain.Admin()) + + // 核心路由注册 + routeCore(authApi, privApi, adminApi) + + // 支付宝路由注册 + cfg.Be("Alipay", func() { + routeAlipay(r, authApi) + }) + + // Relationship相关路由注册 + routeRelationship(authApi) +} + func routeCore(authApi gin.IRoutes, privApi gin.IRoutes, adminApi gin.IRoutes) { // 同步索引 authApi.GET("/sync/index", api.SyncSearchIndex) diff --git a/internal/service/http_service.go b/internal/service/http_service.go index 11ec1b98..fc7ce9b6 100644 --- a/internal/service/http_service.go +++ b/internal/service/http_service.go @@ -8,23 +8,16 @@ import ( "github.com/gin-gonic/gin" ) -type httpService interface { - Service - - registerRoute(e *gin.Engine) -} - type baseHttpService struct { baseService server *httpServer } -func (s *baseHttpService) Init() error { +func (s *baseHttpService) registerRoute(h func(e *gin.Engine)) { if s.server.status() != httpServerStarted { - s.registerRoute(s.server.e) + h(s.server.e) } - return nil } func (s *baseHttpService) Start() error { @@ -37,13 +30,3 @@ func (s *baseHttpService) Start() error { func (s *baseHttpService) Stop() error { return s.server.stop() } - -func (s *baseHttpService) registerRoute(e *gin.Engine) { - // default empty -} - -func newBaseHttpService(s *httpServer) httpService { - return &baseHttpService{ - server: s, - } -} diff --git a/internal/service/service.go b/internal/service/service.go index 31efbae0..9ac6446c 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -28,7 +28,7 @@ func (baseService) String() string { } func InitService() (ss []Service) { - ss = append(ss, newWebService()) + ss = append(ss, newWebService(), newOldWebService()) for _, s := range ss { if err := s.Init(); err != nil { diff --git a/internal/service/web.go b/internal/service/web.go index 6ded25d3..c8e422a1 100644 --- a/internal/service/web.go +++ b/internal/service/web.go @@ -16,19 +16,20 @@ import ( ) type webService struct { - httpService + *baseHttpService } func (s *webService) Name() string { return "WebService" } -func (s *webService) registerRoute(e *gin.Engine) { - servants.RegisterWebServants(e) +func (s *webService) Init() error { + s.registerRoute(servants.RegisterWebServants) + return nil } func (s *webService) String() string { - return fmt.Sprintf("PaoPao service listen on %s\n", color.GreenString("http://%s:%s", conf.ServerSetting.HttpIp, conf.ServerSetting.HttpPort)) + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.WebServerSetting.HttpIp, conf.WebServerSetting.HttpPort)) } func newWebEngine() *gin.Engine { @@ -63,7 +64,7 @@ func newWebEngine() *gin.Engine { } func newWebService() Service { - addr := conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort + addr := conf.WebServerSetting.HttpIp + ":" + conf.WebServerSetting.HttpPort server := httpServerFrom(addr, func() *httpServer { engine := newWebEngine() return &httpServer{ @@ -71,13 +72,15 @@ func newWebService() Service { server: &http.Server{ Addr: addr, Handler: engine, - ReadTimeout: conf.ServerSetting.ReadTimeout, - WriteTimeout: conf.ServerSetting.WriteTimeout, + ReadTimeout: conf.WebServerSetting.ReadTimeout, + WriteTimeout: conf.WebServerSetting.WriteTimeout, MaxHeaderBytes: 1 << 20, }, } }) return &webService{ - httpService: newBaseHttpService(server), + baseHttpService: &baseHttpService{ + server: server, + }, } } diff --git a/internal/service/web_old.go b/internal/service/web_old.go new file mode 100644 index 00000000..a3c58471 --- /dev/null +++ b/internal/service/web_old.go @@ -0,0 +1,53 @@ +// 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 service + +import ( + "fmt" + "net/http" + + "github.com/fatih/color" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants/web/routers" +) + +type oldWebService struct { + *baseHttpService +} + +func (s *oldWebService) Name() string { + return "OldWebService" +} + +func (s *oldWebService) Init() error { + s.registerRoute(routers.RegisterRoute) + return nil +} + +func (s *oldWebService) String() string { + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.ServerSetting.HttpIp, conf.ServerSetting.HttpPort)) +} + +func newOldWebService() Service { + addr := conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort + server := httpServerFrom(addr, func() *httpServer { + engine := newWebEngine() + return &httpServer{ + e: engine, + server: &http.Server{ + Addr: addr, + Handler: engine, + ReadTimeout: conf.ServerSetting.ReadTimeout, + WriteTimeout: conf.ServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } + }) + return &oldWebService{ + baseHttpService: &baseHttpService{ + server: server, + }, + } +} diff --git a/main.go b/main.go index 0d28b464..63ec5f59 100644 --- a/main.go +++ b/main.go @@ -8,14 +8,16 @@ import ( "flag" "fmt" "log" - "net/http" + "os" + "os/signal" "strings" + "syscall" "github.com/fatih/color" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/internal/servants/web/routers" + "github.com/rocboss/paopao-ce/internal/service" "github.com/rocboss/paopao-ce/pkg/debug" "github.com/rocboss/paopao-ce/pkg/util" ) @@ -51,24 +53,41 @@ func flagParse() { flag.Parse() } -func main() { - gin.SetMode(conf.ServerSetting.RunMode) - - router := routers.NewRouter() - s := &http.Server{ - Addr: conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort, - Handler: router, - ReadTimeout: conf.ServerSetting.ReadTimeout, - WriteTimeout: conf.ServerSetting.WriteTimeout, - MaxHeaderBytes: 1 << 20, +func runService(ss []service.Service) { + gin.SetMode(conf.RunMode()) + + fmt.Fprintf(color.Output, "\nstarting run service...\n\n") + for _, s := range ss { + go func(s service.Service) { + fmt.Fprintf(color.Output, "%s[start] - %s\n", s.Name(), s) + if err := s.Start(); err != nil { + log.Fatalf("%s[start] - occurs on error: %s\n", s.Name(), err) + } + }(s) } + quit := make(chan os.Signal, 1) + // kill (no param) default send syscall.SIGTERM + // kill -2 is syscall.SIGINT + // kill -9 is syscall.SIGKILL but can't be catch, so don't need add it + signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) + <-quit + fmt.Fprintf(color.Output, "\nshutting down server...\n\n") + + for _, s := range ss { + if err := s.Stop(); err != nil { + fmt.Fprintf(color.Output, "%s[stop] - occurs on error: %s\n", s.Name(), err) + } + fmt.Fprintf(color.Output, "%s[stop] - finish...\n", s.Name()) + } +} + +func main() { util.PrintHelloBanner(debug.VersionInfo()) - fmt.Fprintf(color.Output, "PaoPao service listen on %s\n", - color.GreenString(fmt.Sprintf("http://%s:%s", conf.ServerSetting.HttpIp, conf.ServerSetting.HttpPort)), - ) - if err := s.ListenAndServe(); err != nil { - log.Fatalf("run app failed: %s", err) + if ss := service.InitService(); len(ss) > 0 { + runService(ss) + } else { + fmt.Fprintf(color.Output, "no service need start so just exit") } } diff --git a/pkg/xerror/common.go b/pkg/xerror/common.go index b502840b..2852f6c2 100644 --- a/pkg/xerror/common.go +++ b/pkg/xerror/common.go @@ -23,8 +23,4 @@ var ( GatewayAppKeyClosed = NewError(10113, "网关请求APP KEY已停用") GatewayParamSignError = NewError(10114, "网关请求参数签名错误") GatewayTooManyRequests = NewError(10115, "网关请求频次超限") - - FileUploadFailed = NewError(10200, "文件上传失败") - FileInvalidExt = NewError(10201, "文件类型不合法") - FileInvalidSize = NewError(10202, "文件大小超限") ) From 3ad6f66a76e437cb6ef31352497e010c1db4fc47 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 10 Dec 2022 00:32:54 +0800 Subject: [PATCH 15/65] upgrade go-mir version to v3.0.0-alpha.4 --- go.mod | 2 +- go.sum | 4 ++-- internal/mirc/auto/api/v1/web_core.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 83348535..fa9ff517 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 - github.com/alimy/mir/v3 v3.0.0-alpha.3 + github.com/alimy/mir/v3 v3.0.0-alpha.4 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index 84ae8631..bfe083a0 100644 --- a/go.sum +++ b/go.sum @@ -142,8 +142,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= -github.com/alimy/mir/v3 v3.0.0-alpha.3 h1:/GyBC0G041NIP3W62im8DtAwxRPSfSaivSQK6MV9fFc= -github.com/alimy/mir/v3 v3.0.0-alpha.3/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= +github.com/alimy/mir/v3 v3.0.0-alpha.4 h1:tSmyyhgutMHjgx9TO9891ZCY4qbr3g8FGar4z+9Hhq4= +github.com/alimy/mir/v3 v3.0.0-alpha.4/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/mirc/auto/api/v1/web_core.go b/internal/mirc/auto/api/v1/web_core.go index 5887e010..3e7d3d65 100644 --- a/internal/mirc/auto/api/v1/web_core.go +++ b/internal/mirc/auto/api/v1/web_core.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/alimy/mir/v3" - gin "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin" ) type LoginReq struct { From 6a53632b9b31b9092ddc34da365e7ec8d460badb Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 10 Dec 2022 10:23:33 +0800 Subject: [PATCH 16/65] optimize main function logic and custom service create logic --- internal/service/service.go | 17 ++++++++++++++--- main.go | 22 ++++++++++++++++------ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/internal/service/service.go b/internal/service/service.go index 9ac6446c..a69c8c91 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -7,6 +7,7 @@ package service import ( "log" + "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/rocboss/paopao-ce/pkg/types" ) @@ -27,13 +28,23 @@ func (baseService) String() string { return "" } -func InitService() (ss []Service) { - ss = append(ss, newWebService(), newOldWebService()) - +func InitService() []Service { + ss := newService() for _, s := range ss { if err := s.Init(); err != nil { log.Fatalf("initial %s service error: %s", s.Name(), err) } } + return ss +} + +func newService() (ss []Service) { + ss = append(ss, newWebService()) + + // add oldWebService if not depredcated OldWebService + cfg.Not("Deprecated:OldWeb", func() { + ss = append(ss, newOldWebService()) + }) + return } diff --git a/main.go b/main.go index 63ec5f59..4c639a61 100644 --- a/main.go +++ b/main.go @@ -7,10 +7,10 @@ package main import ( "flag" "fmt" - "log" "os" "os/signal" "strings" + "sync" "syscall" "github.com/fatih/color" @@ -48,24 +48,27 @@ func init() { } func flagParse() { - flag.BoolVar(&noDefaultFeatures, "no-default-features", false, "whether use default features") + flag.BoolVar(&noDefaultFeatures, "no-default-features", false, "whether not use default features") flag.Var(&features, "features", "use special features") flag.Parse() } -func runService(ss []service.Service) { +func runService(wg *sync.WaitGroup, ss []service.Service) { gin.SetMode(conf.RunMode()) fmt.Fprintf(color.Output, "\nstarting run service...\n\n") for _, s := range ss { go func(s service.Service) { - fmt.Fprintf(color.Output, "%s[start] - %s\n", s.Name(), s) + fmt.Fprintf(color.Output, "%s[start] - %s", s.Name(), s) if err := s.Start(); err != nil { - log.Fatalf("%s[start] - occurs on error: %s\n", s.Name(), err) + fmt.Fprintf(color.Output, "%s[start] - occurs on error: %s\n", s.Name(), err) } + wg.Done() }(s) } +} +func runManage(wg *sync.WaitGroup, ss []service.Service) { quit := make(chan os.Signal, 1) // kill (no param) default send syscall.SIGTERM // kill -2 is syscall.SIGINT @@ -80,13 +83,20 @@ func runService(ss []service.Service) { } fmt.Fprintf(color.Output, "%s[stop] - finish...\n", s.Name()) } + wg.Done() } func main() { util.PrintHelloBanner(debug.VersionInfo()) if ss := service.InitService(); len(ss) > 0 { - runService(ss) + wg := &sync.WaitGroup{} + wg.Add(len(ss) + 1) + + runService(wg, ss) + go runManage(wg, ss) + + wg.Wait() } else { fmt.Fprintf(color.Output, "no service need start so just exit") } From 9be9eccda1d94f6bb5358b63227ec5be9155f627 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 10 Dec 2022 11:05:44 +0800 Subject: [PATCH 17/65] mir: update proposal document --- .../005-引入go-mir优化后端架构设计.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/proposal/005-引入go-mir优化后端架构设计.md b/docs/proposal/005-引入go-mir优化后端架构设计.md index 0168ed80..d42901ac 100644 --- a/docs/proposal/005-引入go-mir优化后端架构设计.md +++ b/docs/proposal/005-引入go-mir优化后端架构设计.md @@ -1,6 +1,6 @@ | 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 | | ----- | ----- | ----- | ----- | ----- | ----- | -| 005| 北野 | 2022-11-21 | 2022-11-21 | v0.0 | 提议 | +| 005| 北野 | 2022-11-21 | 2022-12-10 | v1.0 | 提议 | ### 引入go-mir优化后端架构设计 引入[github.com/alimy/mir/v3](https://github.com/alimy/mir)优化后端的架构设计,使得后端代码更具扩展型。 @@ -18,11 +18,18 @@ ### 疑问 1. 为什么引入go-mir? -TODO; + * [go-mir](https://github.com/alimy/mir)是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架,巧妙的借用golang语法作为DSL描述RESTful API,通过代码生成的方式自动生成相对应的API接口、HTTP服务器框架初始化代码等,提供类似gRPC的开发体验,对后端开发者非常友好。 + * 引入go-mir的另一个主要目的是加速后端服务的开发,更好的保证代码风格的一致性。 1. 为什么要兼容RESTful/gRPC服务? -RESTful API是提供给Web端使用的,包括paopao-ce web端以及后期的运维端admin; gRPC API是提供给移动端(iOS/Android)使用的服务。RESTful API天然对web端浏览器友好,而gRPC生态对后端、移动端天然友好,可以根据google-protocol-buffers DSL定义服务API自动生成服务端、客户端代码,非常利于开发,特别是移动端开发,省去了编写客户端网络数据服务相关的业务逻辑,只需要专注于页面逻辑编写,后端数据获取的网络数据访问逻辑直接调用自动生成的gRPC API客户端代码即可,大大的减轻移动端开发的心智负担。后端引入gRPC主要就是考虑到移动端(iOS/Android)开发的开发效率,在减轻移动端开发网络数据获取业务逻辑的心智负担上,gRPC生态与RESTful生态相比优势明显,因此强力引入。再一个就是[go-mir](https://github.com/alimy/mir) v3为RESTful服务的开发提供类似gRPC服务的开发体验,也为后端兼容RESTful/gRPC服务创造了很好的条件,只要代码结构组织清晰,将会有很好的后端开发体验。 + * RESTful API是提供给Web端使用的,包括paopao-ce web端以及后期的运维端admin; gRPC API是提供给移动端(iOS/Android)使用的服务。 + * RESTful API天然对web端浏览器友好,而gRPC生态对后端、移动端天然友好,可以根据google-protocol-buffers DSL定义服务API自动生成服务端、客户端代码,非常利于开发,特别是移动端开发,省去了编写客户端网络数据服务相关的业务逻辑,只需要专注于页面逻辑编写,后端数据获取的网络数据访问逻辑直接调用自动生成的gRPC API客户端代码即可,大大的减轻移动端开发的心智负担。 + * 后端引入gRPC主要就是考虑到移动端(iOS/Android)开发的开发效率,在减轻移动端开发网络数据获取业务逻辑的心智负担上,gRPC生态与RESTful生态相比优势明显,因此强力引入。 + * 再一个就是[go-mir](https://github.com/alimy/mir) v3为RESTful服务的开发提供类似gRPC服务的开发体验,也为后端兼容RESTful/gRPC服务创造了很好的条件,只要代码结构组织清晰,将会有很好的后端开发体验。 >*目前移动端 iOS/Android APP还在规划中,这里后续的后端gRPC API服务也是为此做准备,敬请期待~* ### 更新记录 #### v0.0(2022-11-21) - 北野 -* 初始文档 \ No newline at end of file +* 初始文档 + +#### v1.0(2022-12-10) - 北野 +* 添加内容 From 6650d089b8cb2ac5b5f87152f7194045d3e19a00 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 10 Dec 2022 14:36:10 +0800 Subject: [PATCH 18/65] add m/s/x RESTful API stub interface for mir --- Makefile | 9 +- ...05-引入go-mir优化后端架构设计.md | 14 +- internal/mirc/auto/api/m/v1/user.go | 127 +++++++++++++++++ internal/mirc/auto/api/s/v1/user.go | 131 ++++++++++++++++++ internal/mirc/auto/api/x/v1/user.go | 127 +++++++++++++++++ internal/mirc/main.go | 3 + internal/mirc/routes/README.md | 6 + internal/mirc/routes/m/README.md | 4 + internal/mirc/routes/m/v1/user.go | 42 ++++++ internal/mirc/routes/s/README.md | 4 + internal/mirc/routes/s/v1/user.go | 42 ++++++ internal/mirc/routes/x/README.md | 4 + internal/mirc/routes/x/v1/user.go | 42 ++++++ 13 files changed, 548 insertions(+), 7 deletions(-) create mode 100644 internal/mirc/auto/api/m/v1/user.go create mode 100644 internal/mirc/auto/api/s/v1/user.go create mode 100644 internal/mirc/auto/api/x/v1/user.go create mode 100644 internal/mirc/routes/m/README.md create mode 100644 internal/mirc/routes/m/v1/user.go create mode 100644 internal/mirc/routes/s/README.md create mode 100644 internal/mirc/routes/s/v1/user.go create mode 100644 internal/mirc/routes/x/README.md create mode 100644 internal/mirc/routes/x/v1/user.go diff --git a/Makefile b/Makefile index 700e2d29..dd26e18c 100644 --- a/Makefile +++ b/Makefile @@ -69,10 +69,17 @@ windows-x64: @CGO_ENABLED=$(CGO_ENABLED) GOOS=windows GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/$(basename $(TARGET)).exe .PHONY: generate -generate: +generate: gen-mir gen-grpc + +.PHONY: gen-mir +gen-mir: @go generate internal/mirc/main.go @go fmt ./internal/mirc/... +.PHONY: gen-grpc +gen-grpc: + @go fmt ./internal/proto/... + clean: @go clean @find ./release -type f -exec rm -r {} + diff --git a/docs/proposal/005-引入go-mir优化后端架构设计.md b/docs/proposal/005-引入go-mir优化后端架构设计.md index d42901ac..24643b8c 100644 --- a/docs/proposal/005-引入go-mir优化后端架构设计.md +++ b/docs/proposal/005-引入go-mir优化后端架构设计.md @@ -4,6 +4,7 @@ ### 引入go-mir优化后端架构设计 引入[github.com/alimy/mir/v3](https://github.com/alimy/mir)优化后端的架构设计,使得后端代码更具扩展型。 +![](.assets/06-01.png) ### 需求 * 更方便添加后端功能项的实现; @@ -18,13 +19,14 @@ ### 疑问 1. 为什么引入go-mir? - * [go-mir](https://github.com/alimy/mir)是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架,巧妙的借用golang语法作为DSL描述RESTful API,通过代码生成的方式自动生成相对应的API接口、HTTP服务器框架初始化代码等,提供类似gRPC的开发体验,对后端开发者非常友好。 - * 引入go-mir的另一个主要目的是加速后端服务的开发,更好的保证代码风格的一致性。 + * [go-mir](https://github.com/alimy/mir)是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架,巧妙的借用golang语法作为DSL描述RESTful API,通过代码生成的方式自动生成相对应的API接口、HTTP服务器框架初始化代码等,提供类似gRPC的开发体验,对后端开发者非常友好; + * 引入go-mir的另一个主要目的是加速后端服务的开发,更好的保证代码风格的一致性; + * 践行 [006-关于paopao-ce的结构设计](006-关于paopao-ce的结构设计.md); 1. 为什么要兼容RESTful/gRPC服务? - * RESTful API是提供给Web端使用的,包括paopao-ce web端以及后期的运维端admin; gRPC API是提供给移动端(iOS/Android)使用的服务。 - * RESTful API天然对web端浏览器友好,而gRPC生态对后端、移动端天然友好,可以根据google-protocol-buffers DSL定义服务API自动生成服务端、客户端代码,非常利于开发,特别是移动端开发,省去了编写客户端网络数据服务相关的业务逻辑,只需要专注于页面逻辑编写,后端数据获取的网络数据访问逻辑直接调用自动生成的gRPC API客户端代码即可,大大的减轻移动端开发的心智负担。 - * 后端引入gRPC主要就是考虑到移动端(iOS/Android)开发的开发效率,在减轻移动端开发网络数据获取业务逻辑的心智负担上,gRPC生态与RESTful生态相比优势明显,因此强力引入。 - * 再一个就是[go-mir](https://github.com/alimy/mir) v3为RESTful服务的开发提供类似gRPC服务的开发体验,也为后端兼容RESTful/gRPC服务创造了很好的条件,只要代码结构组织清晰,将会有很好的后端开发体验。 + * RESTful API是提供给Web端使用的,包括paopao-ce web端以及后期的运维端admin; gRPC API是提供给移动端(iOS/Android)使用的服务; + * RESTful API天然对web端浏览器友好,而gRPC生态对后端、移动端天然友好,可以根据google-protocol-buffers DSL定义服务API自动生成服务端、客户端代码,非常利于开发,特别是移动端开发,省去了编写客户端网络数据服务相关的业务逻辑,只需要专注于页面逻辑编写,后端数据获取的网络数据访问逻辑直接调用自动生成的gRPC API客户端代码即可,大大的减轻移动端开发的心智负担; + * 后端引入gRPC主要就是考虑到移动端(iOS/Android)开发的开发效率,在减轻移动端开发网络数据获取业务逻辑的心智负担上,gRPC生态与RESTful生态相比优势明显,因此强力引入; + * 再一个就是[go-mir](https://github.com/alimy/mir) v3为RESTful服务的开发提供类似gRPC服务的开发体验,也为后端兼容RESTful/gRPC服务创造了很好的条件,只要代码结构组织清晰,将会有很好的后端开发体验; >*目前移动端 iOS/Android APP还在规划中,这里后续的后端gRPC API服务也是为此做准备,敬请期待~* ### 更新记录 diff --git a/internal/mirc/auto/api/m/v1/user.go b/internal/mirc/auto/api/m/v1/user.go new file mode 100644 index 00000000..c087ae87 --- /dev/null +++ b/internal/mirc/auto/api/m/v1/user.go @@ -0,0 +1,127 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type User interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + Logout(c *gin.Context) mir.Error + Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + + mustEmbedUnimplementedUserServant() +} + +type UserBinding interface { + BindLogin(c *gin.Context) (*LoginReq, mir.Error) + + mustEmbedUnimplementedUserBinding() +} + +type UserRender interface { + RenderLogout(c *gin.Context, err mir.Error) + RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + + mustEmbedUnimplementedUserRender() +} + +// RegisterUserServant register User servant to gin +func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { + router := e.Group("m/v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c *gin.Context) { + r.RenderLogout(c, s.Logout(c)) + }) + + router.Handle("POST", "/user/login/", func(c *gin.Context) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + } + resp, err := s.Login(c, req) + r.RenderLogin(c, resp, err) + }) + +} + +// UnimplementedUserServant can be embedded to have forward compatible implementations. +type UnimplementedUserServant struct { +} + +func (UnimplementedUserServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {} + +// UnimplementedUserRender can be embedded to have forward compatible implementations. +type UnimplementedUserRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {} + +// UnimplementedUserBinding can be embedded to have forward compatible implementations. +type UnimplementedUserBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {} diff --git a/internal/mirc/auto/api/s/v1/user.go b/internal/mirc/auto/api/s/v1/user.go new file mode 100644 index 00000000..4751a141 --- /dev/null +++ b/internal/mirc/auto/api/s/v1/user.go @@ -0,0 +1,131 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type User interface { + Logout(c *gin.Context) mir.Error + Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + Index(c *gin.Context) mir.Error + + mustEmbedUnimplementedUserServant() +} + +type UserBinding interface { + BindLogin(c *gin.Context) (*LoginReq, mir.Error) + + mustEmbedUnimplementedUserBinding() +} + +type UserRender interface { + RenderLogout(c *gin.Context, err mir.Error) + RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + RenderIndex(c *gin.Context, err mir.Error) + + mustEmbedUnimplementedUserRender() +} + +// RegisterUserServant register User servant to gin +func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { + router := e.Group("s/v1") + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c *gin.Context) { + r.RenderLogout(c, s.Logout(c)) + }) + + router.Handle("POST", "/user/login/", func(c *gin.Context) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + } + resp, err := s.Login(c, req) + r.RenderLogin(c, resp, err) + }) + + router.Handle("GET", "/index/", func(c *gin.Context) { + r.RenderIndex(c, s.Index(c)) + }) + +} + +// UnimplementedUserServant can be embedded to have forward compatible implementations. +type UnimplementedUserServant struct { +} + +func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) Index(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {} + +// UnimplementedUserRender can be embedded to have forward compatible implementations. +type UnimplementedUserRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedUserRender) RenderIndex(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {} + +// UnimplementedUserBinding can be embedded to have forward compatible implementations. +type UnimplementedUserBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {} diff --git a/internal/mirc/auto/api/x/v1/user.go b/internal/mirc/auto/api/x/v1/user.go new file mode 100644 index 00000000..66446d03 --- /dev/null +++ b/internal/mirc/auto/api/x/v1/user.go @@ -0,0 +1,127 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type User interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + Logout(c *gin.Context) mir.Error + Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + + mustEmbedUnimplementedUserServant() +} + +type UserBinding interface { + BindLogin(c *gin.Context) (*LoginReq, mir.Error) + + mustEmbedUnimplementedUserBinding() +} + +type UserRender interface { + RenderLogout(c *gin.Context, err mir.Error) + RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + + mustEmbedUnimplementedUserRender() +} + +// RegisterUserServant register User servant to gin +func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { + router := e.Group("x/v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c *gin.Context) { + r.RenderLogout(c, s.Logout(c)) + }) + + router.Handle("POST", "/user/login/", func(c *gin.Context) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + } + resp, err := s.Login(c, req) + r.RenderLogin(c, resp, err) + }) + +} + +// UnimplementedUserServant can be embedded to have forward compatible implementations. +type UnimplementedUserServant struct { +} + +func (UnimplementedUserServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {} + +// UnimplementedUserRender can be embedded to have forward compatible implementations. +type UnimplementedUserRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {} + +// UnimplementedUserBinding can be embedded to have forward compatible implementations. +type UnimplementedUserBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {} diff --git a/internal/mirc/main.go b/internal/mirc/main.go index bf45791f..5bef4944 100644 --- a/internal/mirc/main.go +++ b/internal/mirc/main.go @@ -10,7 +10,10 @@ import ( . "github.com/alimy/mir/v3/core" . "github.com/alimy/mir/v3/engine" + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/m/v1" + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/s/v1" _ "github.com/rocboss/paopao-ce/internal/mirc/routes/v1" + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/x/v1" ) //go:generate go run main.go diff --git a/internal/mirc/routes/README.md b/internal/mirc/routes/README.md index 0d7ac0c1..fb8728e2 100644 --- a/internal/mirc/routes/README.md +++ b/internal/mirc/routes/README.md @@ -1 +1,7 @@ ### RESTful API for paopao-ce +本目录包含所有RESTful API相关定义文件 + +* v1 - Web系列 v1版本 相关RESTful API相关定义文件 +* m - Manager系列相关RESTful API相关定义文件 +* x - SpaceX系列相关RESTful API相关定义文件 +* s - LocalOSS OBS系列RESTful API相关定义文件 diff --git a/internal/mirc/routes/m/README.md b/internal/mirc/routes/m/README.md new file mode 100644 index 00000000..2c6a4431 --- /dev/null +++ b/internal/mirc/routes/m/README.md @@ -0,0 +1,4 @@ +### Manager系列RESTful API相关定义文件 +本目录包含 Manager后台运维相关API定义文件。 + +* v1 - v1版本API diff --git a/internal/mirc/routes/m/v1/user.go b/internal/mirc/routes/m/v1/user.go new file mode 100644 index 00000000..6f0dcb79 --- /dev/null +++ b/internal/mirc/routes/m/v1/user.go @@ -0,0 +1,42 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(User)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type User struct { + Chain Chain `mir:"-"` + Group Group `mir:"m/v1"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/internal/mirc/routes/s/README.md b/internal/mirc/routes/s/README.md new file mode 100644 index 00000000..e1769bf5 --- /dev/null +++ b/internal/mirc/routes/s/README.md @@ -0,0 +1,4 @@ +### LocalOSS OBS系列RESTful API相关定义文件 +本目录包含 LocalOSS OBS 系列相关API定义文件。 + +* v1 - v1版本API diff --git a/internal/mirc/routes/s/v1/user.go b/internal/mirc/routes/s/v1/user.go new file mode 100644 index 00000000..555ff6d7 --- /dev/null +++ b/internal/mirc/routes/s/v1/user.go @@ -0,0 +1,42 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(User)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type User struct { + Group Group `mir:"s/v1"` + Index func(Get) `mir:"/index/"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/internal/mirc/routes/x/README.md b/internal/mirc/routes/x/README.md new file mode 100644 index 00000000..a4ec3303 --- /dev/null +++ b/internal/mirc/routes/x/README.md @@ -0,0 +1,4 @@ +### SpaceX系列RESTful API +本目录包含SpaceX系列RESTful API相关定义文件 + +* v1 - v1版本API diff --git a/internal/mirc/routes/x/v1/user.go b/internal/mirc/routes/x/v1/user.go new file mode 100644 index 00000000..8dd49fa5 --- /dev/null +++ b/internal/mirc/routes/x/v1/user.go @@ -0,0 +1,42 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(User)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type User struct { + Chain Chain `mir:"-"` + Group Group `mir:"x/v1"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} From 4dae86cc9c10eda116d8c732fd708db2b63d530a Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 10 Dec 2022 16:01:30 +0800 Subject: [PATCH 19/65] mir: add Admin/SpaceX/Bot/LocalOSS stub service interface and simple initial logic --- config.yaml.sample | 21 ++++ internal/conf/conf.go | 14 ++- internal/conf/settting.go | 2 +- internal/mirc/README.md | 3 +- internal/mirc/auto/api/r/v1/user.go | 127 +++++++++++++++++++++++++ internal/mirc/auto/api/v1/web_core.go | 2 +- internal/mirc/main.go | 1 + internal/mirc/routes/README.md | 3 +- internal/mirc/routes/m/README.md | 4 +- internal/mirc/routes/r/README.md | 4 + internal/mirc/routes/r/v1/user.go | 42 ++++++++ internal/servants/admin/admin.go | 15 +++ internal/servants/admin/user.go | 51 ++++++++++ internal/servants/bot/bot.go | 15 +++ internal/servants/bot/user.go | 51 ++++++++++ internal/servants/localoss/localoss.go | 10 +- internal/servants/localoss/user.go | 51 ++++++++++ internal/servants/servants.go | 23 +++++ internal/servants/space/space.go | 15 +++ internal/servants/space/user.go | 51 ++++++++++ internal/service/admin.go | 86 +++++++++++++++++ internal/service/bot.go | 86 +++++++++++++++++ internal/service/localoss.go | 61 ++++++++++++ internal/service/service.go | 15 +++ internal/service/space.go | 86 +++++++++++++++++ 25 files changed, 826 insertions(+), 13 deletions(-) create mode 100644 internal/mirc/auto/api/r/v1/user.go create mode 100644 internal/mirc/routes/r/README.md create mode 100644 internal/mirc/routes/r/v1/user.go create mode 100644 internal/servants/admin/admin.go create mode 100644 internal/servants/admin/user.go create mode 100644 internal/servants/bot/bot.go create mode 100644 internal/servants/bot/user.go create mode 100644 internal/servants/localoss/user.go create mode 100644 internal/servants/space/space.go create mode 100644 internal/servants/space/user.go create mode 100644 internal/service/admin.go create mode 100644 internal/service/bot.go create mode 100644 internal/service/localoss.go create mode 100644 internal/service/space.go diff --git a/config.yaml.sample b/config.yaml.sample index 1126bcec..2c6c1ae1 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -19,6 +19,7 @@ Features: Base: ["Redis", "PhoneBind"] Docs: ["Docs:OpenAPI"] Deprecated: ["Deprecated:OldWeb"] + Service: ["Admin", "SpaceX", "Bot", "LocalOSS"] Option: ["SimpleCacheIndex"] Sms: "SmsJuhe" WebServer: # Web服务 @@ -26,6 +27,26 @@ WebServer: # Web服务 HttpPort: 8010 ReadTimeout: 60 WriteTimeout: 60 +AdminServer: # Admin后台运维服务 + HttpIp: 0.0.0.0 + HttpPort: 8014 + ReadTimeout: 60 + WriteTimeout: 60 +SpaceXServer: # SpaceX服务 + HttpIp: 0.0.0.0 + HttpPort: 8012 + ReadTimeout: 60 + WriteTimeout: 60 +BotServer: # Bot服务 + HttpIp: 0.0.0.0 + HttpPort: 8016 + ReadTimeout: 60 + WriteTimeout: 60 +LocalossServer: # Localoss服务 + HttpIp: 0.0.0.0 + HttpPort: 8018 + ReadTimeout: 60 + WriteTimeout: 60 DocsServer: # 开发文档服务 HttpIp: 0.0.0.0 HttpPort: 8011 diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 1cffa824..75d363e7 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -23,9 +23,13 @@ var ( MysqlSetting *MySQLSettingS PostgresSetting *PostgresSettingS Sqlite3Setting *Sqlite3SettingS - ServerSetting *ServerSettingS - WebServerSetting *ServerSettingS - DocsServerSetting *ServerSettingS + ServerSetting *HttpServerSettingS + WebServerSetting *HttpServerSettingS + AdminServerSetting *HttpServerSettingS + SpaceXServerSetting *HttpServerSettingS + BotServerSetting *HttpServerSettingS + LocalossServerSetting *HttpServerSettingS + DocsServerSetting *HttpServerSettingS AppSetting *AppSettingS CacheIndexSetting *CacheIndexSettingS SimpleCacheIndexSetting *SimpleCacheIndexSettingS @@ -63,6 +67,10 @@ func setupSetting(suite []string, noDefault bool) error { "App": &AppSetting, "Server": &ServerSetting, "WebServer": &WebServerSetting, + "AdminServer": &AdminServerSetting, + "SpaceXServer": &SpaceXServerSetting, + "BotServer": &BotServerSetting, + "LocalossServer": &LocalossServerSetting, "DocsServer": &DocsServerSetting, "CacheIndex": &CacheIndexSetting, "SimpleCacheIndex": &SimpleCacheIndexSetting, diff --git a/internal/conf/settting.go b/internal/conf/settting.go index e5841c51..7067d18e 100644 --- a/internal/conf/settting.go +++ b/internal/conf/settting.go @@ -45,7 +45,7 @@ type LoggerMeiliSettingS struct { MinWorker int } -type ServerSettingS struct { +type HttpServerSettingS struct { RunMode string HttpIp string HttpPort string diff --git a/internal/mirc/README.md b/internal/mirc/README.md index 5b2162a2..064cbe21 100644 --- a/internal/mirc/README.md +++ b/internal/mirc/README.md @@ -1 +1,2 @@ -### RESTful API for paopao-ce use [go-mir](https://github.com/alimy/mir) to generate service interface code automatic. +### Mirc for paopao-ce +RESTful API for paopao-ce use [go-mir](https://github.com/alimy/mir) to generate service interface code automatic. diff --git a/internal/mirc/auto/api/r/v1/user.go b/internal/mirc/auto/api/r/v1/user.go new file mode 100644 index 00000000..ae9dd9cd --- /dev/null +++ b/internal/mirc/auto/api/r/v1/user.go @@ -0,0 +1,127 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" +) + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type User interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + Logout(c *gin.Context) mir.Error + Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + + mustEmbedUnimplementedUserServant() +} + +type UserBinding interface { + BindLogin(c *gin.Context) (*LoginReq, mir.Error) + + mustEmbedUnimplementedUserBinding() +} + +type UserRender interface { + RenderLogout(c *gin.Context, err mir.Error) + RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + + mustEmbedUnimplementedUserRender() +} + +// RegisterUserServant register User servant to gin +func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { + router := e.Group("r/v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("POST", "/user/logout/", func(c *gin.Context) { + r.RenderLogout(c, s.Logout(c)) + }) + + router.Handle("POST", "/user/login/", func(c *gin.Context) { + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + } + resp, err := s.Login(c, req) + r.RenderLogin(c, resp, err) + }) + +} + +// UnimplementedUserServant can be embedded to have forward compatible implementations. +type UnimplementedUserServant struct { +} + +func (UnimplementedUserServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {} + +// UnimplementedUserRender can be embedded to have forward compatible implementations. +type UnimplementedUserRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {} + +// UnimplementedUserBinding can be embedded to have forward compatible implementations. +type UnimplementedUserBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { + obj := new(LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {} diff --git a/internal/mirc/auto/api/v1/web_core.go b/internal/mirc/auto/api/v1/web_core.go index 3e7d3d65..6f1efce6 100644 --- a/internal/mirc/auto/api/v1/web_core.go +++ b/internal/mirc/auto/api/v1/web_core.go @@ -86,8 +86,8 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor h := func(c *gin.Context) { r.RenderArticles(c, s.Articles(c)) } - router.Handle("HEAD", "/articles/:category/", h) router.Handle("GET", "/articles/:category/", h) + router.Handle("HEAD", "/articles/:category/", h) } router.Handle("GET", "/index/", func(c *gin.Context) { diff --git a/internal/mirc/main.go b/internal/mirc/main.go index 5bef4944..34120f36 100644 --- a/internal/mirc/main.go +++ b/internal/mirc/main.go @@ -11,6 +11,7 @@ import ( . "github.com/alimy/mir/v3/engine" _ "github.com/rocboss/paopao-ce/internal/mirc/routes/m/v1" + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/r/v1" _ "github.com/rocboss/paopao-ce/internal/mirc/routes/s/v1" _ "github.com/rocboss/paopao-ce/internal/mirc/routes/v1" _ "github.com/rocboss/paopao-ce/internal/mirc/routes/x/v1" diff --git a/internal/mirc/routes/README.md b/internal/mirc/routes/README.md index fb8728e2..d7d0b9fb 100644 --- a/internal/mirc/routes/README.md +++ b/internal/mirc/routes/README.md @@ -2,6 +2,7 @@ 本目录包含所有RESTful API相关定义文件 * v1 - Web系列 v1版本 相关RESTful API相关定义文件 -* m - Manager系列相关RESTful API相关定义文件 +* m - Admin后台运维系列相关RESTful API相关定义文件 * x - SpaceX系列相关RESTful API相关定义文件 * s - LocalOSS OBS系列RESTful API相关定义文件 +* r - Bot系列相关RESTful API相关定义文件 diff --git a/internal/mirc/routes/m/README.md b/internal/mirc/routes/m/README.md index 2c6a4431..c9fa71b9 100644 --- a/internal/mirc/routes/m/README.md +++ b/internal/mirc/routes/m/README.md @@ -1,4 +1,4 @@ -### Manager系列RESTful API相关定义文件 -本目录包含 Manager后台运维相关API定义文件。 +### Admin系列RESTful API相关定义文件 +本目录包含 Admin后台运维相关API定义文件。 * v1 - v1版本API diff --git a/internal/mirc/routes/r/README.md b/internal/mirc/routes/r/README.md new file mode 100644 index 00000000..a1aa83ac --- /dev/null +++ b/internal/mirc/routes/r/README.md @@ -0,0 +1,4 @@ +### Bot系列RESTful API相关定义文件 +本目录包含 Bot相关API定义文件。 + +* v1 - v1版本API diff --git a/internal/mirc/routes/r/v1/user.go b/internal/mirc/routes/r/v1/user.go new file mode 100644 index 00000000..a4839673 --- /dev/null +++ b/internal/mirc/routes/r/v1/user.go @@ -0,0 +1,42 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" +) + +func init() { + AddEntry(new(User)) +} + +type AgentInfo struct { + Platform string `json:"platform"` + UserAgent string `json:"user_agent"` +} + +type ServerInfo struct { + ApiVer string `json:"api_ver"` +} + +type UserInfo struct { + Name string `json:"name"` +} + +type LoginReq struct { + AgentInfo AgentInfo `json:"agent_info"` + Name string `json:"name"` + Passwd string `json:"passwd"` +} + +type LoginResp struct { + UserInfo + ServerInfo ServerInfo `json:"server_info"` + JwtToken string `json:"jwt_token"` +} + +type User struct { + Chain Chain `mir:"-"` + Group Group `mir:"r/v1"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Logout func(Post) `mir:"/user/logout/"` +} diff --git a/internal/servants/admin/admin.go b/internal/servants/admin/admin.go new file mode 100644 index 00000000..3fa2a7cf --- /dev/null +++ b/internal/servants/admin/admin.go @@ -0,0 +1,15 @@ +// 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 admin + +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/m/v1" +) + +// RouteWeb register Manager route +func RouteManager(e *gin.Engine) { + api.RegisterUserServant(e, newUserSrv(), newUserBinding(), newUserRender()) +} diff --git a/internal/servants/admin/user.go b/internal/servants/admin/user.go new file mode 100644 index 00000000..6c3f11ab --- /dev/null +++ b/internal/servants/admin/user.go @@ -0,0 +1,51 @@ +// 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 admin + +import ( + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/m/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" +) + +var ( + _ api.User = (*userSrv)(nil) + _ api.UserBinding = (*userBinding)(nil) + _ api.UserRender = (*userRender)(nil) +) + +type userSrv struct { + base.BaseServant + api.UnimplementedUserServant +} + +type userBinding struct { + base.BaseBinding + *api.UnimplementedUserBinding +} + +type userRender struct { + base.BaseRender + *api.UnimplementedUserRender +} + +func newUserSrv() api.User { + return &userSrv{} +} + +func newUserBinding() api.UserBinding { + return &userBinding{ + UnimplementedUserBinding: &api.UnimplementedUserBinding{ + BindAny: base.BindAny, + }, + } +} + +func newUserRender() api.UserRender { + return &userRender{ + UnimplementedUserRender: &api.UnimplementedUserRender{ + RenderAny: base.RenderAny, + }, + } +} diff --git a/internal/servants/bot/bot.go b/internal/servants/bot/bot.go new file mode 100644 index 00000000..6ddd6846 --- /dev/null +++ b/internal/servants/bot/bot.go @@ -0,0 +1,15 @@ +// 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 bot + +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/r/v1" +) + +// RouteBot register Bot route +func RouteBot(e *gin.Engine) { + api.RegisterUserServant(e, newUserSrv(), newUserBinding(), newUserRender()) +} diff --git a/internal/servants/bot/user.go b/internal/servants/bot/user.go new file mode 100644 index 00000000..9f17a6e8 --- /dev/null +++ b/internal/servants/bot/user.go @@ -0,0 +1,51 @@ +// 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 bot + +import ( + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/r/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" +) + +var ( + _ api.User = (*userSrv)(nil) + _ api.UserBinding = (*userBinding)(nil) + _ api.UserRender = (*userRender)(nil) +) + +type userSrv struct { + base.BaseServant + api.UnimplementedUserServant +} + +type userBinding struct { + base.BaseBinding + *api.UnimplementedUserBinding +} + +type userRender struct { + base.BaseRender + *api.UnimplementedUserRender +} + +func newUserSrv() api.User { + return &userSrv{} +} + +func newUserBinding() api.UserBinding { + return &userBinding{ + UnimplementedUserBinding: &api.UnimplementedUserBinding{ + BindAny: base.BindAny, + }, + } +} + +func newUserRender() api.UserRender { + return &userRender{ + UnimplementedUserRender: &api.UnimplementedUserRender{ + RenderAny: base.RenderAny, + }, + } +} diff --git a/internal/servants/localoss/localoss.go b/internal/servants/localoss/localoss.go index 828b3be2..721f0407 100644 --- a/internal/servants/localoss/localoss.go +++ b/internal/servants/localoss/localoss.go @@ -9,13 +9,10 @@ import ( "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/s/v1" "github.com/sirupsen/logrus" ) -type localossSrv struct { - // TODO -} - // RouteLocalOSS register LocalOSS route if needed func RouteLocalOSS(e *gin.Engine) { savePath, err := filepath.Abs(conf.LocalOSSSetting.SavePath) @@ -26,3 +23,8 @@ func RouteLocalOSS(e *gin.Engine) { logrus.Infof("register LocalOSS route in /oss on save path: %s", savePath) } + +// RouteLocaloss register LocalOSS route if needed +func RouteLocaloss(e *gin.Engine) { + api.RegisterUserServant(e, newUserSrv(), newUserBinding(), newUserRender()) +} diff --git a/internal/servants/localoss/user.go b/internal/servants/localoss/user.go new file mode 100644 index 00000000..b8d2309a --- /dev/null +++ b/internal/servants/localoss/user.go @@ -0,0 +1,51 @@ +// 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 localoss + +import ( + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/s/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" +) + +var ( + _ api.User = (*userSrv)(nil) + _ api.UserBinding = (*userBinding)(nil) + _ api.UserRender = (*userRender)(nil) +) + +type userSrv struct { + base.BaseServant + api.UnimplementedUserServant +} + +type userBinding struct { + base.BaseBinding + *api.UnimplementedUserBinding +} + +type userRender struct { + base.BaseRender + *api.UnimplementedUserRender +} + +func newUserSrv() api.User { + return &userSrv{} +} + +func newUserBinding() api.UserBinding { + return &userBinding{ + UnimplementedUserBinding: &api.UnimplementedUserBinding{ + BindAny: base.BindAny, + }, + } +} + +func newUserRender() api.UserRender { + return &userRender{ + UnimplementedUserRender: &api.UnimplementedUserRender{ + RenderAny: base.RenderAny, + }, + } +} diff --git a/internal/servants/servants.go b/internal/servants/servants.go index 9ae3d0a7..496a60c1 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -6,8 +6,11 @@ package servants import ( "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/servants/admin" + "github.com/rocboss/paopao-ce/internal/servants/bot" "github.com/rocboss/paopao-ce/internal/servants/docs" "github.com/rocboss/paopao-ce/internal/servants/localoss" + "github.com/rocboss/paopao-ce/internal/servants/space" "github.com/rocboss/paopao-ce/internal/servants/statick" "github.com/rocboss/paopao-ce/internal/servants/web" "github.com/rocboss/paopao-ce/pkg/cfg" @@ -24,3 +27,23 @@ func RegisterWebServants(e *gin.Engine) { web.RouteWeb(e) } + +// RegisterAdminServants register all the servants to gin.Engine +func RegisterAdminServants(e *gin.Engine) { + admin.RouteManager(e) +} + +// RegisterSpaceXServants register all the servants to gin.Engine +func RegisterSpaceXServants(e *gin.Engine) { + space.RouteSpaceX(e) +} + +// RegisterBotServants register all the servants to gin.Engine +func RegisterBotServants(e *gin.Engine) { + bot.RouteBot(e) +} + +// RegisterLocalossServants register all the servants to gin.Engine +func RegisterLocalossServants(e *gin.Engine) { + localoss.RouteLocaloss(e) +} diff --git a/internal/servants/space/space.go b/internal/servants/space/space.go new file mode 100644 index 00000000..311f76b0 --- /dev/null +++ b/internal/servants/space/space.go @@ -0,0 +1,15 @@ +// 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 space + +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/x/v1" +) + +// RouteWeb register SpaceX route +func RouteSpaceX(e *gin.Engine) { + api.RegisterUserServant(e, newUserSrv(), newUserBinding(), newUserRender()) +} diff --git a/internal/servants/space/user.go b/internal/servants/space/user.go new file mode 100644 index 00000000..2e6014a0 --- /dev/null +++ b/internal/servants/space/user.go @@ -0,0 +1,51 @@ +// 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 space + +import ( + api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/x/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" +) + +var ( + _ api.User = (*userSrv)(nil) + _ api.UserBinding = (*userBinding)(nil) + _ api.UserRender = (*userRender)(nil) +) + +type userSrv struct { + base.BaseServant + api.UnimplementedUserServant +} + +type userBinding struct { + base.BaseBinding + *api.UnimplementedUserBinding +} + +type userRender struct { + base.BaseRender + *api.UnimplementedUserRender +} + +func newUserSrv() api.User { + return &userSrv{} +} + +func newUserBinding() api.UserBinding { + return &userBinding{ + UnimplementedUserBinding: &api.UnimplementedUserBinding{ + BindAny: base.BindAny, + }, + } +} + +func newUserRender() api.UserRender { + return &userRender{ + UnimplementedUserRender: &api.UnimplementedUserRender{ + RenderAny: base.RenderAny, + }, + } +} diff --git a/internal/service/admin.go b/internal/service/admin.go new file mode 100644 index 00000000..ad965e80 --- /dev/null +++ b/internal/service/admin.go @@ -0,0 +1,86 @@ +// 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 service + +import ( + "fmt" + "net/http" + + "github.com/fatih/color" + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" +) + +type adminService struct { + *baseHttpService +} + +func (s *adminService) Name() string { + return "AdminService" +} + +func (s *adminService) Init() error { + s.registerRoute(servants.RegisterAdminServants) + return nil +} + +func (s *adminService) String() string { + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.AdminServerSetting.HttpIp, conf.AdminServerSetting.HttpPort)) +} + +func newAdminEngine() *gin.Engine { + e := gin.New() + e.HandleMethodNotAllowed = true + e.Use(gin.Logger()) + e.Use(gin.Recovery()) + + // 跨域配置 + corsConfig := cors.DefaultConfig() + corsConfig.AllowAllOrigins = true + corsConfig.AddAllowHeaders("Authorization") + e.Use(cors.New(corsConfig)) + + // 默认404 + e.NoRoute(func(c *gin.Context) { + c.JSON(http.StatusNotFound, gin.H{ + "code": 404, + "msg": "Not Found", + }) + }) + + // 默认405 + e.NoMethod(func(c *gin.Context) { + c.JSON(http.StatusMethodNotAllowed, gin.H{ + "code": 405, + "msg": "Method Not Allowed", + }) + }) + + return e +} + +func newAdminService() Service { + addr := conf.AdminServerSetting.HttpIp + ":" + conf.AdminServerSetting.HttpPort + server := httpServerFrom(addr, func() *httpServer { + engine := newAdminEngine() + return &httpServer{ + e: engine, + server: &http.Server{ + Addr: addr, + Handler: engine, + ReadTimeout: conf.AdminServerSetting.ReadTimeout, + WriteTimeout: conf.AdminServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } + }) + return &adminService{ + baseHttpService: &baseHttpService{ + server: server, + }, + } +} diff --git a/internal/service/bot.go b/internal/service/bot.go new file mode 100644 index 00000000..b9c66793 --- /dev/null +++ b/internal/service/bot.go @@ -0,0 +1,86 @@ +// 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 service + +import ( + "fmt" + "net/http" + + "github.com/fatih/color" + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" +) + +type botService struct { + *baseHttpService +} + +func (s *botService) Name() string { + return "BotService" +} + +func (s *botService) Init() error { + s.registerRoute(servants.RegisterBotServants) + return nil +} + +func (s *botService) String() string { + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.BotServerSetting.HttpIp, conf.BotServerSetting.HttpPort)) +} + +func newBotEngine() *gin.Engine { + e := gin.New() + e.HandleMethodNotAllowed = true + e.Use(gin.Logger()) + e.Use(gin.Recovery()) + + // 跨域配置 + corsConfig := cors.DefaultConfig() + corsConfig.AllowAllOrigins = true + corsConfig.AddAllowHeaders("Authorization") + e.Use(cors.New(corsConfig)) + + // 默认404 + e.NoRoute(func(c *gin.Context) { + c.JSON(http.StatusNotFound, gin.H{ + "code": 404, + "msg": "Not Found", + }) + }) + + // 默认405 + e.NoMethod(func(c *gin.Context) { + c.JSON(http.StatusMethodNotAllowed, gin.H{ + "code": 405, + "msg": "Method Not Allowed", + }) + }) + + return e +} + +func newBotService() Service { + addr := conf.BotServerSetting.HttpIp + ":" + conf.BotServerSetting.HttpPort + server := httpServerFrom(addr, func() *httpServer { + engine := newBotEngine() + return &httpServer{ + e: engine, + server: &http.Server{ + Addr: addr, + Handler: engine, + ReadTimeout: conf.BotServerSetting.ReadTimeout, + WriteTimeout: conf.BotServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } + }) + return &botService{ + baseHttpService: &baseHttpService{ + server: server, + }, + } +} diff --git a/internal/service/localoss.go b/internal/service/localoss.go new file mode 100644 index 00000000..18dd79f9 --- /dev/null +++ b/internal/service/localoss.go @@ -0,0 +1,61 @@ +// 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 service + +import ( + "fmt" + "net/http" + + "github.com/fatih/color" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" +) + +type localossService struct { + *baseHttpService +} + +func (s *localossService) Name() string { + return "LocalossService" +} + +func (s *localossService) Init() error { + s.registerRoute(servants.RegisterLocalossServants) + return nil +} + +func (s *localossService) String() string { + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.LocalossServerSetting.HttpIp, conf.LocalossServerSetting.HttpPort)) +} + +func newLocalossEngine() *gin.Engine { + e := gin.New() + e.Use(gin.Logger()) + e.Use(gin.Recovery()) + return e +} + +func newLocalossService() Service { + addr := conf.LocalossServerSetting.HttpIp + ":" + conf.LocalossServerSetting.HttpPort + server := httpServerFrom(addr, func() *httpServer { + engine := newLocalossEngine() + return &httpServer{ + e: engine, + server: &http.Server{ + Addr: addr, + Handler: engine, + ReadTimeout: conf.LocalossServerSetting.ReadTimeout, + WriteTimeout: conf.LocalossServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } + }) + return &localossService{ + baseHttpService: &baseHttpService{ + server: server, + }, + } +} diff --git a/internal/service/service.go b/internal/service/service.go index a69c8c91..549ae2f1 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -46,5 +46,20 @@ func newService() (ss []Service) { ss = append(ss, newOldWebService()) }) + cfg.In(cfg.Actions{ + "Admin": func() { + ss = append(ss, newAdminService()) + }, + "SpaceX": func() { + ss = append(ss, newSpaceXService()) + }, + "Bot": func() { + ss = append(ss, newBotService()) + }, + "LocalOSS": func() { + ss = append(ss, newLocalossService()) + }, + }) + return } diff --git a/internal/service/space.go b/internal/service/space.go new file mode 100644 index 00000000..3866c5ac --- /dev/null +++ b/internal/service/space.go @@ -0,0 +1,86 @@ +// 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 service + +import ( + "fmt" + "net/http" + + "github.com/fatih/color" + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" +) + +type spaceXService struct { + *baseHttpService +} + +func (s *spaceXService) Name() string { + return "WebService" +} + +func (s *spaceXService) Init() error { + s.registerRoute(servants.RegisterSpaceXServants) + return nil +} + +func (s *spaceXService) String() string { + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.SpaceXServerSetting.HttpIp, conf.SpaceXServerSetting.HttpPort)) +} + +func newSpaceXEngine() *gin.Engine { + e := gin.New() + e.HandleMethodNotAllowed = true + e.Use(gin.Logger()) + e.Use(gin.Recovery()) + + // 跨域配置 + corsConfig := cors.DefaultConfig() + corsConfig.AllowAllOrigins = true + corsConfig.AddAllowHeaders("Authorization") + e.Use(cors.New(corsConfig)) + + // 默认404 + e.NoRoute(func(c *gin.Context) { + c.JSON(http.StatusNotFound, gin.H{ + "code": 404, + "msg": "Not Found", + }) + }) + + // 默认405 + e.NoMethod(func(c *gin.Context) { + c.JSON(http.StatusMethodNotAllowed, gin.H{ + "code": 405, + "msg": "Method Not Allowed", + }) + }) + + return e +} + +func newSpaceXService() Service { + addr := conf.SpaceXServerSetting.HttpIp + ":" + conf.SpaceXServerSetting.HttpPort + server := httpServerFrom(addr, func() *httpServer { + engine := newSpaceXEngine() + return &httpServer{ + e: engine, + server: &http.Server{ + Addr: addr, + Handler: engine, + ReadTimeout: conf.SpaceXServerSetting.ReadTimeout, + WriteTimeout: conf.SpaceXServerSetting.WriteTimeout, + MaxHeaderBytes: 1 << 20, + }, + } + }) + return &spaceXService{ + baseHttpService: &baseHttpService{ + server: server, + }, + } +} From 0adfeee6aae51d6a960239e10b8888f347dc9d70 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 10 Dec 2022 16:16:28 +0800 Subject: [PATCH 20/65] mir: update mirc/README.md --- internal/mirc/auto/api/v1/web_core.go | 2 +- internal/mirc/main.go | 8 ++++---- internal/mirc/routes/README.md | 12 +++++++----- internal/mirc/routes/{m => admin}/README.md | 0 internal/mirc/routes/{m => admin}/v1/user.go | 0 internal/mirc/routes/{r => bot}/README.md | 0 internal/mirc/routes/{r => bot}/v1/user.go | 0 internal/mirc/routes/{s => localoss}/README.md | 0 internal/mirc/routes/{s => localoss}/v1/user.go | 0 internal/mirc/routes/{x => space}/README.md | 0 internal/mirc/routes/{x => space}/v1/user.go | 0 11 files changed, 12 insertions(+), 10 deletions(-) rename internal/mirc/routes/{m => admin}/README.md (100%) rename internal/mirc/routes/{m => admin}/v1/user.go (100%) rename internal/mirc/routes/{r => bot}/README.md (100%) rename internal/mirc/routes/{r => bot}/v1/user.go (100%) rename internal/mirc/routes/{s => localoss}/README.md (100%) rename internal/mirc/routes/{s => localoss}/v1/user.go (100%) rename internal/mirc/routes/{x => space}/README.md (100%) rename internal/mirc/routes/{x => space}/v1/user.go (100%) diff --git a/internal/mirc/auto/api/v1/web_core.go b/internal/mirc/auto/api/v1/web_core.go index 6f1efce6..3e7d3d65 100644 --- a/internal/mirc/auto/api/v1/web_core.go +++ b/internal/mirc/auto/api/v1/web_core.go @@ -86,8 +86,8 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor h := func(c *gin.Context) { r.RenderArticles(c, s.Articles(c)) } - router.Handle("GET", "/articles/:category/", h) router.Handle("HEAD", "/articles/:category/", h) + router.Handle("GET", "/articles/:category/", h) } router.Handle("GET", "/index/", func(c *gin.Context) { diff --git a/internal/mirc/main.go b/internal/mirc/main.go index 34120f36..6213d798 100644 --- a/internal/mirc/main.go +++ b/internal/mirc/main.go @@ -10,11 +10,11 @@ import ( . "github.com/alimy/mir/v3/core" . "github.com/alimy/mir/v3/engine" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/m/v1" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/r/v1" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/s/v1" + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/admin/v1" + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/bot/v1" + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/localoss/v1" + _ "github.com/rocboss/paopao-ce/internal/mirc/routes/space/v1" _ "github.com/rocboss/paopao-ce/internal/mirc/routes/v1" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/x/v1" ) //go:generate go run main.go diff --git a/internal/mirc/routes/README.md b/internal/mirc/routes/README.md index d7d0b9fb..c592aa65 100644 --- a/internal/mirc/routes/README.md +++ b/internal/mirc/routes/README.md @@ -1,8 +1,10 @@ ### RESTful API for paopao-ce 本目录包含所有RESTful API相关定义文件 -* v1 - Web系列 v1版本 相关RESTful API相关定义文件 -* m - Admin后台运维系列相关RESTful API相关定义文件 -* x - SpaceX系列相关RESTful API相关定义文件 -* s - LocalOSS OBS系列RESTful API相关定义文件 -* r - Bot系列相关RESTful API相关定义文件 +|目录|系列API|备注| +| ----- | ----- | ----- | +|v1|/|Web v1版本RESTful API相关定义文件| +|admin|m|Admin后台运维系列相关RESTful API相关定义文件| +|space|x|SpaceX系列相关RESTful API相关定义文件| +|localoss|s| LocalOSS OBS系列RESTful API相关定义文件| +|bot|r| Bot系列相关RESTful API相关定义文件| diff --git a/internal/mirc/routes/m/README.md b/internal/mirc/routes/admin/README.md similarity index 100% rename from internal/mirc/routes/m/README.md rename to internal/mirc/routes/admin/README.md diff --git a/internal/mirc/routes/m/v1/user.go b/internal/mirc/routes/admin/v1/user.go similarity index 100% rename from internal/mirc/routes/m/v1/user.go rename to internal/mirc/routes/admin/v1/user.go diff --git a/internal/mirc/routes/r/README.md b/internal/mirc/routes/bot/README.md similarity index 100% rename from internal/mirc/routes/r/README.md rename to internal/mirc/routes/bot/README.md diff --git a/internal/mirc/routes/r/v1/user.go b/internal/mirc/routes/bot/v1/user.go similarity index 100% rename from internal/mirc/routes/r/v1/user.go rename to internal/mirc/routes/bot/v1/user.go diff --git a/internal/mirc/routes/s/README.md b/internal/mirc/routes/localoss/README.md similarity index 100% rename from internal/mirc/routes/s/README.md rename to internal/mirc/routes/localoss/README.md diff --git a/internal/mirc/routes/s/v1/user.go b/internal/mirc/routes/localoss/v1/user.go similarity index 100% rename from internal/mirc/routes/s/v1/user.go rename to internal/mirc/routes/localoss/v1/user.go diff --git a/internal/mirc/routes/x/README.md b/internal/mirc/routes/space/README.md similarity index 100% rename from internal/mirc/routes/x/README.md rename to internal/mirc/routes/space/README.md diff --git a/internal/mirc/routes/x/v1/user.go b/internal/mirc/routes/space/v1/user.go similarity index 100% rename from internal/mirc/routes/x/v1/user.go rename to internal/mirc/routes/space/v1/user.go From 9e1d09a55dfbad1a95d5b7b79e0379505bfe81bd Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sun, 11 Dec 2022 11:27:53 +0800 Subject: [PATCH 21/65] use github.com/alimy/cfg as features configure help library --- go.mod | 1 + go.sum | 2 + internal/conf/conf.go | 4 +- internal/conf/db.go | 2 +- internal/conf/logger.go | 2 +- internal/dao/dao.go | 2 +- internal/dao/jinzhu/jinzhu.go | 2 +- internal/dao/storage/storage.go | 2 +- internal/migration/migration.go | 2 +- internal/migration/migration_embed.go | 2 +- internal/servants/chain/priv.go | 2 +- internal/servants/docs/docs_embed.go | 2 +- internal/servants/servants.go | 2 +- internal/servants/web/broker/broker.go | 2 +- internal/servants/web/routers/api/api.go | 2 +- internal/servants/web/routers/docs_embed.go | 2 +- internal/servants/web/routers/router.go | 2 +- internal/service/service.go | 2 +- pkg/cfg/cfg.go | 45 ------ pkg/cfg/cfg_test.go | 82 ----------- pkg/cfg/feature.go | 153 -------------------- pkg/cfg/feature_test.go | 118 --------------- 22 files changed, 20 insertions(+), 415 deletions(-) delete mode 100644 pkg/cfg/cfg.go delete mode 100644 pkg/cfg/cfg_test.go delete mode 100644 pkg/cfg/feature.go delete mode 100644 pkg/cfg/feature_test.go diff --git a/go.mod b/go.mod index fa9ff517..3ab5270f 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 + github.com/alimy/cfg v0.1.0 github.com/alimy/mir/v3 v3.0.0-alpha.4 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 diff --git a/go.sum b/go.sum index bfe083a0..eed23c9b 100644 --- a/go.sum +++ b/go.sum @@ -142,6 +142,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= +github.com/alimy/cfg v0.1.0 h1:J7KDLEoVIjEBMGlQJb2ljad/d49gJ4Tsl2ogZ9XNhaY= +github.com/alimy/cfg v0.1.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= github.com/alimy/mir/v3 v3.0.0-alpha.4 h1:tSmyyhgutMHjgx9TO9891ZCY4qbr3g8FGar4z+9Hhq4= github.com/alimy/mir/v3 v3.0.0-alpha.4/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 75d363e7..bdadf5e4 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -9,7 +9,7 @@ import ( "sync" "time" - "github.com/rocboss/paopao-ce/pkg/cfg" + "github.com/alimy/cfg" ) var ( @@ -58,7 +58,7 @@ func setupSetting(suite []string, noDefault bool) error { // initialize features configure ss, kv := setting.featuresInfoFrom("Features") - cfg.Initialize(ss, kv) + cfg.Initial(ss, kv) if len(suite) > 0 { cfg.Use(suite, noDefault) } diff --git a/internal/conf/db.go b/internal/conf/db.go index 7f859152..62ad7fe3 100644 --- a/internal/conf/db.go +++ b/internal/conf/db.go @@ -8,8 +8,8 @@ import ( "sync" "time" + "github.com/alimy/cfg" "github.com/go-redis/redis/v8" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/sirupsen/logrus" "gorm.io/driver/mysql" "gorm.io/driver/postgres" diff --git a/internal/conf/logger.go b/internal/conf/logger.go index b514b375..cbe3cc1b 100644 --- a/internal/conf/logger.go +++ b/internal/conf/logger.go @@ -7,7 +7,7 @@ package conf import ( "io" - "github.com/rocboss/paopao-ce/pkg/cfg" + "github.com/alimy/cfg" "github.com/sirupsen/logrus" "gopkg.in/natefinch/lumberjack.v2" ) diff --git a/internal/dao/dao.go b/internal/dao/dao.go index e4b2ea6a..d0b05c9c 100644 --- a/internal/dao/dao.go +++ b/internal/dao/dao.go @@ -7,13 +7,13 @@ package dao import ( "sync" + "github.com/alimy/cfg" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/dao/jinzhu" "github.com/rocboss/paopao-ce/internal/dao/sakila" "github.com/rocboss/paopao-ce/internal/dao/search" "github.com/rocboss/paopao-ce/internal/dao/slonik" "github.com/rocboss/paopao-ce/internal/dao/storage" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/sirupsen/logrus" ) diff --git a/internal/dao/jinzhu/jinzhu.go b/internal/dao/jinzhu/jinzhu.go index 753bb639..dd20aeea 100644 --- a/internal/dao/jinzhu/jinzhu.go +++ b/internal/dao/jinzhu/jinzhu.go @@ -10,11 +10,11 @@ package jinzhu import ( "github.com/Masterminds/semver/v3" + "github.com/alimy/cfg" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/dao/cache" "github.com/rocboss/paopao-ce/internal/dao/security" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/sirupsen/logrus" ) diff --git a/internal/dao/storage/storage.go b/internal/dao/storage/storage.go index fff9d13f..0f03fa20 100644 --- a/internal/dao/storage/storage.go +++ b/internal/dao/storage/storage.go @@ -12,13 +12,13 @@ import ( "strconv" "time" + "github.com/alimy/cfg" "github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/sirupsen/logrus" "github.com/tencentyun/cos-go-sdk-v5" ) diff --git a/internal/migration/migration.go b/internal/migration/migration.go index 7437e996..1cac6012 100644 --- a/internal/migration/migration.go +++ b/internal/migration/migration.go @@ -8,7 +8,7 @@ package migration import ( - "github.com/rocboss/paopao-ce/pkg/cfg" + "github.com/alimy/cfg" "github.com/sirupsen/logrus" ) diff --git a/internal/migration/migration_embed.go b/internal/migration/migration_embed.go index 976b4f26..02ede293 100644 --- a/internal/migration/migration_embed.go +++ b/internal/migration/migration_embed.go @@ -10,6 +10,7 @@ package migration import ( "database/sql" + "github.com/alimy/cfg" "github.com/golang-migrate/migrate/v4" "github.com/golang-migrate/migrate/v4/database" "github.com/golang-migrate/migrate/v4/database/mysql" @@ -18,7 +19,6 @@ import ( "github.com/golang-migrate/migrate/v4/source" "github.com/golang-migrate/migrate/v4/source/iofs" "github.com/rocboss/paopao-ce/internal/conf" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/rocboss/paopao-ce/scripts/migration" "github.com/sirupsen/logrus" ) diff --git a/internal/servants/chain/priv.go b/internal/servants/chain/priv.go index f03c14b7..6c09d0a8 100644 --- a/internal/servants/chain/priv.go +++ b/internal/servants/chain/priv.go @@ -5,10 +5,10 @@ package chain import ( + "github.com/alimy/cfg" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/pkg/app" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/rocboss/paopao-ce/pkg/errcode" ) diff --git a/internal/servants/docs/docs_embed.go b/internal/servants/docs/docs_embed.go index 653e1c07..8879896c 100644 --- a/internal/servants/docs/docs_embed.go +++ b/internal/servants/docs/docs_embed.go @@ -8,9 +8,9 @@ package docs import ( + "github.com/alimy/cfg" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/docs/openapi" - "github.com/rocboss/paopao-ce/pkg/cfg" ) // RegisterDocs register docs asset route diff --git a/internal/servants/servants.go b/internal/servants/servants.go index 496a60c1..dd03b1de 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -5,6 +5,7 @@ package servants import ( + "github.com/alimy/cfg" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/servants/admin" "github.com/rocboss/paopao-ce/internal/servants/bot" @@ -13,7 +14,6 @@ import ( "github.com/rocboss/paopao-ce/internal/servants/space" "github.com/rocboss/paopao-ce/internal/servants/statick" "github.com/rocboss/paopao-ce/internal/servants/web" - "github.com/rocboss/paopao-ce/pkg/cfg" ) // RegisterWebServants register all the servants to gin.Engine diff --git a/internal/servants/web/broker/broker.go b/internal/servants/web/broker/broker.go index 79423901..fcc5846d 100644 --- a/internal/servants/web/broker/broker.go +++ b/internal/servants/web/broker/broker.go @@ -5,9 +5,9 @@ package broker import ( + "github.com/alimy/cfg" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/dao" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/sirupsen/logrus" ) diff --git a/internal/servants/web/routers/api/api.go b/internal/servants/web/routers/api/api.go index 39e748ab..b2e60cb6 100644 --- a/internal/servants/web/routers/api/api.go +++ b/internal/servants/web/routers/api/api.go @@ -5,10 +5,10 @@ package api import ( + "github.com/alimy/cfg" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/dao" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/sirupsen/logrus" "github.com/smartwalle/alipay/v3" ) diff --git a/internal/servants/web/routers/docs_embed.go b/internal/servants/web/routers/docs_embed.go index a636e487..20754e1a 100644 --- a/internal/servants/web/routers/docs_embed.go +++ b/internal/servants/web/routers/docs_embed.go @@ -8,9 +8,9 @@ package routers import ( + "github.com/alimy/cfg" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/docs/openapi" - "github.com/rocboss/paopao-ce/pkg/cfg" ) // registerDocs register docs asset route diff --git a/internal/servants/web/routers/router.go b/internal/servants/web/routers/router.go index e46b533b..80b29be3 100644 --- a/internal/servants/web/routers/router.go +++ b/internal/servants/web/routers/router.go @@ -8,12 +8,12 @@ import ( "net/http" "path/filepath" + "github.com/alimy/cfg" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/servants/chain" "github.com/rocboss/paopao-ce/internal/servants/web/routers/api" - "github.com/rocboss/paopao-ce/pkg/cfg" "github.com/sirupsen/logrus" ) diff --git a/internal/service/service.go b/internal/service/service.go index 549ae2f1..34a04574 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -7,7 +7,7 @@ package service import ( "log" - "github.com/rocboss/paopao-ce/pkg/cfg" + "github.com/alimy/cfg" "github.com/rocboss/paopao-ce/pkg/types" ) diff --git a/pkg/cfg/cfg.go b/pkg/cfg/cfg.go deleted file mode 100644 index f04dc297..00000000 --- a/pkg/cfg/cfg.go +++ /dev/null @@ -1,45 +0,0 @@ -// 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 cfg - -var ( - _features = newEmptyFeatures() - - // Use alias of Features.Use func - Use = _features.Use - - // UseDeafult alias of Features.UseDefault func - UseDefault = _features.UseDefault - - // As alias of Features.Cfg func - As = _features.Cfg - - // If alias of Features.CfgIf func - If = _features.CfgIf - - // In alias of Features.CfgIn func - In = _features.CfgIn - - // Be alias of Feaures.CfgBe func - Be = _features.CfgBe - - // Not alias of Features.CfgNot func - Not = _features.CfgNot -) - -// Initialize initialize features in cfg pkg -func Initialize(suites map[string][]string, kv map[string]string) { - _features = NewFeatures(suites, kv) - { - // must re-assign variable below - Use = _features.Use - UseDefault = _features.UseDefault - As = _features.Cfg - If = _features.CfgIf - In = _features.CfgIn - Be = _features.CfgBe - Not = _features.CfgNot - } -} diff --git a/pkg/cfg/cfg_test.go b/pkg/cfg/cfg_test.go deleted file mode 100644 index 68a3ce74..00000000 --- a/pkg/cfg/cfg_test.go +++ /dev/null @@ -1,82 +0,0 @@ -// 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 cfg - -import ( - "testing" -) - -func TestCfg(t *testing.T) { - suites := map[string][]string{ - "default": {"Sms", "Alipay", "Zinc", "MySQL", "Redis", "AliOSS", "LogZinc"}, - "develop": {"Zinc", "MySQL", "AliOSS", "LogFile"}, - "slim": {"Zinc", "MySQL", "Redis", "AliOSS", "LogFile"}, - } - kv := map[string]string{ - "sms": "SmsJuhe", - } - - Initialize(suites, kv) - UseDefault() - - if !If("Sms") { - t.Error(`want If("Sms") == true but not`) - } - - if v, exist := As("Sms"); exist && v != "SmsJuhe" { - t.Errorf(`want As("Sms") == "SmsJuhe", true but got: "%s", "%t"`, v, exist) - } - - matched := false - Be("Alipay", func() { - matched = true - }) - if !matched { - t.Error(`want Be("Alipay", ...) matched but not`) - } - - matched = false - Not("LogFile", func() { - matched = true - }) - if !matched { - t.Error(`want Not("LogFile", ...) matched but not`) - } - - var m1, m2, m3, m4 bool - In(Actions{ - "Sms": func() { - m1 = true - }, - "Alipay": func() { - m2 = true - }, - "Meili": func() { - m4 = true - }, - }, func() { - m3 = true - }) - if !m1 || !m2 || m3 || m4 { - t.Errorf(`In("Sms", "Alipay", "Meili", ...) not correct -> m1: %t m2:%t m3:%t m4:%t`, m1, m2, m3, m4) - } - - m1 = false - m2 = false - m3 = false - In(Actions{ - "LogFile": func() { - m1 = true - }, - "Meili": func() { - m2 = true - }, - }, func() { - m3 = true - }) - if m1 || m2 || !m3 { - t.Errorf(`In("Zinc", "MySQL", ...) not correct -> m1: %t m2:%t m3:%t`, m1, m2, m3) - } -} diff --git a/pkg/cfg/feature.go b/pkg/cfg/feature.go deleted file mode 100644 index 32810b47..00000000 --- a/pkg/cfg/feature.go +++ /dev/null @@ -1,153 +0,0 @@ -// 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 cfg - -import ( - "strings" - - "github.com/rocboss/paopao-ce/pkg/types" -) - -// Features fetures info struct -type Features struct { - kv map[string]string - suites map[string][]string - features map[string]string -} - -// Actions feature-func map alias type -type Actions map[string]types.Fn - -// NewFeatures create new Features instance -func NewFeatures(suites map[string][]string, kv map[string]string) *Features { - f := newEmptyFeatures() - for k, v := range suites { - if len(k) > 0 { - for i := 0; i < len(v); i++ { - // ignore empty string - if len(v[i]) == 0 { - lastIdx := len(v) - 1 - v[i] = v[lastIdx] - v = v[:lastIdx] - i-- - } - } - if len(v) > 0 { - f.suites[k] = v - } - } - } - for k, v := range kv { - if len(k) > 0 && len(v) > 0 { - f.kv[k] = v - } - } - f.UseDefault() - return f -} - -func newEmptyFeatures() *Features { - return &Features{ - suites: make(map[string][]string), - kv: make(map[string]string), - features: make(map[string]string), - } -} - -// UseDefault use default suite for features -func (f *Features) UseDefault() { - f.Use([]string{"default"}, true) -} - -// Use use custom suite for features -func (f *Features) Use(suite []string, noDefault bool) { - if noDefault && len(f.features) != 0 { - f.features = make(map[string]string) - } - features := f.flatFeatures(suite) - for _, feature := range features { - if len(feature) == 0 { - continue - } - f.features[feature] = f.kv[feature] - } -} - -func (f *Features) flatFeatures(suite []string) []string { - features := make([]string, 0, len(suite)+10) - for s := suite[:]; len(s) > 0; s = s[:len(s)-1] { - item := strings.TrimSpace(strings.ToLower(s[0])) - if len(item) > 0 { - if items, exist := f.suites[item]; exist { - s = append(s, items...) - } - features = append(features, item) - } - s[0] = s[len(s)-1] - } - return features -} - -// Cfg get value by key if exist -func (f *Features) Cfg(key string) (string, bool) { - key = strings.ToLower(key) - value, exist := f.features[key] - return value, exist -} - -// CfgIf check expression is true. if expression just have a string like -// `Sms` is mean `Sms` whether define in suite feature settings. expression like -// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value -// is `SmsJuhe` -func (f *Features) CfgIf(expression string) bool { - kv := strings.Split(expression, "=") - key := strings.Trim(strings.ToLower(kv[0]), " ") - v, ok := f.features[key] - if len(kv) == 2 && ok && strings.Trim(kv[1], " ") == v { - return true - } else if len(kv) == 1 && ok { - return true - } - return false -} - -// CfgIn range actions to check item's expression is true then do the handle, defFn will handle -// if all items are not matched, -func (f *Features) CfgIn(actions Actions, defAct ...types.Fn) { - itemMatched := false - for expression, handle := range actions { - if f.CfgIf(expression) && handle != nil { - handle() - itemMatched = true - } - } - if !itemMatched && len(defAct) > 0 { - for _, handle := range defAct { - if handle != nil { - handle() - } - } - } -} - -// CfgBe check expression is true then do the handle. if expression just have a string like -// `Sms` is mean `Sms` whether defined in suite feature settings. expression like -// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value -// is `SmsJuhe` -func (f *Features) CfgBe(expression string, handle types.Fn) { - if f.CfgIf(expression) && handle != nil { - handle() - } -} - -// CfgNot check expression is not true then do the handle. if expression just have a string like -// `Sms` is mean `Sms` whether defined in suite feature settings. expression like -// `Sms = SmsJuhe` is mean whether `Sms` define in suite feature settings and value -// is `SmsJuhe` -func (f *Features) CfgNot(expression string, handle func()) { - if !f.CfgIf(expression) { - handle() - } -} diff --git a/pkg/cfg/feature_test.go b/pkg/cfg/feature_test.go deleted file mode 100644 index 21c44c72..00000000 --- a/pkg/cfg/feature_test.go +++ /dev/null @@ -1,118 +0,0 @@ -// 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 cfg - -import ( - "testing" -) - -func TestUseDefault(t *testing.T) { - suites := map[string][]string{ - "default": {"Sms", "Alipay", "Zinc", "MySQL", "Redis", "AliOSS", "LogZinc"}, - "develop": {"Zinc", "MySQL", "AliOSS", "LogFile"}, - "slim": {"Zinc", "MySQL", "Redis", "AliOSS", "LogFile"}, - } - kv := map[string]string{ - "sms": "SmsJuhe", - } - f := NewFeatures(suites, kv) - for _, data := range []struct { - key string - expect string - exist bool - }{ - {"Sms", "SmsJuhe", true}, - {"Alipay", "", true}, - {"Zinc", "", true}, - {"Redis", "", true}, - {"Database", "", false}, - } { - if v, ok := f.Cfg(data.key); ok != data.exist || v != data.expect { - t.Errorf("key: %s expect: %s exist: %t got v: %s ok: %t", data.key, data.expect, data.exist, v, ok) - } - } - for exp, res := range map[string]bool{ - "Sms": true, - "Sms = SmsJuhe": true, - "SmsJuhe": false, - "default": true, - } { - if ok := f.CfgIf(exp); res != ok { - t.Errorf("CfgIf(%s) want %t got %t", exp, res, ok) - } - } -} - -func TestUse(t *testing.T) { - suites := map[string][]string{ - "default": {"Sms", "Alipay", "Zinc", "MySQL", "Redis", "AliOSS", "LogZinc"}, - "develop": {"Zinc", "MySQL", "AliOSS", "LogFile"}, - "slim": {"Zinc", "MySQL", "Redis", "AliOSS", "LogFile"}, - } - kv := map[string]string{ - "sms": "SmsJuhe", - } - f := NewFeatures(suites, kv) - - f.Use([]string{"develop"}, true) - for _, data := range []struct { - key string - expect string - exist bool - }{ - {"Sms", "", false}, - {"Alipay", "", false}, - {"Zinc", "", true}, - {"Redis", "", false}, - {"Database", "", false}, - } { - if v, ok := f.Cfg(data.key); ok != data.exist || v != data.expect { - t.Errorf("key: %s expect: %s exist: %t got v: %s ok: %t", data.key, data.expect, data.exist, v, ok) - } - } - for exp, res := range map[string]bool{ - "Sms": false, - "Sms = SmsJuhe": false, - "SmsJuhe": false, - "default": false, - "develop": true, - } { - if ok := f.CfgIf(exp); res != ok { - t.Errorf("CfgIf(%s) want %t got %t", exp, res, ok) - } - } - - f.UseDefault() - f.Use([]string{"slim", "", "demo"}, false) - for _, data := range []struct { - key string - expect string - exist bool - }{ - {"Sms", "SmsJuhe", true}, - {"Alipay", "", true}, - {"Zinc", "", true}, - {"Redis", "", true}, - {"Database", "", false}, - {"demo", "", true}, - } { - if v, ok := f.Cfg(data.key); ok != data.exist || v != data.expect { - t.Errorf("key: %s expect: %s exist: %t got v: %s ok: %t", data.key, data.expect, data.exist, v, ok) - } - } - for exp, res := range map[string]bool{ - "Sms": true, - "Sms = SmsJuhe": true, - "SmsJuhe": false, - "default": true, - "develop": false, - "slim": true, - "demo": true, - } { - if ok := f.CfgIf(exp); res != ok { - t.Errorf("CfgIf(%s) want %t got %t", exp, res, ok) - } - } -} From 4d379e278a7b6921378e467a339059b170f094ab Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 13 Dec 2022 12:19:12 +0800 Subject: [PATCH 22/65] upgrade github.com/alimy/mir/v3 => v3.0.0-alpha.5 --- go.mod | 2 +- go.sum | 4 ++-- internal/mirc/auto/api/m/v1/user.go | 18 +++++++------- internal/mirc/auto/api/r/v1/user.go | 18 +++++++------- internal/mirc/auto/api/s/v1/user.go | 26 ++++++++++---------- internal/mirc/auto/api/v1/web_core.go | 34 +++++++++++++-------------- internal/mirc/auto/api/x/v1/user.go | 18 +++++++------- 7 files changed, 60 insertions(+), 60 deletions(-) diff --git a/go.mod b/go.mod index 3ab5270f..e826578e 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/cfg v0.1.0 - github.com/alimy/mir/v3 v3.0.0-alpha.4 + github.com/alimy/mir/v3 v3.0.0-alpha.5 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index eed23c9b..df94f30e 100644 --- a/go.sum +++ b/go.sum @@ -144,8 +144,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.1.0 h1:J7KDLEoVIjEBMGlQJb2ljad/d49gJ4Tsl2ogZ9XNhaY= github.com/alimy/cfg v0.1.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= -github.com/alimy/mir/v3 v3.0.0-alpha.4 h1:tSmyyhgutMHjgx9TO9891ZCY4qbr3g8FGar4z+9Hhq4= -github.com/alimy/mir/v3 v3.0.0-alpha.4/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= +github.com/alimy/mir/v3 v3.0.0-alpha.5 h1:KFv8ulmC1hDPDezh/dQ+ZwZwmmwrcWUV4TZJrMBZB8I= +github.com/alimy/mir/v3 v3.0.0-alpha.5/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/mirc/auto/api/m/v1/user.go b/internal/mirc/auto/api/m/v1/user.go index c087ae87..b31984b9 100644 --- a/internal/mirc/auto/api/m/v1/user.go +++ b/internal/mirc/auto/api/m/v1/user.go @@ -38,21 +38,21 @@ type User interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - Logout(c *gin.Context) mir.Error - Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) mustEmbedUnimplementedUserServant() } type UserBinding interface { - BindLogin(c *gin.Context) (*LoginReq, mir.Error) + BindLogin(*gin.Context) (*LoginReq, mir.Error) mustEmbedUnimplementedUserBinding() } type UserRender interface { - RenderLogout(c *gin.Context, err mir.Error) - RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + RenderLogout(*gin.Context, mir.Error) + RenderLogin(*gin.Context, *LoginResp, mir.Error) mustEmbedUnimplementedUserRender() } @@ -66,7 +66,7 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { - r.RenderLogout(c, s.Logout(c)) + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { @@ -74,7 +74,7 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { if err != nil { r.RenderLogin(c, nil, err) } - resp, err := s.Login(c, req) + resp, err := s.Login(req) r.RenderLogin(c, resp, err) }) @@ -88,11 +88,11 @@ func (UnimplementedUserServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { +func (UnimplementedUserServant) Logout() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { +func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/internal/mirc/auto/api/r/v1/user.go b/internal/mirc/auto/api/r/v1/user.go index ae9dd9cd..55961d75 100644 --- a/internal/mirc/auto/api/r/v1/user.go +++ b/internal/mirc/auto/api/r/v1/user.go @@ -38,21 +38,21 @@ type User interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - Logout(c *gin.Context) mir.Error - Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) mustEmbedUnimplementedUserServant() } type UserBinding interface { - BindLogin(c *gin.Context) (*LoginReq, mir.Error) + BindLogin(*gin.Context) (*LoginReq, mir.Error) mustEmbedUnimplementedUserBinding() } type UserRender interface { - RenderLogout(c *gin.Context, err mir.Error) - RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + RenderLogout(*gin.Context, mir.Error) + RenderLogin(*gin.Context, *LoginResp, mir.Error) mustEmbedUnimplementedUserRender() } @@ -66,7 +66,7 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { - r.RenderLogout(c, s.Logout(c)) + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { @@ -74,7 +74,7 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { if err != nil { r.RenderLogin(c, nil, err) } - resp, err := s.Login(c, req) + resp, err := s.Login(req) r.RenderLogin(c, resp, err) }) @@ -88,11 +88,11 @@ func (UnimplementedUserServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { +func (UnimplementedUserServant) Logout() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { +func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/internal/mirc/auto/api/s/v1/user.go b/internal/mirc/auto/api/s/v1/user.go index 4751a141..a14c1e42 100644 --- a/internal/mirc/auto/api/s/v1/user.go +++ b/internal/mirc/auto/api/s/v1/user.go @@ -35,23 +35,23 @@ type UserInfo struct { } type User interface { - Logout(c *gin.Context) mir.Error - Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) - Index(c *gin.Context) mir.Error + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + Index() mir.Error mustEmbedUnimplementedUserServant() } type UserBinding interface { - BindLogin(c *gin.Context) (*LoginReq, mir.Error) + BindLogin(*gin.Context) (*LoginReq, mir.Error) mustEmbedUnimplementedUserBinding() } type UserRender interface { - RenderLogout(c *gin.Context, err mir.Error) - RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) - RenderIndex(c *gin.Context, err mir.Error) + RenderLogout(*gin.Context, mir.Error) + RenderLogin(*gin.Context, *LoginResp, mir.Error) + RenderIndex(*gin.Context, mir.Error) mustEmbedUnimplementedUserRender() } @@ -62,7 +62,7 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { - r.RenderLogout(c, s.Logout(c)) + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { @@ -70,12 +70,12 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { if err != nil { r.RenderLogin(c, nil, err) } - resp, err := s.Login(c, req) + resp, err := s.Login(req) r.RenderLogin(c, resp, err) }) router.Handle("GET", "/index/", func(c *gin.Context) { - r.RenderIndex(c, s.Index(c)) + r.RenderIndex(c, s.Index()) }) } @@ -84,15 +84,15 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { type UnimplementedUserServant struct { } -func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { +func (UnimplementedUserServant) Logout() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { +func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedUserServant) Index(c *gin.Context) mir.Error { +func (UnimplementedUserServant) Index() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/internal/mirc/auto/api/v1/web_core.go b/internal/mirc/auto/api/v1/web_core.go index 3e7d3d65..4f797538 100644 --- a/internal/mirc/auto/api/v1/web_core.go +++ b/internal/mirc/auto/api/v1/web_core.go @@ -38,25 +38,25 @@ type WebCore interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - Logout(c *gin.Context) mir.Error - Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) - Articles(c *gin.Context) mir.Error - Index(c *gin.Context) mir.Error + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) + Articles() mir.Error + Index() mir.Error mustEmbedUnimplementedWebCoreServant() } type WebCoreBinding interface { - BindLogin(c *gin.Context) (*LoginReq, mir.Error) + BindLogin(*gin.Context) (*LoginReq, mir.Error) mustEmbedUnimplementedWebCoreBinding() } type WebCoreRender interface { - RenderLogout(c *gin.Context, err mir.Error) - RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) - RenderArticles(c *gin.Context, err mir.Error) - RenderIndex(c *gin.Context, err mir.Error) + RenderLogout(*gin.Context, mir.Error) + RenderLogin(*gin.Context, *LoginResp, mir.Error) + RenderArticles(*gin.Context, mir.Error) + RenderIndex(*gin.Context, mir.Error) mustEmbedUnimplementedWebCoreRender() } @@ -70,7 +70,7 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { - r.RenderLogout(c, s.Logout(c)) + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { @@ -78,20 +78,20 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor if err != nil { r.RenderLogin(c, nil, err) } - resp, err := s.Login(c, req) + resp, err := s.Login(req) r.RenderLogin(c, resp, err) }) { h := func(c *gin.Context) { - r.RenderArticles(c, s.Articles(c)) + r.RenderArticles(c, s.Articles()) } router.Handle("HEAD", "/articles/:category/", h) router.Handle("GET", "/articles/:category/", h) } router.Handle("GET", "/index/", func(c *gin.Context) { - r.RenderIndex(c, s.Index(c)) + r.RenderIndex(c, s.Index()) }) } @@ -104,19 +104,19 @@ func (UnimplementedWebCoreServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebCoreServant) Logout(c *gin.Context) mir.Error { +func (UnimplementedWebCoreServant) Logout() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { +func (UnimplementedWebCoreServant) Login(req *LoginReq) (*LoginResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Articles(c *gin.Context) mir.Error { +func (UnimplementedWebCoreServant) Articles() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Index(c *gin.Context) mir.Error { +func (UnimplementedWebCoreServant) Index() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } diff --git a/internal/mirc/auto/api/x/v1/user.go b/internal/mirc/auto/api/x/v1/user.go index 66446d03..8b579f67 100644 --- a/internal/mirc/auto/api/x/v1/user.go +++ b/internal/mirc/auto/api/x/v1/user.go @@ -38,21 +38,21 @@ type User interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - Logout(c *gin.Context) mir.Error - Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) + Logout() mir.Error + Login(*LoginReq) (*LoginResp, mir.Error) mustEmbedUnimplementedUserServant() } type UserBinding interface { - BindLogin(c *gin.Context) (*LoginReq, mir.Error) + BindLogin(*gin.Context) (*LoginReq, mir.Error) mustEmbedUnimplementedUserBinding() } type UserRender interface { - RenderLogout(c *gin.Context, err mir.Error) - RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) + RenderLogout(*gin.Context, mir.Error) + RenderLogin(*gin.Context, *LoginResp, mir.Error) mustEmbedUnimplementedUserRender() } @@ -66,7 +66,7 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { - r.RenderLogout(c, s.Logout(c)) + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { @@ -74,7 +74,7 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { if err != nil { r.RenderLogin(c, nil, err) } - resp, err := s.Login(c, req) + resp, err := s.Login(req) r.RenderLogin(c, resp, err) }) @@ -88,11 +88,11 @@ func (UnimplementedUserServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { +func (UnimplementedUserServant) Logout() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { +func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } From 2397eff99d9fc5cf6933c756a559d7db3bb22d87 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 13 Dec 2022 19:51:03 +0800 Subject: [PATCH 23/65] upgrade github.com/alimy/mir/v3 => v3.0.0-alpha.6 --- go.mod | 2 +- go.sum | 4 ++-- internal/mirc/auto/api/m/v1/user.go | 13 +++++++++++++ internal/mirc/auto/api/r/v1/user.go | 13 +++++++++++++ internal/mirc/auto/api/s/v1/user.go | 19 +++++++++++++++++++ internal/mirc/auto/api/v1/web_core.go | 25 +++++++++++++++++++++++++ internal/mirc/auto/api/x/v1/user.go | 13 +++++++++++++ 7 files changed, 86 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e826578e..80d99a7f 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/cfg v0.1.0 - github.com/alimy/mir/v3 v3.0.0-alpha.5 + github.com/alimy/mir/v3 v3.0.0-alpha.6 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index df94f30e..dee0dc5e 100644 --- a/go.sum +++ b/go.sum @@ -144,8 +144,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.1.0 h1:J7KDLEoVIjEBMGlQJb2ljad/d49gJ4Tsl2ogZ9XNhaY= github.com/alimy/cfg v0.1.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= -github.com/alimy/mir/v3 v3.0.0-alpha.5 h1:KFv8ulmC1hDPDezh/dQ+ZwZwmmwrcWUV4TZJrMBZB8I= -github.com/alimy/mir/v3 v3.0.0-alpha.5/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= +github.com/alimy/mir/v3 v3.0.0-alpha.6 h1:4xcyE12MgzTbcIcYtnt3ILrVrxFjI71qhqh0JL2gB58= +github.com/alimy/mir/v3 v3.0.0-alpha.6/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/mirc/auto/api/m/v1/user.go b/internal/mirc/auto/api/m/v1/user.go index b31984b9..431343e7 100644 --- a/internal/mirc/auto/api/m/v1/user.go +++ b/internal/mirc/auto/api/m/v1/user.go @@ -66,13 +66,26 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + req, err := b.BindLogin(c) if err != nil { r.RenderLogin(c, nil, err) + return } resp, err := s.Login(req) r.RenderLogin(c, resp, err) diff --git a/internal/mirc/auto/api/r/v1/user.go b/internal/mirc/auto/api/r/v1/user.go index 55961d75..1850b157 100644 --- a/internal/mirc/auto/api/r/v1/user.go +++ b/internal/mirc/auto/api/r/v1/user.go @@ -66,13 +66,26 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + req, err := b.BindLogin(c) if err != nil { r.RenderLogin(c, nil, err) + return } resp, err := s.Login(req) r.RenderLogin(c, resp, err) diff --git a/internal/mirc/auto/api/s/v1/user.go b/internal/mirc/auto/api/s/v1/user.go index a14c1e42..ef2c855b 100644 --- a/internal/mirc/auto/api/s/v1/user.go +++ b/internal/mirc/auto/api/s/v1/user.go @@ -62,19 +62,38 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + req, err := b.BindLogin(c) if err != nil { r.RenderLogin(c, nil, err) + return } resp, err := s.Login(req) r.RenderLogin(c, resp, err) }) router.Handle("GET", "/index/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderIndex(c, s.Index()) }) diff --git a/internal/mirc/auto/api/v1/web_core.go b/internal/mirc/auto/api/v1/web_core.go index 4f797538..613977fe 100644 --- a/internal/mirc/auto/api/v1/web_core.go +++ b/internal/mirc/auto/api/v1/web_core.go @@ -70,13 +70,26 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + req, err := b.BindLogin(c) if err != nil { r.RenderLogin(c, nil, err) + return } resp, err := s.Login(req) r.RenderLogin(c, resp, err) @@ -84,6 +97,12 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor { h := func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderArticles(c, s.Articles()) } router.Handle("HEAD", "/articles/:category/", h) @@ -91,6 +110,12 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor } router.Handle("GET", "/index/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderIndex(c, s.Index()) }) diff --git a/internal/mirc/auto/api/x/v1/user.go b/internal/mirc/auto/api/x/v1/user.go index 8b579f67..89a3b086 100644 --- a/internal/mirc/auto/api/x/v1/user.go +++ b/internal/mirc/auto/api/x/v1/user.go @@ -66,13 +66,26 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) { // register routes info to router router.Handle("POST", "/user/logout/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + r.RenderLogout(c, s.Logout()) }) router.Handle("POST", "/user/login/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + req, err := b.BindLogin(c) if err != nil { r.RenderLogin(c, nil, err) + return } resp, err := s.Login(req) r.RenderLogin(c, resp, err) From 39d91086e2203a3a7ebe62c4a8e15777084168d6 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Wed, 14 Dec 2022 10:47:49 +0800 Subject: [PATCH 24/65] add discuss documents --- docs/README.md | 1 + docs/discuss/0000-讨论样式模版.md | 26 +++++++++++++++++++++++++ docs/discuss/0001-FAQs.md | 17 ++++++++++++++++ docs/discuss/README.md | 5 +++++ 4 files changed, 49 insertions(+) create mode 100644 docs/discuss/0000-讨论样式模版.md create mode 100644 docs/discuss/0001-FAQs.md create mode 100644 docs/discuss/README.md diff --git a/docs/README.md b/docs/README.md index d2c7b192..fda64147 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,3 +4,4 @@ * [openapi](openapi): api相关文档 * [proposal](proposal): 开发/设计 提按相关文档 * [deploy](deploy): 部署相关文档 +* [discuss](discuss): 开发者交流 diff --git a/docs/discuss/0000-讨论样式模版.md b/docs/discuss/0000-讨论样式模版.md new file mode 100644 index 00000000..a7e50871 --- /dev/null +++ b/docs/discuss/0000-讨论样式模版.md @@ -0,0 +1,26 @@ +### <主题标题> +====== <这里写主题描述> ===== + +#### <话题标题> +====== <这里写话题描述> ===== +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 这里就是你的回复 + >> 这里就是你的观点论述了 + +* [北野](https://alimy.me) - 2022/12/14 10:07 + > 你的回复 + >> 这里就是你的回复 + >>> 这里就是你的观点论述了 + diff --git a/docs/discuss/0001-FAQs.md b/docs/discuss/0001-FAQs.md new file mode 100644 index 00000000..5d45a73d --- /dev/null +++ b/docs/discuss/0001-FAQs.md @@ -0,0 +1,17 @@ +### FAQs 常见问题 +一些常见问题的解答。 + + +#### 为什么要在代码库[docs](../../docs/)中写开发文档,比如[proposal](../proposal/)提按文档? +* [北野](https://alimy.me) - 2022/12/14 10:20 + > 这里有几个原因 + > * 开发文档跟随代码库对开发者友好; + > * paopao-ce的开发是离散组织式开发,代码寄存在GitHub,并没有一个统一的开发平台; + > * 为什么没有使用GitHub的Wiki写档?这个后续会把一些文档Copy到WiKi。 + > * 文档跟随代码,将更好的与代码共存,而且Markdown足够用于写文档,这才是最核心的,怎么简单怎么来。 + + +#### 为什么要在代码库[docs](../../docs/)中包含一个[discuss](../discuss/)?难道没有其他可用工具更好完成这种工作吗,比瑞slack/discord? +* [北野](https://alimy.me) - 2022/12/14 10:32 + > discuss目录包含一些关于代码库开发的一些方案讨论,偏静态内容,代码库内置这些方案讨论,也便于git进行跟踪归档。 + > 确实有其他一些社交类开发聊天工具可用,比如slack/discord,但是目前paopao-ce的开发者社区还比较小,暂时还没有开通的必要,再一个国内访问也不是特别方便,暂时采用目前这种土办法过渡一下,或许后期会选择一个社交平台供开发者交流,比如飞书~ diff --git a/docs/discuss/README.md b/docs/discuss/README.md new file mode 100644 index 00000000..a957312b --- /dev/null +++ b/docs/discuss/README.md @@ -0,0 +1,5 @@ +### Discuss 开发者交流 +本目录包含一些开发相关的问题交流论述。 + +* [0000-讨论样式模版](./0000-讨论样式模版.md "讨论样式模版") +* [0001-讨论样式模版](./0001-FAQs.md "FAQs") From b5130175fa0d5a910474e65c90034a93c5c201ad Mon Sep 17 00:00:00 2001 From: Michael Li Date: Wed, 14 Dec 2022 10:51:52 +0800 Subject: [PATCH 25/65] update discuss documents --- docs/discuss/0001-FAQs.md | 4 +++- docs/discuss/README.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/discuss/0001-FAQs.md b/docs/discuss/0001-FAQs.md index 5d45a73d..83fb01e9 100644 --- a/docs/discuss/0001-FAQs.md +++ b/docs/discuss/0001-FAQs.md @@ -14,4 +14,6 @@ #### 为什么要在代码库[docs](../../docs/)中包含一个[discuss](../discuss/)?难道没有其他可用工具更好完成这种工作吗,比瑞slack/discord? * [北野](https://alimy.me) - 2022/12/14 10:32 > discuss目录包含一些关于代码库开发的一些方案讨论,偏静态内容,代码库内置这些方案讨论,也便于git进行跟踪归档。 - > 确实有其他一些社交类开发聊天工具可用,比如slack/discord,但是目前paopao-ce的开发者社区还比较小,暂时还没有开通的必要,再一个国内访问也不是特别方便,暂时采用目前这种土办法过渡一下,或许后期会选择一个社交平台供开发者交流,比如飞书~ + > 确实有其他一些社交类开发聊天工具可用,比如slack/discord,但是目前paopao-ce的开发者社区还比较小,暂时还没有开通的必要。 +* [北野](https://alimy.me) - 2022/12/14 10:50 + > 再一个国内访问也不是特别方便,暂时采用目前这种土办法过渡一下,或许后期会选择一个社交平台供开发者交流,比如飞书~ diff --git a/docs/discuss/README.md b/docs/discuss/README.md index a957312b..3b983ca6 100644 --- a/docs/discuss/README.md +++ b/docs/discuss/README.md @@ -2,4 +2,4 @@ 本目录包含一些开发相关的问题交流论述。 * [0000-讨论样式模版](./0000-讨论样式模版.md "讨论样式模版") -* [0001-讨论样式模版](./0001-FAQs.md "FAQs") +* [0001-FAQs](./0001-FAQs.md "FAQs") From 1946263788198ee2525ea4dbc6c43de440767a3c Mon Sep 17 00:00:00 2001 From: Michael Li Date: Wed, 14 Dec 2022 11:15:57 +0800 Subject: [PATCH 26/65] add initial docs/deploy documents --- docs/deploy/README.md | 9 +- docs/deploy/aliyun/README.md | 2 + docs/deploy/core/001-配置文件说明.md | 95 ++++++++++++++ docs/deploy/core/README.md | 4 + docs/deploy/huawei/README.md | 2 + docs/deploy/k8s/README.md | 2 + .../001-本地开发依赖环境部署.md | 119 ++++++++++++++++++ docs/deploy/local/README.md | 4 + docs/deploy/tencent/README.md | 2 + 9 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 docs/deploy/aliyun/README.md create mode 100644 docs/deploy/core/001-配置文件说明.md create mode 100644 docs/deploy/core/README.md create mode 100644 docs/deploy/huawei/README.md create mode 100644 docs/deploy/k8s/README.md create mode 100644 docs/deploy/local/001-本地开发依赖环境部署.md create mode 100644 docs/deploy/local/README.md create mode 100644 docs/deploy/tencent/README.md diff --git a/docs/deploy/README.md b/docs/deploy/README.md index a870fd7b..cedbe93f 100644 --- a/docs/deploy/README.md +++ b/docs/deploy/README.md @@ -1,2 +1,9 @@ ## 部署文档 -TODO \ No newline at end of file +本目录包含一些paopao-ce部署相关的帮助文档 + +* [core](./core) - paopao-ce部署帮助文档 +* [aliyun](./aliyun) - Aliyun平台部署文档 +* [huawei](./huawei) - Huawei Cloud平台部署文档 +* [tencnet](./tencent) - Tencent Cloud平台部署文档 +* [local](./local) - 本地部署文档 +* [k8s](./k8s) - 使用Kubernetes部署paopao-ce相关文档 diff --git a/docs/deploy/aliyun/README.md b/docs/deploy/aliyun/README.md new file mode 100644 index 00000000..bae5e98a --- /dev/null +++ b/docs/deploy/aliyun/README.md @@ -0,0 +1,2 @@ +### Aliyun平台部署文档 +本目录包含一些阿里云平台部署paopao-ce的一些帮助文档。 diff --git a/docs/deploy/core/001-配置文件说明.md b/docs/deploy/core/001-配置文件说明.md new file mode 100644 index 00000000..b1af7e2b --- /dev/null +++ b/docs/deploy/core/001-配置文件说明.md @@ -0,0 +1,95 @@ +### 配置文件说明 +paopao-ce使用YAML格式的`conf.yml`作为配置文件。[`config.yaml.sample`](../../../config.yaml.sample) 是一份完整的配置文件模版,paopao-ce启动时会读取`./custom/config.yaml`、`./config.yaml`任意一份配置文件(优先读取最先找到的文件)。 + +```sh +cp config.yaml.sample config.yaml +vim config.yaml # 修改参数 +paopao-ce +``` + +配置文件中的 `Features` 小节是声明paopao-ce运行时开启哪些功能项: + +```yaml +... + +Features: + Default: ["Base", "MySQL", "Option", "LocalOSS", "LoggerFile"] + Develop: ["Base", "MySQL", "Option", "Sms", "AliOSS", "LoggerZinc"] + Demo: ["Base", "MySQL", "Option", "Sms", "MinIO", "LoggerZinc"] + Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile"] + Base: ["Zinc", "Redis", "Alipay",] + Option: ["SimpleCacheIndex"] + Sms: "SmsJuhe" + +... +``` + +如上: +Default/Develop/Demo/Slim 是不同 功能集套件(Features Suite), Base/Option 是子功能套件, Sms是关于短信验证码功能的参数选项。 + +这里 `Default`套件 代表的意思是: 使用`Base/Option` 中的功能,外加 `MySQL/LocalOSS/LoggerFile`功能,也就是说开启了`Zinc/Redis/Alipay/SimpleCacheIndex/MySQL/LocalOSS/LoggerFile` 7项功能; +`Develop`套件依例类推。 + +使用Feautures: + +```sh +release/paopao-ce --help +Usage of release/paopao-ce: + -features value + use special features + -no-default-features + whether use default features + +# 默认使用 Default 功能套件 +release/paopao-ce + +# 不包含 default 中的功能集,仅仅使用 develop 中声明的功能集 +release/paopao-ce --no-default-features --features develop + +# 使用 default 中的功能集,外加 sms 功能 +release/paopao-ce --features sms + +# 手动指定需要开启的功能集 +release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,redis +``` + +目前支持的功能集合: +| 功能项 | 类别 | 状态 | 备注 | +| ----- | ----- | ----- | ----- | +|`OldWeb` | 子服务 | 稳定(默认) | 开启旧的Web服务 | +|`Web` | 子服务 | WIP | 开启Web服务| +|`Admin` | 子服务 | WIP | 开启Admin后台运维服务| +|`SpaceX` | 子服务 | WIP | 开启SpaceX服务| +|`Bot` | 子服务 | WIP | 开启Bot服务| +|`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务| +|`Deprecated:Web` | 子服务 | 稳定 | Deprecated(关闭) OldWeb服务| +|`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM,默认使用 `Gorm` + `MySQL`组合| +|`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM| +|`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库| +|`Postgres`| 数据库 | 稳定 | 使用PostgreSQL作为数据库| +|`Sqlite3`| 数据库 | 稳定 | 使用Sqlite3作为数据库| +|`AliOSS` | 对象存储 | 稳定(推荐) |阿里云对象存储服务| +|`COS` | 对象存储 | 内测 |腾讯云对象存储服务| +|`HuaweiOBS` | 对象存储 | 内测 |华为云对象存储服务| +|`MinIO` | 对象存储 | 稳定 |[MinIO](https://github.com/minio/minio)对象存储服务| +|`S3` | 对象存储 | 内测 |AWS S3兼容的对象存储服务| +|`LocalOSS` | 对象存储 | 内测 |提供使用本地目录文件作为对象存储的功能,仅用于开发调试环境| +|`OSS:Retention` | 对象存储 | 内测 |基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能| +|`OSS:TempDir` | 对象存储 | 内测 |基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能| +|`Redis` | 缓存 | 稳定 | Redis缓存功能 | +|`SimpleCacheIndex` | 缓存 | 稳定 | 提供简单的 广场推文列表 的缓存功能 | +|`BigCacheIndex` | 缓存 | 稳定(推荐) | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 | +|`Zinc` | 搜索 | 稳定(推荐) | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 | +|`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 | +|`Bleve` | 搜索 | WIP | 基于[Bleve](https://github.com/blevesearch/bleve)搜索引擎提供推文搜索服务 | +|`LoggerFile` | 日志 | 稳定 | 使用文件写日志 | +|`LoggerZinc` | 日志 | 稳定(推荐) | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 | +|`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 | +|`Friendship` | 关系模式 | 内测(默认) | 弱关系好友模式,类似微信朋友圈 | +|`Followship` | 关系模式 | WIP | 关注者模式,类似Twitter的Follow模式 | +|`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 | +|`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 | +|`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能,提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) | +|`PhoneBind` | 其他 | 稳定 | 手机绑定功能 | + +> 功能项状态详情参考 [features-status](../../../features-status.md). diff --git a/docs/deploy/core/README.md b/docs/deploy/core/README.md new file mode 100644 index 00000000..fc82b4c2 --- /dev/null +++ b/docs/deploy/core/README.md @@ -0,0 +1,4 @@ +### paopao-ce部署帮助文档 +本目录包含一些部署paopao-ce的一些帮助文档。 + +* [001-配置文件说明](./001-配置文件说明.md '001-配置文件说明') diff --git a/docs/deploy/huawei/README.md b/docs/deploy/huawei/README.md new file mode 100644 index 00000000..8052deaf --- /dev/null +++ b/docs/deploy/huawei/README.md @@ -0,0 +1,2 @@ +### Huawei Cloud平台部署文档 +本目录包含一些华为云平台部署paopao-ce的一些帮助文档。 diff --git a/docs/deploy/k8s/README.md b/docs/deploy/k8s/README.md new file mode 100644 index 00000000..e3b23686 --- /dev/null +++ b/docs/deploy/k8s/README.md @@ -0,0 +1,2 @@ +### 使用Kubernetes部署paopao-ce相关文档 +本目录包含一些k8s环境部署paopao-ce的一些帮助文档。 diff --git a/docs/deploy/local/001-本地开发依赖环境部署.md b/docs/deploy/local/001-本地开发依赖环境部署.md new file mode 100644 index 00000000..9fd293f4 --- /dev/null +++ b/docs/deploy/local/001-本地开发依赖环境部署.md @@ -0,0 +1,119 @@ +### 本地开发依赖环境部署 +本地开发依赖的环境部署帮助文档,包括Zinc/Meili/Minio的部署。 + +#### [Zinc](https://github.com/zinclabs/zinc) 搜索引擎: +* Zinc运行 +```sh +# 创建用于存放zinc数据的目录 +mkdir -p data/zinc/data + +# 使用Docker运行zinc +docker run -d --name zinc --user root -v ${PWD}/data/zinc/data:/data -p 4080:4080 -e ZINC_FIRST_ADMIN_USER=admin -e ZINC_FIRST_ADMIN_PASSWORD=admin -e DATA_PATH=/data public.ecr.aws/zinclabs/zinc:latest + +# 查看zinc运行状态 +docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +41465feea2ff getmeili/meilisearch:v0.27.0 "tini -- /bin/sh -c …" 20 hours ago Up 20 hours 0.0.0.0:7700->7700/tcp paopao-ce-meili-1 +7daf982ca062 public.ecr.aws/prabhat/zinc:latest "/go/bin/zinc" 3 weeks ago Up 6 days 0.0.0.0:4080->4080/tcp zinc + +# 使用docker compose运行 +docker compose up -d zinc +# visit http://localhost:4080 打开自带的ui管理界面 +``` + +* 修改Zinc配置 +```yaml +# features中加上 Zinc 和 LoggerZinc +Features: + Default: ["Zinc", "LoggerZinc", "Base", "Sqlite3", "BigCacheIndex","MinIO"] +... +LoggerZinc: # 使用Zinc写日志 + Host: 127.0.0.1:4080 # 这里的host就是paopao-ce能访问到的zinc主机 + Index: paopao-log + User: admin + Password: admin + Secure: False # 如果使用https访问zinc就设置为True +... +Zinc: # Zinc搜索配置 + Host: 127.0.0.1:4080 + Index: paopao-data + User: admin + Password: admin + Secure: False +``` + +#### [Meilisearch](https://github.com/meilisearch/meilisearch) 搜索引擎: +* Meili运行 +```sh +mkdir -p data/meili/data + +# 使用Docker运行 +docker run -d --name meili -v ${PWD}/data/meili/data:/meili_data -p 7700:7700 -e MEILI_MASTER_KEY=paopao-meilisearch getmeili/meilisearch:v0.29.0 +# visit http://localhost:7700 打开自带的搜索前端ui + +# 使用docker compose运行,需要删除docker-compose.yaml中关于meili的注释 +docker compose up -d meili + +# 使用docker运行meilisearch的ui管理前端 +docker run -d --name uirecord -p 7701:3000 bitriory/uirecord +# visit http://localhost:7701 + +# 使用docker compose运行meilisearch的ui管理前端,需要删除docker-compose.yaml中关于uirecord的注释 +docker compose up -d uirecord +# visit http://loclahost:7701 + +# 查看meili运行状态 +docker compose ps +NAME COMMAND SERVICE STATUS PORTS +paopao-ce-meili-1 "tini -- /bin/sh -c …" meili running 0.0.0.0:7700->7700/tcp +paopao-ce-uirecord-1 "docker-entrypoint.s…" uirecord running 0.0.0.0:7701->3000/tcp +``` + +* 修改Meili配置 +```yaml +# features中加上 Meili 和 LoggerMeili +Features: + Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex","MinIO"] +... +LoggerMeili: # 使用Meili写日志 + Host: 127.0.0.1:7700 + Index: paopao-log + ApiKey: paopao-meilisearch + Secure: False + MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 + MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 +... +Meili: # Meili搜索配置 + Host: 127.0.0.1:7700 # 这里的host就是paopao-ce能访问到的meili主机 + Index: paopao-data + ApiKey: paopao-meilisearch + Secure: False # 如果使用https访问meili就设置为True +``` + +#### [MinIO](https://github.com/minio/minio) 对象存储服务 +* MinIO运行 +```sh +mkdir -p data/minio/data + +# 使用Docker运行 +docker run -d --name minio -v ${PWD}/data/minio/data:/data -p 9000:9000 -p 9001:9001 -e MINIO_ROOT_USER=minio-root-user -e MINIO_ROOT_PASSWORD=minio-root-password -e MINIO_DEFAULT_BUCKETS=paopao:public bitnami/minio:latest + +# 使用docker compose运行, 需要删除docker-compose.yaml中关于minio的注释 +docker compose up -d minio +``` + +* 修改Minio配置 +```yaml +# features中加上 MinIO +Features: + Default: ["MinIO", "Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex"] +... +MinIO: # MinIO 存储配置 + AccessKey: Q3AM3UQ867SPQQA43P2F # AccessKey/SecretKey 需要登入minio管理界面手动创建,管理界面地址: http://127.0.0.1:9001 + SecretKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG + Secure: False + Endpoint: 127.0.0.1:9000 # 根据部署的minio主机修改对应地址 + Bucket: paopao # 如上,需要在管理界面创建bucket并赋予外部可读写权限 + Domain: 127.0.0.1:9000 # minio外网访问的地址(如果想让外网访问,这里需要设置为外网可访问到的minio主机地址) +... +``` \ No newline at end of file diff --git a/docs/deploy/local/README.md b/docs/deploy/local/README.md new file mode 100644 index 00000000..a04b93e1 --- /dev/null +++ b/docs/deploy/local/README.md @@ -0,0 +1,4 @@ +### 本地部署文档 +本目录包含一些本地开发环境部署paopao-ce的一些帮助文档。 + +* [001-本地开发依赖环境部署](001-本地开发依赖环境部署.md '001-本地开发依赖环境部署') diff --git a/docs/deploy/tencent/README.md b/docs/deploy/tencent/README.md new file mode 100644 index 00000000..4674183d --- /dev/null +++ b/docs/deploy/tencent/README.md @@ -0,0 +1,2 @@ +### Tencent Cloud平台部署文档 +本目录包含一些腾讯云平台部署paopao-ce的一些帮助文档。 From 9e33e9695809bbac63e08dcbca59bc3704f23d4f Mon Sep 17 00:00:00 2001 From: Michael Li Date: Thu, 15 Dec 2022 11:23:34 +0800 Subject: [PATCH 27/65] upgrade github.com/alimy/mir/v3 => v3.0.0-alpha.7 --- go.mod | 2 +- go.sum | 4 ++-- internal/mirc/main.go | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 80d99a7f..472bfab1 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/cfg v0.1.0 - github.com/alimy/mir/v3 v3.0.0-alpha.6 + github.com/alimy/mir/v3 v3.0.0-alpha.7 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index dee0dc5e..51625619 100644 --- a/go.sum +++ b/go.sum @@ -144,8 +144,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.1.0 h1:J7KDLEoVIjEBMGlQJb2ljad/d49gJ4Tsl2ogZ9XNhaY= github.com/alimy/cfg v0.1.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= -github.com/alimy/mir/v3 v3.0.0-alpha.6 h1:4xcyE12MgzTbcIcYtnt3ILrVrxFjI71qhqh0JL2gB58= -github.com/alimy/mir/v3 v3.0.0-alpha.6/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= +github.com/alimy/mir/v3 v3.0.0-alpha.7 h1:CuT+wx8KuwgPjzNz5AUDlobqSgFOWNvyzF2tBXm7Hek= +github.com/alimy/mir/v3 v3.0.0-alpha.7/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/mirc/main.go b/internal/mirc/main.go index 6213d798..05431a6c 100644 --- a/internal/mirc/main.go +++ b/internal/mirc/main.go @@ -21,8 +21,9 @@ import ( func main() { log.Println("generate code start") opts := Options{ - RunMode(InSerialDebugMode), + RunMode(InSerialMode), GeneratorName(GeneratorGin), + WatchCtxDone(true), SinkPath("auto"), } if err := Generate(opts); err != nil { From 3fabcb57f70fba1e6ff88e9e9e2293bb5f4f594f Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 16 Dec 2022 09:57:01 +0800 Subject: [PATCH 28/65] upgrade github.com/alimy/cfg => v0.3.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 472bfab1..a8248e78 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 - github.com/alimy/cfg v0.1.0 + github.com/alimy/cfg v0.3.0 github.com/alimy/mir/v3 v3.0.0-alpha.7 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 diff --git a/go.sum b/go.sum index 51625619..afcc929b 100644 --- a/go.sum +++ b/go.sum @@ -142,8 +142,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= -github.com/alimy/cfg v0.1.0 h1:J7KDLEoVIjEBMGlQJb2ljad/d49gJ4Tsl2ogZ9XNhaY= -github.com/alimy/cfg v0.1.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= +github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= +github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= github.com/alimy/mir/v3 v3.0.0-alpha.7 h1:CuT+wx8KuwgPjzNz5AUDlobqSgFOWNvyzF2tBXm7Hek= github.com/alimy/mir/v3 v3.0.0-alpha.7/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= From 745f3639d5c7e65ec40322c1d2e0e46ea5e5af80 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 16 Dec 2022 10:54:01 +0800 Subject: [PATCH 29/65] optimize phone sms verify logic code --- config.yaml.sample | 2 +- go.mod | 2 +- go.sum | 4 +- internal/core/security.go | 9 ++- internal/dao/jinzhu/jinzhu.go | 3 +- internal/dao/jinzhu/security.go | 61 +++++------------ .../{attachment.go => attachment_check.go} | 4 ++ internal/dao/security/phone_verify_juhe.go | 66 +++++++++++++++++++ internal/dao/security/security.go | 18 +++++ 9 files changed, 117 insertions(+), 52 deletions(-) rename internal/dao/security/{attachment.go => attachment_check.go} (87%) create mode 100644 internal/dao/security/phone_verify_juhe.go create mode 100644 internal/dao/security/security.go diff --git a/config.yaml.sample b/config.yaml.sample index d776769b..d9da6327 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -23,7 +23,7 @@ SmsJuhe: Gateway: https://v.juhe.cn/sms/send Key: TplID: - TplVal: "#code#=%d&#m#=%d" + TplVal: "#code#=%s&#m#=%d" Alipay: AppID: InProduction: True diff --git a/go.mod b/go.mod index 0215af0f..c56c4adb 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 - github.com/alimy/cfg v0.1.0 + github.com/alimy/cfg v0.3.0 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index 7262bc9a..58b7f668 100644 --- a/go.sum +++ b/go.sum @@ -142,8 +142,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= -github.com/alimy/cfg v0.1.0 h1:J7KDLEoVIjEBMGlQJb2ljad/d49gJ4Tsl2ogZ9XNhaY= -github.com/alimy/cfg v0.1.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= +github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= +github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/core/security.go b/internal/core/security.go index 63a7ac21..a5c9045f 100644 --- a/internal/core/security.go +++ b/internal/core/security.go @@ -1,6 +1,8 @@ package core import ( + "time" + "github.com/rocboss/paopao-ce/internal/model" ) @@ -11,7 +13,12 @@ type SecurityService interface { SendPhoneCaptcha(phone string) error } -// 附件检测服务 +// AttachmentCheckService 附件检测服务 type AttachmentCheckService interface { CheckAttachment(uri string) error } + +// PhoneVerifyService 手机验证服务 +type PhoneVerifyService interface { + SendPhoneCaptcha(phone string, captcha string, expire time.Duration) error +} diff --git a/internal/dao/jinzhu/jinzhu.go b/internal/dao/jinzhu/jinzhu.go index b3eb550f..0451670b 100644 --- a/internal/dao/jinzhu/jinzhu.go +++ b/internal/dao/jinzhu/jinzhu.go @@ -42,6 +42,7 @@ func NewDataService() (core.DataService, core.VersionInfo) { v core.VersionInfo ) db := conf.MustGormDB() + pvs := security.NewPhoneVerifyService() i := newIndexPostsService(db) if cfg.If("SimpleCacheIndex") { @@ -67,7 +68,7 @@ func NewDataService() (core.DataService, core.VersionInfo) { CommentManageService: newCommentManageService(db), UserManageService: newUserManageService(db), ContactManageService: newContactManageService(db), - SecurityService: newSecurityService(db), + SecurityService: newSecurityService(db, pvs), AttachmentCheckService: security.NewAttachmentCheckService(), } return ds, ds diff --git a/internal/dao/jinzhu/security.go b/internal/dao/jinzhu/security.go index dfbe2c74..5ea1ea25 100644 --- a/internal/dao/jinzhu/security.go +++ b/internal/dao/jinzhu/security.go @@ -1,18 +1,12 @@ package jinzhu import ( - "errors" - "fmt" "math/rand" - "net/http" "strconv" "time" - "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/model" - "github.com/rocboss/paopao-ce/pkg/json" - "gopkg.in/resty.v1" "gorm.io/gorm" ) @@ -21,71 +15,46 @@ var ( ) type securityServant struct { - db *gorm.DB + db *gorm.DB + phoneVerify core.PhoneVerifyService } -func newSecurityService(db *gorm.DB) core.SecurityService { +func newSecurityService(db *gorm.DB, phoneVerify core.PhoneVerifyService) core.SecurityService { return &securityServant{ - db: db, + db: db, + phoneVerify: phoneVerify, } } -type juhePhoneCaptchaRsp struct { - ErrorCode int `json:"error_code"` - Reason string `json:"reason"` -} - -// 获取最新短信验证码 +// GetLatestPhoneCaptcha 获取最新短信验证码 func (s *securityServant) GetLatestPhoneCaptcha(phone string) (*model.Captcha, error) { return (&model.Captcha{ Phone: phone, }).Get(s.db) } -// 更新短信验证码 +// UsePhoneCaptcha 更新短信验证码 func (s *securityServant) UsePhoneCaptcha(captcha *model.Captcha) error { captcha.UseTimes++ return captcha.Update(s.db) } -// 发送短信验证码 +// SendPhoneCaptcha 发送短信验证码 func (s *securityServant) SendPhoneCaptcha(phone string) error { - rand.Seed(time.Now().UnixNano()) - captcha := rand.Intn(900000) + 100000 - m := 5 - - client := resty.New() - client.DisableWarn = true - resp, err := client.R(). - SetFormData(map[string]string{ - "mobile": phone, - "tpl_id": conf.SmsJuheSetting.TplID, - "tpl_value": fmt.Sprintf(conf.SmsJuheSetting.TplVal, captcha, m), - "key": conf.SmsJuheSetting.Key, - }).Post(conf.SmsJuheSetting.Gateway) - if err != nil { - return err - } + expire := time.Duration(5) - if resp.StatusCode() != http.StatusOK { - return errors.New(resp.Status()) - } - - result := &juhePhoneCaptchaRsp{} - err = json.Unmarshal(resp.Body(), result) - if err != nil { + // 发送验证码 + rand.Seed(time.Now().UnixNano()) + captcha := strconv.Itoa(rand.Intn(900000) + 100000) + if err := s.phoneVerify.SendPhoneCaptcha(phone, captcha, expire); err != nil { return err } - if result.ErrorCode != 0 { - return errors.New(result.Reason) - } - // 写入表 captchaModel := &model.Captcha{ Phone: phone, - Captcha: strconv.Itoa(captcha), - ExpiredOn: time.Now().Add(time.Minute * time.Duration(m)).Unix(), + Captcha: captcha, + ExpiredOn: time.Now().Add(expire * time.Minute).Unix(), } captchaModel.Create(s.db) return nil diff --git a/internal/dao/security/attachment.go b/internal/dao/security/attachment_check.go similarity index 87% rename from internal/dao/security/attachment.go rename to internal/dao/security/attachment_check.go index 3bd79461..2425220b 100644 --- a/internal/dao/security/attachment.go +++ b/internal/dao/security/attachment_check.go @@ -8,6 +8,10 @@ import ( "github.com/rocboss/paopao-ce/internal/core" ) +var ( + _ core.AttachmentCheckService = (*attachmentCheckServant)(nil) +) + type attachmentCheckServant struct { domain string } diff --git a/internal/dao/security/phone_verify_juhe.go b/internal/dao/security/phone_verify_juhe.go new file mode 100644 index 00000000..5981c6c3 --- /dev/null +++ b/internal/dao/security/phone_verify_juhe.go @@ -0,0 +1,66 @@ +package security + +import ( + "errors" + "fmt" + "net/http" + "time" + + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/pkg/json" + "gopkg.in/resty.v1" +) + +var ( + _ core.PhoneVerifyService = (*juheSmsServant)(nil) +) + +type juhePhoneCaptchaRsp struct { + ErrorCode int `json:"error_code"` + Reason string `json:"reason"` +} + +type juheSmsServant struct { + gateway string + key string + tplID string + tplVal string +} + +// SendPhoneCaptcha 发送短信验证码 +func (s *juheSmsServant) SendPhoneCaptcha(phone string, captcha string, expire time.Duration) error { + client := resty.New() + client.DisableWarn = true + resp, err := client.R(). + SetFormData(map[string]string{ + "mobile": phone, + "tpl_id": s.tplID, + "tpl_value": fmt.Sprintf(s.tplVal, captcha, expire), + "key": s.key, + }).Post(s.gateway) + if err != nil { + return err + } + if resp.StatusCode() != http.StatusOK { + return errors.New(resp.Status()) + } + + result := &juhePhoneCaptchaRsp{} + if err = json.Unmarshal(resp.Body(), result); err != nil { + return err + } + if result.ErrorCode != 0 { + return errors.New(result.Reason) + } + return nil +} + +func newJuheSmsServant() *juheSmsServant { + return &juheSmsServant{ + gateway: conf.SmsJuheSetting.Gateway, + key: conf.SmsJuheSetting.Key, + tplID: conf.SmsJuheSetting.TplID, + tplVal: conf.SmsJuheSetting.TplVal, + } +} diff --git a/internal/dao/security/security.go b/internal/dao/security/security.go new file mode 100644 index 00000000..75cd003b --- /dev/null +++ b/internal/dao/security/security.go @@ -0,0 +1,18 @@ +package security + +import ( + "strings" + + "github.com/alimy/cfg" + "github.com/rocboss/paopao-ce/internal/core" +) + +func NewPhoneVerifyService() core.PhoneVerifyService { + smsVendor, _ := cfg.Val("sms") + switch strings.ToLower(smsVendor) { + case "smsjuhe": + return newJuheSmsServant() + default: + return newJuheSmsServant() + } +} From 47f6b0a8ac28a417747f3c5b8d4b49336c567372 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 16 Dec 2022 12:32:22 +0800 Subject: [PATCH 30/65] add ROADMAP.md --- ROADMAP.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 ROADMAP.md diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 00000000..76df1453 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,32 @@ +## Roadmap for paopao-ce +paopao-ce roadmap. + +### v0.2.0 +* [x] add `Friendship` feature +* [ ] add `Lightship` feature +* [ ] add `sqlx` feature +* [ ] add new `web` service +* [ ] add `deprecated:web` feature +* [ ] support run multiple service in single paopao-ce instance +* [ ] use [go-mir](https://github.com/alimy/mir) optimize paopao-ce source code architecture + + +### Next +* [ ] add `Followship` feature +* [ ] add `Bleve` feature +* [ ] add `SpaceX` feature +* [ ] add `Bot` feature +* [ ] add `Admin` feature +* [ ] add `NativeOBS` feature +* [ ] add `Mobile` gRPC API service feature +* [ ] add admin web frontend +* [ ] add tweet forwarding support +* [ ] add tweet resource access control base on simple RBAC support +* [ ] add user's `Activation Code` feature support +* [ ] add user block feature support +* [ ] optimize current message push logic service use `ims` module +* [ ] optimize media tweet submit logic +* [ ] optimize topics service +* [ ] optimize backend data logic service(optimize database CRUD operate) +* [ ] optimize search logic service + From b5312cc42c2040b00babe63a667b6c93d0afad0a Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 16 Dec 2022 12:35:28 +0800 Subject: [PATCH 31/65] update ROADMAP.md --- ROADMAP.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 76df1453..b5a74054 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -6,9 +6,9 @@ paopao-ce roadmap. * [ ] add `Lightship` feature * [ ] add `sqlx` feature * [ ] add new `web` service -* [ ] add `deprecated:web` feature -* [ ] support run multiple service in single paopao-ce instance -* [ ] use [go-mir](https://github.com/alimy/mir) optimize paopao-ce source code architecture +* [x] add `deprecated:web` feature +* [x] support run multiple service in single paopao-ce instance +* [x] use [go-mir](https://github.com/alimy/mir) optimize paopao-ce source code architecture ### Next From 0e7f47f7a39be7169c1be936b5c6393a7fb1a58f Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 16 Dec 2022 15:04:07 +0800 Subject: [PATCH 32/65] optimze service interface add Version() to return version info --- internal/service/admin.go | 9 +++++++++ internal/service/bot.go | 9 +++++++++ internal/service/localoss.go | 9 +++++++++ internal/service/service.go | 19 +++++++++++++++++++ internal/service/space.go | 9 +++++++++ internal/service/web.go | 9 +++++++++ internal/service/web_old.go | 9 +++++++++ main.go | 11 ++++++----- pkg/util/banner.go | 10 +++++++++- 9 files changed, 88 insertions(+), 6 deletions(-) diff --git a/internal/service/admin.go b/internal/service/admin.go index ad965e80..7acd408e 100644 --- a/internal/service/admin.go +++ b/internal/service/admin.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" + "github.com/Masterminds/semver/v3" "github.com/fatih/color" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" @@ -15,6 +16,10 @@ import ( "github.com/rocboss/paopao-ce/internal/servants" ) +var ( + _ Service = (*adminService)(nil) +) + type adminService struct { *baseHttpService } @@ -23,6 +28,10 @@ func (s *adminService) Name() string { return "AdminService" } +func (s *adminService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + func (s *adminService) Init() error { s.registerRoute(servants.RegisterAdminServants) return nil diff --git a/internal/service/bot.go b/internal/service/bot.go index b9c66793..38fd97c3 100644 --- a/internal/service/bot.go +++ b/internal/service/bot.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" + "github.com/Masterminds/semver/v3" "github.com/fatih/color" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" @@ -15,6 +16,10 @@ import ( "github.com/rocboss/paopao-ce/internal/servants" ) +var ( + _ Service = (*botService)(nil) +) + type botService struct { *baseHttpService } @@ -23,6 +28,10 @@ func (s *botService) Name() string { return "BotService" } +func (s *botService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + func (s *botService) Init() error { s.registerRoute(servants.RegisterBotServants) return nil diff --git a/internal/service/localoss.go b/internal/service/localoss.go index 18dd79f9..4c09412d 100644 --- a/internal/service/localoss.go +++ b/internal/service/localoss.go @@ -8,12 +8,17 @@ import ( "fmt" "net/http" + "github.com/Masterminds/semver/v3" "github.com/fatih/color" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/servants" ) +var ( + _ Service = (*localossService)(nil) +) + type localossService struct { *baseHttpService } @@ -22,6 +27,10 @@ func (s *localossService) Name() string { return "LocalossService" } +func (s *localossService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + func (s *localossService) Init() error { s.registerRoute(servants.RegisterLocalossServants) return nil diff --git a/internal/service/service.go b/internal/service/service.go index 34a04574..a17476aa 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -7,12 +7,14 @@ package service import ( "log" + "github.com/Masterminds/semver/v3" "github.com/alimy/cfg" "github.com/rocboss/paopao-ce/pkg/types" ) type Service interface { Name() string + Version() *semver.Version Init() error Start() error Stop() error @@ -24,10 +26,15 @@ func (baseService) Name() string { return "" } +func (baseService) Version() *semver.Version { + return semver.MustParse("v0.0.1") +} + func (baseService) String() string { return "" } +// InitService Initial service func InitService() []Service { ss := newService() for _, s := range ss { @@ -38,6 +45,18 @@ func InitService() []Service { return ss } +// MaxSidSize max service id string length +func MaxSidSize(ss []Service) int { + length := 0 + for _, s := range ss { + size := len(s.Name() + "@" + s.Version().String()) + if size > length { + length = size + } + } + return length +} + func newService() (ss []Service) { ss = append(ss, newWebService()) diff --git a/internal/service/space.go b/internal/service/space.go index 3866c5ac..73fa41ab 100644 --- a/internal/service/space.go +++ b/internal/service/space.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" + "github.com/Masterminds/semver/v3" "github.com/fatih/color" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" @@ -15,6 +16,10 @@ import ( "github.com/rocboss/paopao-ce/internal/servants" ) +var ( + _ Service = (*spaceXService)(nil) +) + type spaceXService struct { *baseHttpService } @@ -23,6 +28,10 @@ func (s *spaceXService) Name() string { return "WebService" } +func (s *spaceXService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + func (s *spaceXService) Init() error { s.registerRoute(servants.RegisterSpaceXServants) return nil diff --git a/internal/service/web.go b/internal/service/web.go index c8e422a1..e983e6c5 100644 --- a/internal/service/web.go +++ b/internal/service/web.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" + "github.com/Masterminds/semver/v3" "github.com/fatih/color" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" @@ -15,6 +16,10 @@ import ( "github.com/rocboss/paopao-ce/internal/servants" ) +var ( + _ Service = (*webService)(nil) +) + type webService struct { *baseHttpService } @@ -23,6 +28,10 @@ func (s *webService) Name() string { return "WebService" } +func (s *webService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + func (s *webService) Init() error { s.registerRoute(servants.RegisterWebServants) return nil diff --git a/internal/service/web_old.go b/internal/service/web_old.go index a3c58471..de51c072 100644 --- a/internal/service/web_old.go +++ b/internal/service/web_old.go @@ -8,11 +8,16 @@ import ( "fmt" "net/http" + "github.com/Masterminds/semver/v3" "github.com/fatih/color" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/servants/web/routers" ) +var ( + _ Service = (*oldWebService)(nil) +) + type oldWebService struct { *baseHttpService } @@ -21,6 +26,10 @@ func (s *oldWebService) Name() string { return "OldWebService" } +func (s *oldWebService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + func (s *oldWebService) Init() error { s.registerRoute(routers.RegisterRoute) return nil diff --git a/main.go b/main.go index 4c639a61..aafc14e3 100644 --- a/main.go +++ b/main.go @@ -57,11 +57,12 @@ func runService(wg *sync.WaitGroup, ss []service.Service) { gin.SetMode(conf.RunMode()) fmt.Fprintf(color.Output, "\nstarting run service...\n\n") + l := service.MaxSidSize(ss) for _, s := range ss { go func(s service.Service) { - fmt.Fprintf(color.Output, "%s[start] - %s", s.Name(), s) + fmt.Fprintf(color.Output, "%s [start] - %s", util.SidStr(s.Name(), s.Version(), l), s) if err := s.Start(); err != nil { - fmt.Fprintf(color.Output, "%s[start] - occurs on error: %s\n", s.Name(), err) + fmt.Fprintf(color.Output, "%s [start] - occurs on error: %s\n", util.SidStr(s.Name(), s.Version(), l), err) } wg.Done() }(s) @@ -76,12 +77,12 @@ func runManage(wg *sync.WaitGroup, ss []service.Service) { signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit fmt.Fprintf(color.Output, "\nshutting down server...\n\n") - + l := service.MaxSidSize(ss) for _, s := range ss { if err := s.Stop(); err != nil { - fmt.Fprintf(color.Output, "%s[stop] - occurs on error: %s\n", s.Name(), err) + fmt.Fprintf(color.Output, "%s [stop] - occurs on error: %s\n", util.SidStr(s.Name(), s.Version(), l), err) } - fmt.Fprintf(color.Output, "%s[stop] - finish...\n", s.Name()) + fmt.Fprintf(color.Output, "%s [stop] - finish...\n", util.SidStr(s.Name(), s.Version(), l)) } wg.Done() } diff --git a/pkg/util/banner.go b/pkg/util/banner.go index 31e25ba9..5e9795c2 100644 --- a/pkg/util/banner.go +++ b/pkg/util/banner.go @@ -4,7 +4,11 @@ package util -import "fmt" +import ( + "fmt" + + "github.com/Masterminds/semver/v3" +) func PrintHelloBanner(text string) { @@ -14,3 +18,7 @@ func PrintHelloBanner(text string) { fmt.Println("(__) \\_/\\_/ \\__/(__) \\_/\\_/ \\__/ ") fmt.Println(text) } + +func SidStr(name string, version *semver.Version, size int) string { + return fmt.Sprintf(fmt.Sprintf("%%s%%-%ds", size-len(name+version.String())+4), name, version) +} From 76582ec451629e59787ddce7e327b1d4ec732a2b Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 16 Dec 2022 23:43:20 +0800 Subject: [PATCH 33/65] optimize conf initial logic to add merge config.yaml support --- .gitignore | 2 +- go.mod | 55 +++++++-------- go.sum | 118 +++++++++++++++++++------------- internal/conf/config.yaml | 139 ++++++++++++++++++++++++++++++++++++++ internal/conf/settting.go | 17 ++++- 5 files changed, 251 insertions(+), 80 deletions(-) create mode 100644 internal/conf/config.yaml diff --git a/.gitignore b/.gitignore index ea7a71a2..c67a6e18 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .idea .vscode !*.example -config.yaml +/config.yaml *.log paopao-ce* /release diff --git a/go.mod b/go.mod index c56c4adb..eee0423c 100644 --- a/go.mod +++ b/go.mod @@ -24,13 +24,13 @@ require ( github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible github.com/json-iterator/go v1.1.12 github.com/meilisearch/meilisearch-go v0.21.0 - github.com/minio/minio-go/v7 v7.0.27 - github.com/sirupsen/logrus v1.8.1 + github.com/minio/minio-go/v7 v7.0.45 + github.com/sirupsen/logrus v1.9.0 github.com/smartwalle/alipay/v3 v3.1.7 - github.com/spf13/viper v1.10.1 + github.com/spf13/viper v1.14.0 github.com/tencentyun/cos-go-sdk-v5 v0.7.35 github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc - google.golang.org/protobuf v1.28.0 + google.golang.org/protobuf v1.28.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/resty.v1 v1.12.0 gorm.io/driver/mysql v1.3.4 @@ -51,7 +51,7 @@ require ( github.com/clbanning/mxj v1.8.4 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.0 // indirect - github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect @@ -59,7 +59,6 @@ require ( github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.7 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -77,51 +76,49 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.15.6 // indirect - github.com/klauspost/cpuid v1.3.1 // indirect - github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/klauspost/compress v1.15.9 // indirect + github.com/klauspost/cpuid/v2 v2.1.0 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/lib/pq v1.10.2 // indirect - github.com/magiconair/properties v1.8.5 // indirect + github.com/magiconair/properties v1.8.6 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-sqlite3 v1.14.12 // indirect - github.com/minio/md5-simd v1.1.0 // indirect - github.com/minio/sha256-simd v0.1.1 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/minio/md5-simd v1.1.2 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect 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.3.1 // indirect - github.com/pelletier/go-toml v1.9.4 // indirect - github.com/pelletier/go-toml/v2 v2.0.1 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect - github.com/rs/xid v1.2.1 // indirect + github.com/rs/xid v1.4.0 // indirect github.com/smartwalle/crypto4go v1.0.2 // indirect - github.com/spf13/afero v1.6.0 // indirect - github.com/spf13/cast v1.4.1 // indirect + github.com/spf13/afero v1.9.2 // indirect + github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/subosito/gotenv v1.2.0 // indirect + github.com/subosito/gotenv v1.4.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d // indirect - go.uber.org/atomic v1.7.0 // indirect + go.uber.org/atomic v1.9.0 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect - golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 // indirect + golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect - golang.org/x/mod v0.5.0 // indirect - golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect - golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect - golang.org/x/tools v0.1.5 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gopkg.in/ini.v1 v1.66.2 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect + golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect + golang.org/x/tools v0.1.12 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/uint128 v1.1.1 // indirect modernc.org/cc/v3 v3.36.0 // indirect modernc.org/ccgo/v3 v3.16.6 // indirect diff --git a/go.sum b/go.sum index 58b7f668..81c5d8a0 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,7 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -19,6 +20,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -51,6 +53,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= @@ -500,10 +503,11 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= @@ -700,8 +704,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -724,6 +727,7 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -744,6 +748,7 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0 github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= @@ -948,14 +953,15 @@ github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8 github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= -github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0= +github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -994,8 +1000,8 @@ github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -1050,16 +1056,15 @@ github.com/meilisearch/meilisearch-go v0.21.0 h1:SwYMWJVi6vDdSDJdOmbkJ4T26PavjYc github.com/meilisearch/meilisearch-go v0.21.0/go.mod h1:3dvPYZGUWu40qHoTK187fmqF2lrarboPa5m2Yu2Seh4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4= -github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= -github.com/minio/minio-go/v7 v7.0.27 h1:yJCvm78B+2+ll1PqO9eSD1as6Ibw3IYnnD8PyBEB2zo= -github.com/minio/minio-go/v7 v7.0.27/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0Vb75Xk5yYg= -github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= -github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= +github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= +github.com/minio/minio-go/v7 v7.0.45 h1:g4IeM9M9pW/Lo8AGGNOjBZYlvmtlE1N5TQEYWXRWzIs= +github.com/minio/minio-go/v7 v7.0.45/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= @@ -1183,10 +1188,10 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= -github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= -github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= @@ -1204,6 +1209,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1256,8 +1262,9 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1289,8 +1296,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartwalle/alipay/v3 v3.1.7 h1:J4U5slABafKVD/b9gPCZe/3HAPB8Pa2NOYOPcugEJBo= github.com/smartwalle/alipay/v3 v3.1.7/go.mod h1:cZUMCCnsux9YAxA0/f3PWUR+7wckWtE1BqxbVRtGij0= github.com/smartwalle/crypto4go v1.0.2 h1:9DUEOOsPhmp00438L4oBdcL8EZG1zumecft5bWj5phI= @@ -1305,11 +1313,12 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= @@ -1325,8 +1334,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= -github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= +github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= +github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -1344,10 +1353,11 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -1466,8 +1476,9 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1511,14 +1522,16 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU= -golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1568,8 +1581,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1641,8 +1655,9 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1762,6 +1777,7 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1800,8 +1816,11 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf h1:Fm4IcnUL803i92qDlmB0obyHmosDrxZWxJL3gIeNqOw= golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1815,8 +1834,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1826,8 +1846,9 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1902,19 +1923,20 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= @@ -2010,7 +2032,9 @@ google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2038,8 +2062,8 @@ google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106 h1:ErU+UA6wxadoU8nWrsy5MZUVBs75K17zUCsUCIfrXCE= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2072,8 +2096,8 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2088,8 +2112,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2108,8 +2132,8 @@ gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWd gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= -gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= diff --git a/internal/conf/config.yaml b/internal/conf/config.yaml new file mode 100644 index 00000000..00c31e8d --- /dev/null +++ b/internal/conf/config.yaml @@ -0,0 +1,139 @@ +App: # APP基础设置项 + AttachmentIncomeRate: 0.8 + MaxCommentCount: 10 + DefaultContextTimeout: 60 + DefaultPageSize: 10 + MaxPageSize: 100 +Server: # 服务设置 + RunMode: debug + HttpIp: 0.0.0.0 + HttpPort: 8008 + ReadTimeout: 60 + WriteTimeout: 60 +Features: + Default: [] +SmsJuhe: + Gateway: https://v.juhe.cn/sms/send + Key: + TplID: + TplVal: "#code#=%s&#m#=%d" +Alipay: + AppID: + InProduction: True + RootCertFile: "custom/alipay/RootCert.crt" + PublicCertFile: "custom/alipay/CertPublicKey_RSA2.crt" + AppPublicCertFile: "custom/alipay/AppCertPublicKey.crt" +CacheIndex: + MaxUpdateQPS: 100 # 最大添加/删除/更新Post的QPS, 设置范围[10, 10000], 默认100 +SimpleCacheIndex: # 缓存泡泡广场消息流 + MaxIndexSize: 200 # 最大缓存条数 + CheckTickDuration: 60 # 循环自检查每多少秒一次 + ExpireTickDuration: 300 # 每多少秒后强制过期缓存, 设置为0禁止强制使缓存过期 +BigCacheIndex: # 使用BigCache缓存泡泡广场消息流 + MaxIndexPage: 1024 # 最大缓存页数,必须是2^n, 代表最大同时缓存多少页数据 + Verbose: False # 是否打印cache操作的log + ExpireInSecond: 300 # 多少秒(>0)后强制过期缓存 +Logger: # 日志通用配置 + Level: debug # 日志级别 panic|fatal|error|warn|info|debug|trace +LoggerFile: # 使用File写日志 + SavePath: data/paopao-ce/logs + FileName: app + FileExt: .log +LoggerZinc: # 使用Zinc写日志 + Host: zinc:4080 + Index: paopao-log + User: admin + Password: admin + Secure: False +LoggerMeili: # 使用Meili写日志 + Host: meili:7700 + Index: paopao-log + ApiKey: paopao-meilisearch + Secure: False + MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 + MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 +JWT: # 鉴权加密 + Secret: 18a6413dc4fe394c66345ebe501b2f26 + Issuer: paopao-api + Expire: 86400 +TweetSearch: # 推文关键字搜索相关配置 + MaxUpdateQPS: 100 # 最大添加/删除/更新Post的QPS,设置范围[10, 10000], 默认100 + MinWorker: 10 # 最小后台更新工作者, 设置范围[5, 1000], 默认10 +Zinc: # Zinc搜索配置 + Host: zinc:4080 + Index: paopao-data + User: admin + Password: admin + Secure: False +Meili: # Meili搜索配置 + Host: meili:7700 + Index: paopao-data + ApiKey: paopao-meilisearch + Secure: False +ObjectStorage: # 对象存储通用配置 + RetainInDays: 2 # 临时对象过期时间多少天 + TempDir: tmp # 临时对象存放目录名 +AliOSS: # 阿里云OSS存储配置 + Endpoint: + AccessKeyID: + AccessKeySecret: + Bucket: + Domain: +COS: # 腾讯云COS存储配置 + SecretID: + SecretKey: + Region: ap-shanghai + Bucket: demo-1888888888 + Domain: +HuaweiOBS: # 华为云OBS存储配置 + AccessKey: + SecretKey: + Endpoint: + Bucket: paopao + Domain: +MinIO: # MinIO 存储配置 + AccessKey: Q3AM3UQ867SPQQA43P2F + SecretKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG + Secure: False + Endpoint: minio:9000 + Bucket: paopao + Domain: 127.0.0.1:9000 +S3: # Amazon S3 存储配置 + AccessKey: "YOUR-ACCESSKEYID" + SecretKey: "YOUR-SECRETACCESSKEY" + Secure: True + Endpoint: s3.amazonaws.com + Bucket: paopao + Domain: +LocalOSS: # 本地文件OSS存储配置 + SavePath: data/paopao-ce/oss + Secure: False + Bucket: paopao + Domain: 127.0.0.1:8008 +Database: # Database通用配置 + LogLevel: error # 日志级别 silent|error|warn|info + TablePrefix: p_ # 表名前缀 +MySQL: # MySQL数据库 + Username: paopao + Password: paopao + Host: db:3306 + DBName: paopao + Charset: utf8mb4 + ParseTime: True + MaxIdleConns: 10 + MaxOpenConns: 30 +Postgres: # PostgreSQL数据库 + User: paopao + Password: paopao + DBName: paopao + Host: localhost + Port: 5432 + SSLMode: disable + TimeZone: Asia/Shanghai +Sqlite3: # Sqlite3数据库 + Path: data/sqlite3/paopao-ce.db +Redis: + Host: redis:6379 + Password: + DB: + \ No newline at end of file diff --git a/internal/conf/settting.go b/internal/conf/settting.go index 116fdf95..2e6a6a73 100644 --- a/internal/conf/settting.go +++ b/internal/conf/settting.go @@ -1,6 +1,7 @@ package conf import ( + "embed" "fmt" "strings" "time" @@ -10,6 +11,9 @@ import ( "gorm.io/gorm/logger" ) +//go:embed config.yaml +var files embed.FS + type Setting struct { vp *viper.Viper } @@ -199,13 +203,21 @@ type JWTSettingS struct { } func NewSetting() (*Setting, error) { + cfgFile, err := files.Open("config.yaml") + if err != nil { + return nil, err + } + defer cfgFile.Close() + vp := viper.New() vp.SetConfigName("config") vp.AddConfigPath(".") vp.AddConfigPath("custom/") vp.SetConfigType("yaml") - err := vp.ReadInConfig() - if err != nil { + if err = vp.ReadConfig(cfgFile); err != nil { + return nil, err + } + if err = vp.MergeInConfig(); err != nil { return nil, err } @@ -217,7 +229,6 @@ func (s *Setting) ReadSection(k string, v any) error { if err != nil { return err } - return nil } From bab9fd46f215af7130acf1bf41ef6c6dab62587d Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 16 Dec 2022 23:56:16 +0800 Subject: [PATCH 34/65] optimize service create if needed by config.yaml feature declare --- internal/conf/config.yaml | 31 +++++++++++++++++++++++++++++++ internal/service/service.go | 10 +++++----- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/internal/conf/config.yaml b/internal/conf/config.yaml index 00c31e8d..307e8451 100644 --- a/internal/conf/config.yaml +++ b/internal/conf/config.yaml @@ -1,4 +1,5 @@ App: # APP基础设置项 + RunMode: debug AttachmentIncomeRate: 0.8 MaxCommentCount: 10 DefaultContextTimeout: 60 @@ -12,6 +13,36 @@ Server: # 服务设置 WriteTimeout: 60 Features: Default: [] +WebServer: # Web服务 + HttpIp: 0.0.0.0 + HttpPort: 8010 + ReadTimeout: 60 + WriteTimeout: 60 +AdminServer: # Admin后台运维服务 + HttpIp: 0.0.0.0 + HttpPort: 8014 + ReadTimeout: 60 + WriteTimeout: 60 +SpaceXServer: # SpaceX服务 + HttpIp: 0.0.0.0 + HttpPort: 8012 + ReadTimeout: 60 + WriteTimeout: 60 +BotServer: # Bot服务 + HttpIp: 0.0.0.0 + HttpPort: 8016 + ReadTimeout: 60 + WriteTimeout: 60 +LocalossServer: # Localoss服务 + HttpIp: 0.0.0.0 + HttpPort: 8018 + ReadTimeout: 60 + WriteTimeout: 60 +DocsServer: # 开发文档服务 + HttpIp: 0.0.0.0 + HttpPort: 8011 + ReadTimeout: 60 + WriteTimeout: 60 SmsJuhe: Gateway: https://v.juhe.cn/sms/send Key: diff --git a/internal/service/service.go b/internal/service/service.go index a17476aa..c1f8aa94 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -58,14 +58,15 @@ func MaxSidSize(ss []Service) int { } func newService() (ss []Service) { - ss = append(ss, newWebService()) - // add oldWebService if not depredcated OldWebService cfg.Not("Deprecated:OldWeb", func() { ss = append(ss, newOldWebService()) }) - + // add all service if declared in features on config.yaml cfg.In(cfg.Actions{ + "Web": func() { + ss = append(ss, newWebService()) + }, "Admin": func() { ss = append(ss, newAdminService()) }, @@ -75,10 +76,9 @@ func newService() (ss []Service) { "Bot": func() { ss = append(ss, newBotService()) }, - "LocalOSS": func() { + "NativeOBS": func() { ss = append(ss, newLocalossService()) }, }) - return } From da633590a1655efe664509e8e352f378d8bfa9b4 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 17 Dec 2022 11:50:29 +0800 Subject: [PATCH 35/65] update spacex servie name info --- ROADMAP.md | 8 +++----- internal/service/space.go | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index b5a74054..5efdb9cd 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -4,13 +4,12 @@ paopao-ce roadmap. ### v0.2.0 * [x] add `Friendship` feature * [ ] add `Lightship` feature -* [ ] add `sqlx` feature -* [ ] add new `web` service -* [x] add `deprecated:web` feature +* [ ] add `Sqlx` feature +* [ ] add new `Web` service +* [x] add `Deprecated:OldWeb` feature * [x] support run multiple service in single paopao-ce instance * [x] use [go-mir](https://github.com/alimy/mir) optimize paopao-ce source code architecture - ### Next * [ ] add `Followship` feature * [ ] add `Bleve` feature @@ -29,4 +28,3 @@ paopao-ce roadmap. * [ ] optimize topics service * [ ] optimize backend data logic service(optimize database CRUD operate) * [ ] optimize search logic service - diff --git a/internal/service/space.go b/internal/service/space.go index 73fa41ab..30dfeec0 100644 --- a/internal/service/space.go +++ b/internal/service/space.go @@ -25,7 +25,7 @@ type spaceXService struct { } func (s *spaceXService) Name() string { - return "WebService" + return "SpaceXService" } func (s *spaceXService) Version() *semver.Version { From 521cd80116125a4f70ad37d9718d003c4b69b656 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 17 Dec 2022 12:09:26 +0800 Subject: [PATCH 36/65] update proposal documents --- README.md | 4 +-- .../.assets/{00-00.png => 000-00.png} | Bin .../.assets/{00-01.png => 000-01.png} | Bin docs/proposal/.assets/001-01.drawio | 1 + docs/proposal/.assets/001-01.png | Bin 0 -> 233790 bytes .../.assets/{06-01.drawio => 006-01.drawio} | 0 .../.assets/{06-01.png => 006-01.png} | Bin .../001-关于paopao-ce的设计定位.md | 11 ++++--- .../002-关于Friendship功能项的设计.md | 29 ++++++++---------- .../006-关于paopao-ce的结构设计.md | 2 +- 10 files changed, 23 insertions(+), 24 deletions(-) rename docs/proposal/.assets/{00-00.png => 000-00.png} (100%) rename docs/proposal/.assets/{00-01.png => 000-01.png} (100%) create mode 100644 docs/proposal/.assets/001-01.drawio create mode 100644 docs/proposal/.assets/001-01.png rename docs/proposal/.assets/{06-01.drawio => 006-01.drawio} (100%) rename docs/proposal/.assets/{06-01.png => 006-01.png} (100%) diff --git a/README.md b/README.md index acc0d1d1..c3d668b1 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Web端: 更多演示请前往[官网](https://www.paopao.info)体验(谢绝灌水) 桌面端: -![](docs/proposal/.assets/00-00.png) +![](docs/proposal/.assets/000-00.png)

(back to top)

@@ -493,7 +493,7 @@ jc/alimy * `jc/*`是代码库维护者的开发分支,一般包含一些局部优化或者bug修复代码,有时可以直接将代码merge到`dev/beta`分支,原则上不允许直接merge代码到`main`主分支。 **代码分支演进图** -![](docs/proposal/.assets/00-01.png) +![](docs/proposal/.assets/000-01.png) ### 其他说明 diff --git a/docs/proposal/.assets/00-00.png b/docs/proposal/.assets/000-00.png similarity index 100% rename from docs/proposal/.assets/00-00.png rename to docs/proposal/.assets/000-00.png diff --git a/docs/proposal/.assets/00-01.png b/docs/proposal/.assets/000-01.png similarity index 100% rename from docs/proposal/.assets/00-01.png rename to docs/proposal/.assets/000-01.png diff --git a/docs/proposal/.assets/001-01.drawio b/docs/proposal/.assets/001-01.drawio new file mode 100644 index 00000000..49545269 --- /dev/null +++ b/docs/proposal/.assets/001-01.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/proposal/.assets/001-01.png b/docs/proposal/.assets/001-01.png new file mode 100644 index 0000000000000000000000000000000000000000..cddadbde0485f1291edab144e415febfe2311343 GIT binary patch literal 233790 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

c<%ytQc03(LL=VP;944B?nq!aTzM16h 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

DX@@yIvdat@|iAH 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 BG%i9=Z)lL2*j~YXD-ES++dj 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

V8hNrXK+6!U2oIG-=O88z5o^z5oym7*MOr8 z{>`p8&vG<5iJRRsD1LP-{EgzMy|8G*CR^sRUIV#zLTa{VE+SrX7T7ajujSXdzcv!; zy2wu0=CS4ewhItScb0D-!R21o=~4q%(x>Gl(WUalO<4aX4~&lWvjSs%zpzR z2?tCjBGaDYI}a5!&>~`5%R7Fao^@&`A?)g1A=`yNF0Qxv3yFP1IrLWSGxDpRo7zOJ z9kL8=o>Ugj2??(kJSg98p?G$JcS~L)ut&o{EjfL+QM(l=$ZkPBV?*YZ#m6IA@-$u~ zSQg1c&g_(@(&o>y0IJ~sV3AQPJk9r}YQ(rR+Q)1#vpFw3uRqzb`cmcPl*}O?*$9;T zZs>~RHlqIaG!txJITPEGi%B0`HeMx($a!NZ_4kpry&MYUiI%W$^$82!&O%*a6S=>7 zva}y*1vbYzebA-hj_@$HXt$cig>p)6tNK{cg8CTP@%g)AIgQo_zFO6+DlDnHv?Msr zHTW2S8u4aZnx$M*(I<`6{ikJ zL~~fAw1HJ6MV1kMb z(h(VL?8Bdv{*BU93j4^-*FdS{osdvZtuyQA63Y9sCH;+-s$+M%y);4*3O}k zx0frzYw?*m4@!uZNAhb^?=biV60@zwW-rSPeT^VS{T`-zkiVHY9|~*3WE;3lT2;Z| z5BQxmD3Sa;lgXq1c-ZA3x%$+#a9vj6B!$3i zOzkIhlP|S&%BmV!s#MKtrc*m?yC*Fc7TL{7>I#+ZWWMQUxuuVqHH>X&ezz#2N?CV3 zb0u?E8|5r+5{^9Y?gZbKTwld{j zVV|C_{upK%>0}=CH!ga7&v0gq%<H(Ej9JNC3y?LdZw&C@zK4fz%pcfco#|y3hO%cXL78;N|0uSKu+z(Zk%=7v z_DHdH;1R&S?2OzlivJ)~vEu*5k#;rli_3;w4X|j`C>dqCw?`&jYrV00SlX$x1g>&8 zAhf$5eR2@r{G5V{GSe_u6weE6p*AvdS*1f*c1O6>YE;R74tc$4+N_i$g!(+AttR}f zq$b4}leOcTR-91l;N?j_mCJr1p$2R5pQ{hpA$hzdPA}xwbV^J$Dwjnt19ym$HsvVK zYi09MlKpQvmR$RjyPSGLvn=~B6x60r=Vr`AU)CZ@U;JxV{6GHb#Rr|Tg#X9S|GDbX zQG5B~13(*g-HQ9q{ru1I^XG{9>zBb}uKeG}{J)RD|DVSul70)=MtOreA43jsL7@y} z)vFchN)Z=No-mGi(I87<^|;J@_fNX%?}MC4291(uRy2XqB&z!2-RaaEu>4pVZ3C@{gw{dcVS92RM(@r6@Wnop9G|5H5b&`61=`IL^|~^+0u#W11uBpSFQ~spk@Gkv8XmR%-+!o-x&U16WpU

_&M#szsd3IOcovM9&2b=>RWPM;=`CDnS{K~VtE zv=#Jbg8qB%ObJX$uuE954eTb90Tq`Wk(1~`KSKZM$Mx#xAcI!|A=!Xd){-E8Od(V zPeCv@%1fl7ZN*47AAv!WP=N!^!c9<8o7PMosrikX1F12}(@UU3y>Ya~8UdIN6}H>W zByt#ya$-9l3xI5<)zEZ@RkMJ)`eHx-Ce`_}TkSziPUnq!*ITwcMj{qloNx=aN)>`0ftFd)w3hO*9bDi@OKQn+d1C5|_0C}iVikRpmfY)=59*2&B-vX9EW^ZI`p6XKI8WF=A zGMZ-UH{P(K_Q}?kDX@d4a@XM^%Gj4}I5Y2zxqi3Gn6qwGjyqvGh z!2d`FP41o#7@1oA5<+Ok-`_>kxwHh48Ig$02XQw5)^V*Zpf&kGEm4eGmwHpEKvwd* zI=^prD)3dhH|x6$*u7Y}Bk0n;K^1XIv5W1{*2MM|mx zxsqW+EPzn}{XIk=UpCQ+-<2U1V_0mM854#PNLie8wJnr;-U z=|x7fY7z2*L`>`ku&$CHI$(@Oua6Zsg4Qr(FL3A;FyMZrSwy`OX%Ylxz5iTy!8WSD zhqZ^zlc;?Nxz(?KpK&(|hLrpi5YZ$#*zpC|iCZHvh?q~3V2zuKFm9?tBSz;r#-@F2 zjEuelkrThJ184U)xR?h~`L6Up7IG$6zMLM|K;w6t5b6WRLc}D~r}*z7Fumr*CFKRA z>^!L=k%YuOHg5+LurVs`GfThx>()8XkgBRbiJ1#wCbT}L2w+{$8MC`+z21D#AgY=r z(Ez2KH1F&X-1V%MF$4Y+H$ctuW`jIq64BKwu_uPuLHe_x*9@k|F24sdyH7p!L&nm- z@tCR&m;#K*=n&C^(ZXxR7u5I1gn|DO=SXIvPOYo6CZO|S*O&i)y$=4mW2oo>Y1JqY zgzdcZY+RAf&ZY`^VOxK74(v$xs@tJXQgcw&0Ay+KPC+sNXXh@yz(&d7Pfj1W4^#Kw z=l);F&`TTHhR0J4E}+*Yv7+Sj6gpJ7LZQ8Dn*f|EV(!t=P*8Hf5vwOaK_Kv^21@01 z#q(NxUYh|W4+Cfsw~o!$0RynAX~y4Pi`@w%*1$HHM3c0H*z^{*zGz=^EpW1vW1}|0 z#?29SqWSlZuSo87I}HtyaGWjDr)Q5l}-$N@>8ZXH*W3>y{oP42fgq6|j-v0lmo4qpZcQIHWrul#1)Fft&3O zsw4Du?0RM*roX57PdEgLc+sZ8-T^n+SH2Lb-{ALTg~51n=yX-KqLev7_fw)Y=Gh%G{NE;PJJ39ooJzgL(KZYj|e-+gla4A-?Pp! zhR}&oJV0)pfC!F&vJnG=Wx3Fcun>ZgBGpKxl@9!GY&K6jTlrGwh!p}H`azyj7{c%W z%D)g1YJxa{+CMddgxk*os3BOS2b9@u4!8yJWN$+J5(77rzvdWx_;2(drU0Pcea>BI z1uiQ}q_uW|j? eFoChTyvZ3=8(>mheFOvl$;&89=Sk_m`+op63n0t@ literal 0 HcmV?d00001 diff --git a/docs/proposal/.assets/06-01.drawio b/docs/proposal/.assets/006-01.drawio similarity index 100% rename from docs/proposal/.assets/06-01.drawio rename to docs/proposal/.assets/006-01.drawio diff --git a/docs/proposal/.assets/06-01.png b/docs/proposal/.assets/006-01.png similarity index 100% rename from docs/proposal/.assets/06-01.png rename to docs/proposal/.assets/006-01.png diff --git a/docs/proposal/001-关于paopao-ce的设计定位.md b/docs/proposal/001-关于paopao-ce的设计定位.md index 36b3789a..754a40b5 100644 --- a/docs/proposal/001-关于paopao-ce的设计定位.md +++ b/docs/proposal/001-关于paopao-ce的设计定位.md @@ -1,11 +1,14 @@ | 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 | | ----- | ----- | ----- | ----- | ----- | ----- | -| 001| 北野 | 2022-11-04 | 2022-11-04 | v0.0 | 提议 | +| 001| 北野 | 2022-11-04 | 2022-12-17 | v0.1 | 提议 | ### 概述 - -TODO +paopao-ce是一个清新文艺的微社区,提供类似Twiter/微博的推文分享服务。 +![](.assets/001-01.png) ### 更新记录 #### v0.0(2022-11-04) - 北野 -* 初始文档,先占个位置 \ No newline at end of file +* 初始文档,先占个位置 + +#### v0.1(2022-12-17) - 北野 +* 添加部署结构示意图 diff --git a/docs/proposal/002-关于Friendship功能项的设计.md b/docs/proposal/002-关于Friendship功能项的设计.md index 37a2ed80..bdc3e69b 100644 --- a/docs/proposal/002-关于Friendship功能项的设计.md +++ b/docs/proposal/002-关于Friendship功能项的设计.md @@ -39,24 +39,19 @@ Friendship功能提供好友间分享推文信息的机制,更好的帮助用 ### 疑问 1. 什么是弱关系好友体系? - -**弱关系好友** 在Friendship中的表现就是 **你只能通过对方发表的推文去判断这个人的思想三观是否符合你的脾胃进而让你决定是否要与对方建立好友关系;这种好友关系前期是非常薄弱,只能通过相互间的推文产生灵魂共鸣,进而互为兴趣、互为好友。** 有别于弱关系,微信的生态就天然建立在强关系之上,微信好友大部分都是自己熟人、朋友甚至亲人,因此微信的朋友圈就是强关系好友体系下的小圈子社交,有时谨言慎行就非常必要,导致有很多人随着年龄成长到某个阶段,对微信朋友圈非常不感冒,很少甚至没有发朋友圈的欲望了,究其原因有一部分可能是圈内好友太熟了甚至有点“严肃”。需要注意的是,有些人的表达欲望并没有因为微信朋友圈这种 **强关系好友** *圈内社交环境* 而降低,仅仅只是被压抑住了,那么一个**弱关系好友**体系或许可以打开这部分人的表达欲望,使得他们可以在有限可控圈子内尽情表达、享受言论的自由。 - -2. 如何形成这种好友体系? - -形成好友体系分 **建立、维持、解除** 好友关系。Friendship提供 *建立/解除* 好友关系的机制,泡泡广场的推文列表依据这个好友体系为每个用户生成个性化推文列表。而好友关系的**维持**,本质上就是用户推文的持久更新、思想的持续演化,使得好友对你一直保持兴趣;Friendship也为每一条推文的访问权限进行**标记(私密/好友可见)**,这可以传达这样一种信息: **“时刻让好友知道我非常在乎好友、对好友特殊关照,你看这条推文就是只有我的好友(也就是你)才可以看到,够意思吧”!** 顺便一说,每一条推文的访问权限标记(公开/私密/好友可见)是建立Friendship弱关系体系的隐性催化剂,可以加速Friendship的形成。 - -3. 如何开启这个功能? - +**弱关系好友** 在Friendship中的表现就是 **你只能通过对方发表的推文去判断这个人的思想三观是否符合你的脾胃进而让你决定是否要与对方建立好友关系;这种好友关系前期是非常薄弱,只能通过相互间的推文产生灵魂共鸣,进而互为兴趣、互为好友。** 有别于弱关系,微信的生态就天然建立在强关系之上,微信好友大部分都是自己熟人、朋友甚至亲人,因此微信的朋友圈就是强关系好友体系下的小圈子社交,有时谨言慎行就非常必要,导致有很多人随着年龄成长到某个阶段,对微信朋友圈非常不感冒,很少甚至没有发朋友圈的欲望了,究其原因有一部分可能是圈内好友太熟了甚至有点“严肃”。需要注意的是,有些人的表达欲望并没有因为微信朋友圈这种 **强关系好友** *圈内社交环境* 而降低,仅仅只是被压抑住了,那么一个**弱关系好友**体系或许可以打开这部分人的表达欲望,使得他们可以在有限可控圈子内尽情表达、享受言论的自由。 +2. 如何形成这种好友体系? +形成好友体系分 **建立、维持、解除** 好友关系。Friendship提供 *建立/解除* 好友关系的机制,泡泡广场的推文列表依据这个好友体系为每个用户生成个性化推文列表。而好友关系的**维持**,本质上就是用户推文的持久更新、思想的持续演化,使得好友对你一直保持兴趣;Friendship也为每一条推文的访问权限进行**标记(私密/好友可见)**,这可以传达这样一种信息: **“时刻让好友知道我非常在乎好友、对好友特殊关照,你看这条推文就是只有我的好友(也就是你)才可以看到,够意思吧”!** 顺便一说,每一条推文的访问权限标记(公开/私密/好友可见)是建立Friendship弱关系体系的隐性催化剂,可以加速Friendship的形成。 +3. 如何开启这个功能? 在配置文件config.yaml中的`Features`中添加`Friendship`功能项开启该功能: -```yaml -... -# features中加上 Friendship -Features: - Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Friendship"] - Base: ["Redis", "PhoneBind"] -... -``` + ```yaml + ... + # features中加上 Friendship + Features: + Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Friendship"] + Base: ["Redis", "PhoneBind"] + ... + ``` ### 更新记录 #### v0.1(2022-11-04) - 北野 diff --git a/docs/proposal/006-关于paopao-ce的结构设计.md b/docs/proposal/006-关于paopao-ce的结构设计.md index d60999a5..180e8afa 100644 --- a/docs/proposal/006-关于paopao-ce的结构设计.md +++ b/docs/proposal/006-关于paopao-ce的结构设计.md @@ -3,7 +3,7 @@ | 006| 北野 | 2022-11-23 | 2022-11-23 | v0.0 | 提议 | ### 关于paopao-ce的结构设计 -![](.assets/06-01.png) +![](.assets/006-01.png) ### 疑问 From fd76d626bc1cd00b822de998b23bea574f071d68 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sun, 18 Dec 2022 12:19:47 +0800 Subject: [PATCH 37/65] update proposal ducuments --- docs/proposal/.assets/001-01.drawio | 2 +- docs/proposal/.assets/001-01.png | Bin 233790 -> 233979 bytes docs/proposal/.assets/001-02.drawio | 1 + docs/proposal/.assets/001-02.png | Bin 0 -> 99270 bytes docs/proposal/.assets/001-03.drawio | 1 + docs/proposal/.assets/001-03.png | Bin 0 -> 156762 bytes .../001-关于paopao-ce的设计定位.md | 49 ++++++++++++++++-- 7 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 docs/proposal/.assets/001-02.drawio create mode 100644 docs/proposal/.assets/001-02.png create mode 100644 docs/proposal/.assets/001-03.drawio create mode 100644 docs/proposal/.assets/001-03.png diff --git a/docs/proposal/.assets/001-01.drawio b/docs/proposal/.assets/001-01.drawio index 49545269..e3bd7cc0 100644 --- a/docs/proposal/.assets/001-01.drawio +++ b/docs/proposal/.assets/001-01.drawio @@ -1 +1 @@ -7V1rk5s6Ev01/jgu9OD1cZzM3d2qZJOt2ark7jdsMx42HuPFODNzf/2CjTBqCYMxAjFmKlUxmJe7D0eto5Z6Qj69vP0t8rbPX8Olv55gY/k2IZ8nGCPTxMl/6Z734x6X0OOOVRQss4NOOx6Dv/xsp5Ht3QdLf8cdGIfhOg62/M5FuNn4i5jb50VR+Mof9hSu+btuvZUv7HhceGtx749gGT8f9zrYPu3/ux+sntmdkeUev3nx2MHZL9k9e8vwtbCLPEzIpygM4+Onl7dP/jo1HrPL8bw/Sr7NHyzyN3GdE4Kf//nvLESzH9HjZ/PO/Pfrdo7usJP9kN/eep/95Oxx43dmgyjcb5Z+ehljQmavz0HsP269Rfrta+L1ZN9z/LJOtlDyMf+Z6bGrtbfbZZ93v/x48ZxtPIWbOHN2aonZKvKWQfJDPoXrMEp2bsKNnx4WrNdg1y6Owl8+2Jn9Bj+K/bdS86Dc6Ala/fDFj6P35JDsBJK5KcOpmW2+npyOTJrtfC543GZHehnSVvmlT85IPmT+uMg3Tue+QRLfHLazO6bfp2YOkjfkfh2sNsm+OExv42Vba/8pbscjCPMusUSXmK7EI5arziOu4JGtFyb/7hKLJ37xo99B+ukaJxXNj4D5DYn552Echy/QoUVPc95twTHYppxjiCF6Bss8gwxlnmG3K3jmhz/v+HVBVncGzm1ZNDBRZ18k2PdguJ8DNTG1gIlJ/ybGgonvly/B5qNYWAMQE8HCX8N5sL6SsXszMdGQJ6hg4lkS4Q7TvgIPa0ASpmDf6eFvoCYWIKyBiS3BxIJxE3tt04/7l/X9Ik67Inlc9sWb++vv4S6Ig5CLz+Rxc8EJ4T5eB5ukb8O6sqkDeDdeHsG3FfMRl/MTklANkQXj6txUo+d6e26iwE2odzfV6MTenptM4Cbcu5vEnu3oJsI4RhfSywO80U3FnoYB3NQ36RFD7C2PbqIIuKlv0iOG2OMe3WSaSDfSE7vto5tMC7ipf9ITu/6jm0ybH8TQgPREBUFwU3KdYLvzq3UDb7c9mvwpeEuNrYvZCWhrct2EkxVEsyN1Zq+hKgze7BQM2eVyYH9mr6ESDN7sJnJ1M3uNXv/gzY4t3uyEitzesdlr9OIHb3bTtDUzO6rRKz+ZncVAi3W4X1a7QROrOzyzE0kcY0mMriw7hiCxj/1PP34No1/a2P4wSFLM37BacIRtgTYWS8geS1xhW8pccUE/OonUf50zshy6/lJI06u0l2wEKfLXXhz85q8lM0h2ue9hkNylMAqCOdsjlj7HLrEL99HCz846mVW8EJPFyy4Ue9HKj4UL3UeR9144bJsesCt/4LwhBvcpfS777PHJh+MTnMCSG/wa/FzQwR80foiLzru9Ln4oaANV4Yda8vuUPhc5e7wq/FygPAwaPyZtiX+sEl5oGz8Wuox/TKcX/rkFSQRDwdDpu5OIbkISAX1zDcx+E5KIDdHetwCI6kgim+V9Omllks9sqN1OJXaJ3n+mX05NtvlnduZh4/NbduZx651tvQVx4bRk68/CN6eT0g12Tt02Mflth/bonFmYHH1scKpZ+mw7a57pgV4buoEOMHUAUmqHbmCmCYWZbCVNb3utnSgSyVLlU/cexmTAC5+NwiwSV/vF8Rs2PPMSLJfpNWaRvwv+8ub5xIUsVkgubs4m5mdJV7n0vc9md2UXm+RzqoqIO/fWldKEMUX5jLSmAGGHhE9PO1+Ny3AdgalH7igwB+qOOazazGGNzNEKDEXJLfj2mAblm2UUJud+TA4pTNeUcwgGvd67ATAK7ohRmsUiVoFR7hKSTmLWc7SSbnz3oyAxS4qntqkmn5pTg2rskWpawacoCf4jJYuNl54rnxf1QdgGV7CN4WKTpxukP92ICt1nL7GOl/Qx8R/fZmkj8uh7UdIlhF7tYB6LPMNoDRKSBPzAjKUcR2AuND+B+vq+LSK8/6lsZrRsMA5DOmivd4tlEpq1Tn/+buttOJda/9uHzC53u4Mf7pMDEN2+HV4p9n3yaXX4/4FOZs5kNmNXTB7xeNHs+2z3PLrqNl/fH//1RYBfPmL4vg4SHEakGoTzI2K/zPMd3uLX6oDjb8dUNYbWDIOmABIeoxQCuAUQYSCQmCxnuQAiRyqQqMOQqAcemEFXj6icY49MRzv3iLrhJ2/xLE6e1cZBLfsERlemZK5i1z4RRUXWjBoPm1Vqt1vxDmVBukZvjKi0lUzW7cMpBPTbVNCYyTIR9XlliERLSwOM2cR5SC8Ng40xqrik2QL+tjTwt2Qu1ujvtppEkBClg78lytaDObmnkzSXYPTx1Q2rDj6ukTDWTL1ETHm8dExUJkEWxlUQrT2yckenJD9YoaqZt4TVqibudeiVIl7vMKEYWVvVtIBwAvUQ1aomEWUwzXHrmBrili0EqjluMSU8cTZV47HjTk238MdfllpTyzTyP/CcyjFdJ3nuekyjIqJzfDfBdBHPhQHvsjEpGZqX3u758MSXZIi2S8mkOutUKbRBnE+bQts1zkHb6BfadRIUW6DrtqCNWoB2q2jGw0Azcfi4oDGaCbWn1BDwqgmaRf22sHgtgLXidYXz16HYjyks9jzBZOn5ztNiAld8Tr6xFo4/f2pJsKheZFg6mUrZ8nOEqMsT5XMs8AVB4ikgxBdliLXJJmwMuZJNsmWae+uuUB5S1G7aXXHBhXDX3RXZdOKjghLAwdcUZ1eJKoehvnx893g5/hbJ7sJt4SvxIZI/SFW6qmHzfQr9M83Y26CczxrR2chmVZE+iI0asxkxrSm4FJxsoZrPqDgUIBNyO6YSCmIhrIBXaGUKq0V4YsH6EwsWvKmGWOxGzGKP1FIVKOGWqIViXjbonljE8YiSbMYeuEUFneAKOkEuWNf72hxVcJku6EWdVk85ekHFZPckIrlcADr2kFl9KtwynaBetRmhN9VURIcr8RFqdkwS6oRyHlAO32BdoyjeJT0ODGRFavWtKzJ6176Bawu7ghLQ9XQMKlPCS5SAfWNpAJVIAw9vsX+c+PEpOcM/rDhRpRQIT6GTenCi6Hab5ZLhzuz66UQqNqRxJbI7bIa7L1AIxeo+i+C57OeW69MdF8EjVBSob7AIHjLYemosnui/Ch6homA73Cp4tSzcbW0gwgKDD1HeCmELGLj34kvEFCW6IRfBE02sAYZF3WzQVfAQ0pAnJILQkMtlilysAVWIAs2gS+GJONbAxjU0i5ur6YAMNpD0DpzSW1EHc6xZKPMTLGXTe40UcyxaKPMTXJqy9yIp5li1UNZAgfRcDXivRsGD2/MTNoCfeuc9S+w3j35CGK4N2zvvWWL3e/QTyrtz2vCeJfbhRz8hYgE/9c97Y+lCmZ9srBvv1Un2GPqa2AgJdcL6XhTbuoWV91GeTZnbve814K1bWHof5QvW6mP3W1h7Hxlgbbn+K7RZt1CPEOXdYX3sfkH/fNCVeZBB+ITXxqV5UP5IZVdqqTYPysNjcKPSJzOcsydM1FTnsS/QDoaNIeSS856vjSEMmEAZhmAN1EoMYXL2BFUYukDXGDaGCG2Lh2gJPbSOIVg1uhJDxO2Fh2poLsOPIQyoofRer8qus9jX4O2OQV9FA7vfhCZCbIj3vjURW9k8kdNMjgaTn/suFMYkuurFZI5Efba5VTjpAyEHc4hqPOsDwXLDnU/7sEWZ6OOWCrPPz54YSKkwu47CdGulwqzaRQaPrcHIHS0AUZTcbqFYmF1SAOq00sLwioXZNVS8sVgYnMJQg2zoSDbtINQRNcIbKRdml8xwPq0YNcByYY4o143lwhpPIQUNjg7lwhjzKCkXxhb5P1c/bC6ZHq6gplji7ngV+bqUCwCtr5oSIHCJOg0K8TiihHizlcVcy9DOPaLSeFuVxYRQTIM6SY4oQ95qaTGEYRkrDd4ZUZq7sdpiiLj8fEkdXhqZ+iYLR8qqT8lCkzEGubiNA8jQoGSRI8lAa1qG7DV75NTt1DDORsHnw+k6VyripyRW1gBW3TTTIMlLB1xJtLlLyp2NWNIkptAAS66oogn+0Ks8lY5l1VgMUK3/HoP+3vRfjHhhqHFdNYQtIDF1XVjNrZHfpxdydSysxmIU7ZFrUFCwp/HIheGiKYgV+y2nxoptjuXUuqXiksIbnQEagrA5oDEEdL9lp9yOarW2BWjUAqBbxbA7EAzn+eFXYxhRdwqC454xLArUOpdO89HS9NMkCKF0mmvZxEtfm1XkLYMEjOy77LWbtKC9sPe7fMXajiuqueoSavlElKFVVGPD7NXUQvulFkx5TDWuFJL0usGVuq6p5l6wkvpYU+2EluYZMm5VXu/waqq56pJ8m6b661BTbTB8ZoBQqTmfIdPpu6qaK45s3EhVNbcy13d4VdVcyXiCEmoZWlW1wZALxm2RCyb8nMSuqYUa4oDEh66r5lYl8w6/rhplfXd5AFwj2MUVeZ+DrD+kRyG5FvmSGv3OpKJgFRWh3FttFoSr1XVdOI4aWPLGqACQloXjuihuOIBWPeE9EOhfg2j+3eh6uk7GDXWXFshTQNbhflktqeqysgCF5Rwkq1zKpl2YqoRQatRY0aHBKjiARYoccn6Kb7OJf8pGC43aIy1WScdPwYI+Dlgch0J41H3r3aoLKX/pZTJ8SchWzIH1Xg7Tq9Ktx/fNgovCjFlqdlZax/gehXG4CNf5WTACk0372euif6rpVGRvfSlPHVpqg29atJcpqFFnAdNTTLRIiT9YnG0ouDhDlgJYOmZT3FYzTFxNSceueV/hCSh0S2COYu0izbBibueRyWXKetu4IiBkdkZYFdHQFFbIgKFzHkx3Bqw6K9CqAxayeGCZI2HxgHCaIsuZmm7hD6x8DLVX5TC7TL6/GmZgTSDH0axd7FuGMq2WWkZkoZ6bRnb/vqBlg5hrhFZbCqdJnKlzSq5jemN/jSWSjRF0CDW9gjDtgAZry9cHGj0LNLN7oGEJ0EQJ4qJhJFw2QJV+OXmwJ/ezSTrQVzWCNC/VJWL/LVYnSXj7OGQz4yYwhzQbXCgmnLJd4H2alCkZ9SVUAtabtyW5pLYE+DDxuD0FFcmEa1V4mY14uQwvCDlWV4BJNqMwddeJjyJv+/w1XKZy4cP/AQ== \ No newline at end of file +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 \ No newline at end of file diff --git a/docs/proposal/.assets/001-01.png b/docs/proposal/.assets/001-01.png index cddadbde0485f1291edab144e415febfe2311343..35fc33a3126cde16e8db7b8a10a8d8a01600b13e 100644 GIT binary patch literal 233979 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�A8;xkzlDEEC~eihk}!)6pc6uwUq@)a080w7n{ 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

bKmp=;5BnW0jPg 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 literal 233790 zcmbrmbyQXBw>OS}iV0$&B8`9^mEC)bpu4+!tLX0T-WDdPgrLVnP^{yzyFgG;zyKRX z>_9~f1QAhq7vJwa_rAY-$9V4_zcDr|o;9DC^O^CPbFIND7K1os;MjqFettv9Bpk=j zuU}t3KmX4`{eTwymMePT)W^;tV*C!(hQIgo8{N-=7dea`mDZs2i-%zUeH9N*)|l;% zcnB^Y48|Lja)-@q0xp4eqgkOPNb4}bXq(Z3tSttdL?ioD&=}}Zx@A4>Yk!C1LWZ3DUg57 zi`Cf7Mu3O_N`_8Jo&p1bz*9gVC_wyQ4E9okra*u;u2dzpY5%Y3dU;nmr0Re3t+0w@ zI1-0Sl={qqxg3TKN#OsRUzgHm*8;-&m+1bPytlK%Yf=73XQfLk2UY@(hu{H`E3{Iz zO=<*4wErPh+FTL@Zka2CNv&+Y)D1H-sqBA`Zju5l{A*|yAlS*Ee-DBXfNXl09gcS; z11$ud+KFP~KyrzX4pD%u5(?7+mfG|Pox)D{K*1y@i@?M&e5zjQV0Ao<6)UED&^m&V zYT$c}6eR)&aB7B0;A|Zn?Vg%p;z*i zE{MqkrjsNzlpdu-y4(&Kmd3*S$QG}f4s0-nX)+)bETEgt3?kWBG^ET8+;D9O2FdI5 zG9W|+9!l*M2kv%lqA;qx zI=Ku6P-B!DgN|*Kx_rqbI|~d)aa1;k6lkY`Bn*@f=tBdx!hrMAfw?dexQu9X$W$_k z1O@q*q@YNN$H5{CWlRzSEH#@XR2NmqR#9*)v&crrTfj0qm0|Kgg*Jvl4f4X7ZUYh+ z2uv}dFgoCZ3d|r=aFKAF9F8^s6BAT8f)37tz$iF7hC+o=7fvk5rq(x?z>#!`k)6VCLj8p`k43pY?TBZ|9Avy?N89;;3P-zqh!ed6E z0PDv%^-_vQ#Lz);Fr3%~gMsmKjTazeoB0Bk90hZ@c_gvL;?Zfb1USZSN2=W(gULvQ zP$4>_rdOtb=rAM!MqrW?eMUggI1EPuLh8XRh1y9$;ut(4NKH0S07|cns5YBihTicp zFe^hWMAO-LBnc}*GGKNZoNE`^eRKtpO@V9FP=lTeWg~blHJK$%MsqDjoC>ZaxXf6w zkWBSrv|I?rL#BA}5QiffP%;9d*Ahf1vL22gn+$T4T?nw-%c9E#<-*Bo7?uVs7sK($ zk$4J}2UB8TPQ47tgxjrpoD!!{lI%nXK}F~Ejzj0^4QPg*Ez-dq9zNj5FbcR54A;8x zV6(!f62R#^rOD!;L$NZs6XwF3oDeg`PKI(cDz4YfL?-hg1d~~efiTz*IER2kV8JYz zl}vV04X$J@lL%(gl@K9U%EhU;c!UeEb_X4c&{|X|G7m670$gWI_R2^|9$U@g;4yrH zn-8HX#59-B3gP2q2sz5=a$A&mC&MOoNw7kVP3{2W^&SD%%AO<>F)`-KKRTG+L|&FaZLH#ezT?=3Xx-1+$=T zE`dgeATUxnnd4CN#6m7ot>l6{8X?jmm-F!e8Pjayt6<4KyT%I#ZVeQ2GTfPL0K4&2 z6-^}4_>eFw(m+qvfSpQ|M$hmX=x8gJsj%w|Is}Pk!_!bG64r-=!i@qUu(K?J*9+w< zQ6#Dk%BMm2N)8GHg~}*)r5)=4CVbDHr?I*E_w z8?7Xn5o-iYOd`Vy7&3^{VdAQ}UIEPjgja%G=`r%qSQyZo;nupj0-()BKyvJ07K_fM zQB)R&P|9(+dtCz3DT8^)e7iuecFOEfBh09v2oR=Z7ofTdFkjTmC&y0kcoyMGJAao+k*t6DM2MM>UBt`2EkX54H^Q%A;!RIEIPxC<50O6mJh9? z^5q;b+Q|Sw9_C+;s@H63Tx#zg!VPwbjbo>yVK}By>ry}+2E4@z;sJU9L`jUy>2NS9 zie7C+IY~Y&4B~{+RR{|mhiCN07m@&KL75<4sYukTC{O}ZVu$G&Muv!oL3or5k{uud z`yecu&C2Lqw2Jhvfe9dv7^7ktX;7CM$|d2YdZL-F!7kP1FS zEED3$Od}dYR+>F*tP{;=i@8{~5$iEI*=Q}tYh_#MOtuv*R~qpIz?Ev{VknBv@wp&c znoUCi7E18Y@Ngvnl`u4w9nUc+jS?zM3-UoZ9KJ}X!qRmyW7U zHt>Bygq&`{uy`^711t9O$Q+c&V9??@G_IRT2g^AyE*8m9Lz6vLn^q5I(*SlII-c7B zW;;Pnoy%dd;Pn`+L5)BfybdXjDKnb%KCVa%Kq?R$Y{Ti`PCXANw?3L@4CJGKEHcPD%2b3qUYGqD^QY#=E5H30uFBS@10tXr6M!WcIkko9% z3;AxJh-5QjY+8dh8E@4YoOCW9Dd$N9Py|WG(}N*Mxv60#P|MH=-?r-M(GaWE#pxng8& zhaKe8lVos=N~++H`9e6(=CEQJLNf+z1?!0JWVBDN(n8HRq7*9=nm`zw+p0E7IVv#N zPEtG6G?7*z7WqJMl33>jJd)0bkuXg#pM#-A8x%;M4elYBdsR#YwovR;jZ#8T!;O3! zfKQotE8Wh6iRgADT7ZFS^=c1BVbIb<6pGPJcSb#@WDnf&oQ!xVn2l%z1Z#mhxIVc|n5=fIsW=>nq{JHWG$Kt0f$Cj& z0#*nob5t07GT4q5O9&95k1bH4*~u2Pi9)8a^>l|pYw+690wEb~2dja+6hovi88Wm- z$4}P6oHn=^O=nne$vBITD+J+5a=1rAWzl&wqKK!2CiCT9kF@t*M6r5NUa|#d(1Q33 z30ke<$Z;aAi(@C^dR-8m#{hi1(kVyv&f$jWATTVE3T1$OE|*Y9g8&*zVDr2-hY#$+ zDk&(qJW68CeH$>G&KWN{`el7<8Rl z`mcaxcM|Agz0+wUNXRg}N+yK~csdK(3+x$GV`VYzIJby~Gxb6YgdH!Gz?n=T*2ZG_ zU{Eoas&_k~2&{tWG`OukDTgg(+2kZLiJOe(OL%gbl^`|}KwLD_nw)H>xwU4IgdyM} z?E0S=MARLyqx^#ZWT{3Ng4f7JxrKL#IXn z*E$~+s~34RG8hX47!N^)g-b|QxY}aSX%Qwh0DLeqD2K7nqBUf?1_JB3{hV+i(h~gfFoo>HPA3155++<(7YBfL&zZOEeRx?IrrMDP zG0XrGsOfwv1mKor2I3C};^L@uB#p*OA}APQwu6i#fJ6cv!zLlAEFOhd!S&ibMlv5E zA=vl?th+ZUCy_NuqLwQDmxR1vlgDgv=$shKSF0 zISmB82L=RrCxJpscG`&orxgx(3AkJDvWNj?!~mr?r&vNa!UQ5Gz?@rZwZh;Q3epId z!QmhbPsYO_C1woU$}_6S3YNtQw@Rr{m>q)G0N`2f1wj;0fdbG4krs50F{nfe7@FYLf$4m}@`2^xY`sWP z&+!sr1ecLZbU~OFDn(7;2sIFb!$B}}ZNLU8m}IC_$f6OgXe`@c7U`T?jgv{n2w6%z z3eVK2)ZpG?1w^R>O00OPpzR*;WsF@VKZGhlTN zjyPFL!ccWuG)HWf%S~{q48f$RkQO2q3Xzh%AR$+-V7bLWEXLprYPlwv0tJyEHi*`b0{ z6H{b#_m*3fJ}%G37Wjl%1{Sy#P=o*qCeQ?86IY}|Fo|p*)GKytd~BHrt2UZw6a|z7 zmID4pg5nDJXopnh@CsoTnz$D_;cy-&E}1}(8}U+*0BRJ2piZ{ig~b_!0w{*Uu+rTM zg_5H4Qd|HvFpnD~qDs6_c`uShvwLf%y}#at{8MlJSMe3N|BsS41YcLxcb}hMlph&~ z=6TXT&gs8kJ^yMK5?RXfw;9( z=(_?jJ}_i6?RQV@@3%K;GEBnappF(9*!;BPTIYqDQg>ZhQ^V4W^Fkye`ru~{V+H;% zr|lPG=W#jPFFupc*&ee!DA9j)#{csa6_l8?J$UK=ljc8$v1CMT-&N7aw$r)!e;M@O z9SZz^4*p-~?-1omP80e6+z3%_b)c=nKLxTeSm-zjd8aDV^T|@WR zvP+jR3YBW*vuEjD=YBp)|NX1;+wIflxtp2Bo*>_x&zpa4Gk$xOH$(R2`NjJ`p9mu7 zzbr%9-)>*r(|x{uu(j;`tiS*MJ0vo)9Q)+s4NuBl*VXJX$kysu^rTo*k&PzSN7M1_1{Wg<8SXtO#G`j5Yvq$x?uIKHuP8rZU2|2EPJq!pW#Up1=867%&c*h41tmzVHT|q(j+~V1pmzUhTch6WW zRo4zWe{550tIeB!GwtlDGGAL!Y1-pAZ{F;{uNl>zc6v+m!6CzI4=S&3xc~jb$(GOV z6S?wFn#bpAho$&_mwLZ-yV4qN>znOGCvR$-9~{&?I3Nz2bXTQb{OOt+f0!LOV#zk* zO!AU#Rfdg+zV!9myFYZOdSv0Be9O5q3*YzrQ0v8(ua{cBUVPP_+0*%}kLP!v9}D|@ zaYyDn>5lrfqqq-fQU8lQef=}4UZH2to~_u~uOjlq<%kpTb0^q$zE2d2%5jT=$NaT> z$;}BZ(md>~xhtZog8IE^_l1lbH{53&^Gq(6zi8)0hnz_7k0p4!2M7MzQQzlBX?kwP zyyT3GXXY`V^t0C$7G|$rJy0ueSDxIcFZr2MI`sb5qf61Z24C;ky?jxtb5~jx0fkCT zOkCS3G9D-%HR0sF=&W6pINrJNJEtd~$o+D%aw3!&`1{!V?Mt?FEd6osr1TN{@=@Nw zc|MzFJl>iDI*95QJSZtC=|}V7@>_f8zT)llrkqf1@QI^VZBZw*2@#Y~j48 z>2pt(nTJja-+SuW>H4NqS#jUSSf_1!ew_RGVwMxu+}W`L=W>*3g~u1({Q0gP1OnZu z%I)62f8kBvh1^5?TRM#QH+OvaIi~w^Njcy%DooK8Eq~WFEvbL?CnTW!^z?|SrMJuH zmvQRgt#_N(74sRv{_yf&pVmz){`I<6Dac>2Y^ zbx!H4Q!`#yUq03Nt$z$7^?|FfDRPFP(VJPZ?TfTmddHfKQ>*rcDwc$2$XVU7412HWJK2t1k_Oq>4>(OI9 z>pMhK=W-sn_t%+QsIkwEPM4F9TefcZ-kfOKiK%bh`=qu<)Y1a_bwwvX{&-&A(V9B` zenE-8<4}Ib_oa4xTgQ|kcYmcdJaxY)TCn)r+nbuFrJbhKuJiN1Zh`4B4rHgtR!w(I3f+0mpif9O-pxboAJT3m0ooGV(=P)l;& zG^?wg%vyZ6Z?_QIk^o)3=%0jxeThTyJlE>3QNJRwWEjW&eD9 zX&$lbalR|%&Yrh+QGKIp*Ws3v;6FIeu+uFr)GS=y`oi^t_g){PQ{Rk=jt2bJ{@hn_3469*;!E=bcVG_N zPM^Os?c?(9t((@zbuB(zH>kWWp{x7M!!s6#Uz7M{B8DM}jf;!RvIo}%_LC~>dEl>mQ`tki%Jot#M{bQzw2F*-yL14uztn(v~?-Ax(~h!-`g5o zr^*}N@+Feh2M!!a{SA89{JZ5w)5f^5+h%?jJlcHr<0{lWc>1D6-Op+(PHy8O7u`&q zJEx`OF`+nsHs2mG@BF*tOU{~z)g=wzFP@w;I8Cil4V>)F`nxgYnschPU2-P$#> zth?dC=qHCJTy-AYJK@5~IqLB4ALES|x^(A9J8x>$b*G#+7tXJv8$Z|cNB$k<%S#`VXAwpLO){+I2dkL z%pgy zTW9O1+WYs-dmVUPpVg7EskP%H&o>Ia$nAa9|5jXVKdWop-=&Lwb>$RWpT!5zVy zqrTsnI@NXY^VjII{P;gH%hsH})}NR^h&*Oh7IW7+T1dp{(Y0ViXu+%eO_*2Hc5V)^ z{CWGG8B0--Wc|>dCyRI+&gU2AXN8#>Cif&FDHDf{j$HQR^_jKYkmpklhb~(vli-Hl zY5sokRcmxoZ2I)qH{1W*9Z?y7rFzDzFRu=L5!LU#Dt`JcPBv%JkFrH^$_dL0T?H@p zw^CCdU-@z)q_yqv#EzH=4_5xT$9lc*X1~LiS6djQ(?g|(58ncx+xreH9yMsz-~oPw zsUo91)R0AfJ#BKy(v~w%A1azV<#YQ4hy3L)<7RBXsUtQel@B^{rT>@%<8wa@J>&fm zbZJy%bkB>E0gJ}1)!aOItYqM`@~%mYGrxkOmh2){*Gz1yCXSo=;PBkY+%HeoT}?R- z|CaQ4WWe)7-!BGDf0cdmpw+#nXN$3CM!NmRib11Gn8j%?)O+8~J-SV7HtHY#>1??M zgEgHsJOVqK9~jGj?JV8d4}WcEgzw#s`O2J>X_=`gk5O*R3FtRCDERnJ#k1T~$GhJW zK2qjyIn(&a`>VU_^NYGyr``&_m2K0WhwOS>TRY>Y_u;TVgoo27hdK@VhON)^7vTEF z+dsz}PsjfLWSV<&PMwwPCtf`%Uu|J7+Vg$)h4nxbJAZU{^%COK;!O47$cazephfm& z50Q$}z38HTMsrkF;fNHOJUhP#oC3{yoL`-4*Tl|w7nH%?9XF7+W5@Z*F}R(Htr?&5 zLrB>tqp{g9Ljq6(`i}jk<*7l-{USXDBi^k?>(qlDI<2b=E}7)aEt5Pv-E zts-d1;t*SE)1>;$paHq`SLI3Zv&&~>UDf8pP>pCHC`Qf=8bI_DC$Zx)BbO$1y(*1f;fH#GTKS~YC{-_#OH~aXWk8j^^2n>$WPo3(BnVisf zRnn-=c{z2cN0;of)W_B#V*1@n_SQ2C6K@`#>D#G@+auD)ysv=8$5quxb~fSsNP`^Jq7mt*^ zq&|CDvN$gULs;`)3G>Hk{&4}Mf#Hd@WWe$MJbvu5@X+JgEBDSQ%2N}DEV(=`;i}nJ zYpvJdukQs-2BShr|m+ZV*uZ!&cV|7n!%&c~n@lrkL(7+YP=*Wwvt=oObhJFDQ! z{i?J&gvsI$wstEMIZ8YvAb>WKJQhK6%Gl4OW+UX$d=McFNBXK{69z`TsoRAt%} z)Q%LNQ*+{S-3mDGKg$tI%46q|mTV)(97ay`Up=!WXzlFz&4=nNA5LD*e>{EG;9E(X z$t1?{!PRjA;k%*Gy(@;?ggWlBA~uFh>gO00>R-zl9m(>EaS*J6C@uDJ5>q%mYEX2q~k$`uUMa252_gSh1x zYe%dl4dpg6@(!#*Cg8>o-FP#7S>%M;%Y5dx{gMAyq2?hyF#C`3@uB3Q(6*9YGgBL1 z%;=tYX;AUxO6F{H%K%w^+DtCmw#U$Cti-J z+*-^IzB2UCzMl=sKfeCze+TLE)U;vV%X1DMq78d^zE>%lo(=z+ zmycbWzj*@T_dObQrB z6l4T0ogEoeV$iSfG;P)RJ$kloL85gPVli!Yw&xv0w!~hosSN7d{G491y;Zi?(|R`} z;%V_lQ2{Y-YIak(=ac#1T8%#hu)$o}=sRO~M}baEcpD;Lj&A$)Xlhg4_rkra);pfL5px2#@%c*5`ozvnkPH5|@(3tW+qV&w*F&~na zy>4ZlFTNcJpR^@r-kiwM`ay5{9r-}whNa8J<3)WC_`{`9H$u>L@FrMc#SBV6i?GZ&E&t8YiKh{sO z0Lb-L;@yVqJHwy03|ifknp&^5?5R)7xe1+4BnGjrW^U<%7A6qie}OzYbY1Ul8@DQQ zY?oG}E+)t_3ueTP&CXuCiWM~=KP2q@vvMm;V-z%4k z=iA3V)gt%Srw&;0uG2g@m~v;orY80~+T8sx5j$hRO3H+1{)&Sim)YO^qF)Hm$BxfW zSUmyzBcf?$$(1wr7T|m zs76ybcEinKQ@d`y+0eAO`Y*b7Jaad(I_TAlsb>e^RtJF-V*6HV{Kh`lh9H*v2gBFD zd=VaoidxYW0P3!anw(N#&H!FUyxw~MkC-c1W;u0-5EG!2$nKwb5Q@clcLz6#R_QxS9TA#16w=gcIT)>_v>#z)~+29IUyK# zth(h-YZ&=r%&MX_bF%j3V|N_86rkS6&Dz)(vO)U3Zojo=+1}3$0VTqu|E%cG4C`}k z%GIi>%Pp?h=;#>4Lsm2g(3MXg^9CWF?=)|Gb#zj{sMy#5e%gmO*zBj!iS}<)IlOu2 zkYC5f9Kcr9^XFp-A|U4{fj2kt;*C_bF2?U$$z(^K&%W+}s2lo)_W&HY6(g(j_Ym zx+1@06})@g0nzA!DStMHkk-UjYHYnIArW~?Yq4jQ_3DqTD{4Dh$=wcySg`jON(bfPUqF_ zbf8!^4QiBh*dF^%3Nk*PD|v*R2hWgje6KV3cG$?TH(jJz`k1cOm^zIIh7=%;H(tPhEa#>6f@kv?O{&uriGc3b+uz!!=8 z*M|qjL1`tbLz&Gbfg$ULYz^v97JQ5*%W49~6mG8Aba;rjqHrjmk@wv2pf-Hyp@G*R zkK*PoSrs0YblD5Kw6rF7^n&uiRF-ws#w}(R84=CT*!$4;K2ZPXd378B>v#WUibZp-MkFrswjof&22` z1%1Enyz>{6MwiJ5>B%#eoPX!OY)zMShsA+*+Rl^BYz+ziH4Zd&fQ z4!rf4>v({fAzt47Wb2Ez%e}?Ly!AtO{5xa6l`$-N*Gw{b02l%p_l4rr_U0>;jTJK)o*01|a<(aJd z3vtokv)IKeTaO@S%*%Q6HTt}EC22@La$dS$K|jK=EL=u(pyy!p*ti#;1pQ^QkEFUB zPd6kuV}HrtTi(w2=C}4%wYF$jzx69!*P4?vm*j(D@>zoCBbF{BIL9`i+^2v#&R@H( zW>0$_?kNjNKv(}Pizq*E`@lNUv7&?knX>fP`xkThv2*=b1=KECxLXl_y;MZ}m~>N7 zJ%XTFdnV||GLAXRzhFT2?5qvMpY2=Yf3%;EM>cI39?Kp+zvt+kVgI}mT+(lqpK=-S zF6Uz74l+5vkubz|bo*a}p3FS)kstW>k4IS@<+F2dZ~Ts>aZZK3$pLKQK~mkiZ3e7t zLFKI*1IE-j3;IGgjoS&&c>rQN6J}l?WjaMVbAFa^%kNuJquQ=2s z%1(X`Q>B+~SU7e-Ol}oybLa2`Y+^EaX+0-BY1-kX)e$KFP?$7s-5FOd{?)<-iTwlW z6FdD&Y+)A0?9oSaYcE!G+D$j+%*z`6G7dGE6LaQUdiT+bOY+Lov!lzlzNowiq+j=g z*SQY;hlV`w)ex%{bnMu%vA=xIC4h$DwjVe#I5M|8Jb?K==g`8G)zUP{)6A=mv3qiI zXEepMPTNg0=*i!2k&J_%HU71=(cds@Yg20T`?GZ&v`gus!5=pgzO8S=echwJ=U=57 z8lda0r!g0^QwiOF1@#Xd9T!)!b3)?T%D)0; z?2Nv%F3^1XazMh)N#GbTB{YX6Nn#Jb9XB9$Xky)ny2hcX9gTrYq81gljuYINwdUKW z>ExgH|38H-Kr2Z7kl{mj?ZOp?y2`2+c2VN{et6M+W6rq&pBEk-?9K}hnm>DW*fZ^4 zd-JE2PmdxrX$~)B)OZfvO{_h2@8sVHS}!e&oAknXZ1NxZ*Z}w{e_v(QmB6EmxP8{H zUA0I2Raz6_yK|St2=F=_7aNB36_slT4Q+WctfuAxq2PD^%WC0 zqfn^QJZ9z$Qb1Y!LHWQc*{rwmM>?N`y4G#mHaWfPM$Xzl4Ma|9ytvXeJ2Lgh<}aRa zdxj+1dC}*|<6iHo!UqkQ8=|b;e&flFRX~Yt`;KCJ@-brg-iI%i)rqs-(#MgnT5_+r z+FBF#%^Udn;vQLW_?20=c4G%sR#sLwBn_{;zk+pR7^s`-WOAN09w5l;C}@l|Ks)TskeI0q-*Z( z9tj?{1fBWMw*a=J{NYn$GuH)GRb}tM+|;**RsEZ_qX19pu`g{FS>- zRDL<|{w!lv(Ze$&)6%6&{ddLfxx^Q&xOYPVYP-9M8GH7LiAYhEc;4B~7hcrmJUkX3 z+4A@_ma*=@k@dp{1d)F{j+=kfnDrsf*%${YMpATb=)Z}#x`%sa=q zA=zIu>!Lrd3r)R&sHm)7{~~Ghm>o!Q!td8`!^4bY1p}cJeKuk8u}cv@3kTUJXH91% zPW87&duP@ymdO;EBuVlr>+ZTGs>xfgp_c2LJn)pbu^Gp(p*vVF3(l@TOSx6*wWBgc zo&A2@sa+dauyuPybjQ;CL7b%_Njp2AO}^5AZw9?QCttgHT+LQiaNdT0-1zn&C^B$x zl4bjAIPld%M8u1^8;zId&plKzdGuhys~d5<;zTu$&G!V^_iFCP2Cf{O8a@tT3eD@; z$KCt-r%$+t6 zn>q9fY^TZZB_yuiPigmG6iLX7$Pvz6IHYgiS(jVRyFcd=i#=llf@cV_U$mVo1}g`e z&b?QG*3NamI+%633#7Wye-pwS!QtLbewlsz%dg|i%+$_Juig61{SQy?LS9|?tIvZ& zb0+;ht*?&=7@Fd*F0xLmMYhE4i~V{LW~!Z9Ip=ilrTV!Gll0IP-xmLFufKh24$-hX zb8#uXB(`KweeDnzWA&RcZPyz+&%D_%>+83?Vd1`xPdWP!ogb+#o__(S*>r5)MgQ5( zo6b#L*O@QQNr@3F7C-Ar{uw!q6*D4iBsykUvn*~20I8xYf-)b5ja!h8DEeth%l%j% zS{2L##GA&Mw*23)VP*iKVy*wI(rydy`$ zre5d{PwQ-ZRgKzZOc@-33{)36`!P~}^YWn+r&_XJluZ<^(jP7xHFuG?3$;sm{K1zq zrM9P}TGHTznG>R;YL;?CFL5x(7ys;g`iX1YqAkDWo;hW{@0Z$lnkr}1{ocEF;EjNa z<(FpEZCQ5yQ`z|P8=J?YGQ&ZGI~u)_{f35zU0}vd3X2YD>yK-#!O_<)nD_ePG1UH} zx{K4o7r%c|ZQNYe5t%q1{hx)9ilAHjP$<+G;Jb-q^_q8h0H>X~Tt4~Pa`%NF0jG=I zAri!KxIVtt@9zaO?`CJ^Z)snDN&Dp7NO+TRy(?!NqF?Y8*r1#@8|N(Q+j`w!bY9kH z<dLPqUySpN@uT-y@+Bks% zIE|_j{F=3EH!Y1(`w7!+Q})op=QhFCB`~kvuG$u}YC-*>-@}Q)&P*-+5p!r9jPkS?ZXC-%y;(o)ac(hkq&gQV9^8{X zeQn^a9i>49iRVIN?3F0gY<}49r?bNslJwz-BlOhi?0-}+BL+aO$-62xOrCXX7kS;v z^Q<|WV_3mKhMLE#^CF8^M(=GS_UxR0Jqvx!JxWY=X#YYCuxqnF-`P3572ZTnDX`sM zIUh2o2;1#_+xLsWd(`)vGC0hm**59@-L9wwJ?(>cDR=vQf9|S_4t~~?Xu9x5^|c@} z#r4OOQcG2BG&o>4P;=CbKK;}X$|UF*}v&FG`vwotY0Rd>@qwdLDE#DM%S?-Pbwy00`nc;x!9 zejl=P#PvQ03Tuk?|BC5U6pV!EmJS=1T`B^ZhjjmFXNFq^i%)#K_dlv-$s1?tbQ6J> z*!e{ft84XVuHP^8Z?~Ek_rwO98FQDU)VB&V@PEud*+6z`q`lzIR&|&-T?^3AOc91OzYd5}h;j zJ?CzYDe4f;aq`b}@7Zd?WDXtw<bi=U&j&vmAc7-_`UyYh#;ch=9z6O2Fi;%?s4s>Alh`HQ-}Py2e_ z+ziI8Y$_O3cV&59+Mhl`MB{?T+el1u#iYZfq2E7A9hGZdT~XS^I#s4QuSYTr$2zYQ}y-h*yE}V z{f~?SKB{{N3q199^z-8ho06>vvAEdxVc)|q_5E%X!XSf#>ZT*+ z%%61Xb<<92-Ov|5**gzm&kI_<*8Io=eXc*tS^Rx-)AN&~p8+p5Mijccy`eeAZCH-A z`R3_pSnBQu)GmF~A<+>_bm+QJ3=))docMYv&9vlLfz9!;aoCC#g4Y3c(N*E!f)}*C z$V?2nfAr~l%Z>xv{TKf17+ilH^?Lo?e7DKjN*kZyX4sT(W6d#tQG4 zu(K77lj0nUiqHB_T0ASWPgOgi>*+yPOZ4si|D+&5={v+SZCh*VjYiex&6|frjLZSj zwppbLenk4#Q~sxm9}S~#IUPFQNBM@+zp{^Ae`!Y{qu69TV%>=!I2+o^nf~qNEZKsm zTTYMKHqAA-?#C0*tK`o^T_Oh-uLUy z{CH7?5}p3UZ2LIs(HUmX+x~@~8?3XgyL;%E?VB!jLe_7HWK9ThfmT`mo)bF7UM5f5 zoJE~Fowx;ZPS)A_CW~5&VT2li-LQVxs-?5$7Oq-6*pRob-^oM&vpDj6(Qe?o zydmx#=fL>w5g`wcp(2MDcMo00_?&Ygvwi8ZEgi7IH`{zuAI+ZP?K{og9F{g|wx=7Y zsBd#$i7Hdw9P7xQmbn1=Hnz}xamJf)j5_A~*B9p_ci0c-T5gN?8Xq5d@wgCs=JVT# z;x`xjM_gLi@oZ9gS81A~rC|ub!O&uC#Qcw-()OPzXMX*C{ZiuOS*HdYx13(Fzht00 z)iUm>uWPb5uQu)5;`9t}dELc;;HQz(G7FdPpE@qyJ236X>(tqce>*wMm$KTa_9Gy3 zKv;|6n(%J6mdMb?CHXv;KSVdhUkD2CiPc z`V#p45cf%*a~EsJhO*Tat5148+SbT3?b$;~wYsE+ZrHb=u%z$_(Yf%(x?kQtzV=VC z>F-@B$%^WbUv2AlFX?%=Gw+oJ>$zf(vA>gjf<=rbU z^zRrFoaXr=-IUs;_8M!Wf2A(wMqlW9oAQVFY>@uJmvHdTEgwVbqBFloW)RNiSH75@ zd5c=K;@FIi#vXHN+lN7|KP!hbEB8h&TnX&Q%fHzhsZX+o#eVs^3HWyynFF%azuT}U z?O8i-tXl7w^nciT>$s}gEozi*Vbk545|EVcE=d)TZjkPdE#0s|xbB;OY7<0S-ru2V+FyR&%cSqpgm|UVgJXF86NCHYjw>`RF z=XSO~g)64Kw7g?DSZQl)Mom3jToT!Ew~Ef`)d+Q@pFtE>PxEsM7jTO4HoT1WJS64rjgl1>6 z&E-$)I=|BQKCBgpr(>#EslW9&tko=J9USW=3$$;$mGLXTfa~V2S$2lk_uZuXZjvaj z-2iVQawEvZZZeG1{CrpKah+LTc-V3+8urt!S@z;7Kc7R$kC|k>b-uiN-hN70l6ZSK$&=4ANtA~kS_l-=Y{CW0=*OeO_^I}0s#dPJ<=(FZShhaO6(Dh_z3a42_O(y%Tv&)euyO(R! z&g1jdJ!g&0G$Ipf(&@u*WJ-*Ee+rQU#-WF0|DSX>chg^|SN=?w1i}nPQTlbn%VMCm zZBb`ANdSa_>#rDo^bm4S@IzSdZV?&7r8(ErSW$w*6MvB+xuk8X>L_7FZVnAqJa#W8 zB}ojshvfzB$vh6b_mqEU5Sl!W!gcf29jQd3(0SD6U;o>`yepz3LZm!P=VI%pcR?V_ zaYoz`;kP9Dvav~Zy%g>=A(Y-iIL5XT&3qDLFkJ;e)BfThVC~OQ1;cLBsUhax|0ax9 zxBa!*P3bTYhsl>$K0r3vDf{11t7SWigD5s7C7To7;ashCJM-T{COB_ONHi&r(cHP{ zN=hVBzUMr>5tefd3(~CumeVJ#w1${*1()3=jtt8bbg=-+rSgH``F$!8kIxLyvIQbjgb?Yl zD2v|LeBO?W?TzX5B>dFx_lG~o6aR*dgP)?8OjO7Rv*G&aJ`R)}pj~b8TN#U54Ck?` z`F=?dC_ffJ7PKy>2=1lulPK_IJWXh85Od;-16fY};CRuKo$zl^_L4>7#t6bX=32r) zX({Se!EoL0JX5Ow6ISd1idx=u?u>hI!~+E7i6teDwrhNc%t4 z6cGe4Nc7XSFNj2wy#3tHT$}XmMeDKl<%@(6w;O61UnQ-VYm5g}gC0~1S1yx23V%=RyeMsg^GkF zx>lPgM1oJw8Gd`Gme2(37)Fn?)MUrYx0;b6B7^OaKz56muNWSauG6dCg!=6|$I-tx zleNyoF&y=pJvg8V32K|K)*xfCE2m>g1dPk;tB)HRD!muq6AF$_dntR#-4|eGB$TrF zD3XJ?pXJdWPR`3ynha56NKEO3OtgPFV5ij`Lb^QKw_H&KEe6slqk3m8G9edn$s+ry ziToT>^x*-iDK~T0Jpr<_#cep zioov*JE6aJeJx`vj@mLL-?S)2jlU_vWu24Fh!i2a$NscY*HK|o>SO4HdF#sWL}C%i z;C;crQLRG1GUHDcx@Ak_*_!2lg_t3@24~76kH1SZknwaD>5AEKW}vzHb=u&!ETuF} z(tMp&WZ_^E5Jw^BV_4BWow36256PV7tZ3QI1~!1W3sK{hH(p|zpkG~6WUCoQeY{)k zB^EV#YDOdy@KGhYHrO7Pz5kdQ7e|InDfD-k`ncs3c9_yrpO48|I~U&19!C4!c$bOj z9hs9uTi|JD6lHuy5=wGD&bzd?n6heo`9^@;p#1MU{PYTsDTSK-zc`^}6VBzrvU8RH&K4c0sKkoaN=jH9 zKYg1JlVnpso9rYvpXrx0NnTr{b$09%PeKlzz{M-SxB!zvB~Y!kRp7m1hf6yPVD^uG z-NV)#&k$4ko*73RWJU4WH;vP8jXQ&Xt>E(* z%y%m*kE2actA7O+v9g{|9n~(gCp4N|X^)LJCwZ)P0wCoAhT>WJd z(_W%oUC^pHee~=2x9k`rmwa<qa*KUIatlGD(gDQryZ8OY_x#%g#1Mo<3$r=RNcl=q^@=x8Q1HEeiMAlUVA_Nr|D zSmwTtoZW2!IfdWZoanEppFwmf-7S&8L50I&-mPNXUp~nK&mWnRB2O4a*>Bw~KeHuCHjV%Mcq=zjLsp$qoGK;xae{kB(yJoU-ymWMSsLR^D3r|o;FRe4l+TCz zNU~u#L-J#pR`8oenz`qfzZ!D9ah$SQxX<}|9u;g+X{Xny$Q`hOT`?P%m=s`071r^t zP_ADNS{(ZqeR_S`J~>Cam!3#q&Cqub|G%<4LtYRgD=U8Q8c^8s7Ng@| z_d)3?;nxPwSVxWLSGINbQ_XZwT1^yIs60dIyjY$3@O71{Q~%+s zJVz4VzK`U!kM=FAB+bvm`>rvMyG7Yw;$fBDLFH{{LPw2{-vs8f+@BCVZlkflXaQre zTO#o_t21C)t&tA7FM|46!MK?F0jrN`{~x7|B$}#zP*&A{>>ShBH@lIZS~tsIiTrMV z@66TyBuX7bdmXpL_`&q^Lo19zUE<*JckREpucqJbE!Hms9C#T8N%QtyI>*hm zf1LYvX@@~)o6+?KoqE?&89zVkcX7=(9XBIeSQW43bOagY zmo>rS+YQbL`>tu}3XIbr%EXX`cdS)a2*vGQKVpeWyG^+D$yas~T%g>t`#sz^)C0h- zSI533e6=$)bpM-5_M5B+mg;S`o<8*9?g9M4AAf?e;mX^D35v3Pln{!3SjCfJ z(7hRS7UlXKi%jX0lV*X#wqdlIA1l(~$dCcPg(dPMrNnJdM5SB@2r_Z;-&3F0m)xJ> ze{JDvMQ)4e1Ar&2e% zeBZbp`=@nx&wdKSZ!76kd)^CGCKt%(Zj-b3|;nIig{22d7uJ zn(Vr2b~T>sii@&5Na`2dsy(_Bnmz8L>m3i@eJtb5l8iu${HfRL=egCV-2e5#pg$Fr z@A(1!WY!|y8HG-nDe(P1KN#iVY+X0%VY>UqWHVxKJ1#@l=i~{Q?@5Z8fyB(Gcs+Y| z1}bPwox8^3`kMk5-oHJRA=|Tg*tt)hAuDLS6d&aVUha>4PtkhsYLbo}_Mf$#Gk|z9_iRt7W`!#nC7z_xNZmlh+^v*~m1W3fDX;(KB4Mg_)BWxzE($&UdI z)A4%5D?&!wtN|@ zKA^zHiiREF4dy5#*^EIqZ=5AXyxjJ~^cMvcjYUb?zUNX>T6Y$lVzZ7|mp7qai#%|z z!6}z$)e+gw*GYfOH)nK2l%CFZw#Z!=wpaXU^l0FpD?5F)GhW#;IpHzf;NYV{M6PyJ z*ZhQjc5a$U5sMtH<1TYfU^~jfRWJe{CZ5H|Fx4nC-wE6#fAIRDPxn+Q7l-GqS?KJEI zBgH;}ZHHPic~np8AE1{8T?tr}!DLTUPW5a%j1{!^wDIIh?{8I!x;MP03l&pW$KiBh zmB<;_4vwgF#V)OVHUyr+i9_GgN_yl z(aAXpHhtviN1OaMe|(r}ro&qFa*H?JbU}HI8`$_R>TcCJ4E*VeCg1UO9l?gqeu+b_ z=laK;xoULvan@rW8F&W~tJ(f9l#1*`LHPyhQ5Q-gO8k^b56y5add(Qpg@`+Ui;CoO zx&iG(^THdfac6ZfuNW1mYwDHsOiDe)ZFf4*X%%#V!%`UCjkH3}=TVFUM@~qtPwZ7A=*c8OGX053j%# zw@d;EP`BSbe4E@FvxAaM^x0zUk)`WjDRB>Z5yY%teImIlAr*A9;bS`9oL&ec%=V|x zz?)sK?y(R|C`s{+1E1Ul_Q};yQzx&UjLRQX(YM)XiHOK36xL1eVGZUls zX#H4I)q3WZrQDOwr48TRx}=9mjhh+9#KI{9@u!bZ5jVYXbH$-w_J<;9m{M+1O)5|P z;w*CtG_1^2*~_f6cw0{3-|$xodbwNP%=Yj9zr%2ppNfM6TWMhSr)D`k5vpDzO~pNm zlGh=r%>ykZ!-F*=39o%rO^K=Xh`~ox&G&gmTT4DSdw7gF^;=Q+7J(|$!;oLy9%;&}74M2b%_DATul>dR^JKG$Ys}sQ z>w@BklXcT`_!z~%kz@Kozk`3D82CR11AH2f2jh!*OGk zVj^g7GWRXdwziWv7;&77G`G)+csZI^L|9)-_Bt`+{b0HtPcgOq-2tA?jE6zLTu>Zu zoBU^`e8K30W)a>$jg13@c(YU_9lOyZ!p_`G4vUw(tHImZ@pXv=d1{%aVlI<`aaa_Q zAUQN?%uxpwc)xX*CZbhsr6Bn7XnMSeOxT-;xVmo+C3z76AdCm0I{6Dxb50_4G;{mcq=3iYs--|A?{R<-cXpu_xf5Rure^v3J(uHoA%oVQjstU(_ z!a*5OOs}1)g?P)ns8cL>`zE8~a#P>5vTIs;|YRS;b?p46E}l zl)dICo(Qv3nEi+h_d7=loFb9mIK7S=*vyeL0b|fuNLCqMDL110-3_y0>xUXJR@w#) zI#>|@RL8haeK%1!yngis=`v-8h+}D9qUX6nT$q8b`J=P#XJs^;gi_CO(8$}do#8MT zjTC!`FUc$aDK0gxgjZa!?D^C|;M1Fu;_x6Xj;Hiy3#Bz({SDAsyA&}G6V+_V5|Lrj?IsdmTaBZ9O>&m=f0za`$J*e?tfl z0#5`1mVC&w5BW$(W!e0r&6v!iVREoJHqG$4fFX_#vG+={f`ySj9LZvI6li}YL|x>7cTO=Y+;taXZ)!i2MDcVHR1`m7Q>d2psNfeE zCxnfQ7u#%F5aro<$qT5uvJ;kfnMOoXrUUeEC$EZx;#hkyW!{X2jjXwOsH&|=$dqjw zjdau{a;)v|+&;5HA=pU4$_NjMnh`|D!9I-6kp;2TlwGO@JD`!rnuA0KF#M|rUEJt< za~9^t-;scCP=Y?CgAsmeLNJ`@EKMO))`GJrbgUgxAd$jIGzLt ziNaUJl_UEWtTx!#98d_Fm*lWh7cjt-7}V6@!6dZ)?}k0bL9iUT3)plqN|k5upz|Cl z?GurTvgVoK$*8WA2c|z#5@5hhdgI4l-ieI$u4i-tQ|4Nn1Tb__GW~0Y%Ymg8Qx8B5 znJ&=|ZO0c4{MBocw=jvD%muRlW$i9A&kKvc?D zEtl{|jTNG4(&X%Wt7HEqXYn9Np)jwYO6I_p3SAE4e>2Iz{Ic5p_ZatCO* zX9w$F#jGiu9u*zLFmVr5v%_+XAcL7+Tkc$^ns!gYLLR>o@<|W$_Tj2=hDk|&CP*OB zIoy#qfNF*Wk$@4W`%#c(gi~lx1IVY+fX1RyC7hC;jpr7Lk70o7R5d9p0nM9nA!P%i zo1IR;b5YHT3Q6Jf=CgpIrH!ahR0K=9U?MGH8JpGXs7ry-8Q*mkqbpz*207uzVPH!@ z&bj3$U~Kd>!@|pbLKDjQa99O?MD3ROtN)K?fSGA@WlrO@j{&y8%#Q4|m1gG_ke9!Dp}oHiFN#GQt0Uu=4j1~IY+ zhx=No7M(5;EzeSh!wu}Gn08JMC8Gp(?WNs@#Dyte>0o~)ZTC2z7#%((Mg_gI9KE5? zqzx|*SIx0e@pz~7QP*e_35EZ@4@ZvT<{_y$p7>`SKk*;`Eg1HOS8~veWNrEIhL0L` zNytIERMbXjEl*6OQbI$QG?E)tD3Caf_k8tY)k7%aog#859=`4Q$4>#FZ%D&RiVKV{ zPb_!;WdI_?0wsYNseRic&zpt~C{n$MUL1{THj2+>KSoJra;W(80VF9}2c6om`H4Sv zycF~15q5(+(xYE9sfiAi{naA(RrRQpW* zU{sd$mWU2&k-=oB2FAA5%XTyv>eUIICZ4(!i3EJ{NeN_ATMYeTY`!w^DaEi{MQNTe zQgua8Pwc!r0+ z>ujA(!Kz51X-}|tA8zPYZM~o$dPhHm&a*l3Oo?zah8J6UyeYki%*~A9hZu_Stl-=2 zGq@hh!`U#oQFF0ke-H`7i`V0sKIlX$;$?*Lqb~G0X`-k1f#M4ctMt8AsvG7_`Y*a> zeB|CmR6{LpOTj&f*f`sG>0iTsHRFUu)?VE46YP^wpif4DBjXI)E*dTT;1$jto(>Wm zF)sR41}ti{OAOsaRk*2I$zsgG zdu!!peH`?A$TwmRBWO?%+9wcPP-Ky8 zgQ&kkm`v$yn7St0JQtDd`iSld)F5hyQW5Pq&CFV7XvEKgmCMD>2uZ}aHXQG<_b zsLBfQI~`5twiFNdGR%hV2l#SYz~EjYslCezod&R9l{h^t$Gn4HMyxKS0GEfbUp(Sk zMo>Y8_y%-FR#zg!<5|%+E*?vyi=jK@{wr6)Jc9`c_sJ9ihQmno;=y9M!~}WB6O>HE zyb+jbT|M947kJa<5pT5isX;{EFoTF$4Y_KGs7XpTuDIVS9#VgNi$S<7nnx0@W{;JE z`QK%6+*Am4HnU%VPH8Px^hpfRdyk0l6-YT%G;L2vA7564{XSd8qlFj|L8Sxp6npJU-IK5B%Mv_x53<}N6s-e z>vx&jK{gAegQYb09@bp;dqYCFYsNrKh_q=Z*CItGRrHkW=S>l%1r7=OeDLVoOHO?& zO>g>#PKd#poGIMVfz!qqE1A%qq%PEZ^60-J3wSJ8NwgtgQC=W2mdFXrC_XcsHwY5k z_82ou$vVGEQR;iU%(Fdpsb&E^@e{3y$1*VIx%o>HdUfhX^_CVfhEsFH1{aNzXZxs4gyxaYRy_LR~DMe?*vv8ntVM%_4nNN-`PgamxE++m!l4Yfgr%WmIei zi;V<~78vqD5gM=P#B|z zcIqYr(z4w&h+g(=nO~PA<6SiOrkpbi&4~RGPpIF9PiKV2d*sBolKa~nSDwLZt!q@V zx5o$Bt*iUf^O}hXh_bhl2;6mUV58StbojgQ_#Xo^FxwKtgR`qA1(wtS<0$$N4C1^Q z;1ApFs46VSXsD+>Fo^|BE&CArY!XYejWj8}MkW-qmmXGmC7Sjadnxy6nA2v7_VR^; zX{Ke~32lf;m3t0g1!somUG1$IgDDiSEogCJ4fEhja-&xl(vS@}avim-Mc-fZ78Q;{ z+NJQ=aXLIiwDn}ja-&XLYI4ZFrz%mA#Z#8Ff*%#76*0x zawvcy&rh)q=z`0~*szFlRj%|~ep+x_#~xSwmwyGs;IL4*Ql0vq@j}HhU`r!Xo8600 zilAJ-g`~y%x`)uf2V&GYnchr6HU00T8i-*-QE8z5ahVUb1N+>rCqC@d;6r@jA;1ot zfo;pXi(SEuj2io)PZs~U8~?MwQtXj7E;%_AfQyEJ`fdk!;G;@Tmh6j>1IA)%FA!4z z1rVNgs>zanz@pvzZ>fD*jd_s$VjjOgZquaQdh$efow^6Xp%bvgjf^ESX*g`e%N|K` zO?>~~^f7>@!k)UqYJ$GTcAg-TkWB_i2G^zihrzRqOcjJ;rL%On?=SYJu{4U5yH8d- z_l>0fmxuvjHRKT&xST%Mi|(Jh7DVlHhrK8z44)ou&-l~0t)N+wSGo6j8vmDI$`=a| zpYZ1CHM!+H7}wh^UbUbetr9aaRfNKpmI~4r^KHaQvU{GHlKEbYU9#u>&n)y3K2PCd zW@dEi8XBj6c$bT@ou8Y71@?VWAOHvSK}0s&_lh`%e=Eh;(p&)l-v;GnZ|W5*!i&`j zlUyJmK1tZ?Vy2$Hp3pqMpj{uP);#%TE#~vnBZuRf)WbUEb8#rP>wnvu|NOKH;8HsI zt7-84e-8xS{=lut!Y@ZYK&XD5o4Wh{-(>Yd*3Z;~03rrJJRw=a-bXqK^XS!T>V|9q zpQ;CeWtm3p0kCVi`RS)#FuMOzH~%?E0wBBq&&v&Ueu@I3|V1-+_6uE^?y0)B`RxaPo@Df z-+6oZ#S8`blNMKuUR>vPr%*aYc8?Q7pR;}jKENoj2gHc6f$YllvOls}AsHqz39lUs zKLdb!Tgz2+w(GNL+Y7dn4gC0@9?n%q$V*Ojt()9%4Z6AA&UOTzyWVoWl#u-i5Aw6T z^%Knu5D~5!es{Y@VmFJzHZ$zEMZkZZfO2v$SWHKMf`I^c;?B!j=OX>jG&!j|I7o6pcb)!8&qmWUPo z5~XhUp$F8UA}{MEI`Z2+hrvmNmId$;`97??ExHgrPt+WKtX{7EGg{(ZXwIE_fQeA z;KO!)EjN^+1Cda-f?0CsEiw_DOU}VuEwkV4W-@$-$jbs8p%v2}EYSytD00D%!Y+HT z$G*NO<{U4oicRz%z%0Isi3UD3BLgGEtEd_+{X$?fo}t75JfHl!VxX9l=0c_Lqw0170h9TU9wc6M*% z6i#9KqHogeTRj7)^9L94fh)}p>^5EGJwyxeilzYtzo0au__=1 z-AtXYu}UCv@Vqi4=C%ZVdzT)Pk&z)RjCfcMFag`xS@y(wUMIhi*8u}#2ar)Wg(P}) z7203gf#=6#|4rTT5^XM_o0UL?INlWtV-=P^ad0(%$WZ`^Ca~PE$Xw8u-6h;8g*z?7 zX@Kb^MOL!Ww9CcM+qaP~B%Tk3`x_FmwwG+t2XS(6sL8?kgKmGgvUjc6aHVh2>+qaOP%0%i%qE<36iMC@Xi9xQhC zI^gk-rJsU<8*N}33}{#8C4icSORqEAAG$lCQ-x#Jg$sJOgje{UE}vsc$f4wOn#J;(F3$} zXU%42W=1c`bt}ch%~h`D2u32{Oyj-53cuS}o;2f|Hv}Vg=e*IF4ueUo32hd@FV)6p zumre}aHyqsxdp5M%Hgx5Aut!Gsa1l8n`-N_B!D7QO2sjgt-ynLBKLzAUZ{l zT>U)H%)8(a7^K2E^sZ31E;OmtfDq2KJ~ev{xI42(aXb9K+cbdDI9D-nISJq%NTplc zwzB{hp>o2qg}KbH(*wrgBysnf(2AbOLtO#{IuhHd)&w zl_7yg8K3w;i%Jz8)-mYqMA!l6C1y3*=BFXI1@~oN_zkfYe^6iHh0CX_!e6QgH+hVs zAw|WP;~UP(`0qw4&Zu&vH6zoe@@1mH$gi3Ky(ot(Q4k_rG*u4h`-cZM|69dR{?RFG ze<`0%Lb*W)8P3C2rqeTZQYaaoTdCo@vHgXJ_1M5=zZ^f&Lj01f@AW-i&tx7-6-S8p zruAlR)Q7d7D|ViY55cbGa_Sroy*Wew%02rDPv7zsUmscTu|Wr z@8_4HN?(Ufl;*t-0S&840XX=35 zUyqIdIaCKg^IDLhFvc1IXY0{1m)7iqaf8;QLke@8qhTmuC{L6m$C|Rj` z1@Bchm&~ak)4y7PAU+n*PPCXl9w1>vH(_^Wi51JqMmeE#=8q|@oBNS18@bqo3elyP zoc?>aUv6++m<^=(??3JTe$ae}_)sC1gN>l?u^J5CK6^MHDN2RAoEwv+%w#eh^CCp| zwhu;x`wL=+KL&8a$dcdvVTc&bcGN;ay8bEC%VXO$RD{2>R(9dY52s(){`0wOE~fO{ z7rVy8n6_~0u>9$5&<@|rzq3y6Mg@(9EU=3dtT(5w3es4 z{qHHD@i);q`mMHrb7@Jcb@HziW-&IG%S|AbNMDxsQ9})>KdzcpvYwmO279HgIQ9#) z;TrcAP}`7>uzR`FxLa{XhgkrG{Ow^4zm(~Ob~r~=g9axc1r(*2gI>`mN4;c=7KezP z6f2!HU|m2JB7qi_m5;Gwa;~v9p=zbt2ZTN(;<$;v93x~}y>4QLd5&eDb2=nM+3{Tm2BG4y6e~QCcgchHPet*xOFm=L9_P)|bz8Pk;+S=fekU9(N*qOsMV2S@fQI#= z0#II9Qa}KpWF~mr?7Rnqv1NPC=eC~p!0!~-31l~T-Tk+YVa7O4VK<24sAIb?h5i~; zsTYn-ZIQop|E=2yIXWsYvVS)h^SavUIRyXg-2)rF#zCB(1u`Fo){ zg;_VgCW{cx%kj~E)BC32xA(oMC!m~X1#nd6g!bi*xhcNx6bknWr8kn5OZ0s@&sGsI zH^&(gxj#s)v$u7E(rM~CN{@G-qa(bgX7{?-DM)y+C(^_9f6PQT`jMLk(Us;Hpr%v*(2+P*J zP7!eJ)b4wAt_%yS)0c^NhTZ$F78|y|0k{Bf1=qr8tH|AEa-%I`G+g1}pe0*yhTT)v z05Y+8jh13B)8jJ0RHTH;1$`3%ygQ&qxS+8Q@fe zPNfExZ!xFRWp~XB{*!x)YUK-c@69l7KEtn&yPzRbi>FX40^by2WGrOaU22YFi(?!s ze5Lg{y=zY$G-@kR)~TwZ%+LP=fRzGGt0AOSZ>M#u1CRLL6l#FlOE?CloZg{(l)kPv z+R-8)a~%GvjUX9#36@FBbTbA8Aa~RF3w3b7nxm>w)rkD21Z8H zQ6qD@V-K;0qsAaxktg_(YWCv|;ZX+ygYeveKp^!IQpWJ|SMrU4cf4?nq-5>?x2ReTBq1+TUHDd=3 zVzI@S5=@5x){UQYX>5Bq8+3&fFn8b8VC9AXlA?zB9X`S+qHR;zJw7B{=|o$Nw$~Ui zQ_PI5dXdPy$~$Fp#)O0$Y1OYo?lLNFW#B(e$2NTiG}PZR-WePZdJPlKyD-3cs)=D| zfSvzIfk3pY)Q!oIngNUPBYAFsU=1%?iL(|@1H9Q2k%;$|^+uM8!+W5U-_X%o%2Gkp zrC5YV%Ps3-R7rGvg z#*My(y-zgDdM=T9Vx(CWdzHqal7V@S(L?SdD0=J0XxY36BG;{rRk@vA{5^Pe>n zR(MZ!WyMsyuVyVKLX}7pBp?t0Ea3}P<1>fhPB_RCid_31sN$O(tStZltSlL{ndNnX z?@9FUG?s^VY`o{}W@M=<_kY|EZvddu^hK@WLu)&V;ho8I+uhzzrg+0Cv16$(*NMi( z$}oW?`y6-O5&39)Q@UCWpuR{rQ)G#w0^Jdjqq<8JUBE*qe>IZvQz3k5Dw`u_CLCpm ze>;PzL7V{RG_2W*!kUUsKEPv{1V?A^fGwsUnPZP6ELAM?rVIHx4HQ$-@KU?JqfgpI zDtrTp8EZRfj<=GmTCSF6v<7eTS8s7VtWWexU z!fvz#64jF0Xv^oDkrxOWP5P<88qP+nh}0KH2J8g>s#PaqcZqp8`JtVEEn`}+>sR1P zn4%Rt+!x+JMAwwKM*xLcs8jVqI$Br3dH{&{u92gUEBBf+&U4Hb)S0p;U6wK*fBReP z0~OV6-XX!h^$X|-_eF$-&6R57XSz(Io{pj2aee@hAOP7A>}sJ1o8sUj?w6Vbc!KGd zCk)*W7Au@+0=g;z@`1svjRxlVMHa7=nX5G;a6v*%yvsK#9^v7%`Bn3q2lxe&z|i0r zr^k4rYU{m5XQ>c_^3qM`olCg~Tx%G}Obyhn5sAvZ0}7?QPGy<!2!L1Q3{0tircOogrobH};NY zph8S6IpD`zd8$nKA2ZOJ5NvB5>#mwstC0=e|3Ie|59csECRb2g)mn~DAY9Y2&$i$z zh%Ee4Gc0COEg1m{qcYkknAnBgvF8=;m0jNK?2v$(YWrMxd%5oZK7ciqGZ~dVj1KC>X?daqmIuFpDrPF&P>_p@b$Uvhap+1GZUHA+VQYmeSH8HypegOMeG+CeK+ zW7S-JGV0k}zCZ(2_`{U8=Qk%FK@;*I1At&?w6m3cRG!ixIb%!f=$kh zl%kI)=LvBkifgj-r}g&(O$d9oQeIL`nZI>ci2+w>7hB4LoH9@#V%h<=EMrZ>8lB@B*!-?iHE6sd zbJ#;_uTlJw9QPm4>+TjMwnU8)g2fFcJmY`mU>Qzgwn0StI^}h`mF=K$%ke zp&^|tB(Ls_NWx*QS>H|*$pU2sIDvQrD}-jK%{{>B3CpMVmokc_F3TAgt2F`TvKp{3 z)40w>dUg&#V8%-uqC(R4^Ozf@ffG>C;tZ-b3$w6XuY)~#!;gp@RuCDRvAtE^AmKJ{s&l%2w&@_S-S!3=(jHnRyF2C%Z&$k1RI}*AQ;TZaE%N7Yo5GsUsoNn`$dPDOVS8cX6 z6^`Bo=aEc1Egbh3u@(1k*P;UgpXz z_#VE2r!1`Nf#=2ckDUg-U3(m*HoyuP?>oNF^N%C`PYF=xTVNh!67vn(a+x7mN9==e zR=YKO-#?xE*6`i!#ND~c<7`O&@R=>4mLUX>#n_Oyqhrdf9h*k8yMH@{IflP%7#6l2 zN0B9d1MTb?8Huv;*B5hOU|RdP3OH!4!!#_~i|b|-Lp{_xyjMd0&vq5;w}k#9q5Zdl z-)p=AMS9~#E0Rhz<|>hbjI15*+8#F9im0cJx}~Vt&|b*HT!{XVESdXX8H7HY9ULj8 z@l=wJEC^mb)Sg4}%el*^oj%@lpU>^z`l~{jlb^7;h>k?u4rW5Y0ddM;6Z!UyeopyD zfKg{BSCI%#%qeipKP&F`Qs{00$j zD84`!54XfxWDDR8lQ+gN1rI8u)W^xcGDPl+IM~cMqG(wx8HCviOty4B)Vn9^MtX=V z(~T5e=v%CT>HuP~XiZGm4QK=CB_f4G|5;faX$(n3>9j*{{4^; z^qr{YpBD=6FoZMOhzEZ@2XjM}(IFeCv92NtH4u^bMC;qm$1I{NLX}~0Xp@0I47~!I zt0qe^_e9gEzdaYnoiVbwLGe4ZHc%{W8@6U#2Z-L}8sdJ`?+$5cN0Kim2IvznYqI#d zaVp@1tmB-ADoF5hDi|O7Z@1*)F*&)Bt7SU~^O4pmN%Pn`5vtpKOYM~?rJ4FaMV$Zx z9xncOPp_KNUD6EMOT4iwzLl^ZS3LAK$*B9KS$+HNX#&NVLLrF0gxH$YDGQsIZb`FP zYr#-et_ts^A)v;T+v-}|YgK~cbgO#6#S-u>S|dD1-yTuoeq205Z_Q6zZA72oeS03# zwRVL(dy759zv#PDibfk)mL(R5bfg(gZfLo1?2{Gug1rH3YhckCilwr=`G;qo#dn*0 zxs6%oRQ@)_=R+^nM_b`O0%y|7FA~^Q1(@#EL89_r3KoNa8DDKWI#Lr;U?*oI@J<}m zFR1xgpQ6djWgPwnq19OH6uS>ya?NDFUC=7ab4y;&38{Fnw=Z^wsMxGE`OFm!Rv^1C z`;&=}nkV@H<!*b+O4l=@)vTgUyq}udf|oI-WdQ{ML@mK0 zKr%jSh*`2Y+5G5lSnxUjL+pmYU|`WMLu#9dlykwu#y-qzMZ=6HlseLmC|GNyQGfH5S#`fH~U+3Pm z_F4-ab*`L<%g$(8z{VnKqcXs@e7nHhw=ym7Gx$F=U3FMgTi1u7kq+q|q`N`s8agBe z1Vp-1(xJP%5fDT=6_9SF1SBK{BqXIv`S$qU?@yom=$&)U-g~X}t8FK78Axht?BV;x zRqQMGtSJX4cJJdC;luw!OORm?Ohv3XcRM3N!6it&@n+28bySvoLswdCACVo4T0B`a zSqt|Efd5_wl zg9#idGLoA{%GhU&K47p=Q*&~7PpfNNci3d?-VKfH`y37zd$=Oy`y*w;(R7EhZuX=m zqu`xuH!m4lT#DhhxCG9v%1ah892&MBIM?{i=UB)PwTD{E{oh-%?ZI^oNU)4F-0V|7 zXJJZ{q9HvJkUc~&TN0&Umi+Dn;9I$~&8lJktNA7J)Bq_Ro~*`U)d2AkqSaHC{4#9x zC+%qi^s9d_KIk&6gO(x@L(3BNDr_s470T7NQ*7r1J5imPiW9-fkMKF-_9=zZuw<<^ z4@1O%5h_)^5F_8iE@j$4mdth-@|sk7b!{HVT5|o}0}%oMWw*gu?GI&|b$Q zHz}{ouc^RE18P(inSeM9X2kQ~TGq@FWUKcG+_W?|19)$U?$wn!kFpho@X~bM9hwul zNZ!uN45LS0=;n&9t^rM`-jXKgS(~+|$~E#+RkZyv9r49*=62hT`7hxWUp^BNRtj2Hc!=acnTe&!cB+LX zwA!zWjDul2@DY5;I@hUzSVNQn?X|^#G$;?OVItz>HRPE6rl^o=x$a8?LOr-Y;MSTB zyWL7_6yZ;k7#~aVeDD|-V}Yej-CvG9+AH4EltE&{+L#?>bx=9M@n|>mFo_meJ*Ycj zEYgLqKHAOj2~lbLDK9$k$P^VDO>l95ZkBO`1IvsiEHJwU*@{J=e%8ce?CB;pSi)`T z1RkUV**^JrNU+xf>N+2<&40yacYI&*)_vc)=hj*%%sVA5Xkx6bx>5HoN29OQz2AgjN!=1^Lg_}uBJ&@ zHojZ149eM?HKqx;S^+fM<$7UKCY-? z)U1tIlziWh4N1Q8uVC5_%v$g7I85*QkgTZG8vqhc3bo7Z(FX=xEa z+5LVsVRN8EVjwZev)H=>{{gBGxIfa5xSPXLb}=8I($f>FQa0FVcXw?Q$qKdw=ECaf z6L!dt^P3Y$)~Vv{Uf!`OD=4fKz9kINg;SyX!9d*reBrB4~;fLqc&>DEA#0A0%Zr`EWKqzcleH zSw}esgHNeN-TS#1h~dhj(+5*a^(6B5bAQjurI@WJ+=gf}jRO&{(udH=hwEc=+-9PX zO3UXphf(fu_9?yi`PpYK`Q&8RlkTv6|=4-anDb#=%9V<*q zUnL76(6^lCu9jYcbToovPF#*Tp~zq`lOmc_I4Mk4jws88;vuGVHx9DGE0jow?9v5* zz7<3%1c>7tS;rj5;6y<>|GYFe8)UDHLqbE#f3yC4^?C_&n9U&;hS8U{O85uxIElA zGQsqknvh&ygizF(VR1d_e3v<5M*fWiOJQ z0G-EcNg`7%dshfL*Ir;QU5QSx>Xs0IO(5Vgy64^Uz32uWItB6+1$v(f#2}YOa5$5^ zoDLP$lXGu9?X33Yu+uPuI1JYWinX9d9b!@}M^Haf2+-7S6Kot4huVyZvJ#^dQn!Bp z2Tael-AWWcPdyG%Ozns-U}-sejM|R@9q(`YhGVBr7JY|Zk)>$mPNVBsHC*vg46^oMcrz0zQFAjHtr z9bhJP9XDW}b$-5`xJrhB933<+WG&CtINlUnnM8FJL$kF?DYWl`Z2nxWNimUX(MJ-Z z%G2T5Hf(%~96;Cnl3kq5kez;412CN0MlZ+{|96`05JmO88+cXbMg~rbqK6dSmsv-M zWnvDnAdUU|l@pncuRk6jvUw;XJ~$JjGM{kAQ?i*lXb(w)&$32LDgFl#VsmLt%=ztL zPSYNgQ0O5$BNgojM`m6*0 zy$TAJ*c?Yyo$O62_Y0w1UJKb9VZRCAd$(?q2?Pt>Mo3^H?((EBdQZ~UQS=?A;RBCR zJ|#bwEDnPIZNjxhF1sHc#uG{7TN5Py-o%im#StVucI>M%l@$)kD5@QHrfBMbdT%KcT7b{NSV=Pz4X7UOlCIMP+HwIL_qF`^eH zUYDLaOE+h|U9cn?5p)oVVj3{>7?zpMdK`N-{fYmGYxxoAH%xR)r5ogB8&(LINpY*h z&^+qvyjlS^A%dEA{yuAsM(G=3h0-5>Ze@77DK{DGW|Mxzh&bTd1W!OTcmCNL%qJ|J z7}>l=+hZQ0r+=5}Q}Mr1X^W7L-pk9i={kfo)y?sJ38FjZm7J<8U}O z-_isP87=Iwa7&^Kw6)3aAVrlM);M`pwc=tiAhQO(vueIuDH%+Qbon2^>{vwf=hZjo z0ic>-?EXDM(xDA zP;U^u|_?;o%A; zjXxv))5_?+ctRH6>2c#R-m@eEc7pW%ugY4DgA7D5XU7Be-k2QsPddFW{aVxHzu^|&(xbuM3Pd+_&Opy->1pY zC$L!wTNF1=sA^R^vFs!^U(1ZXw(zdaVI5QxriCnOwpvmzp6{~ z8%%)@l~^q81zb3%XGSjV`UFrbiWnJ*e#){~e1J(80gS@|+b^_g?)OC3us>f;g= zq~MAV%K#A=;rYhLtnpA+WV(kav8oYKhG)aLFaA5|>&ciUM0Eo@(!RTjxy9f~!=3XF zk)+CUQ;l}_UWD(ug4g`kilPE9=jh_?%gBS&MeuVA41ai@?eyG|-^{xe*R}M0jz`-5 zo-^6=R9)ov0NHc3zK$wY2lU2R!PwS^*haIt4^LbI_nyHn8_VrJ5MNnjV+kW#u2~a@ zA&H6{3aA7CM4@~N><3}Q8p;X~nUZS=HVP3@LZ7D!#jo&PrmRv@``fn}#_vB#lO2zf zqLHN6)dDyHjxXw5QH{wu{u~G?>^_!T8H0HXS>RDpn(e1K{#A4SQcT!|4C_~~qSL1h z4@(v$7JVc%yV(VgF}yJ7qoR}?spOLl{pXibn%i`*0>7zo#*&o3i~ia5dyuMpUJmEr zNy|6=XKxQ*x<$P{axz@Ee7@NZP$E${4+8|#8G3pFu)G`}%^IC`12R=f2kB2Ty;CMn z6#bORf_)6RD^;grth5b(6C_;{L>>Z_@;|-EC#rofrGK2mqgJuaMnSg5CidfIrI+HA$~IQH=>y(ba`X?YyF}fkb%Tg^F7yU&SFP80 zNArj+*+-3y=*rqMilX0Hnns_ZEc3j~kXiH$@5~GbfjSnYwh<5i*-?^WU%?%uL4!ES z!$*T%?i;>vKZ{vwiJ$a7ujt1kzazS7j+=}_BUvs^0{Y$1SJ1!bHe9K$3V3T|DYB%w$}?bCFoW@*fM#3W(Mf^D zbUdYbmeJSDVVd(vkgcH@Aw6-aTo71^)mTV&f_w5l?}f^eqFM=)zZk7-N7^uEiqNOuf z#&#b5%2sFluM9>n4<7on{)(0G#AJ+O-DFCj&r}`-?3@@RMoC#tT>dtv!lnkzU79=H z;dy=JWwtEwLlMS2XTRSuS(&4|Ku3~F1N6ekej|j^oio2XfhuEGUiOaRt0pCG>)1XG zf4g|Wun9x|u6TX^$1R{yV-sr_=nC9aJY_}PX26O~a_{zG8?W9YLGotjsaJmx4j2j7 z6yz|T>2&3Idnb^Tf9D+ok>a)Nukzgcx@_HFXt0X!@E$Wf_%m+kAqKHltpbvcitaEW z!x6_4c!l1SYmLg{R~-_yl*V4lX*6cTCUk_X$8`|RrFpBsoQ6_%CqG>k^;}W29Nv92 z!cqw6D2o9lP~Y}j7M)=_;5}oa<|s*PRlZQ23e|8&Y@?|b!TZ}BwlyjZ6_o1|eQH%5 z%!wTlLS9A=0 zyYBB_ZnCp+-T~zQs&H&nMmwx{v?z7O`+q;+INP&~Y`It$@J3f)Kd8b8^;D`A5udFI zYH>Wh-d|Pm(s&+f;$X+|LQ`}csC-k5y#Ujtg6Uc?g6>vY*?jQ#B(qD6G7ek4O&jOe zd+XWU1Qdp0rmpiX<50Aql8uKZhJXH0_syl1N+&QA@D6DHagW42ZD~Q`s(aw zziUnays6;;fO&egg(QUPkM*40x&M8JI)^&yoxY1Shuu~##Vo6u=5kRjrwe!>@2B0V z8`}&S4<3CzfD#LC#7%EkS+Cd`dsfql*QbyAOjDCiJ#9|VyH6j;$WQ17$Vo<AH^5r&OkopeGZs<$c_+e*mA-O`BM?fvY}gLvEX9pCkPND7$V5&jsTmho zqi>d>ogj3W2cL*Oo{`wGQ&o+OT)36&MZc7}On6L?kw`b5YAN^pyYCZ*-g#cu+27zj zBcUHwHICm%85anekD+Rr=oq$v2`i;fLqhvE9A$!!#f#alJk8NM%cI0$bcTen5N9) z3zOqoBA2uxuf)z`2{Va7_EeE$ETAbhma|Qej1BSf=3gClreDP}O6v}L+b{rmZ2m9- z^3sr=08=m#?wku`cg!%dkwyfT-C5Z=A=v1UEv8GJ+S!FbMi~WQ-6v$HzNl8_cdSdQ zQ;cla1roydQ$EK0V;>C3e#G*0W?4S`%le%6{x>c@hcKjdG;O}yc*pLp>u$*0f+#JZ zJz$b|wc9Uc|4%PjXVPq%EDKCG`Wat!vo&3(Ijv2Wn?eoiB}V?7@#yQA_*cG1A$jX~@vSzfnXza#@0?AtB_dyLX|H4F zYSz*4lAb^z_|RA1)Z^`0iru<<+UP?B@&&(sPXo)X?sssOG$*p8Ce4W@s+2S)s;7Rp z^!2yRq3FVj(lEwwP|I9OHp{T6;@@S-Jhl-tjck0=zZNsU90p~;2!+s~>zGG+b*u*6 z{+VbKAV_F*j5nm3Eeg@5oiP#-s~l}>EX!)Pmb$$P45IFu?u5zBwEWGVE}(k&YWO{= z%NQFrn;GSuu>H(C%{k?X%e<~)pW>tVO?GRiPsX5rYWnGCuXO#qc5?cBqaD% zeAep5?Xy`{;dF};UStpm2aK5}qsQ^E#)iyb(HHY-g`;y^>i%xw>i34k5o99<9SymG zqjO>_{e1uIO#Ol>`e*L1qfT&BRbXzQ$Ek}*;e^k;@H+PG&+u2P4nfb&2()(Qw7YAY z3gxR^+W(AlV7_+M%8-4g8ME`|ftFIVrLJZd?{lBoB%zF<2iQonv9E-Apqp;4v|qON z#>JbRXnA6vyFVA;5kFVMQKFuj9a?Qk-AyW){d#)+`9oIj-1Nz1*6YTIll$?xsM1bq z)xZAHL3@)oO@U@tBrZ{UpB|hF*&Y}bo(Neihl6b>{eIs43s?KzdhW;XJ0!M{CPg2< zE4}b%v5z7Y{{trjW^-r+eA(upp-%mn94e$ zQ85l4^q@Os8{2v<|Uf+p@O$_rFzkR7V(72E8B zbH|AlSVK+uoU3?fG|+LM+2m1;ay!h`kJ5J2ry>pJC3QDOKqYVNi57tNOy!I{W1m5~AQ1Sx{>FotZZjXLbL37IN+f_5@P&Ey(h4o%^ zz-PE=a6&WoVT~*Xc7peGZ(2m6>LcckvVI;(g=Z7TRf&a04RCG2Q|6j!KgEs)$_qC99UYedY7$*MMaR%j>qkLHh8H94 z<|i84fWc;ZW*&^zz#tb9wy%}R#aGWU^0+jH729*6Z*S(yAAmt+P@FJpSDv$S608Z{ zX1S(_L4nfV%NvLb!R?QTSs(9Xm{T>f3XvU9?pU<|eO5V{Awmd`e9%ZuikH|5fxcI+ zJEIllbe&f3mPx7lGw#!=ORDCe-q53^6&_Y64JQsyXCEnwf-)4nvWhZrx&4|Ll$Lki zaq*p_QrMQfWb}4Sq-oY9UAj{g0X-hQF&8G=ZXL|W!Gl26yh3g?s3^e)QtnobIl*B5 zc^&-CbCJ1&1Rqc8?sz{*4zB{cz~zb2Q=H>YbpJtORu)J~DW*LFrqzji6AD^d+6wH5 z^^|^2-y)R=TSj3;*IZG6i%5TNt@^uHGtdGseDfI7YAlCg6B1M9wq!r5imh~gW41uL zpC;@SQ*W(-gT$+s@G(Xz@g*bf$VPIdFFar6O=zBB61pJ@jJf~3-BVW3Ye z>@Pdl{^jJe>}4PfXvhA#>VXFR<_u3J7zr%Ry|!M($3;3N!_?89(|#X4A-?p zRiu6E&kR+W;y>?k;msXZp+YhF8>VF7-xgilDpWp8W$MQ6!-P^CF9P!G^_J4Bdzg+d zhRR<9{%|CRr*km}h_<5`UYdSn)EwgbTRTbu2h}(fzRp3X%g-HiS>4l=o5(mj89q9< z(Y`y_H>_wbF!VMhTB@q#&*f^@uWHq->Q5)1qgi_+LDTBTXuiBF-E(JStzqH5N3MWV zVP(C$i}O=TpFfNctjtqz0o!B3g5J;ZaBh;L=7NDo%WS}I37*^tKtLPM-+uhne2;K`H+6zc)c2am)A}Pl zE!;kU^_&SY8cTR`F~12-CSy#02;N;4%6=ZWFzQ5?z7Bo&Ay3EI6s+NWIonf;r@+X& z^FAM9{oDL{C*-@+hvm<>uCPN%9&Fpo1gJHP)^BMG&Hzu6e@GxOCn186HQ$}0TsvbU zw|@1`eA=;H;LrZ(3?`?tGRr=y3B=2b9urR*f!>=F)(`L&F-X8;C;@6>LG&#Uzl)W; zEAn5-i(VNlgu1*m)#ndqH7#p1DrP0vQ~v=QntH(VDM@_8Ll;RQuj#^*`?3iDll%e( z+Ifz+di*D4op0LqHkS1hysR(6$e}TipRZP&T2*geWG$xjq|gEE8SY#>j#S;8ZtS^h z<`Koq;zvn==k)Om-+>}uo|AX+LTxym_~7GS0p{e@2Vv2P4&1#5mCqWyfWo@)ueb}# zDgZzP)bj1i<||YcdNW_p>6@W?X6)GZqV74R5QvvnWfq)}0>iB@`#(FS-6I9&RNJ*Q zwo?7YvQO{GPRCCfMcCLUr2aQ-z&+WFP*2OppIk0&;R6g=2m+k#ZZ{DpmjtqYIsF`V zWR&~lE!fIW#scW%Rvk#Un4Ot__DiG_eKN&0GYOc+ob)WO7@ydqu-U|bF0L=nNEq#1 zS{o`KUOYtlcEi=65ezT< ze6LApLxK%g(4y2Cc8{LOr@T+G_@R99i*lG5)7H}&+!hFHfiGz>>&gqc&cfC5wZNFv zEw0UasXop1|1vEJz25jzNU;uLn%_{W3CB@nPQ6OPeDihX*>-*a0bQ-W#Y&OE>Ti6> ztD-!lAyWf+>AT8Q(+>g6(@vah90j6hlXCYC#3!li#=l|A#78H%%-(;V7%u%Z35!6= zrEx|0)Py4JGgNmGl9z=Xhnj3*0bQi}u_Mn%2K+<%1Rue0`odWOmXYQ1=7=JDlNCE{ z^9}x)lY8;q)!G2ke6V7>Kw|C9e&}0iXsh0s=#1IpO_RHPw-umNJ(rX~6a7&t0oDFA z+zUY-Pxir6YMnJfI%1(gMi2UW&`-eht@pa;Z{}#VH8hF@4amC+`X?~~S#0=jwg=eo zGMqZExAc(fT1YB*F%esJ=3AI=Bk1SLd`Z5E>v+;~0{4*}jl*wT4oSemhWH21gAUf< zjw%5hb?5}h(Rh?6))?WRHjyC9J&}Wh!iMvY8;#4lk8<0G8DsAZF3UB5)vc+ylA^){ zw)|nmuQD__O4We{awk4A1FY#CTXqA~chZs!QhXvb7lz+EB%YnD#-@99N68UjT4Fj% z6gu1FeTl;k`>a4_DmZd`_EKzmHRo%%D^4ZQiXQwZ27FMBprY1JsP?5z8p%#9xAhd& zdEcbq^Lv;B^jm{&UZ7FA0Bj zk9{L&m53>-b$PS_PBtzuAXZj2sC-UmeKmV}H$Z#BE}mFTLo*Kbt_5TJdsK0nv01(b z6B4w~^_>9%NYB+* zN(YW${M3-Jk&Jv`6^cx#W?0d0n+!!K-yq?*4_V#^b5yk}J&`z}w zyk^BA>Yxn+S-if}p-tO-qWq3^6Cs8s}$q%gty3lSXU zG4&>T0H$^N$;Xfs`-m<}1%$h9jE?nUUmVr;14~EYLuWePt00XWSI&{2kx6K@e)EuTc4;oPJ|1eFHSSM-*FE6&Q;)9o16LTWsOs$_+Dh2;@{op1MQtg^HdbZ(W!<{p z1l1xb3bM}2ycZtq$|~O+AkxT%f12RA%=Gj#KXt~cG!q`jU-^k!{OZVi}*na8$Aq6aQm4b z48Pn1p2(pYbrpN2Dr(FnzrE^;J@T(5Ir`p0(4-XTCFwEDUb*;M2DQTanNzbKWAqub z_EWsGFM*j*_?4sKeS8+=p&pup{$qa7VnH=47AsQNWMTU$H^&KmS9n0iTNwn^5h<<>wm5^|93J7y%l?CW#y|BZoe zCW6HdX`DIJBt_EsP3tl+rL2(@T!I;JT1&kO!=Xr<>ApA#8Y~PhI4f^?K8iIuV&Agg z@WmPspw8B-fCH-o3%^VzWENYgLOZqSn+|M6;R76!x}o>NoI2?02ZesNFU7ab=ad~0 z^PQ)JJk_6`AceJ?en^Y|D~5Qp>3k}9H& z!w2va2wCjZE%X11ZnqDDKY^u$zNXXTQfp!@3Het0P#R;8u_RRVIuv29)Gljf;PY2N;smZwZGgPPBtPz zi@C2_^o~sFL+7<$?59S+7T+D1+m&lw%Wicsi!GGIEr1YDb(~=A@%P0nsdP2>aW&-8 zg1Qq1SHQ@;m8mr}{gcc-tq2=hjzcEm6O6(&EMA;nY;wj%s`ISs0OwYbG_<}H<-O4$ zj?sIN_91}=a2}E8mf`*%K=Dw8$+eX4n)B%*J>bmyy%&_BlDH(mvACtH5nh6r5Y7Deh*qmh z7}!*;F;y(1tko{rQgV%ai8>_?nsiS@IL6)+936f-9j|!t?ZT=C(T`Kd+Bnm$0K@OX z46g3cBvvh4WyiCaCTUbZvk0++cUsxO+WHn#Iqx;dcZ!w;(=16U#6>a-~d&x-qiF5+N9S$M$$i z+|epQ+9fRlmnvf!#BeMiM9ANvz}oZ3L4%6drmLKywDWSs-{v3C^ONUwt4UGju`{j| zSfAGA0#ZyduWTaj@X>`w#)>R~QQ#3)-==<->d5AsReR z$R-j(4xV=RF723nzH#X5VmuO?Qa?d{z&XxJm1m$8JfN_eV%6T!n25WSk)}~6pd|Dd z=(Fz%U0$^xNsWuV!ld_QWn>r@atM%Vd{4sXwU~(gSEw zd6g`I?^?|*G^>=NWX%=O2Ib8qa?&E{sCDC4l{Ibbq!@lVm$WJ6hrXwX4j2P zk-*jH=hve=%Z3+5N`@S2TnNHupp_Q9Q#z_#-_FKTa@UcZ>IWW13&CWAsc~jo`Z*&z zKBPrtLt2t&5VeZP79x$;C_HQp>Snar_eS7duwz%TTm8l*?f;L?3yt*8K@F9KMBrga zg85&0#&6q@>d#l-av=^G=BO9*;o{mj9Kt0K2@@Yv=N6_=bDCL7MH7?FFFrP)Pv~@* zXx5U1t|y=b|7C*z=JLJx5lLs=d5Tcm`{>+F&gB&t10kFtu&(K*kg|nYq06RdAk$P3 z*##(2E#5O|ire%0dK!BpU7Hfnnr<`QXCcjLAew2RB9)!T3~O`8kKZW=gp~wd#6G`c`1Yc8FA;v)fyY2PeNUoxyZclhjt#zelmoi@Z7QBmqavfu(7VGISkKXrO9}bk zDyz(ri#36J;eSo*(#IQ?Abk9d^%A~zwT)|lmqosh$qw$FNGh$BIe z%mtXmVPYiwWi4Yiq^z{85jk?a6OT^?16JnW+!EADwygN=fk5EQhs&~(?{GD`wkajR$UJTmR#TczZSq87GynNMuC<^l+um0x#0p9OPTi2#%^Q-`QEK{RuP97HDJ!~(iM@`Tm-@*B3&gJpypG< z)-aN+n&jmrqN6^kTW6HkoENyPImNRd^dxhw8;qyQL=YACUYKg~kZ z?S4EUPFSEoA2V^;7kGvFYO9TdG@=Gz2?+g)2fY>&>J>)Y-3sV!XPqTF`RFl34PQT6AQm2>U|4xtfv*# zwN0ow3@ocJ9(_$-&<)UW<>$fACKF2ts3`6MPV`hkX|(psqEWx2?~~MYoTHcu!7D^GW?H^vAzd#v-q|P8J`vCF zl_YXTh~PTP;||)$k;m(0lP#aVhL%*(;U#T$l{&ig&3@B}t`7u6ZrOSCfz!v#H>xqZ zo1wii(eQq_P?FTC^`TA*WMj~g;?M#%aGaM;Bw7$>+)Si zdW#BH`~2I+OaJ<8hv-0YIs_Y%k?;{%Ir0%<8SJ@417_AK>=pyE@CXT;aJfw}5eX$} zo%A3^UmQA)DH%^9|6F;_?ZQU|i5d8LGI4oO1w<~Fc*!0GXl{7z_~>>TMI6L&72_$> zv0(@T7>;2>AWbIYj#}JM4N6QBq+k?0QF@qz@|H?lI4M4| z@qAm<0Mb|v`DXnPt!g;h$i0d+JxdDwQs83Wv2iTJ2>`><{r!b$j}bHt24ptcatgpg z27K1l7--9EZA;9nbnX>o_aq!rJs zC>hVRnP1`=XLI?Sg)bD*8>o9zd}vmmJ|+V1pcoK~HcJ;0{Yx2Y$xrv5q*WY{5wkdo zLD(m#ZRzkh|5}eJvA7%vb95)YwciS5W>6DWlr@l92hkOC z4%?egx|-$ig|qHEEu+txaP6pUM$0ofnt^y?C~-ymoMkvK+u)KWOI#{QqV4;uug%G z&Ur%-*G)t1#~*p3ceP@AZQ9DR{#@g@=_;XUVW8p}s*E+eV>#HFP1;$6QGEZO$!e$&*{aiZFkw?Z@e6jg=E1)aniq z>2CceE`ucOgbJQWGq+}dYeYYYVoFdxy&Nr{qNyz*Xv{qH2j8P^Jn1XcHkVHYJLNXz z`h5Id%G{4gV;k%uOA`ean)7dMMmeo5^W`3dQN_~RlDRb<{NEJl*kOynLs0H;#Kaw7 zPB1w;hBef?MNZ?tUyoa8JDkJ-vkzTLstHE8dU5HPyjjU0DNTs{kQ|>WNB%;M`b(;d z3lO)IPlShX<-)Vcpy;EYY!xAj+i7?bqj|uEce;Scd3XvUizGqv0=&S1H#heF(*_>K zL*!@y7~#?8-%&cs`O3Hw{D%-s+D)b0^exwAOY%L{s@S!Dx~fP=e#1-ZZJGd7+ooJ% zEvNCPPYj~y!wFdMKzfXw4x^gp7G|si9Xm^_)X|H$Lts8o>i$lTT=J|a!_n?} z6zn)gP8eLC4E@6*%y0=}oSw=`8^lffvx2W01Lb|?57l1%IPQAT|!j;pW%$5&dK@S-zz?f+}s~>Ziaq8j>7HM9?;K^ z1HO2qqZD1tN$6uvbY*fecPmSs_YoY@*RL#0$vfrcc>cNbjUM7~H^_`pqKnS9 z1kc4FuehXiMVNC4how^?H&{#E{lHHhcN6HFaBD^5+R5eV4589OtLMB*mUjssZW;Ylw;Crg?=137@bJZPPI-sAZUN7$ zNg0fnz}Ic5Qp84b^*7f4R^XPs;3;q&HW^^9(S1%7bg*JZ=$SXkVr)j=Fs7D;8ZrC= zd(Y$IEl*&@Lf=r3X#!kcGD4&n+MHk=x4#P*)Qo%(Zd7sHzj-=Zoz%GCIjz1|&@(l9 z{i3i(0pU*tC`aM=1jP~u<$R-3d3X1EZo)WQ8vsbAhDM6g>ZH3L3?gYb$WEz#kS=*7 zX1z0xa3Uu&d?vO+;DS?QCBaJeB@|poinYuwM|h|RMb-Yhl7!F07)DfMSw^UBg^2Pm zX678r)naI0nP>mLVyf*>lT21%j`Y?O4}yRK+_RXAD1}0|QGNfCtX*5Iq(-Bw z001m^%REfjyJW|E;=)(E`?NsNPUq6(m5CkwWH9DFpgb#VrF>5|)rtV?Xm0qz9>}ux z)I%*k)+cNOREQtev-yZSS#$&cM1+)Plndw|JV|qN6}m)3VaY~o z$hBqyNaGk-t4l5aC99nign(0^okVQb7zj zWv784yoh@R_oA%?VWA{^;R4(Se_;OmArH9!)u#M7c;c6u_QM>aav+cO|3z;%BPvVH zsF)JtQMd?_0`p*>uanaxex~WFya}IWjd;2E7hG38TIYNT{(UveE{aAoF=dE!^g@Ak z)(ygUX%$vAk;OBK)4SY-kMViU6RjAeW;FkxI^kwg9f&@ve&9bYwhi6FkGu!zUOvJg zE048FB+k`mzlgQ2pGegTBm!ZzrXIesa!aR)L&_*Y9!h*NMC! za<=}H^fu*8gp5lhzx1qK6Zj_gOH(ye&?=G$?a_Z)9=uQ_nHA3Hdec3Y!%gBYBaZ5a z7x0s8TzJv3BD6c;LF05)4@l>$+enZoTX-RLJ)+sb)iPiFBX@4Mw0m=T3owsyy_!Or zwNl~VB6zsHZK)u`w!ot-2Mm%Cudp=aE45|uJY*$wfjQ&~WK zN$2@`p!($=BAv)LeX{eL-Zry)o1P=4x35cp3e*J|{dvjrE`zA>2V6~BWjkTM7G=^d z)8XA%)78bq5uH^OC>B4Zr5mCXIA8+#(DHsB^hF#Dn=GG&u3ZOo zsNcz`=#(R*a5?A%&w*2VtbqGs&mA>MVOZG+1?rM3G}QAw{n%jXmlH9IhFSx+rCF%; zKd*`h4**-QIvL2={PaI3&V+`Xmk=9SAooGWr+0wB3xk!vx66p@aP+?gY0-SO6t zQl>YDREY;z1xAi4tz+=kU(j45LIL?bcycV_MBJU~oowjoCm0^eaM}+-;cUE79&CX# z{70Rij_D;ce6Tq15NP{&<9?Pz@~2~lKD;BY$Vomj3NrpROhkwR>{o9RrJO)6-vBD9 z;|Q-`96I|qemp|&59>%7AK`V`!GmKa4*Sy-n49k0*pPXPG4htM(q53}Q;_ck8VLM1 zsogmO%4$9#3FM>k){&GV9v$_Xz#tY{XZ_ul&zZLuoDM7fW=lZfe)9=Aw98QhZ1hL! z8_J&NSVjg;MXYc;dwtk&zUQ}+*w_PURFZR>EQ^T#{aG8!NcJObhrG&kz2WXEXOMXNUKI^M_7hz1Ef~;<2Q;Rzc$( zvCvUiCqN4aEkh9#7FMQb+Et@=JCLjhocdG|PuZ`>c8>0cm`pvr%boDqcj&qb+-7nG z{vPP{fgGM#X~p5?cvs(jXD?79^$|;e5n!6$PzMu8zd>S|A2v*za()bt<4yWI%wvQ> zQ4BfZTV{njWs@KX{jdSa13pt`aTm*-S{$=S)e>rfBeT}~h0P zYl@hlk??$k$og7at=crQSurxvqn`{yMQz#2`HkV=mDO_pc|Gnx9xla-UcnOd&eN3c z^_?3fxth`~D5Mp8Q_SBH>3`4-%jd8rYokwI`MkovL{V=x=(a@UxOYJK$*;y|VykA< zmicUWAktVk7hqhva}3`i>MR+}^YcM^Shh@eJmpEvWr;~_@7wuiTK~0R3?kp3_kWM> zr*5mayU+bD5}m}!f`O9fuyOZ0$F!y0N3vx;A}r7?31B(`EI*o$?PFsZrO@r<^HMI= zDWC>^hk?A8uutJle(|~_!w1iH`ziIGeH*F89R|x=2-CmJJc>lLGS^Lsg?E9M?W^hz zUl6MGT1B740|^3Te*X~uM%Cg6r6_bjY-zwCJ+A4#4}ujnmf!#TpC+B_8v0%Rh`il@ zTH_gjW(GxC-31W?_1UUXfhti*t?WA7xlS!cDR1m&NJ>4MlSH0?RA$QMCoMdpkeGZ# z{-erHDhuhQusybhWwP7GpaS(2>noZzz|hbWGyCX!#%h3cj~^hs=P_=3PgQposJxU4 z@PODNjR)NE7uLAbAq6ErEF-!>K2S43Hyl85q$vX20GFf?v>B!r{(#(%=#FqY(yqSA z$l@vQxd>cA}3hGlf@qm@*P<#>2;HzGKubQmOlwHLlL`Lo6(tvI65{m)$&?!Aa6g=QJf=TBu^>zbo)13~=zX7v!}ip0DCe zC6kxwdN&^L=0DJ5(yK74<(%6lz>wD)wuNf`=!aF`5krw)WZVV`4zi=exPXmGrY?utqG$!V zTmyhm7xbz56TZI1G~dXIFIM(FY~60zx{|qYE@)r#jwe;r4C` zOt4A?>d@kJ9Zp2G$3{h*(-~-)12P?teJstJeG)eVE4S6+CM6ykZ9Mx<- zCJ2Oi4GWj+E0;Sgl_<0@@!F=ZJD+`4UL&Owgpguyn;4qFhM1(E--0cyF1ZLWs@aCU ze4u?3w(O63Iy}_>PwORJtnyc0cD%5<0sJK?+%VGEFqg0FPuovLvDHBwm7F&SVQ2AO z)TgLu24P%p53c|!R-_jhztKbi4xc89WB$Bxcno5Ms^^r|Y{$|3ByHw}L)opDXav{R2O%cePf5D}J~^M!eHM5nYDPxy3UrPy z(Y5G6py}>}e(w1#XbB~!Nx!M+*i_aEBpA>jL$OgJNWHyR1222!ND&xjKRJPMT2pm} zBG`t3496e3{&3|w)U@izeu;D_QtLrR2{n6{0TScZ_MYGSS)O=Uqkl%|()#hhp}Z(N z=TRhmIJtq{J-X0S)Kf~qT0+KA_X&(f>&wDg^!RITq-X)Do~ZzgMhZ@l%Y+022|B-5 zq#0m;>QJhk2A_4~kf`b*?P7_^@D}^orKaGDiPy=W> z*t9M(CulIqIj_cCf&`v{F!X8Z+F-%pw^pHePxAeM2pMh@A@+VuYEz?aZ(-n@H!Vc` zezg1s#L=xh>}ohAh~ls(L0+|M92)JXQuYV(mz1Z}tMD2h!&X89Du5WgR-S4FzQbF1 z$Q$xwfYg+SJO$E-qH7+-<3kE%kA&KQpB%f34h5QqJ`CWX^Gwk?Wc?qmSJy&JM=kD+ zGSXt(SKZI{9gf81h$V2dcfcPP2X5zh(*Emx<#(^oqMDHmbs)+8pNU`KQPUH=rro@o zsm#taTpDq~F>VA51*t<=xB~H|PO~R)u5kB=j?I7`?7UdjrTeS%0Tx)SKi=U#K9+XC zr&W4@suIx+V)}LY^glE}foK-wXEzkD>!BC{O7aF7L)C_T%XwG@PjrSR5TZj<`knwe z!`Qx}#RL??@thbPbjnCTxa#=DY_y>%|H5s$UZJ#Bn|&HbGy4QV$oUuO&6!kS6A%3Y z+5GXP4s(y2d)l=|_{TpYiyrX9j8LRtZ3rv$o`yvAx^(;Kv3QSpRl7HXaYtRHe)bk8KP`4_Oo<1?(J9;G@)ZC@AY#pIj%_?p$*u-Ot~$-VQ~9ZG6AA8WpCPH9`*q z=IXtakmqLq6g2-rDvUjshPn`E4X}g&WzD}YZ$S}Est8|u%y*R~UJy4ef^_8zeVdl&-4F%bCe#zqLujVAM*vEi2ZcfmCJ~nL*GY+Lmug!Lk!)5JH!x2y)`U! zC!QFc?7DMjEIIu!+<)-<=%KW!xh=B|tw-DeB9v4C+|T5(K2Jy8OICg%es*Va;rnW^ z$gGl!xA(o*w_IEP_p~`J$Qx-f7-op3Svx_p2%$(1g(!lVKF1e{;k0+oH^^# z^}LOfu9E*%S#lSkvH_$v&{l)G(Vck&1a#GaC8;pr6}iDDoLv-Sa1|LyV=y4`E9)OI zaaZTo`A=R&M~XkR`%@wxwi9-$n(y&~RGI@@kb_e$BT2QM*{Hrr0KlT27}6b6Rk7nR zk!7G#>h*=@zi*@p`|dy>Rqy5TEKwKxTO95N zsx^oLyP8391b-YvZVlVQKW1r;pt1soKREAieYBpIpYQ_{FrL-9xC88tNQ^%_N&N~i zI}%|9Yf$*UR~=@R)M)JeNk%kPk_u=n-*7+ZWA2zJeF+?$(%9de6v)u@+xgSsA=jsT zuH;YbgG)!zAiVJn0%3rN?0|>H_NWga7RG19>8PT)0}R^mPof$E^~2VNY(HE>1*9VW zv7AADQ;wdwQI-i@pckg+9S26V8g!3gM`~9WPTd3G`o?)D^^cC1O-?2sq48!y>mRvd z9R!;4r&Dex`X1q=;UX!@mlPShamT8^dG7TUXu&K%4G$UPMvQjt*xPb4*N;WMv}1j$nbV~D6RLm3`$4Z!nHJZNg?^v+NEAd(&IimMPb z{UV8u+-wT!z4i*GwJG0DVMQZ3VE(bc&63w%HsfY@#+lkb{h*AIL&Ry|hJ2_y&CWG; zK5Ts3DK2C;R#1d7t^R;>)yhZnItlKCx>LU$SXJNP4}eU5ee#Z(Uc%?5?ouIJ9$ive zD?80hEb$vFw`goKz_yC5w3scOiJ$kJO&R+k>BwSdL4>*0;031I_0;YpfV9B~;4c*I z1tOtQ(8_E#(v28TbvyifQBc#)p zB;xn?pa99<1$TR+FBH_rY-EjT%cOYgE3W_c{u2J#e>XCLc$F=B8d9mQU-Bh7v;Wfq zfL&p!EpkJ;u{5x&xfcLcvBsZs+SLD!K=WJi$N38fy-k!@*FTc^w5wrfX>7wbdmy;+ z>TN72^l_QUc#xkMz6DjBCo>wHDos-IbVO+nU}iNZpsY5e9ldnz2iMH$#A53%`l?}u zOML`Lsd+Ksf8w15yOM03LWB-_Pg~pg&3cXebe~5YxscAO?aMDlp54UyfHU(<`5UgU zrvn0OdKFLKBFA!H12!q(LmBR63+#F4FRg*J@26OZ5RDyMk^6T;@~NFAP!3+)DGUu%q zz^BLV_t_AzJ7rxO|1{;zr@5WFj|+8F%*zDsi?L#w&I%u7p**Uwb*pRtG`mwbG%nE- zkIwHFHp?CxfBj~UL?~hIkE(-)eh-9_iR}GSAd&lJ+*_`#^Y85gFon(X)S#eopuDZb z*Y=GUCl5O&cl&O9lKVK1aLHK|LkauER_Xb^3h{LxH@z#qcpu=mGF3S*P95BG>Yr(6 zELn{4{Sdc|?^Hz|ss5EH9X+O0NTYDL8*vRiIO*U5_o*}1&u!Z0fwn(Xmo{IxKiG)S ziQR*VWwjNr+ZQQG8UHTenGHMVp-iC`k^N;z{6tLjC@T%mz->{7!%GmTd%5Y3m~Q`m z=4{gH4*1#R-43Oi%(=Lm>5CH(M7Y5J+!5{n@u-dq_|>mwfRru&9I{93rJ2w#$cBhDMvsTO)tdPWgO=UjmptGipMN*wI?lqE^VkdS zmL6neoS>D%(LUYpLqbuF2sm{Qn_EAWjg8STq`58k8K$EgU@}EeRA#P`67eqPiZ_sg z7PN`Iz>uKzM&n63^xoq0DvIGuH5MZ#Mw9G`TuS997mgjPv0|1UbU09NO1hvcoN{cH zU8Wg9%LV=GdStr;XOF(Qas`XNMZ*ipLi*(0s}HU^Dj@iq6^mAw6tyep!GI}>OM3t6 zO!E}))iDQ5&p~!YA3O00#5ec9d)lDU)q5O5E8C()?o9HHopZBVGb-4pmBhA024!?g zo$BOmG~x?8DP<#DZG-fGaq5AY^(~ruwT) zP|P_CT8g4^XsT=VkylR2FHZX&@VNwn&zCO}lrJ6T!}C3|BF+yY1+BBKskcQgvBvHA zT%66b-;mDi@e@_5UNaugS9l8d+Rn#stQf^nw>$C_hr(W|#ee<0y0KGrLx#CuEN7w? zoO=Y;HIW^C`rM3nh3S>v9Y%NTf3j!{Ld5~kK z9|`E>GklATT%ke9rrb{f5H(1#Te3#bP(wQ^oxjzqC@T#R0oU}!pt{M6C#GUAqDkDS zBO))zPfmpA^|{F&dye4TUW#;L@_%C5E<#=}g@%jbTuPyq`!=-H+4w8T1tW8n?&8)r zKoAU_V*%K=1G%61U498K;2yJ=o4(ovid1sA zx8utoGRvl4!S!$8`=bcOe6z|Ifj$OZLm-|#`T7Ua z8M=&rey?ZgF{XoC&j(3V6bXKMDt7X65#lh{(|>k_s!a2B6dOI*pq16`y@G5UN2s=D zH=jf%T@38V&Kap`Ro|6N{a&;n8np_0f#75$(>mV=N#e-JyENFh6hcy+7(x*xC~O&S>gT$yj9Gk!Yn@`-Mo6 zSa2+pk0-S8_3|IyR)}wfa^T&d%BQe)r<#uV-M5JZo@n+*3k}6fI)wxCS>yxa8=s~_ zHY`|U>iPpP(meA`E}wk99&F36XcX zNZ{ooE+AA3lSNXwV(Pb1`V^1J&HN$vVDo8UeISsIUU>W@Z3MyHPw0{m8)vU(cmSk! zBD?3sdbg*Sx4`#8P0Bssj5)U-${eGd@09P_(2RpWNZtItp@IgS<09h9DkA$pBi{F4 z+k;QsCM0_4C%|Xii-=6ha>j(ipdAmGfzTTc?AZE-dDRWP`9YLwygOD6P*##PzF!`V zR8ok7^$oeZkXiC$k}4IwzR)RV*ma@n{?DH1yQH47>0(r#AR13qYgWNC-#{J*sg>9G zasCEP25*Au;JE~c^#zb3nz`2X^9vl(tNwx9_b*L_gw6h=dX)vf|1kQNzfm;@5$tWD zSWmg^PPYSDGH0<>oBv5-E0X%T6*GcQI?LF_G1nW2Rsx)c!vn?E4)=_-tYXVRnTpI- zyBn)-;19d|2?5@iO%8j<^Z`^7n z8dNRK*k`O8(ydrgEzYfVxHQ{c22t&*jLz3E^Z~qb?#2kKJ`Yx@qI(P-N1jr_Gkro| zo-t$bH<-CcXhFfMjpNc5D3F2_sd;>0d=<>9n91Iw__73kNY&61r_=yN@FP)a0{gwS z%F?g<8#ngvA-*=}qwou1L}qFHb$}tec|f6oQn%u6F2>G7f;@_xd4vPgZF*B*aR~Y7 z&@+-X51H-7Kkt9|kqFOm2%S=mG&|-M?EsdNI``{`FAXa^A~ow*<>0jQ%+YPK(^9Z{ ztA}4M|9%KT0d%I;-2V#-2xbm?IB6s=u0il329E@*yHuz%XhD^1puYqyz*?r36Na}2 z!=T6n^CCAo{W=I1DJ@o_$fpAX=<>kX-aB ze)7!g*#{8};W4t&PZ_lPm-4|DD@)wN!q8z%4}j4=F+UP2lEWnbYuvUoqzK#nEv>f46J zw%CIoBny!eSC#5*1HD7o)Tf{+WJVZF5A6yEPw!{z6aKXW0!xrg6r{63V7iX98l~|h zQ{>cP??*1b=G~LNmH+I}uqAgdc?7}9O1gEPLB}*?BxWbptleV@a*Jiy>zoE%8wfeF z=<%)LXaBr{**^6kp0y6K5UHN%$R!PN!JBk7`G14zPhAvC2;vL#4Mn?|qp0Spt$G-c zw|T^YibV@qU}j~g&YM=lRdH{t(*X@|kmsm;2Az&!pgG2gh zy1eRo7YG~epf|n-nU_hOmv-%F+wTot)J=r$JCD$^!X&s5U>n3}J0yB?OX06M1KRDU| zQa>)>MVSBw<-yW}eK;3Lgq|+HmH1c0x*WvPW8s|9W6KIOJlpsRoY5vISRkv)H>Uec zs1!{^6q7P;P3`IinwQE|B{&ob*;5QkV~~d`PMrB=RR-1z>1$5`>$uBttA67Uzh9To zz5J{9G~mVyWwvv>tt%UV){bU;a`hfSkbhx5HA>q8&e%`(1kO2r1cW_#w9cB&mw|f^ zsVa(Bcl=X1Xc$yrzi!mE!FCUyA$IF@KiBB7uAbbRr9 z&2UGceD^mLl475KckDi8CLxo;xIj+0K40_B9jPO^-f-u ztmP3Is|PafWi&Tt`w|M7VB5(9Zm4atkb=)@5||x77eoZZai@oP@asn-lwzYuUgFNk zybUk1bzhq}yp0U;H1?l>Q^DwnCZTj;d!wSB1=1ud=LaS?jw^Bd8?^9A?xK3yjzc?l z4P=SoVzrDEq@yRqnkx#2!*-clg{1P+KIu=|1b`EeTRWDVmLd%0cCp( zZ-hg#Qcyot-}O=(9_{7p<`|D8<@^}4D-#Q1-^rxcPmT4{o*jXk3bFnZ;>i84Lg>a~ z*!am8ZxNrY^#|iSh5usv5tP*cQe4g>DgSX+|NUK^3E1R)d*CSL4g=HXrf$1#$l@yz zV>p_(X0URSuyU#x*doqqh#!W%10pwxpkg2{6C9!WnQZ_diGvWTQ~*cpy2&4Mw(YYIK2q zYpZS>v?xGVKHl9lHC&fojRKCQTKjnw?KZyiAp^TD?;x{CKFj@WUw;BbTW^tp89s1D z7|UwuKKrMBaY81QoH{9)1$-)MNm*BG;;xlx7vhO1-^~wL{2`R3^!+FVO3gT-GjGd+ zL1qE?)D78mBY0NInE%)>0z!DfS$aN?pzDMz;Uq5XT{H=?W32khO4aFaqA+A#P`?N- z7TI$z-?WH&z^aLw1xzdoz>Dpum-H}aRo+>8T?4WO=(Uz)x}LMRf+Xp`ra{Xa9T-OgFYzP-Tof}=fwx_Y)hnX*}+TOpK`v}L+ z5hst=zOBM}cYq+y_K24=#@cA+D2q|#bJ_gHUju6C-K@9ywPP%;8#COpf8Mx0yxsDy z;doz2w%mNvJD%YePL*0O(0sTmj<(0=gc}@knK^02pA#PA#Ga1)U08I+ zTUM7~NHV@X@bP>Cp~k(Jo<%EJZ8^ri+Rda^^wi7GJq$3C-62vZgg% zCV0VC86;S5;(3p4!!+;=@C)zW0g77jlYA=m{4gCG-)L9Em zwO)?dL-j(VRPn;Ai(lueRFO=^`sdyk=66_(3zh#gt}%}jG79yrX5ku@{K!si|?DGl7{}1@R*05 z9X}kcicA$i_-SE@=js0aPI8pqf?DJ3E6fUH;@g)kPsH;t?K9`hm`?R&^=2q|8^^K; zu^!gNOJMq=iww^~<5YF%!)9f5?CR`L_uZqXhv|9M)zt3{r-#N7g{W-G9mP(V48rY$ zzltfft?&i6CoOM*9D{?fm^i-6W@=+j<53O6?^o9jPVh@-D}qOGyPuC z7Q(t(JS^>#qQPLLVgDG0(k`7bVfLdW!Qe)NbrYa%OEy9J@kKeGN1Hk3D0-;$lpKrz z$t0s4-m`t~&dE7wtC63x6umV$8+|i$Q;oNAi!WQ7yZfN17_R&LM$iB-zb|I`b0ePv z<$srT>ClA}p_~|i^$v=06*&+nuZE_(MN*s+9((OKJ;+LO!*~*Qq2S1`IQ+T6zn$XL=O>FLY^F~luCDvZWt zk&TAnwg6f*xH;`1PLvsEOAx7OttIw-v zTA1ZxcMhUB-|Rts;11Rmbjkc=8T42KXl{JO9$HypGO;@l5ZzmL*X805ODW1%TU%kq zv|3Zpo!EOIvN z?00bwiAmqQ?y|;wdlYu!=hoWXgZ=H6eK|mfibCMdYE;kSab`A%Z-sZ}3qC7XKZb4Vo7iU(-*!pJV-lw+I=d77qKum)9w|2rG(?BYI%*H`-rUYDQ9LXK6EWt7H6TZ@1-nBxUeVD5BxF z$>ds208T0`bTTb)n>AET7q5urhBo?vZ7NIRyJ4u2jy!lir^5yT1H7zxSr*n-F09T* z2S=6h9LC_Oe8K)a^4chp2Zxx~TDC?DmD^TicV5Z~E6gV{5$D9zv?oAHF9(R_9coWC zZ9AqiEQXiV!FyxuU&vjVddIZqa^+^Oj?3oq&s)DDr!F3g?Z<`B z3=|BQ#l`)EidF>sdO$`LZ7%?q%`ka}izyMknbL9 zpMf32xPLQ{nxx|bC+!z7Qt~iM;@(?UZ@1_yfa-1;S6!JKzNi#bEd?V0&esI}cF+z9 zu~-Lm={|@I2aPl24P}*wc641nKfU;f$~f;Sr^1E%pbTm1L|p^5RCW3J?lc8?j>)jx z-{A5m-;-xuVwuepHSZeO2`!=e@7}RJJLsqJ94aQ0x#1^26t84en8AjmD7gcvzph4y z`nU3;SYdRk_$k@$w4-;7P|e6BqW77_eWf|b+c*DvLgV=s->7C;xIs|x`IQT6+SQsT zogW-P!;CvcaIllR_^DO~%8K5fxZKcW8@j)hjv`rsDbGQCGx_S(`%_k!M#2Q#IWpj+ zRVH629RKkXh-Z3pG$SWJnrZ9~T30xo3Eu+S8GDi8IS8z> zkmbeitbiCz5gfjx0T){ek}7woE0vcjLf!j-eFO{GE9qG8*U+*tKl&koTV-G#`m;ap zHrZAy6};f5k*{T9!fcKS(4GK?I++@ecZ!~utz;++ za|*HbiEws(1!njE3^H}mUtZIeeccsrTf+ODsx-964K`{_7ocz|Ms(9ZzcHdK)0@IJ z(g<`8*^uHK#*(9&0N;tTnFrD$O_?gO{37u$46(dNl+hb9f;jT?>Yh`kn3y@Y*5>|= z`H`w$0H{cV@qZy^@tM!4tHVj1#YkL5`EW z0C6~qCnZ}W0y(pLx~DV*YZRn^179bAHZPae6%4I0J(qKsv>conyL&<&+=+VIGOA*wFF)%W_{bDR4hpgj*r zq|1ArTM44#0vZpz8g%L00!)RdWHrSaKH?P+VP$+@0|YlAG)5XmeWOc!fmK?}FE!~6 z!zf<*Dj9YYoV89(&W@a1N+3BtUA|nTF=|oF{NT?CnU{0TzqKZ{%rJQQqvaS^K}lS_DH z6wqxQF$MV4lk`fnh0B`iWeDUhmHsTST$o%`hz*V+4z1+ZCeg2eE}~uj(pSgkclTvp zw}yrTQ^Ue4-2Dys3c0zD75Bf9~O1rr~pt9MY=riLj@QN$^+&j@~!)s5{&UP|uesXmrq{^PMOtQj4U`O6}XVAe|g8l+o! zxFhG^-o1T}iCvn|e%!SUyLluw4{#+XwEb#3vH1I#I4|pi zt8L)=-xZLqBi@llb`5V`1l=p55$Og@w;#%vepxG4oXH=+49aosM}}u>m=1 z^f#!76=78iJBM)W77~(ZYqHiaExO9SR0-Q-^TgHp+q#5ZvY*tGEj~ymx9Nu8OQ09< zIr+rn%Ci>SSZ;{hEN%Rr1^GlLPA7hXyAsEEBn{J{=i=fR>>#K)l36l^Mv}wTIDTQw zy#B^nB}bYKYut#A5|LN|EK$LLDc6GOcI#ZHqKH9!wlW(Q6J8=pRKttr^v*4x{(=k@ zWa)8lDsC@!ZfPDn?z41!bNci%U$*bW)^4b8ywfD@UGaQ~)g|q)mFsg5@f93l{YaNe z@d~2)EvcVGAm>osjA~#F%(zMqWNkK8cA7X5x5co$hk@OyF%Cg*7L^hj7d# zfx(jKO_SvpF4CzpF$11EhnvoQ?Y@4HpX437wK`*2g|;X9hlkSn9nDiRO%vyM<2a5J z4f5G3KS8zJAiNu_q^T2QG;D3cOo2K{M}E?Gy^kd#E-4J_=d3Txn67Hzyl~H&=~s$w zUpVPH#en>QLz3j{m{iQ_vG03Ko82{U439M^9Xw&_k0s0!zG~9}Qy}qz@eQhQ{~ZTZ zKLNLn;VxNg= zPHN)`bW6{WmZd+O)xFX59Q;$-*#<|iVlp52qra6|`Dg4QO5&jFg5-dJ6s+3<)HZf# zS+d$NHhV=wFq%`*NA!lUz`eQXLRH6uZi#79&Q9X!%w2OyG3iTR)wxq9PKCuz^?dwck;wg1H z1{d>pr|ji@vLWsqfKL&Qa~Hnp6St{u3glC0&P`I!e0zBIn>*nRKGhA^B3~LEqds5x z+L0HxF$dFQjl{?6mHeD1c(imMEwDL8H*`|+ue5o@PT{sSCs9xdN+Fft0qfo4g~&N6 z=1tk1GT9~1%N*D`ewP)yMHl6F&8^A__USE}Cl_R*{ZQJ9Zs^=q>Q+>lQ`1(E{a2i| z+v2yo2mk7pQ^^t&G(VRq4h7QEv(!hj;_VXMixo1%(JwM<&VY7STf*-372kH+vA~%D zUBPVZbdel-VeDM7WTjp*N}LA!_uWGc=Li}0kJL=hQ-n@(M$CYObF6cugG~Pd2D&^w zeXe#D`{`hQUaX9sdG>}1m&4}?wMo=R%*TV5p&rwAb)oFyv(7e1@RDJ7hv~f?04`v?k zNq3Qa9Ve4cM&nR!)-Lj~*Fh^8f25fU>I08e)ts}cL#D_(@Hm*FIA%ts(H_t{s)3n4 z{JJJ%O6B1}tj8p2M;eRfe7*99=Vqy_;3ApBa)k#aP8Z^&O-IOfNY_|=SLP8T0437R zt3yLf7RcF{*JzoIc1yPJA19&F+tw)_OH==?zwi7p6jnef3sGI8Q2SMsLqma*ZSHIq zvNO(M%X2;dcj?=$a0)l8&$rsvPhidff3VDi=@N%nlSM{bA2L7d!mx?TKaU;bXUj`F zj_&JKmZdk?CSU9ux8g`K>7-;!Wlp|ENeZt1-8G@lg0<&MGLfQmQ2lkZ`l*MvheH}X z{9z-Co*@1L;D`I$FPDQwHZbcv)-`;)dgtE(-=pg)%Jrl9Wfl48t71VCR`~Cebu$e9 zehK5v%)(1#XE$=Wt{Stsh9FEt3Xg%RSeR;%iFUC`#8V)e75|GMo0x*uJe@^Oq7l0X zx{)|V<*j+hvhHEY_J)zC=t~Z*-hV<*oBjh6DN`g!pZ+P4Qz50b%E~!A5jEP3DW>fq z&?(n_QAz3*6nSv)i$mQQv!8GK?Pb24K2>HQM z6Z(u$@DHab^R26O*aB!U$@6NkqC--i_IIefr;P8oN5n*>F&PO{#d-G|zhP{`<28$O zhz7S>Nd%OcxFSB{FTIt?SqY`T3DwPw59_|K^o0_@LSIYIs!O|qE~!JoMXti@kP(?t zOmy#ERmj6sy0^8K#J9}q`vy+86XVnjOT`Zx7%AF2(ljP1eCKif8QB_B^=C|Qyxn~b6`{~_2{12qQJW5 z*f|56V!J9=T%lv74B`IL&MnrQl;k;06Xqp4xK$dphPQu|@;*Y|G!&{gifH#ZAY$!t zM)}_K^ghVVU!0pym`;-lq=X#5MTi*hW?W>NC1~f#5IsswnT4U?%yDC8X%jMtS69kd zR{lNx$}C-0H)Bwf&c(6Yv&-sO2Q|x4zlhKan|u>v2?qzC_J%(3Nm`jMqtOf+zKfSd zr8qT(8k(!5K2;sPZ<7?0Bg1f$kEh;7I

c<%ytQc03(LL=VP;944B?nq!aTzM16h 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

DX@@yIvdat@|iAH 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 BG%i9=Z)lL2*j~YXD-ES++dj zx*2v*$Eddj-S`<1r3W)*4vV`8tk?gz5^8iM3_Z~Yh}56fE0E|*BR_r+!yPR)$;(6L z+0%ECTVD*>?yWfDgxY@Ykrzui#^Gca;CySCH`4M)gsTF^XCKXlC4&Ygkq;D z)s$6-F6Z3(rQx#9 zoCiwRCHMj5#BL*Voo^;{_DoM*?|18vR=O#nc+Ss0BG;+^>d*v_qvPM?@X7hTRN^tL zrx1?p3F^9SL@T5sX0vw5KMnpkX@)obf5WS%>3{O;pYOQ;I| z#M5)nDmsok$;k-F&tNesCl$#;tLJ2}r+8iHs95!PSq=RS)vVm`IFVdV>n`C+VGIR^ zjt^x;y-UPv&ND_IZCnHPu{0Nxms$D{)y_x85%$^1*}moVC6B2fV+*%00jPMNc$QAxd&MwtGJo2e;&|Xi`wV$ z-aYmO!y{N#U%{JLRA8t}>c$ub8|fMLwq=-(;Ok^r>{aZEqqAf0dL2P}Aw_wJFY)eA z4v~4B&4fBvXNK~G+yk~V)52e)XCINysYDtE9>z!x^ zY#na&g{%+_S0#g>qL|!E7H$r7DXoAx->Isay6ArG6swu~&zy_Xp#>~xy*tI`SE59ntT4$W zsUnMHQ%w_>9+0&17BSA!eGi!7A;aHK_xXM2jYvg-6)rDHrecws+pvDC=mTgnp_#bD zi!wfAY1r!Bj{T_>&9n`-tl5_>^Zip3P+kw0F79~K)9^wM61s%j-_zE~er^i1| z4Cg&7@tt0iDs!t+DPL(+z_AcPRjwMupmV4C2R;&}51vk8|8ZQg`9rioABUy{%d4Xz z0k@Q0=k*sajytz-E`M{PQaj!wDl;!yz~XmQW#;QTg|?rAOBKv`j%V)`$>J=|Nc*L* z#C(%{&M%JR)`>19mHEAJ&{vdVa57}x^Wp+*zKr>%~f z8d}hDC&r54C_w{grgOeHa<{JuRB(37t96i4%mS~OzR@&)<%kn##8VrR4W zZ`ekV8@+LyA2p=8V(}WVi%Pp|3NLxdVDvn+IM#K-2sJ0uyEYu}%u%IY-;atIxGWG~ zkR|)v1wYMEFs>xE=zQE~dn%-&tJa>b!z~&O+O+a0*GDrvGE>gdZ{&7ldfUuoK8Nxy zt*}x7vizxUI*L`Sabsz?|F?1nN2uXkr6dy_)sO8N-3>&pi=Av4%f03{;tIx`34Wcl*(Ycc+R>?>pY{@;W z^dsQOs|-RkDa@@Uy{jBY%kDUxT(_h{fOui&w?8cgDwj}P3T2Ub2BI~9gq)(p7rT9V z(72Rxq=w6DBjz2KbX*8a`7a5w2yO-$Tk!+Pgkr*^66u0~v)(D15l>HSk8{ssxv{ZM-jt(W;Mqkc;&eb(}W$+m0N?^q(dq{#<} zyxA)qg&UMO+A-d$%D))0WO5;0vcrx2@3-;ii!tOO;+z*hK6iX@?r)%PRvj;7===J2 zZRE}^Jw4KY0ZG6@QJBLXlO&@_u49$X6)n*)CHdOCv(gENw|K@fsD2;!Scp)+xv`l! zH|R@3ih2IeIzd%q@I&#BK?F2W!fol|i=T3alYxwS#nyp;kG60I-;x66tySL0SCI2j zjn035EY2Ncck7I0pO|HH5+b3of30F@4w#h<;3DfImjhrew<-Ld#-b4_9BCoTRs3t7 z1-|&tPyZZ&hEpFvx^BGm~8@ZiScU^gPh0W2cAf3gs(u0mA^w=Pyli|qa{5cM0j zC-;7HZtjv{cR%2f#D%v2^Y(6z#{5}iRJoJ=z+;O@lXmi6pRW)ROk0zau6S?6+YC_z zRza@K{|6ZzQTNG;fASy{mQB~v1ramMQxYXEUGZZ|l6A?Ko%AL3Jn`32@b`OW;`9T3 zZL*TrP7wTq;q|MyS-R|9R@-Kakxn{eAr_;vgV)XK$Zp3 zm7c$7L1yY7TFCVecuE3~8S6{j+xg*GA*SaI4LR|_VZ~GXzxTYPPtROL95loJxkPCB zI)HVrc~IFd^lXT_%KCl6_~>;~_{aY&F4G~uFh+q#K+r!zS_Id{kDZIFfG4lD33S5T zAoSliL`*z>>5qQ*>4g_J;Ce_o6%c;^O980kiFpYC^G@K*mw7?Qks<7-LwPa=t<-wW z;XEdrhsU#L%gEizdR&7R?Q{M>rpP?1i#yPLW`;z(mQRSiCp{lgTVuD zo(b4l(=!XF5IW8dc=dL_fA8Kjy>j8dGz1^M7=ZSX`d~H*8;{c$a(!9M*i)%N*5Uv; z~u!=-vt0f41-yHcmCP=P6ZHaUGBe~TTduRy$WdVT)86y#WPQR zzYD@thUQ496*6tZEf8u{3Z~1K|7CqZ<*#WDdIp=fq4cu|nl~`B0lkp|ATG0TqXrXU zk~AH-4HPo&3SL5@^B+NT&^HE9WFsK{B>%kEFk&Wrf;K=E2jh9U{FvrHy?I6JzyQ=p zYO~EB@lkClw9q$m@nkpZ_S{@R{(I-^xwk)s2IYl$p`VuU@0gzZlKLAclB-)98MN%Z=F zpjrjW7%ligiGhy{L>`<*Wj3e(ezs68KZwPgKqNOdOQ({>PgYX>yFjXVdMps*&7MG; zAdJH0^@IPgA3}zRXCWUXDOGd@6aOXGZecW{IIi7zy>P?@oW#Qns&I;tT=zvVAZRG+ zp`pML@ks_~Is*tL;W}ZvxlR_y@fGy8wg{eRYlkuI~p`?LzhJ zZpQwv7NoKBMo5wWZrV(!aMB~+T6rHFTXpycg#7b3Xa5q*Mt>QCO12`Hg8w5=Duc=G zf|u$@08UU1GrvIc#O+(v+{k5gZ892!Pbtfks{M))R{vKuo9jw*yjgl;+@r}J+SuyJ zzDYCC^O?h=Ndvd4RAAU*srq-Sq$adV&vd-9Y3%`mMWLD=SinYoZAeDI?|% zL_ZAwXHUO5()J0U^jkg9e@;97q~|*DA*3+A4U5HUSC#5-tOs*+`x4 z=OEPLCe)yz+g6G!B9|RN!EvU{s*OS3V8Moz%95vZ*mE}vf(D~dX*g_WPfH@!bM)qMHgB@sVSS>SqQAzX+Vec{sW zhmo5FZAe#EO}D7!_o8;Eee*0&vFg9-(iMMj#*1!5f#%*Czg?`B4y{qoXr48G#nAQ{ zW}26y6EpNM~ z>@^>_+vT;L!aK$BJ)Gei)AvVG_9o~Dw)2R^F0FX%-mfb>m^Br1Fh9)##w!Luju_J2 z3?9dmeXCyAldx>2d8X!+hV;p+n!bH`RwG0@ed$p5-~$9-Jw=-iRtc+C+&Wy|zIz6L z#MIn&^)kPVeS<&QN2RGIdFHu;D<90GsaJFh-jh!}={n-Pa%sHec=0>3CSNu-W{~^5 zLAuaFMV{}PzU7UZ9t(Mi9q_02%*V~_mbK8aJ$`0HL;aN}OM*j!o)<+5D4v6{gnWQ$ZAtF%+|IXPkFo}nccxt&yElyR!;(iuo3EV-WU}{*>#4~Ub3P z(0swQd&=rd?X)qaMQ067L%U)G`hiQJ*jS=Mca?zqurlDgOg@O-h@SF>hTn4-$h zRHLacLCSGiPb+@`4&S8d`sqt}0Q&2>NJ?FMdhrx%++;l^5ZNQ`0-mfCfbqwD(ELOG zN_<1SmW*Cg&i=aCiO{Q5A-es#{@irQrP6h@1M>8@chTQ{03 zramnz%~#I984{WA;fUMIlwSc7ucAAAJm>vo*1~>xE*s?mZw()3KTU=G654=8rU9RA z+P!yV?ADiW4P^~+4>1-#EaOc(-8QjJThm5%Jd3*IBMxWAG9)l>1C3NoIiWYKrymwA z61!UM32bNw7#FVvkoGpMJ~NM7RhTwzUuT@4-3lqw#g2`FD{y)L`@7ZDw;!jB+cp&# z1C&U(Bdto%RpyTZ#Pg<;6=8; z8IyGWxruR3P`R*18+|8^C+(Ma`x-I1XP1lMt57d=QPq@&|Ao zYO-E$2668gy)O#!O#C4kGBTjaTInl15^*Ly1ODA3uN$gSQ_*u1tT_tGIj&JxUE?0s zd$mZ!g(`fLkN4nlsoa;9?sjWdH52toKd2zj{o3@Uokhk9_~OFqCmRBm%e_I%J3?N7 zv~c66Wk#~Azj@7Om8jwu5M8%8CbX*>1mLO}%w0===I@367LCwm11xJpa)e&!cql1X z%|T5jy`v8F8(Oya%|pytnADuK){EwhHE;)4j8nU1K6<=>#;PITakSz*i=cqtOO*#1 za<`wBvsE28KH+fE)yu(V!+RtBD%Hv%2W{7!Okqm;x8;F345g?PvKIcqgX`~#W_an* z+G?nj6kEaWGaH^oj;Y_(H`LyKPaOf7iEvgGoc}DxT;go=)~6?_eK}@^eNP7pV+i#w zalWeGj9Nc{Lvna7P#t?V5S8cCYBKx!JN;53GTnStl02mM<}osm48@?;6;IfIJa*G? z5@f(q18;>MPCkalA@7_|*7P-Gc^)x^7@GB28_eh{-I#_vgs79TH)Lv-6|Bs#3|2m31%Z&rQQY{2tN?I}t=f}9{F zwll=u1-fjv$WKjgN(+M|Up(&;PRCB>CW%{zKYu|-qTS4}#nyXWhC1}AU+6SjIB)u# zEkQS9s(8|yM?A##$kyTYFIC+VSD}`bCu4FgRdMUyi#=HZ3*gyRWC_EeNOS}Ye^Y$k z1Q)<}G`|*=c_uSYbiKVQ`!Nhdcs+!(*spMH)Ou=>RJ@z=?$Z_+-cscVL@_VLe4lO^ zbraBSrc z{oVnUFuDg(XEf-xcwQ^$`FuO6WQBfvGW9^nZd4UxwfYej6&;K|a&w(@k^v7!oPK`r zMMkI6?9V0MXmmm9t?-4>S1*9ooRpN72ai>K? zax|J;B0C5JU8{bdGsx(}IuGf)=bT@n1WyO?_!<%=8#WgDpMQU^OXR`mgrUfl^{7h| zoi^4}{U&ck&fUpZbu#cj`b~9!BN(%SDdh-_o=ziA4$pLQu2omqobPR_<>LDiSr6G{ z*Iyh=b^SF8kd?1t*Y1dHr{^Yoj6^J}5vWCLGPXWK8tJtk`-bfheNuSZ|1dSZZ~q6f zjn!0cUYTpE1F~O|Wkgb$6&9U5V)k^3>Gan5sOei^kjP;J`zCE84|~!vT8EJ+PWdCR zZ_=yi&Yv8L9pbghB%Y#o(hw!vZ~6FH;h<>D%rlu`m$@o`E(#wCu3wxA%G_uVZ&h_w zEBd8mriP4WFNzYCU{W?rJg4g5Ogg9qLQs40H)?*IKNLC#6G45(064ocPBY5>nFuN# zYxx0!GNQ4-q-!1pJ@+kp>}oWBsE~(S=9x^3@ zmVRo<^_)AQdD@44emU>{<`YUV)Kq`>S-+W}GO62Vg-kcQ59=v7;;e|#y}Ca?N>ZsX z4iwFr@E?uupm3o7{b2f`FQvZ?IwMH?FF5Jv zT+BKJbr_!$Z+Jd<;8^xK{o40=Sx1`>(7#Zx$ZYNVHH%Dqy>r?^7Q{OTIBv`Eag%7B z(=%iuDhEc>V!c^qp4 z>*m`hZ{Dv5#iC>~pyOviOp;uk#-Eu5C90D? z*t0=Qld@ekEfR+fQzA;PQd*(pju{sXak0)R)!@RVx>Y$sVzuJ0H2G-?JAUQfg20^= zGvT*mjZ2IaoYIU@&f+!Lk5l_HN8X=oWvXXJl41*Ko24S+D6@SRlZapp4rM2C_zmFm zMFBx$l+|7ORFdTI8+uQQB&qX;v5lYE+SehMwx}d8nE%Ut6iGHDCsepq{TJQ!keSQT zpAJPbN}k)F)8anl`)FrOQr%hKB!5hoNTfjkQ0cw^ri(n6@mimc=gMA!fC1^!&|7j} zk}7mwqQdD3maOH4oV_+MI!U3`xsY&T=}W0|nA2fS=0x(u6#e7D;@AQ0S?{J~bpj^z zybhgqI|X8#Z`E+@4e;N3j6n5|b+5}72=fe4P)8m_pHo3)KZ=lQ^_#3~T8e8mL<_az zT3?BnBu!gIWd)0{xmT-|_y{f-N2vzN+G`}|A~{(JGACaZd~-Jo!uvv&f^ob!tQHBnl#)gXw2J?uS(Y{Q z-3j}tG0YUeG}$Q7N%bXzedtS3z4c}0>Wfdbo2i2mg>`Olkj)*seU31t5>NkDuZnt@ zR8T!$)^Dcq8i5{dz+L}Co&9(hBh!KGDZXZXd-v98ZfQe~0?{q*Jo9$`=~IKgC8tjl zB!XN*9W;^oG;d0O2KhSv+He?Ma{7`}FOIqX7F9h^fFRhh=phNKOlFhN%p<;3wjNbh z$j-;(X`DjyO1pKDk}c>-foNa^^!*| zvHZFY(gYHIE3sF0y^YeEVEpvN;dvAL1~A8BPpY4%&qZ}pwkczKrX%qO+mn0ksz89` zpC5t4M<*U*7av5bG42K?G5;^kH(e}xKqe>N|HY)%)Yao>zf#qZ>TjOJ2AZ<*xCx$Y zqE0gT;f%|!veRicVdy0j!?#7DPS*-L`p4?ieVVz=$wW?a{g>fN(#x~g-F1XCeQ)8c zvSPY)*=zXru#>(B=;`=Vj%OJ8p;jJQtwt<=Ky+oaj9Td7AdbvoQ9lg}i4nm_&3u-c z3a8v{>95rCraG6RV^DrtY)abiuswWCx5%@D$+OGt2an5|VX9-MO5i5PQHEz2w3ZM= z&J^6+`X+tRpU5wT|9EivK1%VuM@3wuwxp!>o7Zm3U*DvZvYzR;UXl_Qz^C<(Tb3MS zmYUIyjXe24!qfV{ld=bvzL)-lp)U(n%*w#h!$3_G1&hd))c3%?Ve2gXH2PX&F5@Km z<7PBaIpMCV@q+ZERp0wUztCSqKpeLZaJmpYRC#>klI}$n=0C3(5t=#Ao^Tf9q@Zdz zy|gaOI|WnZ^_*4+YCJ^B`)LkxcGZMUFE;r3dkcTaUai zSTT9bs6C9o%WUCOe8i|gPx$9>nsYN7G7L*U!>nClpd-0E+ar<#njWeSYKmlyJ#gKc zn78zWrk?U}&4;M4Q`=|#QR*CfvZfUd*YK2lU;I$N<(9e;o9|*EH<_NocXiWX-DLFT zo@-9hhzT~}9|Jos{4-qGvaS3_H~iVf5ZxRl#=a}*BH%So0I@_JT$6FC+F zbXaKW7~(s!Us5h=E*rrJcpue!WS~VPK7emYAy$TtGxf^HM z74NekS;Ao>>~QI|XtuIO}?^KtrSWCAFJEXDQt?elp!H zY^ONLIwhz@l6_au7$}1mTDH2MH2Vtd^q$?V`Q2ma9Zc~K0IRQc&ViQiwU3dMABT}|Jxd=&)pbTey z@l)Q=9MJFcF$K(p|C9+7oz^$aZ=Is5GfD;z5h(6MV)3DD=FrdJUNDRjK4aci=b=<7WG~d8(zgrXn*1MsjVX;t!w1`dpZ3=caN&l==5@OJd{0Au-!4@ys^bWYYkcGV!1zzV?@P3Q zO6aV$^VU+Q$t4nW4;8-b(+Rfe&CSsHg=2+-`!s=9Rg(wP$WsiyPu52~S6j7z;kLo- z<`^z95iYpVbo^S*HOa8=;dJW=nr^=XaJD-|c(oRZ$hPD~?6H&Pll6YV?#wgbG3owP zEHzPL+&9({T`q0YwL56*PyHp9T>|HZiyT<0*)Cma$kceU(qHgkCI4ZRW|-APJ5%d{kKhX# z&A{@a;`7G#+zjeC>HkLO+}&VzS?S}+)I#gCue@(ax^WoGs3YMh$1!#twa{|4Z+4TN zC98{ja!Pa#q|errF50i@GZQiVR8==Ut!6utk$hN2Aow0NpN}8{UeE9Sm`ulIRPY^P z8c~5~O%=aA@W-vAF*iLUl((wdr+#1iK{U2bDh$5~9fCa{D63F3<)5m<=={ zMy7|ZAiI!x!!qmGNk|pjlm0lb&P~LVdYy2ZM;r{7UEFg~^lx#_d3@tFM~WI$@iyR> z$Shzm!?4xgqi#GN5zXxcwCspRLi9aY=6gwKlB9tc}fK$rww76ts59Ma6IcV=s+hNL%#WWLosJ z&)$Y8qGDuO7bT6~H3)xK%Y=e#1IFSKJQy- zLEvK<9j)g}6=6`u%u}DR?MjU;%9@CfdOd)xoP2}?Cm?9TK)?3bcS2Z5HzwB9_;Hx2 z(h4P`nfhwk&HNlKlADjqRjd)+M|1*Zla#|yu~viIf|2BtliUI$>I{cT47)wDaGwlx z8m3fb87EAx<)ylCM4c9Hpgl3xBdw74HYmGxx>)FY25CFlo&}C)X8t`7uVA`lrfEzWNJ2h92>u5ga`V z-o`4Ixdd0*a;7%bNyq^!W_urx<8k^7LC`uMDdU|ghPbQzS0(dHsANab#_y3Ks+)fDR0Z(iQc6e?VI6ouq-a#4H4tztOSpmbN~r2l5=8l zLS)fdG9cTJ#~|83Q|~8Q7sG#=^$pObkY~C4=FV``#GSdcPDp~a=1m}2t7>{X+xW<>)7r3%-Xh0be~@ znDE#|`wO->0RX)h+&USy4g}uI86KZ07vrsHozF5H<8F&YCCkTmH~!8qBqPxYH|dH@ z(O^Z=l9P~7cV|ek)(ZovnN!9aPhOufm1Y@0~LlBIS)Ne2j^VgQk%Dsv~QX$)3AR&U%b-85< z8WA)Gm!vFkm52>Nk68zsbXdec%DiWhJ3l{)Ixppbga38%<{awRUg2@o|rP}n> zjgJfb#>^xU+#G(n=`ph%)WJ&hd2Tl>usAVE(45JOM7#o1rs?}cGLi^^2n&u=xl6Hk zhhJVZQVUn0*ZXstMpVI=Kh%65V!cWTVUh;#s^}~9T#77n7u>IBsGf~AKB;Iw9wulj zbC-WX16AW6>`^U$XM6`vxk=7L)@=+KckI9^B!|WgN4w1bm{$fDr&#UQe?%jyR*dH$d)8pLUAy&bZ8G*gmaZ0sTX#JUFlNhHJ+! zdZKc+9Lfs+oBNvz_7B<;O(p`1(>~GrCb&@O>)V^f4dl|e=t-hD1>b^(FO7QXu;;R# zCY2dz@GDp@kDNpZcneJ`oI!Z$E`Zo~xMGgH6Es%X&SAQ~*Z0ELE(qaF*{Nj`o_yDy zehN}9v)f;Pb2+uIZLCa8)M|NT>C0I)22!4<-}Gu#uL@qe-^#%B9Z~Ng&bqDxYE!V? zBX{(}K5@|oRi>wHtyxpr|@j5ZNy*e>~sD`e|@66roUrq8NBD_>aI z{yyzEiRCJC$C5ZOa-5H6(I_}eh`UwW-;^QWkh<+qxk4}Qx@x3Pmw3~YG1dp?J1|=n zwjW%Wj|3`jS~MJQ7%U&QNuhii&r6&X_)_7yce}a{KLMFRztDt_3%#C{A-$lbuoWrv zye_Oth0`WdW(fu*Qk2g-IrOqpk*y<;3OTA>MrR&kTCYC1R1}$`KXOs|dbi3~B1UHF zovu*D&B#*0!DugfW7T*fh$fbcw4GHgd=J)uy!-uY4StzuPG8bklS&+k*+jGjHuyN_ zg0tDJ2LK8j$An6A9}2R{%Q+|=aO=+u0}P$Q&_n5v0@4ygH;gm_(juXxG%|#A zi9?EX2+}AaA>AcN3DTuBNP~Wdd*A#01#r%sz4!Axd#&F(={CpoQ(S8{A{Pgk*>DM~ z;OosAfLs5u5nzwb`|fahr;uEvrT^}`nP(20!SpE8TQQcOV^LjC2)f4uoHL4qy z$f>5trOnodxxI{UP3`Cd99z#%G(0&okGFIKR5)j-p^Iok&Ua%xL^sK2gm$m16kubl zmR#i>4=GgyIq&xsv}v#2M0ckB=)v-NhOlS#P3uw?Z%s`<@h^YxQWP3@Va@Z#uA{;I z!{E*o-qjlfMNR#;h`uy-B*C1daVya{Nz=QXU}UZ9xL?p#b1dgF@*=jJf|_md&>Vdl zXD^dJjLqUNrj!uJu3%Eem8Y(dv)= zl-!5lj?iBRyr_fp2yyJArO3a-cbl<-b&+k{g(#qs%;4+(ksMYEH2E!m(ddb^EcFQl zjF(Xdj-K~c#6J+Lu)yXyf0lHUqENflAx+fS4eIje$G<0s_Wfn!zW<=+&9ApFyKCP% zk<~;YRep1>azs#X%%+EDR4X=9$jMQk-MZPCuEjYUA`q-RPG5$kBXV_tbtcbWuc-5O zOU09gF-j^XP;ou<|9pJ6+ny!hizhUHl5}J~A0u80tgZ(YKw!q3b}d7uZ+p#pJXC#A zx1|TMu%|Iwxo-kmw3dxYx<-x0N2U2;e_u{9q!1f zn>1l+C1FQ(IKgtm%qd@P_?L`G&$%@!_jBNrh142bRG5db_92Fe z1=ulAhSwxFPl~HZJGmFUA8KcO1%~D8_ zw_E@nlkanJOxZz?pT zov=9r#KyFdha%uCPdRu7VDCTtO4Mp=f<{E#mP6#M$?uQ+;m$IY&cbHu z5vik@0F9!H0?hW7)!mKqO^Xs%T6;sF<2ZvCyw?jbn)+_FB&QF#+fQ?5*|P;8%cOF0 z2;$K@18*tJS za0J^ffG?+YN{vA*n6FnYq9ZOeB$WdXS5XCk!|?XVv`~FG?2m!je8eWjP{T$@?uoDG zG?2P&QHY>sS;zBMGU_e?)YRNXjaR|-a%P#q$CQ?-$f6Zivc}L5#Z^R}n`>7%g`;26 zQ&m6K>CcL=HF?a2FRZ|Uzdcy~D;d@hrjqr>b{CkO(1kr3iqI@?uzhmayg92ntW^VU zICDiG>=cuMzR_RTxb9hfyN zuXW98NGJ;}!1@pj54e|qM&xH}np?<;*}f3>%JSWyt6hoad0dnJ<#a1zMnwF(`FsDx z8x;{|(YTIb|;vdAZAL+EF}Y0eA`R;9wysQ|NmkQnC3akU^K5)6 zTHhY~JkwRNzw(yhQ68(x6-mMta}=i=EW#lac9X0d0ED+ll}tvrM;w!dGZk}gclqU| z(LO9B?Myt<7x+@fa3ap+7RsLVawSyo30Z+q`XO4mF2_ zN5|%6C(5pc>mr1;Kf<5R%1nTCP{Bg?g`yZgfT zy+0HcMp^F)KFar5|M3`=<97d<{|QyJ($!Yg<5mkOKG#~dH%_8Imq#Ti7v{QgKuFZ@+6O*@{N`qXoMCk+7>MVlF79&fWh{sA)Bzg>dySy3*~ zxkjLa6`hFQq?~@q7}*vJck?uZ0fcQdGgnh{RjE87nqe0Z8pnFp zeLv`Wlwk8Pdz?%B4cZ!==woT)nd7-?tX#dk!Jf>swX<#&R--t}#`eMu?%aIXV`$PN zr;LS?QXH^-j-! zN~nD2QCr~%^^#c$pQ@x~Yls5nYRE~LCfMSj^P>NUCA8+Ll)j1V6m9qW&o-L;?XWzv zJ1iCWGB0*r74v4uOF(L`t9t|+n2m#`=t3|boH8}wL}jc!9E6$%84Hhs$lb#>stQEz znfrVTrP_`Z9QYC9(ucLI`l|lnnPsP>3Z%hh&q5~FjZ~*DRMCy=D0isA*x5mSN(2ihhE41ZR(R)xdd@ z?KDU4yb&U%Kc#!VxFty7Hs@_5?7gxknUA;{D969DG|h@Kqb-YTN{zhx6PR34$m6HNxTlow>ke7G^=+6<6A&12&75+CEptUu(HzH=*w5eJHbHLjM`n zsz7R)zofZh9vMgeJus4cy(NZk#gjJ6wFHjH!kN z;nPMF@os&xV)yQ9H>TX$0eWFwYs`DZ=Z)8UDT(tt)kA_Qd;; zFO*&nS*F^phU<1BTq|lOnq4RXAtP_nQN;J%XvU&m3ulHHkxcLko;D z;+7HQnTi)RRmr#jpKz;MD%4DXu8zqIc1G`W$hhpSQe^kz`o)WQ0kTURxP~jG7v~wp zzO2li%!+xB$fG{YXL(C}{^kiKLj8DvY$|US2xR0ma7aerBL~Du5f<%M3LG%9O5|&N z0@46B>d2ak(gXJn)_w)1;wU{l^bQbe&D{LSx8%4(g|6*lnGNhCD1Mqm+w37Fbf5Wg zJK0yk9wo!PnS7A=`ok?$)Y1B#u1Ks2c3M0UqUc5;L0*_c-I;V0(o+)ot#k11#Nm4U zuc=--vv!v$7S7O<4$Boz7LHdTc+`aK)8O#*2O!t5H*O&lNr8%-1p=W=am{KEH8Wf* zA5liXT*>MLDK(6uqua+QBrKySUkl8oV7Anx0zz zApSz^N>On0oj>-uu}-WdwTUVd+iGdvShD+jpI5=0J}O+uwX%ERRHNFlNEyrM5L(ac zP^W{?ytltFUT2JFv$yQlN_;FEF?%LufDP}Rhis9Ns679Mx)uKT^SiIH-V9Fd{)Ekq zy#n#*l*ZA9toFA-p)EBy-NR{_9pr;cAdF5YTza=lmQ4wl1zN5Ml}!{toGfOdsOjM4S_#u zd#yO{V)-kiFXY=gKbrV@KCo+l@6}2c5nd}a)WW9~k9}q~tGbM78rK%e0rHZ)e2#6g zhHZ5fhwrk~VV{&#P%IcF7T9_!xZ2#a4t*%}UE*Kk*ZHOh|Diyidx!DBFnI65p33R+ z4(Z+lXRFrL)0Z^D(W${hxc1@@V?JGhPp!YqJE!@p4X zl@ve*3t4Tax~Gd#HG1Lbhx-W#0m|VC?ih%{?F@^c7)a3jB2mR-9>g!g$7tlbODYUOH zZ)xd9DqiAyC~p5)aEhiQURZq`)~P&l$L2{gQ|MLl5P24-I8CFGfMH)4t96Y352fH# z>k1^Tl&KjP603>Tcrt+G9f}ha*B88dfv(^#RjriIdN7KJ70u(wLwb{YRm>ah&C)do zpJAY#&;_1f{#|q1W&Awgac{YVdl~sD&wRE;lBY&@W%EDnsJ^R$k z&HD_?qajCq=S+4QcYC-tb-OLubm>*JLf7)Gv@-4`+c#wPIxuj@D9Rfp0*0kTmj4|= zvdcJ6Gy@Qh1<9!MaMhw~rZ8LmkhrjXQv19v7I0)1Pi6DCq_;X}Gi~)g0ykg~-{9rQ zmhF}@Bg<8XQrxkOXMCWu+76*7n$gP4Ws9YG(Klf=tmm{Xow0CLaHo;tPw&n8b`@dM zKl#}F07{nMKNO~xd~E-2af^F4lDe*~%qUsNlOeJ3*$yrZL+(2yng7K3S>@BIyzYUS zp-s!rIEe@!iW*;Xsdp5U&(!KT%TxsJe6)^oS{u9x)tmY0vXxuL$DutIj~}#Yym1j$ z*=5)MTyP4{9|LDT{ajK*vEOujWqFARILHv@jip?X`8PDi7P7~EUYYXCYLs7MY z@4eO7%~=Cvus*v079(PmGMBuz(J)eE&&Tz?Cqh@>jk3ZBMzLsL#*Vust%h*@-+A;h zaQ3cJ6o*#k42==LeyaG0@V zfQ|0Gc#$=$(HlCW+$g#;*^(<{6>{#o9LH{T;s6TkW7$CA7MY~*omN|(F#|~r_XP6) z%zku94Xi3R-Y3?kCdy=kGgAgZRgHRlnP^q+pUD;qqW@;Pg|e!tNpH~g!U7^BAGuce zayH1*xCUD5qw3^5Q;u3t$}nwkCcaeDtt1F|7YUrfYaaZ79Zfx|Z7f$|_W{@)B!oGN zvD#jZXOtMHybf3mYcmNBz0VzN+ijxgpc*9$!KM_7!AJIV3D!M~6+#T6wFt4lGxMeR z6`8`+=lwTPV^lDer7))rbx%P%vnc9~M#wUpwpfx>GmEGF?jiuMN?mU3Y)@rBa7@qS)Yb^A&&)#^}xkhr=KsE{dInN zJbk)o8SSOVJ6P6mu;!~s`Vk;=_E(}8N56{!AiqG&VFwDI($%xv zcgEC)atO|gw1Yq`Kdw1}9>ge!7T}a+#(4%VGKEvwJUY0R81>awHOexuI)~toNF5JV z-Rmm)=6J;d0OMIh3v`x^Z9cix#remBa0LouzrkzO-4_a(O+^F>@C5p+3xaXlKu%`d z+gen{a)e)#XF=m!*}CdgL$hPgYd&a5ck)_9ki^W~@#iEyqL z>Z%Y-(YM_M!nGtKy7_o0*wb3R8XhA4PYV#{bI_+EBeZXaFZDPlc{jrLH8hVpgE+WX z=CnGOHar$jw6&&9sK!njVSA*~bGJ?La+L?STge0SzHc7z!`l2hN35fMeLsus zozx6Ai?d_4Afz5k$obPzsGa_uok1q$1@HitRLIxus`R?fj3N9s8q@T;_e#!W0IVa9 z4HL4cV$(S6n4gcaiP?s((}iaH$;KAdb~@`}k65c9mSx3OeYYT@8unCiXL!t>WUab6 zC~DIZM#Sj)?2_h24DKCbHp3Px?d-Qx?Mr>4B9a#i3a*iN@tb((hl4+J$5?(t1SFus zh6F9aZK^mn&3{)L;3zoe5DB2trsE(5D*YW&zbL8KsE}z1IJL6REdx3mvQ|#__(KDs)XK1GDY6h}40TV! zzp)4zYRC9NQp@_j=)6$C=p>5O(F@9I5vQ>-qI)Ykd9UY)R6zzGjml>9&uuBczdV66 zlXz1$%N=Z)7qicmFXh7af&Ud4fwC0&YODB13%#O%tlak2wiqBJ9Gat*IJiiYAxm;ldml6*dh(^qV_>3ozF7Pb1K`!)f?sp7acxcXp$ai> zYh^@<4_YVb4D8*$K_99e7=FdyPxvMnPH8`-$*ZO{?ntucWl{L$9Bu;VFrQ2_zqCCS zZ>M_6DMA9pi|=oDD(-Kt#o%mEE0^5-eZL=IzkvIg@i|H7Gb+^~l1n8trj}o;RecgQ ziF!z)8d&d5a8!N2>NuHM^UYIP$miI_lM3(G89jwzKOJAyAI7QQe(?5y?Uh8jTiA*T zaBJXx!caMy8}(0MVkKMG5{L6vshoIuKBB{!-ws6NQG<(qfxao+US(;uHUJ=5+!dztEChhW7pWqaao$pMKIng4H_sxNs{DGV)&0zhw$yLKi6ciU>t2_1s-s%|s z5yua(S5Z%j;y{<$a>{a0t&X@!)x_bv&k;;X!Ff-Pc~e{ZreCE$I0YE8iFG4Oc7I5? z)Kg(08r?F0!Psw(HzHv3^B&(jwF8K;wawEqGA>A|aS~+kbBcY_8xWx-jZjk4i{JJy z25a;l7#cFNdmayqxtuL|xYKw6g+&owxW41_L($5FJGK@O)LIHY@N+Z7O?#B$ReS^= z&o6Kytz-@IQ2j~N%fuc97c3Au&{R^Op%jrdiMw)g012``XFe)COCd@*RUP0(#OJ>H zgZ2Z0pu%W1f3RN3`*`g*tgGSjWnZt|(>YfO8I3_gdP2G(k$*sp=yB{#X=Mndx&VnZv&)5<;bF%O35dQIx~T$f1W z9?3!r;on0TD5+e084TaB{V93`SD=wPx63OhDDgB-g+vQ;(8c`v&_>B$D6@6L1uG-ktz~ggdn+xzpHD{?A_lt@g-A7pCl_cjY$5K2j4}4h<*O# zvq*mnkWvz^`TVMN->y_5IAvBI4VvBHTMa!^=y>VE*tp2g~X1Mim$68XI)4U_!sMlh$i}?~L zk?T1B)3YCTI<*!Viw1_%pehm~?KYiKXSFx(|7Ln+yp8}0_p3Y|)p+0sQ!zc6DGg2* z$uTL)I1VvpJm{6$5Tt5zh*mu|YI@v;4)xKTO&YdM_IOL6A8N{#@AlKCif^|tAUIdC zC%flOh~#M!w=ccr1Y|e@30}XV*r{;CeD2i@V!vS#jxx~g%P^?$-BeM&u<8FY@cud;R2-UmMZ=2|{B%*1cIbEOqJ89*RhV@~ z>we%qQF}=erPGS~#80aTCiN$N6_qFJ_k$!bkQ$0Jz;0x{&pore2{5N%bS4rV5(oJU zABB7kO7TkZemJ1GM7;3OAb1;C$8L@5W8|*}Knf92w5%R;Zmw?o_h$6pwGK~*eu;hB z`ZglgA(3#NNgV@mHeRIr`awMlk9=q+A<*6*!Nv9#ynFJbw5ARZx@;%Q-L%y-UF-;Z zB&iy@Pe}M_LI#cMi8#vJ8A@^okQewXaM|Lg*kXqio#6_!LAPWBK+q_7pXNr5#xQX_ zURovdgH{FCPDeUwEGX*YGy|Nll#OKpC!QchZ>zq zR42swPn+7E91Q$6LeyL?SicZBxTjEDXw-lUZRDpH^P&yo?deMAcLfl*+2K%J3}xm+ zXZ7G+U`bT@&T$lUdsh>b{}G;XBX?3(0G4uBxE%dWO4;+wBkGX1LiOTq&(+%t=WP}e zz>(=LGuNC>!j7LlT+sJ0wUq-O#H*8!7P!h))K7LwC_~;1eosQq5bA-d!aiZgUX9dkTUtG+KJm(}G!m zKJ#x*4yLHs`Ej~AaB}>k{PXio|65b*`~S3qq!qm4{eE8p@wkS-I?6UBMx9oa9Va|>GpBLHo{QHLU+uyGXJF8D0rO*s(1w%d;qgtP4|0%flS~GYN$QH;Y{Xy>j zyQElK{5df;X?QW*CzW+i0*cI$sjCr#42iY;(u(leO>eayqDISXZHRsKt=zY+u+e+x z1blxdmsRX7bVb0%rTV1iRZA>O+_XSFJjmck1k;@360S?msi=&tQM~-TCfcFDpZq*; zKf3Wrp<|9?&U-w7TXUXBLBI&Yvuw0(ErhLv{Frp+w7ZH2pp*n(i?BYV@qRDZk95zn zPqxQco^nj>HFWyQ|nRz(3*WyCu}#vI_wPt<{K1as3@ zpYb`1Y#$cO-u!BHk)}PvA$-O-Y=L&m#a=Iy1;G#uvXgLN+d}=>Z#q~#f4xJz9;8AZ8Z zLi<%*pid);nGC-7^}PGOJXa|2M}TOIsruHJFlKAK)I>m)8c+i$%<<(FUr;IKVCW|= z*Y*GZ(#^ty+Rkoc#`AD0@r(Gh190p`oHKtZ+T2l zr_`ICegae(NN5{&wU3|y8xU^NN^`*I!O}313R;PsM9b~AF4TU!0=bckY9t|bvriI& zu5J3XE%y!42m_~SnZ1{l{^p36ge%*o2I^&S z+&4)!#l&%61|^8h7v7ERe=~N~oxTEkoJq%VA}n3gZJ8h-z!(m=W3Af&4y6$q;WEGS z4F$GLJ9!`?knCPu32b;)BvATE`bIALrc*(epsP8B1bpXiT~0&+c>mLccCOpZS?gI# zSwwUWXp`_`^?$wK)*`_0B)tX6<&H*VQ-kq96kY%ate>6vFtVS=;$k4Loz#gGRlo1| zn`>W&s2BO%a+q02&+@I7D1qG-Agzz>|GEF_%mh96A?xs4!Yfb210>F5YQWXpViw55 zc4f90_zqAdyl!;W?^`)fML$a8{%~SOwk2R2T}ZK%{&fHF5STGt;9Vs6eb298g(O!% z$={W3>Q8>iK`oq5=1-3S&0bFb?E{*M6hjGBDFB_OP0Th!=g*ggctAr6Dpm(Y3ySH} z!R73@mPJ4724_m~4V`}by+)|}yLSu#-nMIK*O64>H669Gl-*tThi(P|<*pXM!)<9M zq85KlnD_V%u$b>O+zeTSJWvlBsBAfmbKyOeanv15`QbUC7j*w#9R-o-1rlUJeR_0yT1aBa8x z(+uNRffmg4uZE{j5AQka#+@Fa6gLaV^=1U@N$W|ui`EONg=ygQma({Ap~b0I`gzQX z3I?tKgc2)+Xb#lZ zu#(nEXLpC2#|fkdca53_L-WP(rp@=sk}L+#qvfZG zh3EiF`6^S4Y`72&+%c2B&`Le(sZ}e*ke=L&_=<6Apx?ouNXb#kY*lfGJmkjm!X0x! zCSu2lxP^rEza{kS94Pp|a(xMieb+RH`e5RSvukuS(r*x52@E+D-a-@A{8(YkiN_|P(^S4j`(z~stp7zB+hyQbh10R1s2B{)0**; zzdtNZR0kR0kej0AYX^?##Q}DY!qWRu2bPKZq0$J3q5|a2;8fqQ6SQ1#5<9w51Wbrz zC|Fp5%Yol2T3!+8_{cMrYm(e%mjw7AOM^ zbkE>89-k0?59Z6Qel55Ey_Wox5(}HZyc&rzj!otS-ylvW3TKXcdJ2=X9`oc+Uew0p znsSUqChg)ixz?^YPUez>95~kN*xP}C$pc6APuD#ew?v)g=Pv%H=Xcq2j4oL*kW;0S zQTl>Z%JrvZ{YF4MH`47erM{W-ntyhv;d^cTx?~Mxi#Qa|*kK5qQVBR^Vx-uV#+|rl^p%XTgageDc@8K@4ODtxE+erp6tu!1Ut?u4SNV~*5}ZRq9>2?9p%C=f z^zE(;?s-pLOTX3&p%by%53eGn4>c?Lf5LIx;UZ>yy$*}Tjjqy0xB0zC9>(bU)EFe{rG z+3X{1F^9B_z|vttP=IUX1;G@4-4m|%oKIfU5)0b-eK z4@$lLDe>H^Kkt(DR6bAynyn#vZpf{Nv-*^`OR5(CBb@CmDxqA7)?}rIv|RSz{=b{A zDDJrQUnp>aT49)aG;h#aG2>PDwKb2)eI6v*U6|(2V=eR&z$<=!2MQ)UN8(ax#Pr*P z8Ga=4+&l?1(@CU!c+#|Zv$u9z^s&@8k4VEgL$-;r<0sSV&56Pq*1;_KmZp|sR{Y-I zYHb?5X+GE{!o@iCVV#Po3B0IBLQz{QDZn&?=W=!3d%G^WlJ3$Kx^VdcYePza7RJhhF-uT6*|jp6{0jRF;t zq|S(|jKvzzNg68x1Vx_@qe%8;AVh?4(a<@5r2S1Dm%+pX*u3?H5*oy=?pGtSCtBaA zr5f~d=o5rmV9~6pfXZ3>8`YGp8BuWIfL)r={lH%uo!+0e*d9i`&C4W1wbfJA>b~%w zo5MRbE!iPFp77p#IAmwzW@z^fMq}-1P(uHK{#h|Flxs^(BuM$863f10Y)2Z5bGnek z!R922SD5h!XfG@^zuPcVQja~vgO4iHANMsSeAHkpT|& z*!muXY*yd-s}c<=N+ep_Rr>t^fj7pHwLrvd3|*Rw?k@KL1)J*2o<7QKYS za*i^z!=^EHvD{z&S0uHW*!vwQH9oV*feY`8|9GDE1}&`Y>wsRW|9bQM!}9Br%+So2 zWi{!I*Q5`3$j7tjI^ih_u%ha=EKCk&WX5)oNL!_|FJf1);M|v&v1^)o%ti zOc6DTlr0_l&bda7B|&UPy7efzG7Nz@t=WIfr|j$-SBm>3A4$ZXQ{JVm{k%>0 z{@o^py0%Zj>ifBWrNL0+)m_?Q$-f}VfBUA-)S;9CO^oUtzHiOt0tSii2Qz-Q&KIbG z7yGdZn7vyGc*&ToNG1GOTfi~pRc)hRTn?zJ$<{`in9&2j?dhm9p>lK^mA&>wjFRS? z;xoV>DilCA{xgu_&!p$2L^|W0FTAWZ!XQEQl(bO^2sH?Oq3o_fwmx5cd-J$YUv)~L z48pfwO#UuoJw_rfR z2@e#YHN(pwy?k@w*HTG6_C$IkN7Qd8Gb}^piVr_Iw6- zUNAJ~eZ0V3cCW__evfVvVT1v|kfbI4zVL88fv1tQHD``oN2fTx$%AKVTAwFQhsQDvDwJh){dzU zPNfEOfbVIJ<^DEG4ajb-v=gMAw~HmalUNTnanAjzz_1#7uWX{IYhy-t#r4{HXwO=}|UPr1(tw=6G#@fC6!4xya_;J3& z9+J^ZiA!RZzlL32dGtYZct$cYVs~YxOsJ@r+K|5C0KMKm5rPMelnB7!#baI!qjp3r%4Qfb zmGi3cbFVQGNIjX4b&6}TDzJ3c>;BNpy-71wj;nUZJl@zxHwXJi3FFYK=07@k{J4-b+@9P3ynHofZCGJ>^@( zIz1#!LoV3ILMD>f5kq!_@vUtBHSS(zE@N*oO_TpdD~7sLS^o=FRM*wO$`fuNA|)Z;U(hZ@lryn9I#X!EKR+CcnQ(t zO_;(z-oFN02>_3DFa`g!mP~=JNmTEOn%%<{co$Q;=)i_N}* z{2_*KKWMv8|7e^gYCj@aDdDo?yvSOO9c z#i~Ywr(B>_sYJ*Esq&YEIS-+$qU#quuVN9{w!Oq05GCYl_|*$CI^Cz=$gBo==w|IN z5CyP84zM~;FvN}VB6S1#aH8Jp_}yZFwaez9vCj9pY$XcxzdyyYOzM3DU+ku9-`lFd zMtZU=23r^c5q>qxS2XJ#=YcTwfoe^jn5_r|Il<5smzws<#NwYKvEkq8kuA&&EDS_} z(nCCfGEe*K&zRUMd}&)F_OV+Mot0wQ(2Z%z*jHU@o5|E?Q}>nDU+YKZV1_82Hkvi~ zSib+yjI#|l#zQj)gJBG%OiKOlERfnL$Gk^uqLnGaNo|x9#qFwhbsJ+JgSU%5NISia z8P;1}#2_Wx$@pR=!Dj%)^RDpNw!)Bv96xv}^GJ-?$WM4-K#3s0`a=T^lM4_O!y1aI zuAta6b_}+boi(0Ju*cYdEtNpk;vA4!2&w3A>_&uo7A(bPV$*rAu*cBh-qO&g@B+(X z3?I&zNYv-9$Ha_Pt*&hW+3wCblg z2|K?UlbAAYwlEER0wi-To1T=xpB09++P-l6lP5F%Mf4t{al&M1c|LQENK8fSU|FOH zXf=|x!t1N#^@c1BR~5U+$>JAhlEdL-@?*0pu&%<3Vb}c*QNdAx`2R+(n4|zm9SW>S zIZUpn0h)aqJQ_mXSQw$3Whias|K&uECG&QQrVLHDRz;&0nQx#0HVPN=kDO|^A_{6^ zj$30V6GZ>T(fK>`p>upW=?XEgL?Qln((D)5j6f04kARlNzd~&YdBM*$z4AcGP@I8+ ziq1s72zk{3H{LGu7(iBV3JsPQD`2ImoRwfaa@vpeWjUVS!5P#LrGI)1QD$FuEZ=|j zYte3)>(|^3z!=y9ihKJL#T{FJv|ifoYqQ}B#Th5+qBgvazg*`^nNQ#HacP+b}|Q8 zS6eX*8+=Of#PnF!dIbRtwoU0fLM+sQ9B^Fq&tz&+)tkHWTca)lA_%^nmU zeh)as)#&EFFyDF_1UwY=4D&7_Z7(bCO(*PlvDI8oV?>PB>`{PASghtLsfwG*>~+UX}^McBC;q-@~d2Y&S51lwjBt>z6Tc(?owR zNCvFLUoI1fLzpaHFHBA$cnLcPHhd7?)2`%#Z8f6VS!>2W@Fac z|5@rm?9X?0q=MyI@oVrba%ROoe!t3?b{+%>rieyX8#>^%9;R`x8#0vIWj-di$jg{C`i;3yg)VTT8JR~_0upD{zzml1-o1(l`ZkC^mcC|0Vk(21 zoF6j^pCl(ekRK)fX?$8tKnQD9#3VmhGna~S`qG;8%sd2=#Q+1tRuWT^>}9WJ+XX)} zR~WM0TYnX@Glg524lVo@`_^d>W|l6tLBu})iX$!l<;GmG%JDGc<}?0XlQsuYvH4Y? z^52D$zZe>-oH3hYeDHNEq7}aQceokySCXu0^szPB!R|SK@g41^{o$rma*r&*VH4vY zy#D3eM8Zh?Znyk@+y*!XIJ?4a6m{{3tQfF*8!LSwOrY)1`HqS6DWeudg8+?ELxH7E z6;g!~Ucovrf!2M>oim2h#p4ohGyEf9*gDO@2FVuKPNFu+U>h*omvw#)3w7UTVpeWTQNL(;7x3Y2)lwA z)|AZHsy@0DJ-51d!Cb`o%>;jTWpA#&YPy>R#JWN@(FgR>DDYy*J{3bV_CR`O&3Ss< zx-~;Dfbn=ROYNNgny@u&e=%TXHQn@E<=MZDWC^>yLsrn64Orrklu-6c^U>nQyZt%0 zYxvpHzk|iu(^F;>>q37=PXfZeJvnF9WJ1CM$5Q6h0${Y5hJhr$*-iI6`WKW)FoTQ4 z#5vl$X-|Bs{q}e#{*EVQK|(w4I*;>th)K0f9fD=UiHbT>B#ZBH{AX8Smozxqsa{~| z`P{9|m2F%U9y}?s{p^-x_`#RBB>Qe(`p40YLrB@)D2QGcnxE`v%AgVoH+43iX((=Silw{lsHxwV2{JXMc)T@aPeOBOot@Q%Rrryf5s6MS`| z#)>O)k4X=Kf?~efb#wNyM@e9Q%Wh2mTL-z|^`3DLo67UkSZVvmiTw@6LGQwWT+9uxk8 zz01;ZVM?%bnmr7N|DN?`qE#$Ava*ocT}^IEh`(k)j}v&>FxG)P#WMCKtByq|F0BgJ z_ji$)?nXwvSLG^g^0w!KI~vi5QJyD<(dbdC!5SWlgNRJZVc}}Md{@ma4k1%^q$Rt{ z6e6DUK3r%_w@?K8>d`-)S`NrJ>MhC{;X{pScGJ>q;0o|QyaR&N>TxmhGu!(@qs7%k z^Ov<7z9#yy2g=tk?sWV&B(se;`03EGjN;fl9uMZBV*WhV+ZKyMkfH1+%nV;^!{quI zgIwS;5URlB0LS04f-lOs49K#nx~kg-EF=5pjR%@7zq{qYpPz=_9gM2pbonb??3G{r zGRvO;PiHVw{i1@gGxGC`^s7SpA7A(}Bu?t1afLUuy4mHsZao4aPC`zxv^bgCzoyNi zNS!AL;(H`P2Grl%#+8d*lg-imQ*hf&GA&M|C9X|-3^Yp)SS0Eu#<(%C4 zg`C;!L#`F^S>J*0h!vpXj!dS^0U=B=4JbVEg>|v*!R=dq;geA%DW7jDqMwx>N-q^5E@0A8N6_Z-~ZJo}Noi z`{+7mBLalG6V)1|n5S#~g!NIBPMp?CKy+Eq=yd90YCh2@2mC(2@&6<0yaTC@zyE*l zb+468TzkvjdtO_1wu~;6o6dslUw*Q8e=)$ON;o2-fd?w z?|*ae<>h#4M$~2mHKx>MQP&*a_8ax)tZf3Ycp(r|iTN z(>4i2+h-t7$Ov-w&0f`5KRpSOe-)^&cXngn5GHCZ_m9s z4$1v8{!VE9wK-7pxn}n~Il3I;-XQ?JY846`;uGSIwAi%eXP=PaHQr>7Zhe^t)g|N; zvQh&`q3O5N&;K*K003h`j=BJfL=$L!_oU{kgQvhyysg|VPL z016ZR5|eXWCu%65^!^gWi%xi6abMTz|frUQ4eH)Tn)Qws@8U1W(omZ*hPOEy! zQ?Bw$Z!;S!?LfoVT|KLYW>1KNIJFPaC3_Q>Kzc^C|2T0=SJVGc>>6WM6CI*oLcak< zVv7k`c-Z0`dB4+uvn~1&53s&pWuc$apv2%IO6oecY#G@^z1R{Mc05PdLL5dd#>it5cO zl^yS#f4;9=ib_m}z^b3<$_Ur+epv+*Fpco>vgss|7S5D{f=v&sV%-O7f{XzK)`mmc ze()J=X+pMxq25g=V7vrNUf4L}c57U$;nn>)BeX;Z+=b>K^W8|OeM51ob#0A#?-cs^ zFF2&jSAJ}5VWY}bv=dejhSi)HU5BrExm;W8s=GS}vSPd3Y zvDJiG`jPhx>`q=o2jC7rV>c}GRgCT$gF3X3VgVJLyx5KJ3FZHpH{(JN`!K+v!$pX& zd%?C){WNtDRmIC}_F62)fsAHkoJTs!AgFR4wfckn755+uy>BA)SKmomP5y-)KvePe z!YGn&PsL2f!$eZ4%MgYNi2@HJM+M!c8)Gr+cS<{#lUp>-!gpRDkN+8;=6iGgjy$Y% zx+wKYZ3*eU*-z7YB!TQRdNN-|6V+DP3M}t}t?HZ)X7z6Szp-+J!Aztql5EWJC~1s; zX-Wuzakj69s>+sq6K(yfekj`0vxLD!6~6#b4LlDs6xH)MCiX4*~OdR^x z@9nJ>Oe`BFKVOSK5`Lf#Hyabh;L$Eq8_GH`999GgU%LB--t4#H(N>QYq{^P97l<4y5M1=Hw>3aA?Jk2kK{Pk7El|Rudz7blQljDf% zW1q^)(AY06+`roF-+LfQfT=Vgx(5!RJmQc|6OCw)|IcTv7mIN%!>u;22l5X{j1ftE z&bOOi2OX-TB`=EE^(u0MH_P78eO-is*I7SInOQCvuuf^}h)0Ljv^vl7*YFCn_uC%% z0^btbCqhtqh4$Ms=&C$bf=mBd95A>;1BJIO77o$nqYTvgY|io-Ak9vEE|QPGt||3) zKA&jriG6(t@6RmBp;HB8k2%czOEV#S55CiMOR9no`{yP$w~1+Fan&6>z||?_4rCvw z@J)V-&JsnxM#vYpMWo+m)9K_51|SX=63**MFUg8mJj>>bX`*gq^6U8&qRGzrQxN|b z-|eb@T>Ayfirc+-z90eSOtFQlt*3^2aCZ6664aj>hCT>`uESKl{j%qPu)DL{7u?FI zA?F{J_+Ny~tCA%Ahc3fmfBn=Y=H%CA-BU(O2D0-YO@pqM&75}(x@e;BLSM`&{a(uB zHqM`sqG*i*k~?12i2&KM;9^I`%Vt%IaT)CEHL+9r?6G*C0lB8rO+W_1lZ;Lc%i$1* z98TW7r)NaMH+hFmP-s&Tcfx+<*k89+0?_UEU#NIyH;gxsTy`_GM|ma? zBx>KE-c;ZaIJ?NcRduZ`y;%z6hQ*eMzsPX?0C2+QriY)ofMXLI^Rnp|J`FZFMeBXj zqq~$N(aBkCb_93iZiB#)KVMpl1ge8Tn|zhP)Nl$7`L}TSNO}|oS?^!8#YFQ?cS!f$ ztOvVzLvL4L9ZME*vk;nOwd2MOoP;@J8%jv2!jI_OLBt&hd&b`hLde@o$BNwEeJL~B21S(mk z!AT<><&~G+9RXkx>Rpz6qYu6xiZ(`jT-a~gMSpo&t2b$%DSA^jqlqkMe7LpV+oSGD zjR52)SVzj>JV>gghXR47j8e-%dZt5RC-`3O`d1mG^FL$<-?M%Tc*A@LtB_J1!*V{| z9o^M%K@^6};t1^h^p;z7QEun!K4jYW?fLwj3)^b|(H;`0Mp1O6`0VB3D2@!MnQ9`~ zzkPH{?>S2Dy`c-*=x+aOJS^C?#i(FBPH8xGjzzh5nbl`0ewPV#%HEq9>BvBlyN(>0uE6&u&sT=^fcppEU%QUWWa{{# zJu5FZKfAb+?R~yAff+-<#9L&LEds^|_>JN;Q`-6P3i&o`dzWG>Xxz&I3j6Y@$uU|( z8n+(kxQF_riE#UPzII`EN{@wWd9ao_Fv&O@P8_b}NZ>vI+?MFG-!Pip%L5^Rb_fx* z0ws;>)b*bEPPq?txc|k=h#zu;UKKa}s$YXJeB{n6auP`~ke=ZJ^}qwfBp%MX+STvR zFdSLpGHz;x6>=D>uSPK_yZ4w8vyrpE1;o9~@ghb+jEtf{pEcrUhDXAE*Hj}KE$Hem zr-EU&7cbvys0w?yOA2+-ouaTm3*TRlsb;4vx&d)YNL=r9ckWdlJrO)u39hJ71w?k~ zixLI`XM_Jf>d6!&4F5QAI7tbm4<}OLdOgR~AN@yw-T73(;aRmel!-G=*Pjdl4y?_= z0S-ZSX}0Vla@B9I{}F$!5#gKx5Gb^l*}q$V<{PWuQOcgEjzjLoZ^jVL$Cp{B>vm0c z%KQTIQn$(7jxQ5QpQ?C%{G9gsNfF~Y1eQWJrY`<}(7i4OQi-Az;3HuowSb1{iAPw3 zXjKp!wnm#lWX5Yx=}+O!kSBdCynn{iF(^)lWpP6GBXz<**$&kynQ!(5fi5$aboV*o zUu`yl+celbV*&<3bXb+Gj{X!x!~G!AfU7j5i{2HAnw24BP8*^#J#{=j1pt4XMi1F#+2Km z%_xSE=AQV8cr((0Y9MF;5?xGICnNF`*K{IeGhmZI7WMlI-sON0g76Py^umf$*6e9i zoMM>$GeE{A4cf({WtR}Q&dQ{Gw72kCsu#ue@YR~%S#p(6v$+%n(EIn1+MRnM=Nc%gHt|r9Pj?}Z zrPP|W$W&MP9A4>cO8J?(K7)4N?Od6JS_;>Cby(Hdq9IC*Dn^4^CM@;uwGca=zU~Qc zmqfw!5?5jgabhpU?5T;d6(lGpzA0_>&ZB!l1bJXLB|BY;SmaKW<- zKDO!ZSA&!x=rHwUq8{7-jIq$ughZ2me)rH4sj1%EjXN3rb^zpLf|N35lL~p4OS`%+ z_(^6i_lNLQV8ngu<}d98^Vz?N%Ilb__}F z|2%cve@uCaH#G~Sh#_U#y@+rkU$}xjk>XJbD0%Co%L(QwURIK;Z+8u>Ky{%y7~RdX zqrZHY>p#nPg1eWZ@l*uE@1KlS8A0bhPo7L6gx{o(9ms8N(I7ets@#F!5vue;*p9c+ zrnbs-^K$LCEL3BG^lczvQ#9*S$-1|6Gjo%<^-)~&IHill6m+R@0*|@dD_Y4 zNn?E6Z^KBYYRd>el?Aj-@Zz>k;a$K=0zXToOzN&)JBE;iIdoBxm5F{5+O z;FTC>{-bvdMB-SOC_R53X?$D_Ig^`o-8T~Iul4K#$D=g+QL2Wrw{8Z%t}D+{hQ}%< zBSi!XJnsceXlb)X&Z(!gZJaSTw<@m|obohO*N-Oe;c|2{B_|Ku3*8e?9|&i)UtM;* zdpWe?d;E_i=dNL|Zp&@B;~sBxcEwsS|;@k_t(tYeph?<57U8-}3%ey%T^84L_Ib?|Y4MFF_s3*yUq=r>rz zv_dNw6RLmS6Gdz0D)82S*8Po9=n^&fKwE1mplpYPrusn>%XLTNU<5+iCoK4J(sXmb z7=lROK3v3vXe8cXjULUI*RBK`NR{7f*>8IV&*G2(_4YQTQFj9Nm=hUK;G#u|ovR1` zns_|ELki-|#tfPPd?U8}j?%{6DagycsO1HFB$vI zelMIUaV*<@YFH(D>y`=c6nFK29L^?1VRzeTjw_(ye%|Kv2g-SpMLhPRLVh`CkwqFk zxwRbeLfMg3&g3CQPT;fYw|hg)3|90bSNIkRQyytLRZ1LTjL`+n+KO;TQf0wyZpHM? z^B)SU+jTcaVR+t`MFD*z&>nfjiTWfr_!FQV4(;*EELOCiG}vl4$MY)%C%AceNM|+m z4CxJ?iO1x!;x+XZfe3Voue2c4|q#EVQr?OVePa}&u&3tfZX=~ zFAGqS0)ka=hNXTJIGjf{y{tfXs$kAP%cKNLJE?_$&hMC~bm8&rN6@hw-j{%xv?Zi< zJE*C%KRil!EuFjB+($zpOJ(*=_B%z@>k{RU@<7UavO+A z+)+90Mf=!D)=0=bla`Hlgu>u`3GBx%W?fV~t^Z01RCQ-yL$?EysB$9#H?%DL)FWP6 z&x7y%H?}Fs6wyFgG9da3P{95mf2cP7U%Ojt-@m@s8zLJi0`HSY>E8;l?%*X5p=pZ#@rf4baZ4ou zyR41X5~k^7+jI#XhBT`=%q{zwyW0siGyddNrF_oY17io?A!bc>#3!B(2zbhVav{p3 zrJ>*zD;`Jx;{Nsi=JuT?g+4&9gK1(limX~6e?0y+i$}vLPFSCY4^sqMWYtahCX)<_ zTUWVCe4=tfciFFpB9!nXSbG+LI|j+|=WeBMsyJHdsxbxlsg6dEhL|T-%qs#cW&J`o zSpL^j=cwAJ&_5_Ge*kBhT(hi>FR1=FBRZ%LZiV_w<%8L^@t@TD9gu)1*v!}v8eld; z+`fY&AG?$2S};B);%L#g;GK+3LQ*{~FP6ZP=jklSdlSC*d%%5o(z3T;!Zkbf4}}p$ zpW}5)>)Y&)!_tmMMx4N*5^DgWr=;hM^I%Zw^84tpL|nFVsypwOS4qiu-nXolFUWUc z`6pMx6$3##7Sa75ZHXS`FwPQ4;OxnKG|#Pxq*aLdW0zg9>^b?($Q#~La}<7MUaas; zEP=Uv!pO!w5;CnwYpC@Zn>@Q<{AB1p5N=dQv5m>}-lI{328wy4!YLOM21251zGP*{ zK=-LV6IHkE`{GJFx@EysBV}gyj~CaU%$OpQm0jcui^m&()a|EOE`|E!1Mw@vH#vx+ zGT997et4lWsrDN&_h0&)d<}}6ycBDZ=R~-5O^5KHv~}KF^XHWXe%sSO5SY|T_ttKE zHa%11A&Wbnm&~ElrRa`xXhuYl#x8MwY-T{b&3wUxGu@{AwD;yC!}0gUWup1$d?E!x zP%3Au#HYB+1}Ck%LlP6Ha{N_Qyc}e^u~JHbQ9-D~i)rtL)1iQ9`8M%=Xb4I!EoFa7 zKAJr8abo^N4C$xI{ejtq?J3B{_-mTtAnzz>z9N2@m*m&_62$)51^xn61m~=XcrQhQ z6Hob1Z&m`h!vVjIZi>#5r<5wV;U}2Dpi3D9{`?bY6^g!)mPN)7FU=Pd9-)x8E;yYf z_3(+Xv#c|@x^^`SEmisVXci;GhP8pTF?e0&0 zrEJp|T-U+^Z^4BttjlT6w!zrFFa#P)gkI_tMGwes zM@4Gs{mkvE_KbuiJc=()0COZ)t=d!5?CwO?N%=+rMSd4Yo%ml&2jVYJ{JjP7hQmE)x>??8A6;RDCWJ15i5?l5&_!X1&P~MnYAt^7`A%R}S%J)cgD8|!zt%6{jFqz`b1Nm@? zc(*K1dCOg0pKrlm>#ug|r|eVqF;XOJCaNa@M!!)1PY`Az*e5%AT*2Vxf!;yW^XU+i zAoPv*fgpQw>MNf0IRNBVG3P;Frf0Pz@6E^iCg?w@=yShIJiZ>k0Me%oGy=m;438p? zd~hq=Cy~61A;@tyxla9AotLrFhSW3^h$Yh=c{UwN$R6%&1p%fX5r?MOnmowb)gB;f zO~Qc|Q%GF6ii&r?&(N=`Kc-eI?YN2atJn7Zbj+Ovt$Vn7r^KE zofGTB<5T(FWp+&Z37+1B$`+^3O5v?dW4C#+=vTrUO&+Ex^Y=3Kp(*r9B#v5}6dVXw z%3L1U6QHGi+d4T9>8aafM@-y#uy8UYCN*`fm;L-3HGYkxHrq2S_W@mboapY4LoO^V zT9S?ZMewRFpfW+qT?z}Sq$uDg@b5&|FwKlMP4&p-b^M7j6aeBlO>Hdk?0x{lCk9{SzkEbplwgtZX4Ir}iYLYP@uh_mNKGDS(-t=}=;hBDdd%COHiyr*OHPi2dwj0x* z$6M_KEtE&14by%z^%?s(@}n7#Ob8?s$B@~B3<_7Q&BcuQ8Ehf;@Bxgkoh;>IzEM|Smmdu%wC#=)7zBBOJ%J9xL|9CEjGW1u_8my!K zBhdfdf#70S3gNvOT;f!Yr)_A!&1ieG4Latrr4h;0K050+Jht_ZaEu7py*tf5lyv@`9c z6;#5^@LnzCz2n)HUtOcqx95G?dz43=2qvS&yiS?#?I>5?>{fW40Ny z@%s@->YBAvveqDwDio%ewGKZn$nUoh4zRKG7^U0N8xyPg~{)I8cJF;M8O zX+^1OAJh3ji92yy#mctSpq*bhr7KHTi0p3}dmzi-u2u263ao)xh_7K(JGs(@8_gj@ zg^ZE*mlO+1;(~9Bxq1d0uh+Fz?#F!+y7T;V)(N%a{R4L!`%NI)1*0HJ4Eg|cmlZAT zAN~K#De?r#fXrOgwakR{;eW3cDyw)m@A`J_PYvCVny%OPJVOY77mDe?49{rrKLxlN zOPZpyhp|?#bQ3Z=?pl@YL?T~xb&@!CJN%tCgON8s!hPfIf<_v4uXfpO-V3`2f?fhC z`rKkU69kwnE9+y}Eui|#WL(B=%E^sEevi$n(GP$Ns$G8MtR{nGag-kB)A#P5hTbdD>r-fT(cp+Nj6PTr^*=kTmQja3Tvt?zx5n zYrcrIxYe!i3;qeEeSS}{NAP)?*g^wR7R&+S>f?5x2NK=re-M_@T*1^2NvV8|_%N_6h(vay@Xc%MQ%EsHS+_{>`gE9_tQKv?cW=&`)ZwVG zR>*u$GQXbs2=xHGvXV!Ji6Q5b{ROByr7?&kFXtKXLHkge)U@{9k*}louiO&6XG)qv zoaRCV`n6R+x4F`Rx(7sjGUW7~oV_;Ixi^6U5AddKm(Hp|}VCP>wUtI|*k*W8E)no!)abT)HSdl~e=bblY{<7E0@9^~JU4bT(I;$^RArKj> zlNtw~1^N5i;jLj{=phK20fU)C?(?}Q*Q(kWgXVNUx}X~$|2IAC z6=n@g&0C`c9SrPDHD=f{vunS90l}bmKK>j#IPaO%4_dR9=Q#px3gmyyc_ex$whioG zy$U1Nx(2d$V{zU&LdzjPIFYequOBWjigvNC_ZQb!aTxbl3C~QGZJ!S>1pyMiJ_76U zuxnJZ^}f23*_`)*fne`u`gW9;jeNdRwAkN2^vQS?Kf_OAxixPS?`su1{of%2+}HQH zo+{PAeTxK)(c_5@-{7t~H|CRQMIcW*Fg7vyRiHuTeg}=z>A8pT?YAlH1)tU`;_(L| z18@oB<;si6Y$cJeuG<$`rKhKI#AH*yXU|1Lpe=H1;j4 zmj@Dkf2~Z=gVf>2dE0pI-w7h#e6vi~nyNl6Koo?zN$uC3u4cPdRRslDU%Jf%9UTB+ z-_D>mcCaj2B~EW<^#XW5xQGqL|E~to`MPF{}gT4z<8G} z#YVH3f5w#hH<7i8*GHh&MIm*VP5t#aF`XtKoq_q4Ru%~@H8L2a(fMJe^vIkv1p+^u%_jjq*aB)9;@n4YsX+H>-$ zvE?D*m_Y7mgBz&4Fn)0x#j>AaEK>!XW@w1?F|Z4^X+Mv;Un#SK3iDcw;ZIN&)2iD- ztBY;z>cprJH;D|G$M1`-0x765b(cbv7XT6$$wBo(ylf+!ZYKX}(E>Z+4zPvzB!t-h zUw4J*`TcYjqmo86i_ugs;o0Kel#(~YAUSnsyqJ1z(B;v=J5`M0VB*?(YaEZ&fH(}- zn-vSFiLf8N!?s2i@ALg+*H|HRo{!EsR{t7M7UDrQl%z4HH<+c@Bx7vCW8b^_o$oj| z9c3o`PNDT3Kb+f{!5AAl=NK=ft31S8WqwoQ3R2Qwbu5P8JkArab0$VExch&|d{a3O zykdL+b5Bf)2mU`}+`L#J*_!)9TkU=d(P&6q5kpz!Q8a>yOd56ZI4Q&y(Rt&b&|`&{ z6ub21`)-#8kXe1=3a{iRV z6!iWck3C;zN#sOWzK471}kC7G))#Az`Rd>mGM*leKrCb6h38ws%z6$_I&PBZb8`%xsba~+(RmnYJ;SB zuoFDhuh29y3PI*Hc);sT-Sk7G)522F-zF7+?S&mOb-=E|Av1}3e+JghmX7el!sK%sNXv!06n zzjCa&WK%;qZpq^Mh(4%;TKmQf$xqCD^f7tNzXPSz@ z-;J=D(f=7FEIsoanV*8sT1v^_cYz6S5{2XiPm-zB)Cte6uHk1xj@}+pJi+9PZ)8oGs$`1XQ6|h_f7f->M4>N z?-R;uLyrQv+a;N+fM+rv#JcP(5@LPT3mb}UjR4|ud=hDj0!nL-o|fAfkjXBhcOTwR zIeUG&cq*IslKS}f-}v6iM-!6=+Z5L3tdOtl9L zZ#hJ33vdAbQ3AKm>K_KiBvc*8b);=N;v zpf9c)R&M^OnU>>R=^;7)DRkt9kE{Kln<~M-XL874jwewJo{7u46|wt_HD|rI1OK0b zChl;Rl|vnpL*M(vr3Wx>3`3QXaxBk1Bz+ zUcZ|u-jo5Kx){ARZ6D1lbjS2BlqMOo3veCEE4w}QZF(-}@!RRVv#mnLZGW`Y2D!VQJ9 z!OM&=TWe0lp(h=zc}$NxDKV-Sr^6Agoqr}g%}50c@g=vr2wk?=ZuQ)6J^#6rS9r_I zai#gj`!|FD4?7uMF5gkfJkUSP2lSX??X&kk$c5VcbPV9vD-wLj$Duptn%S^_BY!by zy;u<;7)uN{x9hLzW?`I!gk!FSx#O2(I;o09fH|#RnaH{PD!urkF?T{OYoNv*wl>}t z|9{`<=)(B-r|!!>S+y8V-~8u@)xCWiy5tvm%$HO;@hL;q5D*V9vXck(Ku?ruh{RTY z>N1Asp1#~lNk zFMWijoU6}-9m5W(o>F&1h<);9S)a(HsJ4z9D!@2ZH^XnbnO9ctMMZRpckOmRL_)Uf z`I+s!-~Eq}u_#0rc&&nhR=tFIeNKMI#P~U_nEh|e9=uP#1uTAlyBI&e{U|{13tant zulmz1vG$o3Zbs6O*yFbAOLk9_=+{UCK(7OWu$*8C@F|Yp0+y?B!_8gZWtj!@L7cAT zo+<$|4WS*x$UCUtX3QvONrzPNCw0D=cpd811qEVN;_c}`+&@O$iqr=Ho#e^-aRB^z zy&zsqe^7B6Sau>YY=7xXGBSY~A7|NGY;;iY72&TMWED`Teo_zOuBHjr34 zSVJRu_#Au%zcOJM2GBBN;ep1;)9&`;?NUbl6hbPuwH$%bXQU$2{DZ)u*;oHr_!GND z)NI^Kc8@+s9gyt=MMNhj3*{v3VXR)-ffUfcb{Al18d2zW)@2+ zQ6q+vo028#DAP3Z(`uuVlBN@*J;0}6ddW$uOKd##ZrQ8@?;Fxqs=4=lvkb@%dZS>* zXP|&kPVzu3p4#;b`IqHMeRuEV(q#NvrHvNMt|cFJGqoV_jrRIVRqGZ`_*O6T&ANB$ zh{Ip0=`l10;0&aloGk8+gB0lEOo|cizqelStz_*1HH~r z2j02ewRtrO`0$ZPC-@4l80e+5v?{ zZ&A9vJcGGdSB+D|aq|L98!Vf@VUX(Si5`z5^|bHZGgdAai5qHS__CUne_sDhwBDU^ zK&)b(R~&Xg_xYw|w8GYSM_wQAL}5BN=-e791=`1GFxNn3Zi5+g&9yQ_lS0tb9v%>B zO=HYUP9L%DbB`!uACMziFMsEYZ*HJ8(Z2GEN^mAKiL#3BL<%jNkm#*NOW^+qJPbP> zXGjB+&1ztHi~UldVI#~7I;peB3-}ep%~EnRjANI=x;T^9s!V_EA!2-3fA6(0Zov!U zk4Vo)$Fv8#njV|mDBT5fD(M&zVx|GblCPOj&w?{GMkg`380{jJY-Ruq9+rs<$H9bg!ZV0TP8%lXMW56n3yCy+C0uXyh))qkP`O=SS}ZR!R2!F3oXqizFTaN*|B0j zpM`Z#bE$flt<_b=fsWI3S9$~f@0BklUGDGaKRkf{GVCJPS870;zBCMAP-2FoPKB}N zdZM-gQOWmHieQAL0Rv==**z=`bT<2xe-0?WMOOizLC=V}Ok#d0LDJ zWjQLp{Mqt~_Y+XNq-f`!qo$o9y;z&VLaU?42_j^KNYg%?6KAc^<;CT~^(CCOG2ONH zZLd$uccDjOlo>l5DDf4|6B3+wNQ-X)x6|ka#nwBk-tq^Rn^c?GXABp*`?v1Jw{S^( z?Ry}(3v_TKIz2BY@e2C829C_>_lvTZh5M{H8t&i0K#KYaz_0{^p{Iv9#G{IQY(Xf7 zxvhlUI4d95gs$Ay9cko(Ibkwz+}Y~y7H*X z?ehl7sq=o9T->r41$HP?g+qPlG@(Qo4m8NI?l+rf_0L97Y9Yyanry4_mOHm}wjXnm zY1R(+^MAm?OR|PzxnwbcNHVV{z!byrvyw3g73&ap*=p+((xlbFWQMpyTQC6Gio$x= zMZMZW9i)F~asTV^Y;O8|V9)AdPDSdk+`2o?tr}Ia?rrhx!^Z|0epnxp@CEHD$6?)`Q5gSWeXuRy+Q(9nYKTKbksYKm zB>wLf_&7v|{WVCCjBF+#Y%?tg|26ni)9h(5$Km6J%7ya5!_y=yY!@Y^S{w|yF|CQ# z{`vH10pNzIAKkotN0CQ)~O_2FYK^ zIV*_+%&C(|W}c4e^saikG{ZA{v=0KbMc!v)i7 z$`L3CIt47Fd{Ftzw&%_k%Qwd80h$?7_}*rcW2uj5bz@E7syXQXSO)!KPbJ`H1WHWv<`At)3L>aw4V+EIw4LV)$d z_vaMppvKpX9aF~_ur5;pd1O zKYAuhA0kn6-8fO#kIV+DXFrpoN#&VH^<nABf z>qK~C%z+ywTXT;*fVm>YAl2PtI(1Qon^GU}&nD4IMD(i0^m3p#lBqNf2FYp*GQ0?F z+@odM8OV{DGv16*J}6q6oebke)Pp1u6?zv zNDQH%VzbF4?UX+FRZ}&Uyi*Yh_rdRR4Ntu}@+f$xk5RaG-c=}i|D&}E$SML-5Kx$LU4BV|VX7M^=3aPB8Q0#O!};{3Y*1eKO=?2X%pUU}Vk+KvnQR9x5;2 zO(Zly2`M_e3x!janXE6m$QO45B8~&zZAji*dtgk;hJF~Z6SANnizjWnkpk75HmWcx zf7IrUr*7%PTIz0Jflqvr%@d6!lJZXFi=`)cdx>+6KU~=T2(gs4nTDdM57R%MW|*$h z=XcIJ%sW#JWS?k3bD&vE=Z?K6_~$fi3BIt_HsPX~p6O7^bqfXp3N?`LrVsV?s<*}$ zxlbl>sOCVGcE%kPOE*b@`_4ENRxv1Ws9^n98A6vMFW=!+`Ja5%QN-5!ATBot6+`Yu z!a|*QQ&x4u`k2*h-+`GYJ)}4~4ZPv^6%?<#zk;DSp+DcXs5P{gK_m(6`SX8o@S4d{{7^a~+Z!zA8SZZ6l_S{1}suZF}wB3T!4{wyhjT&3JSn zCL>)1ZtiP6`Fn$V<=y;_l93fUxqYgrfs)8}R9MN6y#86o!HGXFuRVtT8Jr1HR}@6E zc=R3k^X&tKdaFS1^W8gJt%dq{#B5q=r8wigurHr20F{ASd7>wA7HZ)`$p!26Kh}5c zmX!x~%5Dv7s9h@@d<{|wiG#By_>mT+aAj)VN+vc0AS&}xm8dE@ zuZ~(te2{M@oU|&AkGyMbx+W1pMFF=bXhUzDzHlp_J}xo*>JKR$ulPiH-g#<0W9|C9 z7{VteBDJ3w2C=mS*`dkHHLK0&*|8MuvipMyzrIQzNh@c9?tw^x-%aPEIK>QKo&`h8 z;UjTE&k`ZAl(HkXvM<;ZYE0_ay{wab=%?X>H?6y_MiD=M;}hgwBg}ow zp~p1${d|=1{Y>6kvk*Ha&F;r@Ltj8!Mv8u&G4!7n9LT3U1?q#%>b%l>XgmjiQdBb( zN0;mxK_o5s=%HG+nIJk_A5~Dk94;@BRs2@b)3kBc5v`8_e>&T0OM23DnahE7oyU1z zzB5r>`m4f@31Z8pdv8uzyY8_W9c^T+++2FthTt-b_*h;4TWT){tfU)TJiWqB*Xc95 zSSR+Y3k6@WIx;ul6CskUuTHvEqAQ++Gc3Nid~xD%v4$b!ea5^CPX2PS*N+#=|JNm# zzJLl+z`$I03}nuZ)SZN_)p2-5J$D~7oyZ)e=B)k|GtG~L*o6(=^0zAz2D%+F6cpc( z7JD3))ktVtbRUh?Mi9M12IUx+SU~=$H1lx3Xg4h_4V+Va(1%(>nun)3k-Fd9?#a45 z8`9nGVE!><|G!8j$S25pWFwlfERWWH=cQESV8Vbw09A5D@huz<)vo2UU8b_;h2jtv4c#>y8RSpQd` z^58xrOw?J7-K5j2xS=xE7%Qg5K+ixEJL~}%5SOUSW`tWji|e76tP;RB z)zr_+Nr7}E!R_~>BykfZ>|NkDxv2?Q#?B;?xwf4T-$a-j7Nwkv@V0d2pJrtULVhlr+s<^=aSG<(0Fl z)JfN}t(pg^j(EiTN&~7$ex#u-f&__kWLDK0o1SHOM@+!lFE26~P1xPWtXr{g0DuYU z{zruSxEN5NQ*WkCk)B@z7*>%QTc201(X=+C{6dYcG86KgrfJMsG7Qt_IN|42^U%*3 z*ub-|1mB?bh_7drYJ=UTC+NiIM|V?Df=peYW53c%i;@z*fe2iXdJB7LjU-(;&mkU_ zTw@eHzUlH52~a{&lOiXfJ6&X^Oo(rAI-KLYI0F0hcBq$b~cxV;%j2|hoD;@n>3pJ{@=|}j5 z!E#|U!=%9Kx#}G{3#S)`_%8ZkUm&}W-!H;FuQdFoe z)BC2+?NiA$X1NR%pEIwHEJMnlHhKSMB@)$8>GjiM zby~{}ARCtQu1#Z&^r3jRcEko|5BcEzlAKLqLY4zU-@X0}uIF#ki!2UH9)1iE4zLC7 z4Z#)u88;oqK2Tqp#!KWKBAS29Ga7?}-(;gv2kMFn%zYLX42?iB1daIa@&#nR_m*cT z;qBEy2{pz!|3j_4mmuaTRJ8r6O6$`dy1V*80la>aW26xpt2ClRIU3d6gx&}tHYSDU z9bi=4@(xagsP4y20`DP;wF*6Pn6AvfPs1OE@|lAFZ@7$95iNxA3sUusFZT(eA^k0H z@`awgQ0*paSEfZzri11HXcbn9q1V}f^ap!Fq%V$- z26?6?{U-Elg+Ef4MfZo{Jz1KwxMq_0aDzmnP$R@X17GljIJ?i>@*W4)EMEbMVVP=K z@S{mVznPpm|5@!N`3<3W>AIXb;`GOci`A$8KL_NUrVjBw*i^HvZgNZ}7pF z?<^)3FWw}Nb4hz^^fL{Pj4KYGTLAawonfo&2a|(0vATs<-m-U0K|0%V(CCZ*x}1>1 zeAFDV?r$lU^Ny7~2Tf=B}0rmf89T zemx>bZs&qauiol>sF?z&dgUic$oDx+E?bI64C2BMFDU$T#X36)pm0tuF2u{nOL!xk z%#7YBT)=^P!X3umz}lp&E5dIug%^VzK$Pl&R>~O zg(}EHh(4QDjr`!*A|PdM(DFWQ)#8N$0Ui&C{=mM4)&{)h|(`LPlUSA=S{^ms3_6a0q~Gr_85Pb09bbY`8$dFK!Sx5 zD$aeAf)7TyXP=64{1{xBX{-#rNu0?_gIsc#>$5y_tUU{H5YIw6I=wupDb?$T%0jpO zMr2SqT1o?HYOew^t3UBicnnYE0P`CFb3XzzOAvV9GeR;vKym_C9#L>ESUbGRv$ zOvED+E;!oOI#P&gmMxONx+32im;t_FEYz)R)xff(l7j(=`z5=_K(Y zI#u0Mb}Zwc?&IAB5a`PB|MB$JQBk$s|L_DY%@6_-(xJ3S4<+5HbV-8>NW%aU0#XJg zFp`3#f=G{nfP!=g5+dE*@m}ZtKEL-r*S*&5ICJ*7_P+L~NLjv%^7bdYoUr|T#@^I5 z#&F1h6VF}a<|L7i6F~}A5C6_sSMe&Bd^*{V-BpR&FDa~Ng#P+|k%>|B6 zANK5J_x2uAo=J|D`z$0LbI)w@oUs2qW;IX~iE+3lLEjFuq^Y*`7TxTYTIFmDA338k z;aL-ks|M69Y(9y7n)aIE)t}pZ;}}F|&#ZV{oW0xbOqY(AG!VAK}!F7nxeIIK-DtkVoE{U;M)5ulOo(#=M5$4+Z6>% z)!Zb|L-$PJR5n- z`{3(T8hxok_7t;GyiD$AS^w4<$pcy!<80kEIul*@OGiQw%b2Ek%bhzykg0imQ)ST(^J|b-PRNh!^N7jNQq& z24sJHy(NycrZ?w)H$y;;;x zX8a-aiNHIlo99Q}V!hf5rCX_P*EM@kds%gN8lp}5S01S`KU8tasz6~ds?hfp&g;H$ zl^V*Zkr23M{q??f4%9}_ypQja^I{vSrI!|t?mFj~%szywgw7CoGSYbg2fG@OeqP7z zgO5+Q^Smo;c_p^+od;{xT;Z(0Txnx1;rI92A_k0VG37Ctnw+lTb;rzRdOduN?q{av8-00b>?D7 z1NcA#q{oPno}9#s7H9+WP?s!}Lg8$y3o`ycyHft>4nF>fsdEp?+(Hd_o2`GG&}IAK z_Vx;*6~v2lw_4v|eNpkgLE-P1Lo!*Z$&a_{a41b?e`SacEU>1t{p}+Pq>$iGr(c2| zEXqtb;ArVrsd@53b{u=<4oQ3bYgpbHll5W5z3NuY+#i`r)V(Jtk41m<2Rh2n!Ml9FkqiZT!~ln}-eKvofb&6|*Gzsu6wz?Q~dK9Kfkzpx8o zl`o7|MSLnj6>Cf4luy{-zc_CO*iYUD7u}vm&9z%4*u&ZaFaIl7ALN$)FX6@#AcA(ic;qghNc0b7RDl;% zbr2=ki>W&7hHLLD|9G~oAJz#>AudyH>^;>B$^Y|Hu5U?MN#w`tsp3Z{U%Hl2a1bIYW~@Q0W_;Qjo=J(Ng6 z1*27^?DPzLN0^;rsj9mxxYWLde_jJ2E$%x24k+Uf3<^5cei!>TmlCH*Aot7kw`I;&0qZ$0 z1`hHy4wW=%QFWS9WaeA=?}YnKDepvCQ?8s$E!?VK{`bnqk0MU)dw$llQoqziP58dk zE5PuibucV#Wdg{!iB={fB^!?A;?JVIWME$u%ZtE+omff5h}Y=CcdGg`N&d|aE;}aw z<2Me4s_7$MzxQ+eU4-xjQqhV%!2R%hzdvG8ADj|2((Q&lVV@+onhxt6%sr?jHoe(Y z3Qnyg*`3ZVD826L-{Z3ERWWN&o_bI|*VFC^XxdmDhp0GReITkz_7d^#bw2?rE)$Vk z5{Xcabr2Ey_?2A7(r5sqSm~i&2@1~4Vb`a5jS_lG&2mc-HpciIRvG%6}4+S{4x@f%P8%(QwoV%t;Wh zCj?a7UM_VM3tM-$$u0+|YJ>>ruAFr}!-~Tc%g(n?L4w3BV6-BCs{yQ(P6HdHntlSv zv9U}3bWJSP?rxDAo7)Ts;Cj$m{JaJ_Y-g{>q4Q3LO1QH45}SL_|Fh!ed^o~Iq(K|6=!?h`$;&@?-i4L31B7~ z94wUAkx&q!B(?WI4ulty&xee6_rG?&1Vostk>g`QSr-u5eZd+~Qk2~?Gi2*}&ih5Z z#WyOk=%zOd--s9>Wkp1(5!lwi9Bh`;jNupSAoA8u+gRo6n zt-NL4wFQ*|eSe4gWr5*bA?V_w_$fUX+pL!&dlcXRya)hjrVCn(5q|!zsx{~l#1GY# zKc4frW}?q#;UpFsDb9t#LAeyL2>x@|87Pj1NGa#R7vh{rhrgbmdQC_X6w}v4dukgwlI<-pZpQrr&UQeNb$A)#*BXg@~axRSS z01rpvXhJvCCzx&^Z!`ZsNiEatyUIp>V^96@#C02R5CATg@`oUGkkL9vG~}-H7zmBJ zT0mSHjKnfzyPam~(f`%{hu|}o;5Dih9@g-)?e^^Q?n={>;GN6Uw##hUi|ypRKj53@ zG5h~{nDgfdSh8H{=@2Mr$O)3T-uTmMLsY~xOU0~|5gP%?wB9h&SMy5Dm`EI&k!9$i z|6`}VF;)kI?th_hT`$e7GjsT0s86d_o6-gsh5u^=z=&=)0=e)B(+#LUD}fGAMaZ*)Ih=X|#EY!5Qcl z3dUZ%d_SmN#mfa<%V78^lojb`8G-4*R_-6wl;5Zo50p*uDWUd^Mo(7ce`jBJ&V!AH z#h5i1=_3qUH#0gj_;;#;aO_p#2jDQ26i?&7(FWLC%3A}W{DX2fO^mNJg&ch$QpnFX zw4B3D30%gDz+DJylbVr8k9RpXTzHOtlSWmlqdwYbLWAmKu;ln>{Q27iAh|2&#X(+R zr6o|Iml3>j!ECZ)DVSk}792+KeJJy5?MGdI?U7@t)#o_UtE18+NOU#S4`Xv$m1PFXGAuA*#5?k<$5UZ!-s zN@mFmKGkRfE|MbA=Z5S%;Vo?!S`)oei}kImYc1iy;fK4;){B0=_uMz@a`z{v_how* zcSCZw&@vRfFvc(<=9GlFwba6IOQ+BbMNBH3jdPBEIUmufOt2YvAWET_zeIPW5Rkii zPCL9^tQ%3hdp9WDWSfj;9e!MT$bpd%oJOKhYg&_>Ji}&i6dS8};Lco7$S1`A;{trA zH;qE1TRze-4B(y2H^O%4F`QZmP?;vR`+=Zy$8ZM>;`dFac$zT4B`n^6c_1-3#1%nd z)TkUky~YH&@D{-Nr-xflHzw*PxV`fOe)mM=S~Y!QKVtK_`w{S@3lo?>A5qFy%UjJB zB+F;j@+!-}&G{+>e$f?B*x_a}52O_%f;SpUvOuf|qYbk@?$qGS2V^DPk{2Q;rFcSU zy##;4iPUaqZlv)U`&$wyn??K<`5t>TE*B3ox|dVky!j288cTW*wPwQdXw=Hz z#5-s(y9}ytk%{tlYV^RLpw)`Ot;gS@tG8ejFr=w<;CzNe|0AiCgY70L9WUqpH@`sy zieWk%PLjA;uq>@~DpUOIW5~U+Lc2#d&=Ho&WEa~|hF#sLbugFk43zRTW3v@!{TJk! zzQ(|#+71Bst1{58vSFd@BN*#ffL?Qb+&SqBA)jE@p{+uDC(#uO-yqmg*#58?&n@mELG2#P7MqO?=2np?tgCC{o5kScz}Vcez5YNtP_xY z4_D{UjgM+P>ai@V&_B)nTtJd8egQr^ho$dj{n2cK8358>MnOg z-sI5cCLTVi?azLqVLreclqtlVfho}K`{cJbe{>@)%GaUqW= zzs3No=_%sow4)WpU0Ahesw$m^M3mR}fvCrMEuV4$Wt3}ve<$X-o_xcqO+Otf#b~9F zTpzod?6@cY0Ia_&7k~)H4HRf4XFIr)n17@JKh5Lc=v?#x9vh@fe*-2Hd5M%!26_o6 zih%y$uI%F(Nx7Dom(M@V_I8MVH{2twT}>0|bETqVS=z&7${m;s zUhDEQ7o!-9^%X^wHFY5>72$c|fXf8z7a&^!ez8p1j*OC_HL33geq~Ts#Uc7Ug)N zM4c0z@j9D_6hDuFoq#UC%G$>XuTmX>HB0XhqiV{ z95+J7IvOlxgFg=4*XNa+gv?_0emL z(!;tx+#V||eSdF!tR>u`mHL>0&meHWoUr;2G>q+4?sr_?QWN(0!BTw)jSj=$4Cq*a zB!j)uR8%50=RO2v9L6am&zYV@3VLD?au+Ytn6|%2P}2OkY!?a>Ib}jZg@Swi01!%e z&@c`MP>3uUtMOM{7vY{qmM9iu{N&9H^I!G(wh;t?C-TwTvipyJ*@0?Fi-+ z0$y9}k<8R~(vPj0>Me8tHir;Joo*9$Jj5s5E4yn9d0aAvr?6*H+n@ZyVIbmZS7J0- zGU0WKtGUj@bDB+=u_+6?xm*I=EMuXEli8ME)UWM=%c#(N$R)UKy(Fl3ZZGrq2~8Pv zIu@Q$N>2PiJ_>qbYm0-#Ix0jXe_0NMC{pyM?q_>a^DTo6p|a+ZZr0V8aD3E(k90B; zwKP1)(BHcs33Bi54t_@mZvacTu7f8kR`#!>yqv-{UiX<$Fhr7&;#@|kB}nc$TKUbu z!WraDahOPnSL=IOk)wd*mJ^@usOL-jtdaN=*{rp5j$hiJSC6eOTQ*xyiz_3lw{W$x zm>zsIbszi%UasBc4lE{{(~J#hfG%ZwB$x5~KqDkcQ>P-L)~O)CueH~r183IXh{r5A zqK~XAC|D)PQ2zH!L7l0MJ$RPJ7W3=Qw%*uGFxyVb=kPn8Rn^&no#2~g*>m1oLgP4+ zZs!N}xLXe%48%)qf;ef7Yd;`@*md9Q5+2~TGz|Fi7M}0BxZD3Y|4~1bvt2K5SjZyw z5KG?j$vd?SiY+59TYT2|blH!RL;LyNozs>5+(7~qIzy@Zj;^?Wg>Ql`bVh@8T8~T-vyv)GZ)umts8a5gGLFm zx`#cGN8FzE^$&Y{gL-C=lM>_F@RfIpaD0v6KWiU)r;gkqO+hhY4#c|M1@>pI&w3M( zU%?MaAB0X%@-O|=j+=ox^E0d3tuI$f{)Wd#+q0D0YyYnPd;pqQ)OkqbL%+#xWz3ek zE+%;9&22mIk6rujL_Y7F(ejz_K-Q5{dlQICWZJbBK0E>c&H&t*Ix;qOLS0=TtPQZ7 zH8%SVQVOoFa-5Rp#c7aAOIE3ysVWGfBeq+ZvA84otV)h*E9WfN;-MSpkr`|h`Hzcc z82)>!TkJgOm7oNR<-!7LBS z2(Yucx^Uz!XNy?3u(E%vBT1fN6heCbn}WF!RCq9{j6^%A>&Z~`J?9C1Gv<6V`Qv$U zj9dtidlY{T$H6uiA*q0lUh=<_HPGu$*0zW*8od_S)sdXZRJ^2gYK)XTP)nop&<=9kH%_wXn&XK7dB--w=v6VPlwgESe`!m#scu*hh7Obp!zop3jGl-^1g zhqyilv_(!0aeM`N&MUQmUTjKlIYjMDYZ1K4Eyejy8+AREmh zU3j~Eu(FYbZ@=n05F9JCPLG4F{k8pZYu`FNIYG9t?Skcn_v&L7gbURCW zqrE6^V?G&WodY(Eu1^9ad?~S8=`>%cVg`nM%NMj_!R%G$S*-uUir3*E@JZQjbzG6L z9?hK|2k(C7+`}$1_HXkk&IG>~XA^q?(UFfZ5IhzdJ}vSEd7du-_5tB~W?6M~Se%M% z4WfIrsxD_2 zWXD3$ViORlkkwV@z|<71jaGQ@P?g$hnRuzbWyO~IHGzfBSh`2eO(uQ(fevtY>Cb`;0D3Q^hj$VdcR z_6GRwQd|ME`FP+Alw6+n7eUe|@sUSdV!%EA>H!eAT1&zA4cOdQS}v~92dZC&$i+<$ zCCK7EMSHDMJSqr94w`y+xvU6($Of8`1C=aT$fqhY$v@TCUvkTv zRHf088*+HI+gk2w5IA3N|W93y(`2c*V0~}ObchqAw^8d^OXZzj~BFp@uh4V zMpW)$5dVS|r18HW_WNFYBggtfSIf*$yOHhxDl?!n0@*=w~l6;llu^+R8fNX$>%xq z$S{YC5jY&Jf@Vv7^7|d81S?5ZOxe{IHW-t=Kx)voQudD8LGS0y$0q-)-G#t0VA4!t zGxbwP=i-e!)ooj${<^p3RJRzQF-AD|E1RXN&@Sb}#_NqO=<+?FypF(@+7BX{N0d^`TjGMUeeM(~C252|Q`@(JmQ-(rjm;^#=w@yS zI)Zr@tb&@9YOiwA7_sfb#e7G{=u=X^5fR}%~pQc+6k@-$8(c zqxM~5kFzVyEAe?#Rzb!K#ajP9oa!2FOZ!x?-={W3DlL)zD{9z3S9Y((dmwxTorP@i z+vd}44L6}H1 zKmbn2r+XN`cRjQLegOI@`j$@o06&`K4?^=s^*I7_-rD5?nZIc$cZTmg&ohSN#h?GG zxXT1n!em_*w`|rg_|I=D3Xc{>X$r4P+w7#Ji?<2}Un}Jxrb2@shLXi)G2(QyO<~=F zIv_anm_?_jX#%Sf7b zFIOkHF2HWW#;5(_d?&pvM4q1AWQD>OMTB|%#F+h;m;kOd1}(CL`>t{<+FBpZk`mjQ zI^P%OJR92X@r3akqwOod75|0g{HDuisnc4!Enu$lJW=-2DtY#~YlRX+x*a_&+oc!$ zne84(#*lyWof?Z{lkaD5<`%^_4=(o5+QNU>z|9a#KG1w6+nizy>sscvKX6UIjAj2@ zP~d~MYt@VG<+$kOO3GiPG=~ER*QZ?yo>6Dt5&2oez#qAAa+{h_I(7k&tCxcU?c>0e z$jOxm`}s|sc&yzWl1zkeIU4>IYyncth2t}QdL+!olgsT!<#Gd;n+Ok;IP@Q2J8c8r zMa6vz z+YKTD+JALlR)EfcWQow1_6py!?IaNI(gr4< zB!?T-4h|&Un3L_LQh)Q->lQ{S2XAyb%k^yFI@9TyW_cQ>A#|1vW3&VRZliQ zyqb%&zuWu!3=JrL%i&_*OO<)xf7nb za?}zB{T>z)hR4xkXT7iK53^d+|M7@J2t>2?{x0^|-7mRG_d5|!iKK3l=*#z(&$rno zkYRZvkyvUmGh4oty+_74BhtgQv(f~Mk!Xbx^%mXlbdD|M*EaR6uzpEOGCI1ec)|FL zI`NuRHVChZIR;$WMU>~vNriKSMQG1R_3FE-iA9T!i=)dG1&6kJ`S1Iu-V0)9^)P+m z>qpg7_}4c&g8UT-P$VZ`ihGd!zQ}DPpbK6gc}Ly>O9u_pUTe zzg+wqPGK>?8F#CilE{3MUT2g>A6g3mqw{NE=d7cb@DI8@h_Iv_B?zGCF>#oV;`_fy z0%7j-!jm;l0Ks|LSWQY^DC5xk9x&At!C278bID93eRm`U1-{HyT z$;Rrxj)f|Tnm5*Bej8Z@#9lep;6+_#L5a+B?C>74nN~OyO6M_T+xW}B`Q`9^;rg$4 zT{N>iz+3G-0oz%9|fFOD>LF+T^5{6~y^eNNfszquvyp@g35&{$#jDgM;^eYx*M3E>ylsE8$`^TJwE@ zBWIJcjclK&p)q7?vs32VW{frib=vf(aQ66vH`x0?DaW?c~RDv}Wlu+4|x6Z-WmBE4r~+HGfYhW54z9PkdM@EVv&zM9Lu_&vxU` zH8DJ-N58|+jA5&-;+o=P9wLXyVU27FSI?2~^4=_+`G(Qeo~gM|$Clws&uc*=5)MCG zT|!|@Ct>(+uWG5U_O85YaFPyXCd#w+uWu3YIc?W#jr+k_<&mb%b}4%wFJA zuAUheZmW?SF0%YOoZd-oR5yO!kNO>w+e;UF;;m|!=cE%SB4=?a<6$q$<}KcR8hPcW zy4BNJx!x`rqolvbqrF-lJO}TZDBE59cxGQPG}+6z>&o)7))1^DO*gLA-zPksXr#V8 z4#^XceEUza0du=Ah>9@n+_*f4<@xH6$8MtwA7Pr!r+P+GA2NyCGn>*BrFWP2FD2zh zMSm=&Mc1&V-WARJ(YWm~j|#E$C+uW(Q=*=|H@VMFsAydyKi{{)J&0giR~soh8x#9@ zdA!!R%Pi8n`9;3?6n%5$gT_LJ0uRqGu3yh~cAo`@>yntRMb7mNmHTaW!SJ(!1e3Ch z39IMu+~T8eeFm!z$q5HIiMW5J(k8@GvAe3IyEs(+pSFr*x%=p8JIrmK%F$=&R%VmsZiz!Q5XCcUbsXeS=|z1CvU57nvK?!}n6-@v-=-uCVThOy(CY z=&cH2@8s$WOw0iRafWRZ{e927&ilDVwsviX)o<@|AbjA>ayo|Q?xPb`)e~R8ARXjp zLho0mN!VL0nv;>F@Jk(xIr!*4bAYbofClm{)DcTWEw+a|B5UP2=J=k)dl&sMH$>gewAp#myh)m~ z9g8Mb4OqQXLuc+n)Udi?k~lt5A`+BGF8hMwd8jC-X^uu^1dgA6f33pcH1gclL-$W_ zo$LBBcy4ADfKPR;GSr(W7qzPggtIh*DXPlk-X(w0ro&j@^3rzGNuYt z@%LfDX_bpGmEPCRiWkus zrfR31YGP(pcMl}M8ewS@*BeyM2m`S$A+Cy5lBGTfWEB`eDhw%OLa`ZEr!r{>a!K#AuXbdQ;yg@__? z8#X|El?;msP%|hhCwvP(lv8Zy*r(RfB<^^3HJsl#nBH}Ixu@IFjnDQ(Cy(%qoC-P5iDS2d?Z{qx z2+On+4vu41VGfw|8!bvQ%;AxK8bNRn1D16q;{dE29H(GnrZ{>g5ceateP_q6AvR=y z1skO;=$(f!{1KbFNYLZk%yyuYE874mhYi)9ZKMIzQu6%OoFN$GYgk|;FyRSb5sW2jp6s`2~G=B6Qv4 z1^tU>U^0Kruz=<~O{l91pli&GI#dy{)Ro=-_N~)^8Gp&v!V3UQt~cDCv(SA#`lx3o z-^h9mKg?ky=XzAjSm^KMuXiSp=$`;hkf~`9Ch;jJz~`)lZ0~=SKJg2TMN(m)&GtdUKxr6Q1zGuke0VYkTfK z;2^1x5DG2=z}SjV~+k=zvA-k+^Vsnpyvh3JLUuUD}dGOCeUa&gV$&hopN z#*)NWD27=2+6#AYml)wTRSt7s(+Af6Z@mbyJMfK3np1pgk)VYa zMckmsA9Av<`O7{XUjE6BUMQNnmrARiy5<`bUQM2L+uxZa&p)L~>oRRzoNn5LE^FCn zekQ*Y;rC(Wo;%ma=MqL)cZCqxtWZv3eDX2LFWg{96M*^Bh>+!o4p&?OB!yHG!6Jqk zL#7>ITakVsm?+sM!**06zhBDfM|&%aCBNi7!o=YEkomW$RG;fA47q}C=| zrdH!UNq$4SC;t1-X&<)jR6>k{f<`>X>H6ub3!*b|mV>})}y05i+{Vq}5S1=6X$w=$u~`ZCL)`n9mW)M3_EhFBPNFTAY_7I#tf> ziSgdqQzZv(Z916TFSpTdB{`2Z-;)(F3D1BfZWTlj`IhB)zk&HtC;OmWN~Q1g%Yblm zsRPI0>MwVb>=vM9Vrl1NuvS}m&DaqG#*1q#)j~fxFo>|{(q!3;_e&M0Ij=T z&kDjESrGYbwlW^Ra%d66U2)(AJ9J%@_&uhm?O#RW5^8CCQ(0K2iR$Zw)1}lJC3RdD=A{nzKCy z>Pa%^K7ERWMZb9q4LXaCn2=`>?a4@z&X4(4rR6K_0pQm_BW5F=TPgJr{a}|fMH$7d z_Pe`VIY!0pMRHuShC%fHcO*&f<*vfzuIvLfE4v|BsctW#hH8FDYwcfS`qw*yNP9LZ z4c!uq+?BVbuVhGU;yXV5KQ4gPCbZA3f3t3S`no;Ns-GLpV4{zHLqD#?-!TmU6C4CX z4<(f*z>wO(LU(?=&3vpL)rY!vt}74xIZNOgcD;c(#=kTkH@h^=y=AdIxiPJOAKqKl zFprj7gs&+zzK6;9$agalF_BSZq}TjQlHnHa-0c;?VsxtjRCuGN`G1H@Us2R#61H$R zrq;@66%Qc|k1SrK*nKFiE7A&Vp89{Jm{T+3E)0;W#RsHhIdl#yzlPbRRtRpV{j*>t zvIL#|@NLuF@u^w)9pme=MbiRJE1+;v>+fJbg7M`R~{MELM*}ga+$Si z<$ZuXK15jwZ^->rI4fTAMe=qvKGA6-{APOKYAZBLrsOo1AcraEvN8HItiyWi9?O;& zf@IE@y1;PP4SW9pN48ju2e;3E!`jNQk(V3@e8EO+{e2Se;51e%$M!gcGI*{7RoV*b@;_zmV9QAG$^P z9`^sHF>NJW`w2A+dsn;h1%|E8Ku&2FQ2;f)q=sW^F*)Hzd7C#71v>jKFD0 z9=i3ukL9b4)|o((G$+gMs9#_17X2y6F@IBa3^K3lF=WJl`gA$)69}qcHC%ju*Qmcm zRxUSW!_u(|pWd?iq(kAtz<^R%UmoDS*r^C~oJX1wGkG3)8=--rSz8)u@srI>>f=v>G&pOhL)Yp!3;?c`}?WnC; z4~>>R>B8ocV-`JmA2Iz2+kkNB7G}sSrAqM{3{ArXOdcr*dysheZ&3`3u*2sy{F7We zr(oQawkW#)37%TgFcucNU~9b)a5IUFqPY(V4o%~%pZF-qgUIkIVtmNg@Aw=}h=IrF zIr?he`tZP)04Cn`@5!@GxT?mSGa@J>^?@qj4#})XyJ< zhAR_Cz=6Y{d1dyUivS{CW21!o%iP=5pI1>t?i+A1Uc6KwN-rRB-;4lwra%q3IzhC= zA*|s8h!dcOH zYbyZQ^*mGD4D1ayj9|Wv`Kxuk9Xpw(^Uz|7cH3#ns1;B~pUWn;rCWG4G(V5sa!J#G ztiA_l{;<`|%b|n2An&hKM9Pk=_(gv#Ygj&TL5`(z6WTFMiaZFV%;hJkC^3*S+F*cLZ1^hK)JyTVAZd?D6ao?jQ~J88PFEP zV&HiPGsOo}hpqLZ`mgq~Lr>jpPVd=ArMnSnfH3zfDgM#(;2cg}U9rA7d21@*-^zfN zP(}AT2_OS)6oel9<_R9rpQ?WmDo)J(#GnDCj?T{_K^NNEN zg+(8)=2!W+@a7c=sy(RS-~qvWNf%pL7D&@v5%i?8q_v6o;XnizTo_R{e{ z=7jNT{`D!1@Ckspa)z^~&ld3R#m)!MEEObI%7e9k$>*;{*%y5 z#xsoW0|0mhB0)P{Xn-F876@=vB`c)ed@yWGZ=jZp*Vej&_v{zMh-*W-a8CN%neT=6d##GlD&6RNw>GyuiFl3uGPmc-D29{W1QDUw7}nqxl`D^L@I!K zG9QRNV0{oTA7Su=`Wb`qSLBh%9_3P;}wzj zou48#ve}OJ-gSX0Ll`p)6;3VY}UqpQp;Mj>{_ieFW* z70C->-bbFs=m>~rtnp6V`cZ?xT*E)e6U<~Tz0>5SEK!o<70k1nQi1W+vJ|{T=B%mR zbH^3(_hjDu5~3#M662l-bUypA5~?{-dCm`>BLlTZHQ#TQuUn76t*A4H`2h|tRq`D? z!z~;Gg<#!~p({ffxul4_5yzs&0`fNc#~z^JzMJDLx|b7cJCoIhdbJ3LZM}(QxfjC1 z6ZS?zhoA%d7ku;*b77QFp7IW;WgLJW|J5qU9nU@Q-_BWV^z|LezIWTRQ%^CbuuB><;~m9E?vIy$qH>1*c7p#(^Wf8%EL0!wu(My*j_ zYZLW0A^uS?Oc9hBxzt>WN?IYM?G#kVD@ji6niy~JCorVy8F#P*du-1*<(mDF&-%lp zF$kTF&%DLa5#KB0k=X(0{KhwSqnHM%`+Yp;yMU*L9S^@e|9^`p5f)(uB1-qALx{KX{o*d5 zE|o#tmY(DMx^Qsf{zvF!%v10nyns->!{ZgRHfg3#=8wVa3;P3cgv{rFOsc0muSJLt zCEBXE2~V$m$UFCV7Z@?QcPSi7$A(c!Z&Y6v+X~vZWC0^2CyfWg33S9;hw9Yit@;a4 zkUPcOvu-DNX_J}irg5}a(mgFN_o;ToPa3}qp(4{rN*I69(E`_4anA!|G#uIOLUe^& zCt3lZtHEc!KaK;|nBNOqKZ1H=|GhL%H~ zLUNofdnv^j(C~x*o$(&8NKU@(??15zdr(2U9uVgQ7=m*s2$y23+;a$A6*;}3%7HNm zFZ~}fxfyZyekNB-6Y2S@nOk+VW|lSMV4ET^g9EErbASa+>xQSh)lUVvr-_8l3)p0a z6wNT*@}$TxdDF!7_emi!!eSYVnU3&h`ohAOUKO_gj*pd?X&M<5YV9{{QmTcy)oO1A z>W30mss|Gqz2{!B0tvUK2otyZ;`apevl?Gv;l7p?I?4zp<<=UIJst)$$LzwzvusHhw z-c-|s8z0TDXD*RE|L}^O1k!sE6Ny;3fmM$7wQ+izkcazVaBdsQ`|dlP?xh&@%kLk= z_j;;N^Py+F!KB7ehxlL4pUj4r&w2DJp(ga0_4ak=-|vRzVPKij^`E=st$4ckaw;d;M~7M>8oc70><^Sw`X)wR^ba%iTg>M={MO9wyD&Z4OVXGjfO6l z>&M|ULv*c|a2tr$%75QM3VQFc*J~O86U0!oe2k2l(&GuB8SaNwKERl$E7K*MC5rtb zN~c|emosm2o_r1yf^IKi?jRa@@zMWQ%m4tR{Ha!b;WNkW+rGT?CH~dd6t*yk zU$wX!Kvkskh!U$lc0~>yugQJ}*fOOsT+GHw?N;ugw=_aa!j|e-*~3A;FIsB=71%2y z05CfA%==_E_11saHq|FN>+n3fz-wJc4iiN24rzDCDKndV+M8}{`~sNcVij{PbGAb| zluejG+|TO%EzG^l*XPg@HRLOxJTrB*!|)lKZjisuA|#zRtSvNfMNZqrUVEQ|kHQX{ zH@;4CY?pIOaPZUO{|(pXijJ=47pa3nW>6u)rFJ(RB0@oj)DfipjA+?4TnAH@4$~=+ zaOIFB#I(3=FC@HntT(>&ouVJ1TYd)eH%qSfay{7dj<2y!q&^4DY|F}7jT{&Kgm%Fw z$<%JDo_w+2+&3({u&fzbx5lsgyQ*3Q&JRukbpM>(W}qH|-BounWA^o~T zO!r**n4hei*!NH=3I0^e-(M$Q_}fX&W{C4P7G{_x`y`Q%=4XHnT$--2PCD8F76W~_Yyqm>wv#|Bs!N;5ZuB5bg zK~;@6i69zml_5*{5*x1pWTMUktfWx}V$o`km`FT9$9B}zNAb9SHDz~*Ol<&~1k`FS zG|=-Y8m(0VuQY1yYd2mtKEzW8D;$au;>Q&@3k)xj8Oj!RtNpHG!JH)MS0%YYZui1T z1opA_*O<{coOe6omA>#=^q9ZT(@I-6%E4B)FgpmA+?M!p!8{Ud6Mnuw$R@k#9n}M^ zdLfp7O6<>vmds2n8IgpjxL@E`LDBQZiAzxPVWesz8(aq5-8!Y)dD@b2wN|j$ zce-)PS1&O?)f9@69SCL$)bfhy9{!z4DvmfxpW=gAez@s7HBzjf5Uu_Ahc=0Obo1)l zt9)EJu#hJyDyEu}>$$-jnRC{ef4+Hq07FI7(ysz*xnRzO`qupl;%0FNy-@Uq)&|*_ zQqW!9e3(2q{0>$`2~K>v=7#Y!1s?`JXz@pGpZQ}D$aA8mpod|E!2eU{I-i8Z52jA| zROo%OmtO3wL;rX}0MWYS)elv=yPR-jyhcNe9VE@8pXRguBuv-LW>N1Q~35Q0%UaBgT#Y(Jgk*?>Z2e6=lx-7zcWu6db3bklPyr&!Je zuBktF`E~4S^t0C#Fb)COYW@p7Y7*x5k&Tg5WAF)EIj0C&_b$J+9U41f*YI#_FvRN@WyBri49_ z;48PTg}|SR=U(3;HY^TrrL2RT0iPeLuRzmYw3-PJO&fV}atHL+Z$^(SB#Q45yvplw z)!!TX-QFRccV=2)64=GdU`u_Zv+_%L6pv#r;1qC0<`;JH znee45uN}~A$IlzPo@U-_of7ww41<@U?Rix3?En;HsqljcZt%2lVQE`@_r^y%vL3s% z4nKpx9w@a7zXxUtBOXPKJEosQH4*Cu8+!d{B^R{dat2@KoJwkuSBp>=&qJZh9ZU(Z~!LaJ};U%dLN?|E|iy7Qm<@DE9#<9d&XTB99_olZ{TtP!PjEg#0BeMxGABWL+O zTpc1gY8mvc>U`dF4dpyhwQhmdl|YCcYl{1^*TEa&EXOvDr~)+E9xrOAP=`_-?%7ko z*!>30IUr(hGZIV(+r=eh>kpxUQjM^P%O~Hq!kne=B>_;_D)6`#EB0{ zRa~lPLV%h`v)yJ%XaR2gfI<5-%MXF3wjE|nsO?tw=vy(i^$8yo4O+O>Ttm8Gx25^?prRxnlat^fu) z3Y9hpB~90R(PJlHBJjt9@nfi)!NKmLShpb?>xxedWBMG69`-hCYLRgEE*r(NIhm90 zvLe;qpl59;NI$+>Gdi&DBHmIq8>}UDr&U&KIuAG6(=?4&0r(&HqO15 z7QtkoKb2mkG;3W7JdV;{PX0qr^+896e^WC!SbPgP=INFB8lj(09+@FtA^UB!U;f&+ z!YTPY#S`C0PDIb$-s=F}RB>+nKgK}x-_8`-tRV9uBc<++Q!MCazRC z1)@x}OTw=_0q)s=18*ij$SQ<$t+9C2>K&9!%Lz6%&q{GIu2+V(5+fMURF4cKKBaz@ zH!OeAee{Q~ZeMrPkK)JiTm-3+A*L`vA=l0rrj19@D0oI!C!rNqE|G(WMpk5yn8Rdy zZ7I9&!FPxPgq`co9ps1}H4`Iu!{~uA`9glVQ z|9@RJSy_=SGi2{@Nn{hs$R=fHZ!Q#(?7g?_5!owyglw|PUfFy7&b!a&^ZWjH-;eu` z`|^Ij&pEI2oR!QyG9sw+&P|c|fL)*tx1TAXU$_auI8;Jswr2{4cSJMiac{fnC!dJy zy6y_^I@&*c_ccv&Z29oQJrsYm{+DX;`PoueAXoAv~ef$c45SS|M1f9Om*7>c%xq+=?1KnoED9V zb<{stR4^{GeWX8EU63$c4Q><+Iu9QRP|Gv_!*?}*ZkV!qe*WMY%~Na>1c%5&&(Qkd z0Ev2Hn>b5k25 zA@fIyhe`)g3~W2raJt~D1lRezA@`#o=A>Rl0D1D}4AY~!s`Ymc(9 zLm#ci&cC)|e62n~Sai3G!jOQ=r}sixSiuN ziJBS}jc`4CfJtn0-A*Z;*Pkc-yol_6YJVRz@ zo3@_5ptLd-T^$HaPP)=c9tw5D_=P$V<}H+eD2(uH^U0HTb@t~%O)8JbOeC7s`+D~d znF1zyqcs|)fy*4fUs!wyLN=3hR6atbK0EC(m$udyb+^OscW2MC->od5_Y%=h2Ax}F zg#T&IYBu2vY{_!Cepd0r{2)ZD@z42g+s8e30rt5C{}S6KBc51BZ=&WD`~cgFdfN2d zY8^lM2nKFDDfjnHZg#^UiRI;F+PrI$5EWun ze?&;oxaJ%-5unguU-r-LrTj78u>rS!|N8m@_q1U28z|9m|7?k-eImzvbX)=#K@Pd7LX45?keh@jcZi$K! zu}L@`5uF#bV%S~FR2FSe@@zlm4HEZ@@I2>XqjO$SJPdhdXO)RzOBlG!;D9d@aPdLX zA*#YN)~iGGn=0IQvpzUQHq6TRpxfuQ_e{%`uR!o3A(}fV<{@> zwqAB#T^;T)?r`DcXjMRp;ZxeHZIGp+i2HmedexT8P$CK4AWno73Q1LZUdC7>iMdGY zFPa3oP(JXsi44O$Wq%g?u(=0gr&X|4iFn8>_o4|1-f#QXDjTsXv;LZGn5aj->#?-d zq#JzpXjUkdU*;f5Mp8Uopl1zO`U-Wc%Y{lsiBw+i~Z9PG77=2?#823nBm)hu@KNuOol@y6tM~KW$S81(Tu{SM=IYw3_O@n<5kw$;7U`f%a#kFZl-LIseL-uczFb!&aUJZj$Z>Iqx z2VZu_>p9-em%HLyZL}W@c`~R*`A83g_m^{TwC`2phTn#dpIctn_&!5M*PLDJ-aDpk zF}+QHQZ_|oUohypeb49g;HA|wpE##5lmBS}@Cnyn;Ge^6d@i`n#W@ghM~68;X}u-r1Ct30?Rt93AT zm1XdR#>PXc$>2g ztX!xceo~QXNX8pdhq_|Ca;BRY+De#lwfK}3SuiG9L0=P z_~{mf1|GSn+sbiudHQ)(};LQj8Zx{j}&#yNTMWK3AI61D5HX z%j~aqfA4jbF*p^-MpLQ1ROCE4kRUbe6-A*#$_QALU<7a4M&HLpxj6gLmrr_5`VEGU zQ(LNaqfVS$Oxd!PG@K{AHEWQ(MVKGxr6#8OK<8s7yop$xV@kKMtzYFyl=F+S8r|4T zJ}q0G4wPvO9S2;c0DD3`InBdA}^GUU4F;z#~i*r~06+V)W<@u!R zOts+RwkYL@*KxmY8+G`vm$q?2eNQ8JX`=ow03XYs^)u)vz!L^IZ3e2kgKs-Z$nme~h z>Mk>waE6N~1Z22QfX2XnLU|$s36nr(b4+%&0Sl}MN}5K>)R@z~sr+mGe(#va z2p3=kSCJNif~#5fBmpqBOd;nLGUUmo5##z|PEz*@v%G7Dp#Ky(h^ha+p0=Kco%0qa z@DeuznTVfL@4!D2bXnTqddyy0YjPj0Y)KUS(d&iMmTHGR8^slp^n&M2iM#6mokQc! zA!*143nfWCkleiX1%LO;l_T62KW;{_g{9(QP5rD#-yEA^u}35O-L#VQmCQS(qPHBu zoMZ7AMZayp+s@dxSrpOl8EFVVcs#oO_A46NAB+~LzRlW2o$45cU}{SU++aG0?idx$ zb{eNg?g6Ly$~Z*q6jL%ay)93>g_d_UoZ-)`$D%F(M4@m`ICMOC`r zDpOcb5#Fhok2#UaDxPf2Kk`K>>Zlq93ITw)*IWV=2RNNJnEKaY3H@5VKW zM1f+G?k{Rq)~W7@z`-@Y4~IJ{5pr+8)gk6`{8&am5AsCx#om10(>a>unZv6R2S#_< zDdHX5)cJCOw~{ZbaKVcy<)(JRNN{%4cDsq~plCWmE++HC_TpkpfRF=;U;8$EXdl7} z-6}9~<5||60jZtWwxF!+r}cXovU{VT6Y?qu@}@vBWkjrmmnt{W-wXy`pRI8DCMGQA z0zc#EshRTm>tVGu4QPeO91!EB%baifqG$Ld5=&y`c*vn?yYnxN(QnKpbnN`M4Y;f#jFI z=J^Blgm%>^KS&!}1Uk|59`fUNzq)9-%`lTvk?+)9+3==URL@pW!f_q>6P~MR6|%8z zl5n#M0lfimhj0}_!EoaMC)4M5i`h*ye*>HA;bTap0e-|seuG=FTd1nRutfJ3^3&W#suM$8R0d+nV0(qX?6)On}zeo*7k?@Kz?JdftQ!pD$*V1CI_m(3Nq!f(S2(1T$3p4s^!D+X#(3xT$!#?8E{Gza`#wx*>Y_>ces zA_Jxp{xCXnC*>i2_1{ueuXJu6tXs9`xQ%4MG7wirlO_V0Dy2 z5&&SOYOrM;IvY*Di6Orgy}tVva&||EJ@9<>pL1dl1p35k-{b^bH32n}nQ!(7C9zVc zo!1#ilQJV-u=b9A;Mru|Q~gw@iHZXY@2RO>09)^rYWeJszdb+61~20r!e7pgRbGDJ z@}e)otI!KyUZ7Azo|I?4$Kf`9?Sb&yfkH736>)`s@MOTIJHY=>AjDB5>=Qr&H1?1v zBVg+=pa)VsYSW2x&ZxU1)uHxUm2lo2tv?og&w)S#8I!Y@btl5?MFEC(^d~gvKrjRv zvS4oae$JZErxhis@p(QIPAk%X8fx&-5b^r7gU}Yq1C`M1pb=Dn1F%Jf_C;Pp zi2;S6sJjeE;872TpgM zUQQz(Kx969tMh`$??KX|CyZs_jU*g0gkcz9 zutuzjJ$tZzfd{I$N6%ThDWuo@FloKY)fJCzd0oE(sSFao{{xxsm;V#WTtoU#=|FkR z5`g`e@PC0Ksq$p>F5aI51tm8VHE4Bo^}N#TyK;+?5|juSfuZFl#px?8L9VGeXjWTC zIZRDN2^0tdEb>?ERz(&1H%8AP+1U}WbibqqM@=wXg;D?vOm6qCckFx>IVdlc!zeT@ z1o2lbxLq6{-vd%}gKfCukH#93Xa}?1ayBS7jM4BRTURanw51x7Y7J6iN7+@goMNnN zS&M-biXzvhEq(FxFsU=O_WBw?(H;5R0q3*IYv<3jSBsc3{YopIdD9diPswnze6c-R zMYLdA-hS+mhK^oZLW{*p`<$ls_U5uksPQ+RJTFdfeE~Y_@R)|Z-U9+7UQ6^Fe9M^;NVbsZLQQntaPFN`Dhgc@Q`I7`Z2w3&evF?7)1sIViWQcM>$|dcCv-w}#RS$E1 zih}}5rh>po@}GDh{@Kl)H&NZ~7lq0R)tg&7h!l^G8WgVHncdM{vy>J|HDtQT`XL?} zg!(Vx#6~6DF>nA?^VJx+vs>bei7^zCx0?mRrIDD>w9!$j1Abi*q+_>Ptjqg|sg!|g zP{~=@!!Qo$@8kqj<8vDBDtY9?#NMAu{kM6+;--)dW9D5|-iG@icRMbzrTO{Uyz~#{G)zH%%VUSux>G@HxF)JE{hI@9lFiP2#nC|^7QGp+{ zKRkHwt*WbMHO>-Aa1O;s0y)UZQFD(Xd~Sfu4P+_)9Nm4m-@bC;IKcA^B@et9-|u52 zSAo5lGI;b0zU?l7=cVTHQ?6qs$zV!V7ANf%I6$JyY(8y^ldv5e+q$@;G$2UQY19>k z=k{dx3Ji!`=YpOtcF267b)t=xYE;`($7_H3Odb!XahZvW?f9jqgQ2cUg&iu%+cg85 zk0(w8z3bo~r9(9`T7eYlMI)7r7(uLkTxK*P9f}QvT8O^d_Q9Ua*_p96j{cW1q%+0| zebMn4OnQ{Q!{8fFnRgCp6vexWQxr@(TTP1m#;$Xdr#18r=#7fkJ3U*Hv$YE8$0BU8 z)iUOYndeN*yFoLmE@$0x)Q*JN`yus#xXY;Wkyzq?X9#0)n#X2=WnQ9rpO{D(jVQq^ z&^81QU}C9<+gJ*)B2Zq;8`gjDQVUPtGYuDyb6Q}m!Dz!_aQKW-`}y{c;n@>tmTIKk zhJsad+oZvFL5RFV@(m~hUv6>SQnIY#Mv*{q9Jz~TJ(ECsH4N;*YO(Lc;QkHY4qrkilE2qC3@9jeL!2F&bWp zJyy1dKxQL2=QOIR2`)RZ+YQV7efD}#I|w2 zt9f>f;!R3qRhY%-WF8W)i*EUvk@hg8ubTXpFjMn0VlNoSy&vI=h-)U_B1lsh3cE-QhUAAFsf2Q_YKZ%z^ zqP;tuRcax3cbb%U#xzuw^-)4xO$NZE^>w2_+MSB-5Demq9Oe~HWhGT-Ab#Y^Y_n>3 zI_<&eu$83iRcqR#Bmog4YGc@94z;uI@YyE1x+Q} z0+|dy!sTT84K4X?=ZB*%)Q}4(OlFS$PeL9T89)f#v-_HQ|J{q{gwPpBqy%>bb$81= z#*5V1x4_vkxm1)o6(01bY5O%-(Oc}(_Lqj<$D2u3r3JX#1dhLX;*ZD>tiZ?&T!> z-Q>3|3PT`t)iG29@mGwUlK+f*o&>NdC+y8){^h0u`iAwsoL4)1jNMF>bi@Hp4Ljeq zK0P+F*w1a0qhV4-xrnzEeai}a3`QF7y3Ub_V0Y?O)dU@eHGFX5C!$Pb{4NMEYL5w8 zSAiR-AFc~jydzBe@x`zmNN?gCmcZFr&R{?Jf15Z-WJMSHGn`JFkj|q~`R}aTG1gPr zRdYUIpE_L;#A{eX7los&OoHmQvubGsDx zIPNU4`m}Wn*?y9q;JXT4QE~`MkZt8sJBp!ZcgV<4tM2oPu$q_80(E0r{TdBO+>)v* zt_^$S+1em`_owFp&@&HQIN2jRlnECIx@;#pA=HWf5N5t?WpJ2;_Ldg3uYE2v@YB*O zGDU2&*FBokT385RhOQr6ZLCde zdh}PpO+}MEr&8^|pDG!gq%sblcmFW}U@&&rw&SdEWB?>@?F@o{z_Yd?^x2!~wrn@= z=uvA;P~X}D-)ka@L8mJMkIXFJ;<*VhlkDBO(a(J3I&1d7mxmm>ARxcttLyg_7=42-3LKTtzL{`pKo z`H13`f9ysyOIRr7F!wt5nhy~z?E)kHICHY~$l)ta&gNMlAtJ_Z+b$DitW6VZR5XOb z;k0}-aI&t;M<%eU08{#e$q8INnn=$OM%JFx|3q8Gi^Vz*F{uE}JSFS~b#Z$8hwjz*ldyIdYT2C>AkA zO8z~>XqkKZ{7mQOuH+}AaR5DO#_e0_4(9h<0g|ReoUKlYJn7znfEhU|xX{k405gBy zV6>Nc-q1)tRYZEXmo*BzhbO7sY|v@tIG`fg(FQ_(rXC|XAQF-Rj*9%2cLHvp{G{D} zLneyg*#%lZdHHjGiF(|MowGSc2%I>|1r25ja}!M`Z(1a1`?V)4_0Z&VCc*A=4jd*a ztKZK{R!BBHcGiq9ykK1NF|&^bY!{ZeSLr`$wklF96Z4=}{u-i_u$uw;^6wJTf+EjK z0q{IP%haL`eTuYcdrop>|eIdfK#IW6%8^%o_ggWg144A?c5bN z^)4U`Pg@im^5w1(Mz9H$7;JSXxE_d3-%z!INlBHSY~QDY`HaxKn9W?1{Ar$E{HZCh zAt-hO-dd8C^m zZ4)QP7;L%6)vDYqN!~o*S!BFqgnvH}Up%#=o{4Aa+dOAEK2>am`-7{$)&&b{By>d_ zJJt+91t{jJ#+{X?$>#vdKar_?22cl3tcfs7$1qwUr;uu|_>s1bX)3ff1D)&T?nq5a zHjPkIq_qYgF`7IE#VQC~n0oKjCfGD#OBLjV0y_t7;J*$`Y}wd9H{6{ zZ~A3CI3?Bph>CzgJDTwT3JU4H29!YgqW_(ja@niRN-=m=G$r!= zXsX8Qz&2V8%FxPvlk96(G@*IU>0O`CbStaBWAYS8o!G12-ub&SWQ)QHV)E zL8nda??9ckE^y}TwcZim15S7TUN;IsuUY$U0hjPW{TAs?G3tIZOhrMX7I@`Bi9!ED z47ni+`ua}4dpM}NFo_TGjB%t7I!?0C`y(p#@@Fi8^#H|{&bGg$z3CWf1Rm)s%Sa#( z0X z@WE2L%mpM^KvthKkm(^HpL8TGA-5Ko)j}q_oe!Ct3l?|p<8BCi{LwO*3cFJ6%80fo zqVopyOml1Zppag@#$Y@A4o5j6>SQCgr179{T+!elYK++cm8R*cIrzdl7-KBX-~wEu zevbCD+NTa@pi#{MnQU(mSpThq@PmhRN>w&Mcq$+NqP!jEpD+zckS`V{xL*!DMI}%5 zLBWBYk{BS1z_;4EE6tL2N|cDCLLK{*Jn(nQC;;#OMD@cm=3NwQBAvB)CjhUPu-Ln} z2H^*-Oq3Q(yDAPPUK5J!Jk9)Xr)IJ3<$ITNKzepzlw&V^4S;S2kD^K1W8=y$Y&OgU z7$>a*0j9ZLJDv-o7~WETd))EP>XnOZYCih}wiPAw$to))H<7^Z4Jmjh_-)1ZsL{Mee8 zC2~4Z(_B4Ll39KWMSCa33r6yx<01rG{GXB{vNcCtLc9w*lRGrZipQKyQhx=_(i#S? zc($hD=e(FodrKV3ZZcMhaAvn(yNyHQ5wRjhpZm%G)ZT|a#Rxaz(5>P&{z0CtCk?wi z-BhEFUABYHkYmvJ2xf#ADf3wITXsP(aR;ubcjIpP6Gg%IbY}DtNi*B!wzIwk`%Dg` zI`|_}Ol$POX2UN{v=JLyui{k8FtgFOp9Xk0SUK76CvzrQHd6rWSa^x7i z>pO_*^B_iYEG+4vmoOK?Pg_d=6gk0&e%~h6M#@hW0NLXpmto}CiZX|Q1UY(nzrT6+ zL;wX|p7t+u!JKD(#5ekD1os?>r^i-4`hGmi_ylJsh{{23lOZ8anUOU^(HI)St#Dy4 z3L_hNI566uT4_O#h@q{Un}@0-?)zpef#S8^06YK-Gt;vOzl(Hw8oE8*lrm{C8U$eA zG=f?R4}*{rCy@|!UsUD4TZ;h%Ds8nCRAwj+O2*g$gu)B`fAj_g{ynW@WFlW6D8c!F zzF-vHsqjB7z?huCBYC)6%bE^GQ>FZ$dsQTwmRqWoXi*!zZ236-wNs9(WB zxK{uAZCHE&EANK&Gx9CyK_czy9U`c=rmD3hIF217m7RUZ^}iFlr?73?N$YLZXZSEHUnbT0v{yp9eLKv18WS$x-z4!7!6z+u0oDQz}SptTh6^}ND zs#s95T!EUk3z6-qYl$z^x*#MwWY{i3zCyG6UNP`FML` zcN-_#;1G)T0W=s~k;wiRn`oUCBzf_;sCHqDkc+Y1l?Q1}r|NFk$`DKcisT(kZXs)PwY!L)E_r z6ySM&IaKo@d~-rHwpE$Dw502?*vDR`RLwIa_U7CCQn;kS53o2a<}CnEm`a=9G>i(} z6CaAsLpDeD55M#@km`#+In^pH1UhBED{aP7^so&F5t>T!U}dbKx^0-3myP$`4uL`?=GMm#26LS$&b+!$s1uX*K# zUhi$3`I|A^R10eHx2Y%q@5F_Qtf5qQp@yHrmg|pUUx>g`E)dgBnn$CMTx80iM$rC8 zH;O!cKcyT05UmV%_d)(TRz2JvJo|jt+oi{k4pL%7)Y?Uz!FS+Y2J%)f#*h-a<((?b@*c(x+Qt7 z0eE}`?w*&FI%7E4x_F=DY;MRaqs&k@UCud#2ULmS393JR|J7P=FjEbD&S8R()nVd%H@?pfGPYK zm{%=6Zz!;hlMwaJzkSYpJ;u)NoSGp1I~VJkECFKABF%s?ZYavQ2YPmLD!V`x74u%T zw|w7^T-zqVBxf4=bta8Rt-bFEHvF9X?7rvgqV)|u~pBi_-S^3)LpgOOaO`thu4UBt|N*TW3gEJC}N;l4hN*0nNPPUg6 z^jVezoN(4_4Z+;{^_qx9v)3*p?wG0~_^7vhg&w-*JtWldBS*(Lds_Ng>dZD^X1vEi ztN}D?ywBH~0v;~bCzNDLqYuG-k9<4V6$d6Rhd#WA(|_6u*y3o6U0qXMH$?#=4XA!` zgx`%*A3(OqxL+FUtR^=fRy>i6DSjSJV^o7Jg}+7GBe*;o{SWkX5`WkA*Q#6p`oz^N zydwaSlyTB>M>;Ia=pNI?@y^ff-?Yv%@(O?=B22>8=hz@fSyQ4N0(TNUCn1i+(f-f0GT^pQH3nD;>$$Kd)05W`pK z4JC$@MO-BP4+uVK1s>*@D3cEZf&;`EFxgFfvF+hAv7r4{==xaDbJ9Vqin|2JeSv6# zw#HnFPd{H2T5L@?6qei>p#=gPWx?s33((yV$M_@bOX^y~#aks*2i%ilu<^mrL$SvHyOU-TZOLmxo?lK0?L)KN0bH_TkGPv7&o+d2#m>Y+NZsiHS2EF{GLs%0a z9aJ-D$i!0*qki~Q1GJur5G|P>Kv)NQ?JNKO{^SyPaWjy$KNRr+ELMj%5)N*8&~7`` z?~H@{UCHmND1C~rSOiG};}i8}KG8W^`t{@JX$n)O99t$}(qPXPG=SPDeMz0@8DX9;|(kyeJMd3IZK6l_6XSO z@?urQ(6h;ticikWsu?zIXp5Dy&_h4 zIOLl3z>Tmb!WO1-h&Dh95eKg#nc6?RKyiy)f^60Ap5#NF_7NXv^dUOkW=f z4;wvH%7HTHOSEDfeUGwfUqArRMJPl_eRnW{D9=L&zORF#R>$9Jno542x^0Y9zUV@Wqbd}6fjMTpFjUyquEX;u-Lz+ z;DNNUj+yLb0j`)T6%uoJELcPdcFpJNnY=Z_I=-W$So! zho)>bcR4GrxhcM7|A|i|Qsk(3dcilU#MiV=2C)Zy9QVv9PuW~!^Bcjb<$a?)$84^o z^jW{C=o-W>%YQJi%F}EB)CMtp3uMPAG=FrCs!<`tC?-fNGuYrSOe0q+KFF!1@dFZ&Aind1XBQH z)>JzhW)A-iWj=2Is?S(h{doq5bSFdUA-UQFY|GLmCAeRgv|294YYj7d%INl6Q3)Cs zwWUH^Yv%vsp=aU!R(+qLKwSM7QTFd&fo%8UH{{`0n5>QCSIJ%$`Yl057B#vO@(=V!*fZ@+vm0;D`e%vj!^~Qd z?BEWHLyc$lhHEnb6%@`tdXFurN?tof zZ6Br{pu?`Aqp2fK=H>TA7yMBj|829m^%!PUAsSXXEhe6oCIep93{O4d3SyFv&Ldu_ zbp1L(Chx&L|0c=MEhUjfF6Lx;D*xbw?VNI&X^ZPmzsr_g!r%erG(ZtGnpE;%XbDQ^&}Q+PaS*rJ{@DDc6&lLdD#3a{Vb*I%gnZ;i>AD6c_ymJ0{xS-A26P-KC6Dq!u7 z=2PdQQlO1=uZcOorDBlqxzZ_OSi)Lk~G3V<~NE|AEHDR>PGHk zk>V)ju>SXop*E(qCrf^JX*Ho#X)VHbfSNq*P(0vWF+-US3eGA3BwQbUgA0lU3+AA8 zz*aNZydLmwJc_s%u?Piks1N34M;OPZJB`Q}h>>TaOF{8}iUF2eQrkzTk^IQJ2SkqP za^jJ;QOTeo1AoI2S>(_remcv?QvxTy`5|!$l?KX>h3xBjQojL>DT1WtE;fuLUh&_X z9-)8m&463bApqougrDoy4Y_5&(#MJi4B*rO^dtx zKSt8q(wnGZkvW2>sQm)7R5yvt-)vZU-Kvf)pPk8mz4c-D0T*#Sv?U2c!cq;yRzhpy zcqqmFo*94i83S?<@b!%dmUNv)`z}Kxdf;p1J2*yH-!vis`sVvRY1@%LDltb3~5OL>pCx$GhqR$m__r3Hv!yKRB$EXzw0+T{N4jNu_f5DG~= zOj8mObNQ+cB;ZAz2vj1UX#H1J9@2_KH|5~0G;=iC(a*@%`4ia;2F06}o2`~Yh;Cq; zpnYZCK0w+XJ)hacRYs`DhV=kD(b#-JqvuoyhI$@q5L>cx@8d9NIowFF%lHhps3;+U%ymYtf87 z*~z;c0|k$WWOk<${8JTj4Dv5@#?3u&M#E<{k}tm6hWVwP{ z33D=yM4HbHI0RLP$kJj+R~Ss1rpR6SY>T7AU?>%DmUyjPx^Qt&EAs|BZ0KGzD zl+%w@)Ae>j$peX)^OLfD=9SS?x}}|F51MXre5KW+ta|9@!EI10^*{<|0~{*K57&nP z7(WhG3OZy~WFXI!CFJ_BA~F^Y14`?Y^eGqp^hz3~X>y1&1l_+pdQKFDW%b8`ng9{V zmZ(ih_YTA!hTg%^ru8!Z3>Q@ps7PNxYwi3R;;f#VQoJD=*+4(K@s9o#MC9Btswz<1wq-;y0Pc?n7R zkpAiz6>#G`iII$$f6h@ZNl!ekkNQ__TQyG83z@p^7V0Zw*1^(T{MtiQ3hoo9_3@`A zDr1Dy&Nj&&l@l%OKKHFNLM$+m0!9bxV&E9ZKt!1K8e6i_Ba0mM1N=*8jTJD)K#%rq zl0(kED7q8&nU9Q+FVG_8Iy~c1Dvn-Da~KqT9)W(J9;CXcu{!Io%z}&-{eF{TaH>tv z(!Egb**%5Qy25@fP0=4A|4KL$pzToIQKRdAWpDj}!0k61uT{|)QIge6d&(yn^-AN( z^}^Ooy9RkzvR~!yAi%DfK4Hk+&SAbUA#zfRbp`v>KbqZfC z&2XJ;>3~>lj%*lw?8h3s>e)}aZbv{8E_TukPb*|;WD1@(*)f0gr^Ozaou+F);TX8n zN+mG*o}@FTs$OhY{;>>-T=VmL7ZrE!hB`5uvY1Sv%8^F(#_@iwAZ!LN30ndO^Bgb_#w!70gqAu*{@SJ}oe^!6IBl_g%l zskC`$SX*gNJY;J05(|xW*)j0Spo%tJ6j&!T_|?C4Vt+9E;k{WyEWuL}#ZMI`*DEEG z=Uj_NpdrnDX5o9^337(g!bYGGit*c35@`M}aK7s7j0~(qi zqEvBOf;WXWhat5=ZiI7=LFVF*ax(|x5lzQA)%CotVel1K8sI@`)tx+p(g;xrDZa5A zW!g$c!&qx^I=p3VoULrRq~P1MG713{TW#IBrT2zH1Rt@bK-=3>*U)eJ)cjH3!3|RG zW@F{s&is8aX#cwNsMg4Xq8^UVk>SyUhtQn}fL9kvLYC0te{{pU4czp{fw^tS!*Oq_Y`BbJ8 z8U#1oc#PNVVR)A{DFbU;DZ{_P9EgNJnpAh{-;tvzj^*AdqVMd?4+&Y0H%SFiWF2B6 zDbu)S@BWd4UtS?9_$CbJFErTOXfSV3LDpe0_D!_3x(SSyj;lDuwwq!o^s|j2MtA8uyPSHKQH$=0xZ8NeN3%Z{ z6@2KMD)3!3qt8|oZNo^3XUW98p?U0F0z8Np%ta$=HD)qE6?HMyf(4w z9ycm(ET(y~ef!|U(~!(j5I9uo+-j+n`V7NE6v-x`uwOa1a-oQCS5F-d%Zu-A|L*iTJ&`)kjb?2F*Yr;T-ONwZ_R$p zb62URZ*(7gN*er6XV7|AMIxlu`EjjeUhK3eZE*_X1uC%+u}$%O3^9hehY9AhQS8Zi zy1r`PVI~oFM;@RYhK#2gUC#r0foPV`FyDv6&rYHO2ge@3OZ%n=7uXd+%5Mk^IEE zb2&;mh-Z~m4Izb$v6vHoTz&cSOp7pfReLS5Xqt4FmQrT=|D zLRJ*7?PFEZE=%GULIYPrSDH0GXJXcq3o02Q{i$5t{Mj84LQ1&B=$QJC20^V|Sw}*6 z(^T|${PsqL>dKDBrqEU1r=mFTeqR*(u5ve+A3^ZgrFb_$1ovN3{pvwA@R~w{B(@*y zqpd)=8!#eep>jx6h?o{(bzM#mGPS;ZdhfC8H<+sgOEJY9O@fF)vj92wiH_wdlP4_V z9n~s+UiNS1s6d1JWaQ>yXt^{Y6aBkDxR4kAFtPBB*wK=%f({EbDcyf`dOIU_@2z~u z#XGIakB`y((8-LaKai5$Wjx?#<+_IjCmkk7>AF|M2v>GskR^GF`j9>Zd6z_9kPbV8 zoPm{LAHCKnMhh*n`(ZyyQA4>O0I?MpeVY|FZ-S;1H%glw*9M(@od?DFY8ndbfdFZ< z@Sa+m0kPn^?*lHzljq1)DzEvLA$CKfu#!;j%X|Nr`ao}C#f^}!9%ev!> z&8DE^5Fd-Ds8*kfRCYce4MPfs9s0QE_;>aDs+cDTSeY|RRA(zD-ZR`?(Y}1=-6j4Wd%0a4i}H;1%1Loq z<~R0hRFa~ZrK56N`N_3;k8{~BOXTrG%DLsv8Q2HGm{DE*ESH9RXc$2>9&g9`p7s`& zV&7B6QqtaCVXc@}y{UOtj^CEb^}UdUv7yxab=FKZFnv6QbCovtF@rmE)OVCE0I!Bj z^l7&yZYslETd+>=`m8bfaCKllSsbdb{wuHO2Y+nrC06-6w7{Hn!5s@d;$3WF1YU*+ zu?x16I*;G0O0(Wp6b~rn*Z!;jqM=eu9VYWyb^@Wq@Z?8#q>gba@h6&rk|ImXwaNkw z$u=))8!rE`7kAZHD~n8Tq+Z#L7u^1&oqF4vi?Xk(bj*Zg$F6#gZL6S{n({sh=2HfV zxwRY`5*#@X6*B&!4evc0O+mI>&#W@WV7aXs8-KE!7tPP1=wbF4G`EvXFj7V!42xqc z@N0n!E&HG!Geu5!x2THNK@ zhrmt?S$$$2jwS`;sWEGhX{>dGllBS`)k(?Qj`n|!XOCJsG1ANKNJhSSYrw6e>=*uQ z>V=y99RpIPh#!Au8JM1JZM!K1d4-no7nzOTF_b;(#J zElE!E`GqwE)I!%Jgy6OngPdcDrt=AV;yFXlXL?z2Jec zMjQ-07wnU_kjPM@3rceLBx-$XadUP4^TiWVVznzB%9QTSd;SI>GDMQ*uXhWBbGI(&mqD|J)S3gHJqHzgzw~m-Ta52iI;mfR^bu zb|jx{tFX9biBpJnOe7qMZmKEr_r&!&cT5JW2iX1UiG`2HG)(D!f%!z_RiZ!QH%ADz zS287~*;p-vbxFvqa)&KRBCYDM;{ANw2yK+uR$NJv>f+YkGil{;% zGk`wSa@O8po*2i^#(hQquf4Z^t8#0*h8N4Fk_s#&MM7GT?nXkS!2m>3kWQC?v=Y)t zcZs0VDb1q0kxr2Y>8@{H``+$n-_QGff53Mf@BYby&APbOoadZ#%<~*$oS)IKf}VZy_kqPn;p(DNGL+-E=(T5tocq;s zNr++$3408$aSQRj4sb?wNM7E3bDfwZ(-n@nZ_CcnUq75;B6=u28Q4Djc>GTvZrBjsWsIp zAJ{y%#v|oC?I?_qtZLsu&-?0zyO9(IFk(3HqHjY_DF)+b=6!z)L`JQLr>UY>hP+;w zUztY|3pRb=ULZhsbIlI|icq2Y>|u3$mnb#@^R0@lQzVVUKN|*K1(fKAFK4w1cY{uQ~F_D>);=Wo|Uwbybhw z!Rov06X+YDO`)WpJ^Vy<{_s1;kF8)u=649B@H^@(Q;MYwIwINR6Rt(6o@k z%j2xo0~fOIOt12vgcX!uRDu-MPjWhbzP2x-n3H=nd#|`*bDqqhu-!+KXfE+@4wl?e zqdO-uF4nB$SikUEd51NPT%&kPc;<<=S^W16JMN;-><5+j@s5I8xw=5;cfAnOrr%>{4^8m$RJ`?kgv0yW7i81f}Vd*^@Z#hlvwtS%%EsT8M z3(xq#>^58v#SYnZo|NT1q?q3FJ$hcRP0h$m)RtyEt&X_ZVZY>Z1xbLLpnU91?})^_ z`av#C_#->Y;Xx#`QVXLndIX=Qy)vpPA1k58l7(>gAznnzeXeLScg28VU6&2>TRhc7 zXMIe+1|#LDgEcDsJLmZVD*Uf|j@_sD2%YXvk$rU1gGAz~Pgq%t@0*xl4JE>&;ZVV< zk)(FZ2MrfwB#?vg>q3c~H-YDZTsf3P zIXXTMR<&bpVUA)76hw8TC6t>_%9aiRX#vSRZQ5j5M7U}y^L%79T(IVop{}bfkca67 z-}eShlb;!nyi@gbLR27+*TG<7(9J+aGIV7_q#Ue!LaW$Brg$oj`_q4B|T< zLz~1k#4x&kYW+f*wnwVK6d3sKp)A6CLtuIcQ6RhmOU{4+SA>0Mi(m+(_@--(!mY>R{N!Xki#xV+rmKsT9!f^JEuF`Pti zipg-HQj0wLG^Oj5I(8q@r;$?R_4q5%veH29%Y7kHI?8(0yR;kCcGUOtU~%SRW2PbH ztUVjM`Y>Y9jvY4hPu zLaKh2tGZH5TQ@JaZek#(D;asN91~0f^$p6#d}iVhP=p1|?K!u8OtIlge&7CFZrYz- z>yYE(!<-3=FQ>37QJYE-rr9te1U-;ld_B%bJd(mr)^t|%F8B5P*xk1S)hr$;LojW?=h-te=YzID!2$C^|B+yp21?qW9%6%fE)NipqS$f!H5s>6xV zeQT!k{#VPj_KKc@UsIqDTEjiP;||j~tB$*#Pe#B+jx0)fHCgjj+N{L-Z7@GPQ+CKN zrwOiaB1b`C?^CmDUdo>Nv+QSI#ZNwo2fVX}>yC_dYtqo)L`M(+3{{Mi@X%Z zfs*dYK#WNgWpkG{Hty_KH_)5o24s|iuDg%yp7b8>fc)s!{at^fd}%Hr)g&NfQh5U! z6q_rk6I1y1^lY zV6;DDGAXE~s5A#}ln!fWYt!SgHjkEoEz=uVVBJ#t^6DEuMvhtEBQc7OY!qT@opC3fVjA41137Nu^mYL z#;du`!?x8+YsrusJE>k4tCIhF{>JHOs~E8|5ZWZ)25TJGi74Kk= zOnU^x6@mmwP21-{B*FZwP3Nu>EFW_{bUUG49{Z}jY20@rjB6H(j`_7Gs|5gj!~g(^ zl?L0!1Yw@CUi9hdEa>|cdS4LoquuIptmUSrUs(ILz?>d+v zqozYO(iPVO?%m)?m_8``ew9^0@dwuII6~(|lag1lPgoe(O z)LS1;sdF(p_laEDxpj-*SiFmZJ^m243s|7MEP@4Pt-LW`V`0fKlip;?X@E84?n!B& z;BvR^r1c|CBQ=znL0JS<~N*Vsw*276! zO4PPOd25&JV~dIylDlSZ~S&Zmm-I; z2=)>t=TiCP&ZY!0XXXh~qLZq-AF9z#3~U2l;s+z5x?*t3>}Ofv z(5oiH-U+(acmOl@c3lO0roU{nL3z|3y&;7pv{SuU&A(u2d2jJ3p>c0R9&-Kl{g!B?fPJ zY&BhqX2pUWr#M5$QA?{28c=oceONN1ux3*dlY;yFOYF%5$ywZYz}}(9z_3=9VnV+QR`LcT^(UeXUvUd6CMw(POq;WZap4l{$qE;Ap$?!6Mz;3cEy6BtDi z)Wd!+u>d%De8^Hk6kJ?@1%kxynWOEgJ(Mb7qAkpCatRVe9xQ0a#KueN1Ab@lX@1V2 zgL)AWx?2mWbM@YTf-C*SF0dOEn$>dz#fGjtA3P%6)bevv^@bWmJY(z`)HVUv^d4`p zbl-4c*pmF+8Tn=X11#eo;~zb0Xsmv#K91YQ*Pb*%xka2EhBv zPNv^@*I;UmHc3Bh)wDU$gDckd>o(lF@>CD=w_-O9+V=u99U_OIk>$oqzBt{3q8J~j zIvvHzn($yO`cY~uticmf2w&^%{_#?F4k3QpRoM5)N}ZMgJHg81^3WsyhyBF+SJwXY z{KPMq7H7r2eD$Bf++7C}&>91vMGA%U@KLHgZm3a>KsM0o#H7X5fO4PQS^_wvdCA(n zODOppFhBKKo9t3_a%g<82m?+-v;``#y9WyRVF~dMJUN{pj$)bmGp4>oF|LB>B7%k% zHu8vA(nTn?dr8P!GsG0k-K?awbBV}fdJ|o0VuI! zkVqYUX`+jAB054_*&A|iK$!=m9p8v%$vO~HE6H*hSb2cE&Ac}fj}oD-*mj)6$4kR> zybD^M9X)?Z@UX8%{H#&jk|m_2EP)eqjqJ>6(OR0Yi2~;~VixS}6gX493aM8xcz#{1 z_g=69bN`vP5Mk7`^HQ?_N7q-(Z{sE2Z@4$#EKa^kLOq>-@x-tq#1o4@5-R#ph>s}O zT_1kcg*wWmxs4VIpSh8D?+1=t>!r!!Phk)w=~ zcWasL^vA!ZQ-6SY)^IO|A-*qC`Zjxh)j|}g%bD@;N2g19ne0b+l^lS)S*ZK;R{nDt zp%7J1rRYrS<+*%<-7dgU5VtO;**5liw^+Y<*0YKGi%j`I#_1ygJ0Qeg<1dNca~MDV z%EA1K_5^JG%@TH+u|NkbMqXwrJKLI22*yj)xFMC7P4y!;?yV2?~|qJbJb8M zPXMRrFcU7sDJWGm>uB8U>j9wYZsnyBlKI(J465Y8OeLJ5df{F=46MhDo*bTdI((1p zJp#*hCDtOTn=7o*-)6RLqogtXf~O#gs~Q?Fl%eAFf>~;+&oz;R8BAxahH7wA!W(%{ z{;tX(SEX;xd3UiHPs@9viDLGq!jw4B_w*2l-;^wVG}VwU6PQj9Yv3N%2Rty_$qW-E zE{DY~byTd`8DiA2!5rqXoFfCFx|XhHf~T}F>N~dr-Z_m^;|m#$0I?mvd-*VjJ;F(4 zZg>MUQs}8Xq$AR2wRp!>^!t5LrCezjV%bolrS3ijeT7*^B=a0lrH2NtF);Eu_M?^D zF>QbdxqQV}mL=gj>QU?^XWGjFC1H8RhOyZnKI#>W!4xF!F6F6)8va))aVjcLxLXOa z491|f#3b?{0>?l*;$3aj8W}QW4IJqHz3)&1OkrJaAON@+hB`DQ^=q-Vg6*;$P%n`$$F+bR)Z)A!M8>^3 zI$2w`0t}Wyy=v^Hd~6eDZg9fYej7&kyT2FCQwx1oe>;p5K1Ty^8Y@2RHjrK0X+$fT z4bEceCwbYz=mmAO`wwmH0&L4edJzWn9TA$S?YsxnJ`$ei{5gwC-SiSc!S8R131F8w z3;==&Nh|js2u$d3c0XN4TSi^kPkPt088wI;&^?PMELc8XN(n_eFk~O?nb=HuS!-=a_I3rx$7yeFzGnA8!1r*nPj*M7PL|B`{2#P8@S+e zbJkbtoH0Ar*?*jLNJmN;1xW;(`WuWj*^u9(D#4XgLw|qS9xfnDgFw^1YbSii*rM-! z1$C=ZNqXjsOA@HnJR|yPwDLi`H?c|B?mZsghx;twG&L7>I;#o42xH`w_i4A7zXDzX zUFP?nUTZq~=|D82r4`KfG45E9VjjBHlt{fOG?W2;r*Yhj)@M7`R8Q6z_?+x`{kJ|8 zl1RcVRFcIVOf-1m)i`y4H`H7q#K{6$ZDf&JVAW%A?m|dz)Z+jEkTkuuPkRk#q1&*} zyxzt+-OjDWH(HxDkyn(Tfr!!zK(W`E@ky(d=@%zzGH<>esrso+YEaL_7-=$wY=(&=cwC-km;`fRS{R2X_Qp#CXFsF@d9ayjyw1T%Ht^v8B3Zq_`Ao z`DDynnhEWzJ`hHQW(#ei*Zf7th6~r>WHvA&veMyUkJabI$9>)~Le+~D4`l5->QRWV z_q%#6FyIj6P{zE-{Bn~Toy1M8i{%4TXTdez|Gh}vJ;k3|9Cg58pS)!vUeB79(z}3yCWqWa3ty77)LBAvXLcYql*19GIc3I`@F$0 zxQ=&!&|C#vXmQ-~VEZ_Jq&m}Vxw7mKSdfHLsF^-QR{003dS9uY8T-&k`~Fb4dQ3Av zorv#a0pyoudS36)JP>)>Qbf>cp`%EUkZtC^#Tf4REy4K*AVQPfiuyp(c1l14n%d-% z^IHjq>ifTvppx?B&?1Jo-8Sfs4|eZ)d1damKPa@c1!KZd>3_ zcGBYNUr9O^zMtz9{fV|qlH(M(PKoNbd!w-LR~E3yP|K{hXSS%3{+{M{cJzBf#ToUX z@M8oK_OCuJ8)kSc*PKSE{9Ojt3V#wd_*LQ&0MoWU8An9=vuTr7|Jpil_N7R`R?O3E z1BbyCC$O<6*anqfYL(j>O!lFD8UX!_WUIKF0c*)AQ?V9Hr28edJPQNF8CHUxVPa|GrVF+RG*cOgVH9a{>?AUpuS@AmdOY9`^XJX{ zty#8BVesB_8{2?klU;GTpG#`lJY0euZpqZ=XqOaQHL56uG5x8rEN)RF2K|LV0>j6d zAt9{dX=|j+wr6mc&b{|)^N;u4d5t7nj(?Y3e;Y7S876@ zYb_=rqhf6`x?fGN1%0jVCBWv$`c>28Ak!Aw>%#BIxGMiTk7SOpLk!bI6+Ii__$q!g zji+TiOprzjPV`V+e6_W>;ba#q&fpQ_qz)bM^QWmf`Ee=fPJRv86s^~9+e*-1ZLL?| zHV!_BbOxpz9YY17y-GeQ&SRHI>Tfq3kEK!97=t5y+wW2xZ+Oq`=% z6%m@fJC-XrUFXaEBF_)7oJMH9<gLln7_B^tr<=yi_6 z^30w?iy|U+@5KpQ^m#eMLg;p&Bbf!^aO0D_Czp)oIM1;PYU#_Gu8SYlvvOcxEwYWP zz{Sv+>`D^mHxGC`_SgXZz+R93pH>C_H`sN>M`& z#~#w=^4^z}X?NZ3vz=&daa(_OmlJ>VPN5}x_(D!k!Nbh;Q+^S1J#83gU||53xDg3X z$ICR1*yy)Wm4y1cUbRo?H8}z$_|W*3#d8MXo``QCH*#Yc7Gn8b3ycDCo| zA!|>i1Vqa3H%anp!QzL0gPx)_6(|ixzPgSU1ALQDgHWR->cERR}oPn z3|MsVJxacXh|faSAzFcbt(y5eD^>Q`1}U^?qQgBHwSJp!`S*1My{j|A(j}8DUDw&c&c$s-|y+&gj6q&=%RjvO=&E5_@4L zh0l7rHzPiH>wEg#CT2FHk-OxQPsR4)sW4Gb;=|D-&D>_)7jDVpiRPs-RlgM-y+Vb- z$3B`Wg^sFkWT1lUVaFEB#tp-2*`;)2?Fv*i@=Uqem)x=0|IA(FU!dBwWr)W^R z#1P?pS6&UUT=1e>?C%AJ5@Ak3N?(2UibHF6tiL}WF9(YujrBx6r*<@=>J(+&?c;h7 z*!7@wIZp23{U+;ZeV#pkJahJvGK(pN>_8TQ1Lci1Nz@NO`rpn)3pW zm1(TyriR$7_SOwu*y7etIu><1&;I&?&}a0k5ga6pXcB90`z7|Ku7?=B*-RQihtq8A zUP1)u{a#4eNLo(hu`B2=@aX8XT;bP8Iwgq~aUf$3jS+anULedGt=7lDrw)ag&dJ={ z@Bb<5&uxNhtik2^VJNxHkwT{u=GDG(BReawxS)@L@7kzLZFV{@`ysVn&_9;6N#`rA zY8#k(`aT4_{VKlpWyQ8ACdV1D;N-hj`AlNOd)koV@9()!?b#XywCODCz&KS4k2dq> z{mEO{FAcaI*x}Fg+)$$+_1ZY_S)rJuWk|t~&U9tytHxEf{|pg$ZQo>=gKIrly zmwO3KQIDJb7x0~uu<&orLaJYS5(!O~`HR3A!#vyGC7ORe$qb5lAr%8rfIkXg(Um;UOqG=6ABNszb4FEorV zc7T3PTIK^}v=PqL+*iNlOUL1lz$B~&SzW)7|^Nah(d)P(z*xvH~ z*oIENeNs>99g9od1&@x5y4Rt(tpkq3y-6W4YDxGAi*xZd21!q z#riyD^SuC{+Q`?|HtT!iSbchsrGEkBCt5EL#vAmJtX`I3?|@S2r9`A?jVjPyu>s_{ z2geuW zDTxGrX)!l$vTjPl?>?lyilbZYWH)O1DY!^G%-f|2)4;BKGp@URuYI%nJajj=weno= zwMf$DK|8NN%*DXvRLJ)w3$}#3kJGm{mI5wR66%vy5l(B{!_^xLLP=|=95;t*x4U&+ zz9O5Rdog^I+Mx@HHtcc}V>&XaLn}J@MrL@4J0%x0D=tFA?s?}<-(73?Y&wU=R)oNx za@%}8HS|h*ynOk(pUVO(dNhblAAFI5nMZ+T!a(sX%g z$;Yk7>-(ZfHs>#mk}HoCTL%w^dk>5dSb0U!s!V-WbURMQaBu@s*fWyx%Q1XAVO6iY z*qqEwz#`mMdLvxsir(pQ(R;oAUnQv7H9q{Z8?MIJS|i1OjEJ?p$!1@$NXdC}UN_;L zH<3{|v8{`29`2dU^+2)c9m|EO6}TA=cA}nsmsic27j&LrwBA5Y9xUQk{!Uz5SZtPo zCD?jk?h(5|u;Yc98<0$25=8W|M6%Ufk(IrdAJrx*(tv= z@ONI@tl8IXbr5mHW$sY%P&thD<}j0bykEQ=FT=j2%zmP4JkE%b#25H{&9Yl>uVygQ zDXX%>($;aH%q(f|bpi}Eu4t1YQ5v(sQ{N#vY}K{K%a`e3=J3hQ(sIOvdDo+=!uDHL z0-0U@nP6sX&FZGH)Ra;J!=ZpwhOTjC(&p>xbIrBO^P}Wd)5|V09QEm!Whw6LPgV

V8hNrXK+6!U2oIG-=O88z5o^z5oym7*MOr8 z{>`p8&vG<5iJRRsD1LP-{EgzMy|8G*CR^sRUIV#zLTa{VE+SrX7T7ajujSXdzcv!; zy2wu0=CS4ewhItScb0D-!R21o=~4q%(x>Gl(WUalO<4aX4~&lWvjSs%zpzR z2?tCjBGaDYI}a5!&>~`5%R7Fao^@&`A?)g1A=`yNF0Qxv3yFP1IrLWSGxDpRo7zOJ z9kL8=o>Ugj2??(kJSg98p?G$JcS~L)ut&o{EjfL+QM(l=$ZkPBV?*YZ#m6IA@-$u~ zSQg1c&g_(@(&o>y0IJ~sV3AQPJk9r}YQ(rR+Q)1#vpFw3uRqzb`cmcPl*}O?*$9;T zZs>~RHlqIaG!txJITPEGi%B0`HeMx($a!NZ_4kpry&MYUiI%W$^$82!&O%*a6S=>7 zva}y*1vbYzebA-hj_@$HXt$cig>p)6tNK{cg8CTP@%g)AIgQo_zFO6+DlDnHv?Msr zHTW2S8u4aZnx$M*(I<`6{ikJ zL~~fAw1HJ6MV1kMb z(h(VL?8Bdv{*BU93j4^-*FdS{osdvZtuyQA63Y9sCH;+-s$+M%y);4*3O}k zx0frzYw?*m4@!uZNAhb^?=biV60@zwW-rSPeT^VS{T`-zkiVHY9|~*3WE;3lT2;Z| z5BQxmD3Sa;lgXq1c-ZA3x%$+#a9vj6B!$3i zOzkIhlP|S&%BmV!s#MKtrc*m?yC*Fc7TL{7>I#+ZWWMQUxuuVqHH>X&ezz#2N?CV3 zb0u?E8|5r+5{^9Y?gZbKTwld{j zVV|C_{upK%>0}=CH!ga7&v0gq%<H(Ej9JNC3y?LdZw&C@zK4fz%pcfco#|y3hO%cXL78;N|0uSKu+z(Zk%=7v z_DHdH;1R&S?2OzlivJ)~vEu*5k#;rli_3;w4X|j`C>dqCw?`&jYrV00SlX$x1g>&8 zAhf$5eR2@r{G5V{GSe_u6weE6p*AvdS*1f*c1O6>YE;R74tc$4+N_i$g!(+AttR}f zq$b4}leOcTR-91l;N?j_mCJr1p$2R5pQ{hpA$hzdPA}xwbV^J$Dwjnt19ym$HsvVK zYi09MlKpQvmR$RjyPSGLvn=~B6x60r=Vr`AU)CZ@U;JxV{6GHb#Rr|Tg#X9S|GDbX zQG5B~13(*g-HQ9q{ru1I^XG{9>zBb}uKeG}{J)RD|DVSul70)=MtOreA43jsL7@y} z)vFchN)Z=No-mGi(I87<^|;J@_fNX%?}MC4291(uRy2XqB&z!2-RaaEu>4pVZ3C@{gw{dcVS92RM(@r6@Wnop9G|5H5b&`61=`IL^|~^+0u#W11uBpSFQ~spk@Gkv8XmR%-+!o-x&U16WpU

_&M#szsd3IOcovM9&2b=>RWPM;=`CDnS{K~VtE zv=#Jbg8qB%ObJX$uuE954eTb90Tq`Wk(1~`KSKZM$Mx#xAcI!|A=!Xd){-E8Od(V zPeCv@%1fl7ZN*47AAv!WP=N!^!c9<8o7PMosrikX1F12}(@UU3y>Ya~8UdIN6}H>W zByt#ya$-9l3xI5<)zEZ@RkMJ)`eHx-Ce`_}TkSziPUnq!*ITwcMj{qloNx=aN)>`0ftFd)w3hO*9bDi@OKQn+d1C5|_0C}iVikRpmfY)=59*2&B-vX9EW^ZI`p6XKI8WF=A zGMZ-UH{P(K_Q}?kDX@d4a@XM^%Gj4}I5Y2zxqi3Gn6qwGjyqvGh z!2d`FP41o#7@1oA5<+Ok-`_>kxwHh48Ig$02XQw5)^V*Zpf&kGEm4eGmwHpEKvwd* zI=^prD)3dhH|x6$*u7Y}Bk0n;K^1XIv5W1{*2MM|mx zxsqW+EPzn}{XIk=UpCQ+-<2U1V_0mM854#PNLie8wJnr;-U z=|x7fY7z2*L`>`ku&$CHI$(@Oua6Zsg4Qr(FL3A;FyMZrSwy`OX%Ylxz5iTy!8WSD zhqZ^zlc;?Nxz(?KpK&(|hLrpi5YZ$#*zpC|iCZHvh?q~3V2zuKFm9?tBSz;r#-@F2 zjEuelkrThJ184U)xR?h~`L6Up7IG$6zMLM|K;w6t5b6WRLc}D~r}*z7Fumr*CFKRA z>^!L=k%YuOHg5+LurVs`GfThx>()8XkgBRbiJ1#wCbT}L2w+{$8MC`+z21D#AgY=r z(Ez2KH1F&X-1V%MF$4Y+H$ctuW`jIq64BKwu_uPuLHe_x*9@k|F24sdyH7p!L&nm- z@tCR&m;#K*=n&C^(ZXxR7u5I1gn|DO=SXIvPOYo6CZO|S*O&i)y$=4mW2oo>Y1JqY zgzdcZY+RAf&ZY`^VOxK74(v$xs@tJXQgcw&0Ay+KPC+sNXXh@yz(&d7Pfj1W4^#Kw z=l);F&`TTHhR0J4E}+*Yv7+Sj6gpJ7LZQ8Dn*f|EV(!t=P*8Hf5vwOaK_Kv^21@01 z#q(NxUYh|W4+Cfsw~o!$0RynAX~y4Pi`@w%*1$HHM3c0H*z^{*zGz=^EpW1vW1}|0 z#?29SqWSlZuSo87I}HtyaGWjDr)Q5l}-$N@>8ZXH*W3>y{oP42fgq6|j-v0lmo4qpZcQIHWrul#1)Fft&3O zsw4Du?0RM*roX57PdEgLc+sZ8-T^n+SH2Lb-{ALTg~51n=yX-KqLev7_fw)Y=Gh%G{NE;PJJ39ooJzgL(KZYj|e-+gla4A-?Pp! zhR}&oJV0)pfC!F&vJnG=Wx3Fcun>ZgBGpKxl@9!GY&K6jTlrGwh!p}H`azyj7{c%W z%D)g1YJxa{+CMddgxk*os3BOS2b9@u4!8yJWN$+J5(77rzvdWx_;2(drU0Pcea>BI z1uiQ}q_uW|j? eFoChTyvZ3=8(>mheFOvl$;&89=Sk_m`+op63n0t@ diff --git a/docs/proposal/.assets/001-02.drawio b/docs/proposal/.assets/001-02.drawio new file mode 100644 index 00000000..e87a4da3 --- /dev/null +++ b/docs/proposal/.assets/001-02.drawio @@ -0,0 +1 @@ +7Ztbc6M2FIB/jWbah2SQhAA/+rbdmaZNut6Zbh4xyDYNRh4ir+3++kpGYJDkeNPgS2s7mQQdXYDznSN0DjLA/fn6lzxczH5jMU0BcuI1wAOAEPRdV/yTkk0h6WAlmOZJrBrtBKPkb6qEjpIuk5i+NhpyxlKeLJrCiGUZjXhDFuY5WzWbTVjaPOsinFJDMIrC1JT+mcR8VkgD5O/kn2kynZVnhl6nqJmHZWN1J6+zMGarmggPAe7njPHiaL7u01Qqr9RL0e/TntrqwnKa8R/p8OUJr1d3vz4/Pj0PvqGHh8Fw9eWuo2h8D9OlumN1tXxTqiBnyyymchQH4N5qlnA6WoSRrF0J6EI24/NUlKA4fH2hPJqptpMkTUdqoHDJmRSxjCvK0FNN+ixluRBkLKNyCJ6zF6oJ1WXSnNP1XgXASq3CHimbU55vRJOyA1RolCkiR5FZ7cCSjpLNalCJr4ShMqZpNfZO3+JAqfw96ieG+hchE793Qr0f4lDTM3LKshqrwQlqEADCFMaE+gYJUdPxfBx6drItEMLEbRByPWgQgshCyD0aIM/0jyEBAQE9DIa+/NvrgaEHBMmeIw+CAegOZZteF3RwS84ELZ4jNZ2IiaqbJtNMCDlbaJyJKIeqNqUT3pIb4aYbkcCERIgFEjyeG/kGpdEfD4buxQy8kIfRJk0EhBwfJjAucD2MK0EYvUy3EB+XXAxT+ZMiQzRSwV5SJlx1pagNSKQJyUMWT8IWSJ2jMQoMRr+HPPne3jwHkaHIt+e5OKTBJLLNc14U0PFEm+deWSrvsBUfCjQ8pXZqeHwLHUSORadz8yDtWeSigx6ET+pBsFyv1CAJhWyW2flcaDKZoMjqQrE39oi+VGjRhbAPL8uFoAMNPF9pFsn7ucIpzi3XZJfDBxl8Pi/DFU3O6D5BRO3uMw6IS/QYqkU8BF4cHmzgud9+2sPjaXjwITxE/qhONXnxsXrV9rMHm/4UmydxnLYU3Far8MvhaUktiLCo+wn0OmAYgB4EXbiVDIC4WBlVIdANPkb7PxExIctS4sQRE3TMzMNjb3TNCz49ZEL+uUMm6JjZh1vMVPLB7tlnODPt8Dga/fQ4/ktmopEz4iyX6WVxtHnldP7zNbuXHk/Z3OvU8ZSZkjhLPKU7y/tjrDb4aPHUBbiXmZO4xVMXxAea6YhbPHVBeMx0xMnjqb0Rz3EDrTZ4BhfH00xfbF88OaDT376KckF3G2H1+vJtlKzCIBh+jPZFxlNEe5HrQstK3QYHHu09IYRm9mILpS8pVEHu/4+FHttaWXgnZmFmHkY0zIXukDPMpnKJfMULcaItxF0X3xOT2WmX4tBMR5wl0j2wFP+B5V8bhPwmITHfWQid+OljpiL6YTS7ak+CRPckdAGeZCYlrjlnpHtScH5PMrMOBhqaxV25eRFU+99qKJrc9I1eQjP55pusvCdl8Vn13BYGa9WzKG3K0jrhtW6i9Fyr2XWShbJPcd00NrZQanzEvbFlHtE31FLuhONhPqX8Lf0V7xVM5PVkum0Tn5LlNC3coX55NsrqDE8skQmHKgzX1juepw1R3KnqtbMVcyB9CwjUBio0YQy0Nbrqtj9ih2Z65WaH1Ya/g3ZYGOzNDD9qhsjMIrVqhsqcYN2YKtOym9POdOuGW7PjPabbohlW8eTNDk9lh2a67DjT4fts6t/Y71key0V66maHe+1QFHdf9iia774yg4f/AA== \ No newline at end of file diff --git a/docs/proposal/.assets/001-02.png b/docs/proposal/.assets/001-02.png new file mode 100644 index 0000000000000000000000000000000000000000..488c0a4e466c681c8829f602f0555b8c293b7a6d GIT binary patch literal 99270 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

+0u=#wa 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 \ No newline at end of file diff --git a/docs/proposal/.assets/001-03.png b/docs/proposal/.assets/001-03.png new file mode 100644 index 0000000000000000000000000000000000000000..7626ab790843e20a939a2093bec37ddef2bc206b GIT binary patch literal 156762 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

!&qzB>QEcB^S6`GT-+o7 zj`Q%X_K~V=uT1-8y>;qbYukLprHe6vVxLps#R%M#VkH5MVUpp!l;&+OO-MXN+1g9p zGiNmrf$_j5`?&<44K94hfp^&BFU_?-J^YCM?svblY15|KisdV;zI(lObgbvX8Z>B- zjTt%2MvfS6+l(1yTaVw_#*P_fV+J)?XH*G7X}M$7LR-_a##XFqu_de8xwvM}o^7v9 z{|gU~=U#f*mMmFfef##cb?e%B@E$e!NIT}ZQ#l&uO6<+r89F|@|P^#A}M07*naR4*Nd=!L7D#f2LWBNrl~%)pGzwY0QY@8%|Z_pZCxeg_P&wsY5Q>WUjS+i{E(xnXSx^?SjLxv2oop;>c4nE|)Hu=2=Sl?ba zQ zjaKsPQDsbW`1m{yT9&UNga^QJsU39DMHkt1*Ij4NJoAjLUcH+4j;wIoZMU`Ux8L4& z*kK3TW}9tTCF5oFUDKjeBHm_ryN1zTJk<;!{SZL`f-8#ito1F#XphS*lU>uun$QPzK}G1jZ6w@0Kl8gwdFFL>FO zE?#8w*L31Ke)j1n?Ww1pvKL;O&b8gOYn|2BcCiEZ-OEn?_($xJBabgXTi9v?wbrH7 z@n4G-LyFru27-Pjp)FH1Ld!I7_)xjuk;VmwGpeXX`+5X8k{Mv~0@YCmXPVh_&pl_C z{^An5{kB`})fuxGSYcj`9y!dm-)>vmdBR>ccH3=j@ZiDRx0;(8tOpEeyET?GSSp;V z2$Hd$Uw-*zd*Ou_?CGbUwnra%n3cMnb{KE{25x05SFW)8?!DJ`+G$5SZt{EWLm&I3 zHTLXXs(Jx`BEWoZj|b{I*RDLG`j)pND*=baR3Y8EHsRywqXi~kYRzwGTWqgfKiV1x z9bkjNUWxPntrk7}o!3*9LC5sV8?19(vyFM*ltdY&S4D7GMXQB!&Y^ulyJ3`8{cq~~ zazkh>2l}yH5Nz%7?_`7o@ERUSK{g#5`gNCIY*$}*y-j)MdF$M{#@4P~YeNPPwjH-0 zZ+q{xhi$*puJ*3&cd+5Zho{LXjjUX$UmGiNe;!hyTPyT;j( z?>*Q)^>6=S-FpZC)}C+>(L0Bm^omrLm25dSn4%U(5ksTQi7vVY6-WC1xS=1h2@pP; zmo{J>j>6zzvu72~1((=*LKO!1lScdXuYYYn_`wetaABk0X{ViR^5n_((T{$VExCX6 zg#-7=C!b{2im`nB@yB^k;xK4xYO>>w`+!Y8@(7!>!|;+#{gwos7~~`KtRO9)MXh`z z&;B@|l)`Np*}JQvlJynlv{-ATHsYRL`=NN?vIh@rK?&D^@%!1&e#Srz2O@$j1QwW+ zd+f0XD~e;rjQQKcD1a<+Vx3ECM?!VPGeLaJeSGljHg2#rOJ>cLg!V53t289J)|J>%!UtqOey4ZQ&{g!>~grn02g3TmaSZDtX&`x`~<1XA7!Bck%C>Nsx zClR=zzm1Itn;@yepUEv$hZkOMKmF-XZTxoQtgUsmEnK|J zPCn(6_TdkInAtcF@yw5Z{YG)dj2U(SCPCT0)m2y7?YG~~%n8*MR6-6q=m0z8)DPQs zMEbw&+kv!v>8&H~zgSYK7lo>k6WIFh=tVkFXth4q~s6 zt_sO~Fi?Vb4aN`aR@6qv7O*nZy|3MP zf*u~|n^NF~=So~mJ4L1*e&kX6;SYakzy0lR89;vKl#kf=&ijFN>F%`l%;mNPIk7#ki4_?kKFQi!R@zCYpJBJ$dK^eK=yFaph_ubc8*Q{py>5MOY-adKyXa9k_{O5fX?U?h=Ki}@S;|`X;`}gZ- z?>piM`_?&MwSkSEwIUD`D*}fg4#QZQE|y@iL6f-?jKT2FteU`DTyoL?gF=crO6UhI zim1iGYRDY>-cNpM-#`DSoQo%(cp?LjH}i#R(#<#DY`^^FFWK6{b-m}{1MTcDooRbc z+P`#Z!UPqi<<$-)HP%}#l6%JpwqI;9!;R0{?c8*_L>cgweSF8r$eF$voy4w>^ zJ?X1@?jW zPxjWG)8v&<0bhbKDF%1MCU|hdsuAe#(A;pxRqmT$KP`5q3PjmFxQRFtRG2!}*s9ib zcEr)g+XH`kge|(W&N|CJ@{y0Es;5lYB5?JMoRqi^B#pJ*>`xEeXaDv8eq@h4@syo< z>S^}cjG4sL{rJ0IvqKMjY~Wb?iGq#~V2p{?Xrh`I>>YzHPB>`!Tc@ykuI*(}W%d1s#7HdpYAIdI4~;f)WNA zC6qL~n5~5LZpcz`KD4j351w!$aT@*m_qWqdJI%iGm9PAxxAew*zN5wd^xy;bp^u+x z^A{{M^!l;U^3Vgu0Ku7PbI1s>U}<3;M7>zyfhD*z7%EYP74RV|%{JKSJ7!OP(oXyQ zS=PF4BP&8EVSoGFbL`7!f3@6?<&7DU|Ix3YPmIh689e&!6L#6res;lyHevTYQ;P#* zN2OMmvCoHI@Rk?+9;X?{r;-hCaY+>GhKzpKo72`zvHbeD8bT<0k*Mdm#$%(qJck z_#^DQe)X&`**DHS%@55W+b#R&G7k*&-B%_*6frd_`4V7IP;M-I$Di){ot<#fsdoGc z|7tJ3_!7aiKmPHL-@2Q8g@^mV0}t3|Kl^X?{PQo^LI1L!-ErfU)~RzRXR5d_$Yv7V zuv7<)5AzP9NFKzM$w_3 z=FOXD6DLlz%PzjqhL0Rka%T3*4OuNZG_m1R!^VAC=qBo*T^w$r=Hd;~f}j?MOM%OT z4atOO?P#9?dw{kD@Di6_e)${LhWckcr>icz$WA)t)5M1%Xc{>PIG~R7^^qp7wsX|X z5p`dzD_s7R8=uk-h~HjtTJ z{mYB&-_QJt9e3>e?a{}l*bzq@!FkDm73-}hv~axDL@?=mvwDa=$}R)#CzpJecMr9B zfL(KK8p*jk)gSYDQ%x6}enn4fLVIPx4@1_DDja3%xoy6YBj5nr1%aJ1dZ#4nfCb$XZ2^ptME5F)f8BD+ zEyQhru8L~q4L96CorkyM3k;D14?K|Z*rWH|Zli{8mV7+Y9#&tIRmp!a$_~caS zh?S(b+c<9FdaE+%c=d*{w!USqjXC;7>x@l>bXiwjtfb>F)I0_$QW<$jIL(l#W0)x+ z0D;tSNymTReJ0r>k3Poo`jJN-SshaY*-y(tGFmS9#g+EztFPM7{w_#_v5ciz0w>)X zobHRz2!N?uYbsYq6E|*XaQZBP0$+LY&o*)Y_t?oNf5OiHfB(gn3V@>3@Y-+ReeKc5 z9wQTG;%+;p?1z3fUY3?!do(-4jpJ}6P1{S@wCBSUH{3;2&NeY~}A`h0S%sDHq zc{h1PaD(}`)mB^CyWaIKVou)fFC3U)(=;~puvezPR5~zmW5pIT*YYxVh7R<1il@1u zTrt@|AY9+qX3U&v<9FWOcHLuj_w6IL<4X`Wrrv78NSN(Fd%f#im`^WIacJ$Oi8BPJ88TGi_eG z@m~abBQMf8bBQwZ61B}|3GE0dA;UM*%`!UD7 zpZJZ39(vIB*kiA^%^3Z+7b?nY_dd4EZhKqDx^{d1(YxH|!`m!cIH>%f3ZlNdDnl}L z(~mJzcY`&GtR;}-VTZrZMvWP3S6%xnyX2Bf?AT+EdCTHA{@Zb@@CLAy{`99m+3J~3 zms7RnE-NacFbl;JHlM}(#M0>jrbW=Az}%GJQcazW89mC@ceLA#nRC+ns^In4zy6hg z;!c}3+KYdA&U*IlpDJjQ4o6U{%1<6su%X-xtx`6MaVbc8Lloa=1BkP$X&4Yt!RyV^}R-IV5EMfQ_R;iJWjwW+`u)f3|1JlV)L4#EUF z`)uV*n|k9IYaVxs4cz;pYMFjz_feIVju|)aLXnlB2ma3L`t9OTse6jhrrr-ci7h#Y zyu4jd$jGs=qqG}z{6YUZ_~3)=>R(=B$A9Q!)i*($jyn6bS8Uj*G4{Y6H`+c29bT#$ z$-W-NTQGu6Ir`rPMbLz~@r&82qUe_dv6>(<+6KJyv-#7Q5nO6gx9 z_j@(>w8x)#G6!1(=!#LHN*tA4SC+M&Bqo;;^s-*pTzJ2wpU!^w7_)!BB{z{^WlIO;JMDmbr>Jf;*pQ&rPu^uaLbCY6hU85ax z$RYO33or5cRO{>X(@!V1=ds5gv+YOpNiAena=nT!R!SBFbgWhsQe+H+HlfqqiT8lp zF4RilTHM8^UO(7+ZTl%3u=fR3Ih0iybjCOCeiO2#hU z#@MlAt){cti%;I4HhU!yxkU?(g6O_Ooj*`hGevS+U)e3<**02c}5XUR66$FpJ|yuMl8s(3a|BFFyT< zji0cO{o&5v+rjTS^!2>_H~qWOt~_ABiT0~Y&M#+=(K`mL6mLDtxDtU00^VFfM{ogs zm<=UYbKI5w*0hyPyR_Dt$9>8M?E0N@FP%62?*BO#P?bT)tlRdn_T_)Ek;nYSYU>A9 zc6~)uicOwA0suRCDVn83-_$AWhT#w^<)!lbenp!?gO`_{PCPwGpwNo zVq*We8s=Md7$GS>Wbh!n^G5V);l0vOW^2uIH|H5}7@b^&(?x{@D3kvS4g_p)Ea7gj zv17NkVZ(;oUH9DgR=xdy%5}B0tg&9rz3iN`&$P3?er^i(5!7PM;-52^G_((B9q($H z8AM*fd7X0d$8FBs`2-BYbEcYKr+w;V`}GaKu_g1}Ng6jR(@N}vnrBe}_${1A@LB0xYtt_4V$Iup!Uk;j?+#k6uBv5K1|741f1tH3ea1$<|2eDORGWH_ zJ>8c9Gp9^HC6HoY{ z-T&Z2HfPS961Ib`p%_!gWXXJy-XmTi!uX-efi{civTK)H|Djvk(&fwTrI%i!fK}DL zHniL0_ug)M9Q=OD(Zf_O88xm*$%7a@7y#O|x2CpfG-q2mqvTqP&u;9no&!hQ7tcJy z&iV?pbgKI`|FxHF@Tl#mNQ_n-tBu$X@xu5a3CK?21@lWLY691LH5b7O{iRCQ5HKul z9`&y_V9y_yV+^ZgXsa^lfOh@b#ZTDC_ug-{ow}8?SF((`m%${Voqa42!Fxsy4SoDQ zXmL=bv~{sP^U^D}>)r>ZL-_x|3&9mOsg9QAR*QbRFdNQtNz_=3n^W;}H3Z%_*!X>s zW$@Zin>}Z)jUGMP9((8>+hzAjRX>W5Pv3FJ9c@F)(o*(QY5at0Ck@Y~wdKdb@rA>z zGcZ=qvAJ{S*;eCrFLU3l=D`#wk^#S3q-gJHOn_B@%{Vu5&l0h2!8E{lDllnZV=YT& zSo4UTDd6{ZrfC04QsjDUz^%jS?6v&>Blr|$Uv9fM@!GmAn6gbJS7xyOcBIUULQu6 zVp7TvspP$aeH4bJy|($d^`H0-rsHihpXT0uw6!jH&_?WcqjecDp_J7S__!!#ijt_t zT}5*;s*QFnIWj_ZPOJjCrq*<|RU7K9XLGZ?{MWzQ=>N{x>1{J|fBQnAThOv{v32k2 zehnzWB6FlmBE~Iv$SBi98Bu=+76FSAR^gqyP<;}X=*zJI_6nO`m5f*MHe}P?*0$EV zcJ;BM8z?eLj8oS%7m0s?Gw-1E6*3>hI3lYgyY)<8gOOIP zXG+LELA#?UmXB%sO6%0EnMPGrqi^yz26pk{#T1)@Q!dN+a+#z$rUUw@o(qr}ydG*w z%9_ZIFbCz`g0aV#qHWl@mK#1qw4j7r?JwXi{^ei(#h#t=i0v?LOleFINWhsGJ#=mQ z7_*f#(?KA-5ZyuH8ry7lJ@h2a+R$3rc3Yp;10JS-%P2c{>cp|N0uMGU%B9;7PV-*6lXp z$j7Zq@)Xz)r%YFk8yFzKP-9MkoW0-uCCQY;lAAIP4 zJ@9Y04`8FZ;)*M1;Z1eMtWF5DyKA1{rs!z7FqLKz#p4D12gVQ85YcE+?rvFNoqCO8 zz=6P{+Fy{OKIou>=;ZwFny&GpDqXVJ?CJ z1Wk)-e<8R6rS;EGJ!w1bv{M4^QOXma<09~k+!krf~15TG^ z0tcJ>l{{ajUERm}Z2#}pch_^PayY9p=veUZsn$C8ZW}Q1V(T$@|AcJE;)$hxJWjfy zwx)@K&5C8%*(pmZ_T%tAQbRpUU$@$7>YLd|f9ATon2iM*74Qe8i0Spt+(E4tt*#U{l?X)teWu! zE0T9bu6no{E;e|8M`hEFz!}**#w`fhLC^}A8&ss=wNlM5fR8a>?!D)3o3ziqi5d%l zBi3e7ivx2K)gbvRkv&i{+Pm}4J4uy2`skx+TVKtuuYK)n_Pd*YV}E&Rn%(g0>+Goa zJL`@V*mp>J(HOfUdlc(zRCb3LWF8l!$2OC=rO~A5(jd%z935u zyKw-ISI&CQ8hQ;V2Zz>&2$P&HbU+IjLs;r6>*Z@0fZ|BP)ne*2W9`d*gb&1(7l%@Tuj=B!R? zuWYB{ECIk7fgRR` zAPa16ZnjmcR@oCzJYiEFxzBbQH#$Y-${v|%!ovcAh)4TW*qfc)K@shzD8y{#+$5!r zs#B*tFwx%C6PQ!~pIB!2zl{aB)8I==Y?S6j%WYIIy;{!86e) zRVLZuYr@}3jEtLazS&Mb`D9zYdNr#Z*IjpARjpy%%mo)*VBh)9cgQXoF>EWl{fB6kTUg-2g_50DS0Blo)EyPkF@l-v3}*zhR^8vdb>^;DZlRM!p(f zF#h}a$3ITGEJXe$jD;mZK~6!HT_g|@AS&+~Cb_{y8i_8}eNf4senq488UH!!GvV9S zIE>W^Bwh07Z`$$~{>z5%bG6kC*u7kwMd)l9xZ$x9yth74YxN@LU}1_rHF=b|BXepT zY|YKR2;Ren1pwbqfBI89?X=UXVxk~xIp&yStWTdlG<&=3vde7${r9)mraogsM~*FJ zkGR`P0b9{X3hxtLHi$KWb#dW^7uv-aUraFCi6@?D-~M)WEjApE2uzV#UUSVgHgE1+ z>)of1GgYAMh_-+SYZAIbz<~;pf?@$of#Z;n9mbTHkIvSu*I>FEBcnyn9+(Ggkk$0s zXP&N}NX zgK!&6`C#}4huLa*(X8ywJGqWgAwqyPdGcgKtL3zh9Gmb~k6 zNJfU*x;6IHBlp;$$9=-ajoZ!ulpZ;9q`{?^8X#5ly6v{xSXBd9cHzQ>_T>G)w_SI7 zR|tjM-4Q00*w~qiYiIOAo*D|{f5!jdxtZu@2=mdq7f|JN>x@mmOb~M zw)ENW+pvRfv91GySQ5%!P=7=AsK}Bs)2q#TjwqQFRRRV@gC9iuHC?%oKXdwNcFs4? zr42XAz2Er8H@KkR&M%alVJ(kdZAV9kU3uk|Wa{AG=g*yO{Ra*%-5wSW4#Bwi#OJ5X zv}Zk1FlD*hdFmV5t!wut8fzVO)KOg2*tk&czUZRrFgwCHB16Jq*4Ea>fC>Q}-Crq^ zw#lr)T~p-+gbgVQU1^SDJeAGk383|djK1e^tMAds;0*^essIpwLg4ZL+q)MqyQ(Tr z;JZRdLIP-LAT3XkhYB`5ehsaH2+C6)(lB<5L=2sbAE9Z%z|g=q*n>I*IFwhYKk_1Ue&G*~q>|3WUx2o>rROQy?tna&!syg>P z*4cZn|61$6){frnI2WBlRY(B84?OTdIOLE+;$9y+ZnJs#&wq1TRxv;#r|7wiJCqy+ zI#sEnU3}3H(DCnn9lmz`cjEYCoF94Qk#NZ+m-NIOe(bTwq5~w7i2SWW=Yk6^h#gmt zIp&yf=HHy0ZPQ+i2Gtyhz6^*&P@C^|OsB3L!L&L{MO`rh;mJqbEqdhDxV*~4drZ4UWfm^}S`*+b{m60ufa zjxsLV!mz*18@A+K3u}E6ifMsDW1K?!+8LW~7UulrtZ>d(&X1?FnG&PIc#hX<43q1; z^UjO>0E_$l`SWAvJ>4I9m{KnI9Z^!`LNAjfsXs>{Zys~O3}@WCCMTHYA>7F`-V@F~ z`|KDolEUGM3DIt`#TF6l?6S))<8tCX_uO+aQpAvXKHjsGhiI6Ef7k8*FyH^9kQM+S zR1rv1B|W9;fmmvsk5L+lRYFU%U1ujvi|^>-i!Y8T7W$JG^PcF_^~bA-fX$mXFYbw= zLIP(%x(}GzXzHZ!#k2k{do*OoNa#}ZvhZ zqe+-K4Ae-qxYl?RsT0nRvSM9o&EXXFGN(>I{j~7kPCqHknfv*HT~9q^>>e!QyH)0Z z#R|3GWzpVZw^F(WZ{!^ zQnoc69}9N{X#2Cn4hl22*f!jC=N)0My+4*68$ragZ%(zOmhr#^zESF968BkIlkttx z@08XmS)RICtX`S1$0gzI@9xcNs-6TLFaO(u@WO+qhHVb{ZkW8uuGvCvP!yX3S+teY z0TIR0*q9aw*&>w&MDjFK1E(CsykqNa!_1kV3FrUg1+{_t&2N4)dJ>Gb$OlwB9>n5w z{PD-fNCPjNp%Q&a!dtT7^EwefBUrO24FVT=f0JS_j?@V_j*p#8E4m)S^X;YPT*W2ONmP0m%b9bXweto@3VcV9*u_$+!Z&8*LdbxNv?CGEWL4fV&RnVjy*058}InptXEHuNl$`~SAMZ5EWQ8uu+7Ks3R9-RfiP?kiwx7b&Ji=L^w43DlYo9)RRh;LTmom zj#^jTZR4UZ1;zXK-Z%?M%nKYG{}<)cr^erFhNg?OD5@$tDYb#9jL>PUA!ygjEsL)W zv*(@^uDJ5baM)poWq*zigsL9tyGa?bltTts;Kme1I@Q{kgS+p4@2(g{*?+%%!=;yB zQ9Dv9jBfQm@h+_?fN!^UE!7SH&@~o-P3yIYjr5dxl_IWBKlRJ-?)U5xa6F=ZV{e^T zbKT`cTv|wuYLPFK8v4<5v7$4g)+`KNE(#bL7yx0mdeSHrX2D58-z`_-8nYI8LHIN z0?*SG`qo>(#8aWs4Z?F|goOXG+IdJqqeBVLNy=mG@0Ei+GdMz&Lj64SlokL^YUN~w z`gH&h7>NtqdXaEuQrq;cktov@`sQuu<|(Y+ZRr9F5MA279wo(BcBWH1m3jt@-2Pp6}$D6cb5)&*a``suI$Y`lT@S54H{$UU*?cz{qn? zQ3GQUfJ?9;P| zn>16c3^8x;rxGpkJ)&_{{=R$=aq`ROo)iB2rI$r=C8Jm`bn0GgqzAaETu|krq20RN zTu+HFPz!7@m_FvO`LXAodk*9Sq>xJ`RZZPPgr2Fi%Ph4x(rS8%_dY{&ApzYRMZ;j)P z?nDWVOVPCY!T=5h(lPz*zt`@0l@#Zzkos&?Jp}{n{tOJqb70#wlx@81_BS3S54H|Dn%^(1wA`tNyz)W;VemAz}FKmiuF^W0gLiu5% z9ghK)^(KZ5HrYBF&EdLgT3`VprO(KI46U@*ST(k@KZi7)@u%S&ZVRuRH>u+0zylAA z(X2xcJ#^SNYCa)xFMal@aQ@%U%iHbeI;YF!PY))OIvZ{R4pIan`toFZ+I;0J{}8VJ z#-eCoQW~uO;!-^HcFi@{#Cc11cr$oAJYt3vftO=3+5(&X~Pr3Db4OMP7^zta380y_Di!KvI9j%^R0yTSdfZQohH^@16_y-v5Iz=fpE2(bw1> zPDDLKg|(cw&y7fd^-~&XtkPG~LB^f#z(4-+k0WUv2T#hFBPQZ|;)y55j}&>mDDB^E zx81_x8?Ffld~lb%9Yd}=2a8%rp~N-~`R`*YAOC9ef$q(K35P>2pR<-yEi0CW#}{oC zwmI;&Fm&#VEVX08czh=}w{0~EWpMi6Inveb*CKrk(ayJLsG zx<&uBm%_viHw%|vetApfox<<*>G>FYUV#-QQ>IRfdTb_w!HCMU;~xph)0c%*xSbBmYLEq( zc}JR+@gDUyc<+1P8|MJ87tqkg9QZ-HZMGw=Xw4VDcxHI#oSSgo|GYLVSa@|L`D%wgoG>^5GLIfG0yNBF&jm~+FwB|oT)XbN>mWWw zJ7ba&1a777%xOF!;Ksc&*sTH`m1*w%_piQ`=|n|ON-@V&@=JrZS&#ReqQJ$@t~ofl z|NlM{j-5RxIsu{?&4@84EoS^_H-NhZ_yQruA>D~4MDADzLSJ|pzy+XfEqwp`-yhdn z5o+_*+9=Xt4KY7~_TlESdq&Q_{>u4b|ARjnMx4*DgvY!R8ft33%ie*fbC3BUU1-NW`rJsBoWEtGyqm%Lr2 zMUK=P5b~n;8PfuF)hlr`o|PeNl%)m8AI_K&j+=c<_|myq^-42>5zk{X*m(zlhA^=O z82^LOG~sXpOhi12M!R1wTed8I&jjYR$UR#W@kwkmjZ6k)Ack55g$@xzO|EtXXhBG1 zFonURG>T?4BA6<#d^ z+t{SXCX4X(XZ$00qPR!yo=I8ce+*bi$-l3#5h7qHpnTg`CM71v&twzO)54 z??>*O#J1DO%_2bs0Gjq>iHm+7`G_0n>9m_wwIEk2=WCRb7*3a-S4p6VoJATKkiMWR zAOO%bX8hlH1Q?7*<5slB0xjfhd>DUHOg{eY7~|J*#tq<#ry+!G;b&yp0XV$kFZ}h~ zuxjOs@a2EJc;N9GITf*YLbkcvpq)Q+usr{YMX`DXA+_1mr)M#b@r{5`&mn5)*??1X zQreOpUVi!II0nrfdNf{)O}aHEMLwk<%vt)UH~%*NjA!~4!7%3BpZ6O9Ynvj~W*vBA z*}vt{pd6srI%5`g=XDKE1|Sl72zewf0ppFg4iEkKkr-tGI@)QhW`2p@n8%*qxC7>` zTO1^yp5BZ-`jz6P562k?_%`%sej0~>uJb(l=%exb?|a|-qRt&}J)~P8#GDqPQc4VL zdq2&H_xh2&J{%TbdsW!)&`%D0CGiB~ILo^Q#|;SWZmfhm*R!aH5ARhKWlGDK%jWck zTZG52o)+GD#3NyfB8VQ8o&+7Qzw(Rl%NyPucAU91tT$!Tfqn+Xi4#lgva+w*Ac=-l zDV^$-LaHE6yqsv2LXK-!hs|faBmDJW%?*G1rMzsfg#ltg0X%rmCLZnrW6rP3T`;nYhDZwUsFO{t02LiW*NUzQx6()2ERRlfC#*M)jTU|2 zxsJ4J9EiZw$boIXYk*7WnTHL)GNAYZ46QL%+`>GPiu29p(*J=Upaj@pD13P1h%+wJcbUqHGk=kSMMVo=X()+_VvXvM{mOU3@RhZ`B3>`4j08c=mc~y?ovc+ zMICEf6J+!8O{C@8hGkn00OK_F@-&rsCOY=PKiw@{d)*DKsP9e38fV6xs05vI#DEI( z&@&r*bP4$Tf10nxzNmG_aVXkBukAE2d-#VBg?&D@Z}{gMZ;Wd~ zl$c^x(NiqfUK@f`H11%Ey2Z|}|DKIcz$7(VO9a!rXUgMOObFY5^0Baf-?Um(y(7hT z*_V3~bgWsmH2nMf} zhh{h1;ZMRB=A9f{pqC*Qcpr~OFihNZ*Su{vaAcQHZO_*W{m{Oj``3p4*x|50 zJoob2@FyRg6BaC37#FV5loZBgC@oIB@1$!6fY2W!LC=h1JB!kA&j486bN8L$C)XaF zd5!gbH!McLT4u|$oUe$Gahs~C=#Zx*g)lMmJST0uL)i2`oF2gz?`<^2m`vbw!3n(+b z%;i>eX1*JvB1XkB*kuR{SJr(RMEO@&#tEjle-;QpLXU{&>ek?_9j~tQ(889 z9Ef;6ennr{;n0V|#0|F^yn$iU8td)@dlGc4UHxj%zka8g%R=9Z--Q0jZwvhvp0#U2 zfB)*x|H?C&LEK=I(BHo%^ox3|To(FYe`K zY54qK9+;JUsxDi9YLHruy?Iu>80U5jZAY-%ANql{)xXPr*O!6iTkm}#oO;&RVjKRE z2(0v)3_s9;%fmaz^FSu|@6jYgmH|4Xc8{I)neh0vHmmH9t>Ag;{XlK*6r}a9HWsai z@o#G~@^k!Ve?0!FrE9{`=e!p7-S?wm(c=Hz>q9U6;QsH0{SWwf_}0QR!iRR-CG<%( zO_&_|@P+y&hQ0|CL!WsIxaAuV_E{%aE(>69{N2P2;&F7}xAM2457?XX_Ryz4O5cR= z#Dd9Trz4*T6Q=Jlm`L6u+U-fu;obaV(RN|=tG~)$Q@*&TG=P^M|DAvG-=~+JO|}VH ztRoHtDU94Jh~eZ3p>MrOVb@u|3P z*O&jlFnRqy$UJZ9f?Th0GDfz0zE=oOGj@BGelhW;gd17y{<&Wza>i+ zhZQSU4m@fqufx|!4E9=n*hWx!2iNF54OC9mPO$35uwwbLu;CW(4m|5J(ih$S9)!j> z*<^Y+{P0hNX?89X&*v71y3KXLk7a$F9mEX0N{*`ct`PO@GhF zh+BW!XfT4^7c;QIOQ%o2TfH(o^3$J(Ly!BX@E?ynJY4<1MkmtI?6ZxY`+44PycYTmh{%nA+}{ZOQYg@TjAj&$eeK0OLh?p_?3&Oo7oSH+ zw)&&bhW~ontZ?#~Stq_;7NBE~Jw6nce0itv-gj-3dpv7H--JnF?HjA|pVQ>Z(kRI* zQaYRE|MLl%Pr~cJ`*Qf|&68pSAyquRE{wws*MB2C{M8%;*B^UJE_QAfe!Hf?F6>ACb(m`|*qVrI6EbEOD52PAPu}I{Zz#Td^B6>fo%M_|1>-N^7g!6 zkW^FTsTK9a!HRzQfd0&9UVQG5CEdRC(u%O#ClQ!G8LnJ-%}DAS_kX|t{(Hj#`yUYQ zy6vCBAHQqU&?o(rBD*PFMOT1u;paZpD)@sjGMwpGG-Tjs<8?wtFi)h@aj&h$575(~ zW3=Cy+&>bU5~^O840P-f_rE~IDnodHJVgC1dTD3Rp>z{V?XJ5nEMLBC@J_J}zfccM z>c2AZ_j|s7PuO?A{c9YcGTu!$pF@eQh=Xy{Oo{Mt&*D6)#TanaWX%X*p>w6Efk*_g zKa3~^U|>x^CKXK;?NB{s8v*2TACVdaNuWa%11AjVK&S>X03iJ%5KeIuRAvAwq8dO4 zE(!30FM`{EG2+*OgN8(2`^PS<2!KctM7*7NM>UBYMRq=xSk6>O&>l&y)N9#JP zeFI5JKDX0_uY+3{v#(;43jym#P*zhjJFi+yg|>(5qBv#`Im#DO8myNAQe2s$43Ys$ zgxE6A-HqoGVE}&h%cyUW-s=6Tcv5Ln+#_eWb0orIA}As`x(|Rrmr8)3k?|GfKp+J$ z82;3FN;A0xI#dfWWcsb>qXMuLC2=~GC*!rK&_GT#H&q5TBY+a{TNdaL`4MGFpsSgC z7|+M3HdG?*J!eGHN?O%G1v*;QSmAhHh>d`T>SWl?sa38h`5KClrd$krUD@DhlGf_) zokzz*D-(2RP{zB%1XmeThDb3el~pDz2i~seeIlgYY}mS)>(~#&^QL|x&3vbsV}LgM zUocAT3KAp_UN3}B82{2}$r!eKFC%@Ap}y|A>*B_2osJtoO(m03*JeCd^Ih8k&r$#Y z6_`mxK~!6Gx+)62xi9lq*H0Z+iAomb@cLNT-$hBcUM)(ARWm6iPM{-2EJR(TZG0D~ z(D_uUt9M+iUTFt(Ad+fi2RxM}DsbqeR=!-;iM#MTy6NKSh>!uRm9(yb3Usutv)VT- zRy>C?$~{La!xP4o>$PYkQP0mqOKr>n5ux4T_E2f}aV?yBf26K{?VhLjJ!OWBum!rA z1%J3}GImlma^1>f32#z9JZ)fyJ0i4P6rQrYdfJ#xGVGO9G5RPwEJf}{K`Yj~U0$Qq|oqiC;u}B2aHdLU*aoH*8z%db(DKjdjY}zw$B6?kutv1Z!N_qsmXdA?E3%bj4E#0-7Dyq8-IOZg{*vpFLp+kN^}BhDjt!iP}OcwoFzhTh)+6QT4Zwti3hGFaFF$YQ?*hCq3u^K>c<3@@pjh{SN$7A;aO(JJT= z4hO`f>xxkghRK*?L>Xg%L@qm}2ojG1sFNBHxzV1R7Y(@0oH;Yj3ETxn7e_&qjL@-n z?p^^xV<2sY*sOk~Cp<4>TL$RBwQx_;4$Vqx>n@tsXu~|!EmAPJ7sZaiA`H?c00g3` zQby9cUR!c;3qx~&^LcN| z2lbyI(keiou>o|5WLT5|4dBMRv4yzEhiVT(&(eeSRT?AdS-B!ovxrd{`wHQ7h&Hye zdEZF)*sXsz-bJjCP|K3UYf;tF>tanX#-*oPjnMVFZkm0*3UoB9sRqYctkULA9h|1N zZ@^Gxcsz1B`$lb+<&W)#YVjXU&>@G(i)E-gNre>kRNH*2!=_exh^S&n{R@iM5b~GO zV339O>(eU?ryQ-)$FwtVGGqXVNC*JpxjQ9}$p`CoQs#p1SpnZv?a<0NM1%y&q$!Fb znuXkpr;vc5_s=K;Z$JlvBYhx676teaB}zatMVdsGL{0E8iUQODB&`Sl&cJ!6?T}sT zuLV$*@qSx*hIMr;fCp%n*+|YhXbv{ZiCI_AUdDB;!Me+e6t%K%P8rwkm2*^}qk}hT zv66GuB&-t|sSHm(Tps;~8*Zo((HKLyS)o#1IwIF-f{xUPNJzVrlFFi2dB0VO@-|6$#>xm&( zUDK)|5hXKj04`%EiL?hjAZxl`)iEL|uEVeZ9rVm=ma-z=Wr_?Ht5=GkL#j$|gOpC8 zd)IDNuVpX%=5d+hy4`U+7T*)GM0_oC4ALK-N}1e~vCu_3*D&^_^oqMJw{xDi@^>oG z(dOG1UXxxaWAKeshR2KLjf;55-wTgwG$lOE+hiD(?=l>WNOAKt-uw33Z{Oxq4ty;c z=hQo(;}eDuNpw7EypB#qxF35Sc~KajCxQoq=*Vkl?0^d4{9A9mHC~QBRT=R1RdV<) zZiMO;JO){|(Q^xZaubswXtKOIN1h4`~h*%g)(kXPHqQd#4F&HY| z9r7kJuJ0MM#-;R$a{zb#&Y%qiI&eNjjp!dpRK9H7B0;wz31pTr_ZSiBBcSxHAgN7z z>ULVjGXou>cOo8Th;hAL`9Bl>AK%P<%gv^loVkz4xy&(yIg3K&$bDqY-4MApR>X%7 z&E{N=93i2(OF5>46ecA{2%|#vUElBj@O}UI`r-A{>+yU)AFs#r^?Y8hC>bS%B(y?# zqkCSylefD!r1bBGUNjisRTH;RXsWu`6HyfH#>{rn50f2%e*qQ?xr6_L@Tf#dq>Z3V z{Cx^Yl@7nH8RztAM(eGSs2^emU^qcGyTW8mYBOpkU($$J(Nt zva~&k7kI)GEOUxlVR(>|#hFYN2M?hT`&sj1uUHRO1OEb9H^usqV1M2l zfU3{yZ1iSFeZ3>~yh{^^>FaHaA^Qf~xItKJEo&by;p5>!=TnH?n->Kl_5g>S=GFHc z7#!ltv7{aKR^1?SwBA9*&SI!t6Yi~_ayrNhB)S^tb$v&AAp7DGZ~1T+FLTHz^>`Di z^g%we_pR5j`}NX9=-6V{0N>LDek$?hDp&J;V9{>yn-ck7KzCjM$|FFnkHNCtK3ScoS5c$2Y*6nAt({E&c0cf5}d zxwddNKWedFBE8GDi{II1oD)>nTAwm0@7px*l_J!>R+XoK9y9?JjHe3iZ?tD5b>jnX zwKS$x&#+-K7A$^@P5U%&H2nU_oa%n*P6NafL%D<2z^J67&CbzsjTZ+)5~{4I%0q9l zD_IvtUa7W)rA$lW1uBLEEu6a7dg&UH=`aP`>n{YcT!G?Rp;lPDT)we(V2Fq>!EeNDvFiu*Of|XTva8SosgNtfj$ZAGWe_q100ZHmB}@R6Ir2|2?Ua zKD*7stE6k7XSm&|Z4u%)suk?%tD{PmpZ2y*%w4Obb-(R4Xcp|FNM?ew^`grH0*R22fXXoqI!fFT68}rahjY@p9V8G`w_TP_ z(ss5pEHljCu4(LtNbsrjx?m&CE*ydb`G0&*OFj%zN@;Sg??xEm%`|RlfIOX_T(v8(&?djJ0LOyWQ-n?J-V||_4 z6Qj^?#IhZvQEvrOWUwAqd%-Z&)(p(l$&yt4@+}Lw`W{jdFk((HS=1YS4_tfXG|GC}{yVm8w+rAPB_=p;s z4uEq+7H;XJvctU#WpPnOMxMj^ED&7ZcAU}NZdW!Z?j8eRNp3~0NnNooO#hu!_zomP zmQ`Vfr&D0xZHs%MFdHN}&cjzPKk-}y!UVx)XdCyWgzn60>#l}0kXd$Ocu!S3Pkgw> z4hKSgWl1WWX~y=4p$eU*V&C6v>A6yss@-$y56R^!xY*|LSS~+jX9`$U z^kiOZmQ@=Ou`eO0e23cg{_gW%+3K$^fNA1za(@|;v>T9wr$M#Eiwa2k6_UywZ<1r? zAbaF}lOAvg6ykaEMMHpeW8&7qo;#6TrC)XV<-U9Q6?jUnU}||>?C3F@p~)7 zS?PsrTdyN~GFoFoj}!9~P!hL!1GT>*_SaBO=`%D=G<_d%engK*Ok>5O(zwpYnMwI% ztMKn9hvXiiL=gZm?#=q?ryrUZLXZ^N_al7IJ@N(^v6{0V_|R4H-WS=rdm zzoEyE>g#0{j5j@84WvdHhsIiCHq)Yp94ixu8NMHTtN0rm^Mr*|;g*NBT}$PBKfm^! z*8b#WX9$!e1RE3zLWOO(XW7sAF!F$M%(Z z{;_jGo`sdL43NuLf)2cad=qIVw-_|1xhBh=?;lNmx;i(pt4ujHnR1l#1&=t=hqWrq zAC0{g>_)SLLxciE555Sk+19OG_FK-9!%J*jlH5rksgq==Wy9q{qf#>usFS-}vp+V> zbeZ+G?WxU|YN##f32cJ}{rUMW4o;fY6bzu%&xeeSQVvkzSu&3&X3c%8k1d2`- zuSIUo5l3S#=EG_!Jl)yl7D^d;H4a)X9x-zX+twB3O^%k(fTtA_+L6Ju#dRG+0mRnj z!<$*G+Mm$x!l=e3Wtec&Czyo6_&d9=qWyF!K~ifX^n0y$V_W64Ckh^KEcaEpekhJ< z$=g)(Om2?ISUx?a#UA02Ep?`Is^wsd-nKLKFKoZ_&Se{O*RzMpwBE@I~-tR)iY z60@vx&w}Pq;ph(}D|Z8oX=RBQ;;G~rzP7qa2Mj8)a}uRo+|*cqiftca71 zSxSz50vIy5tgM&z;M{E~Hrp_|Mivx^89^#uA}0FG9ZGLgOaFk(>N`29zQ>QcUADX5 zwww(M8wlD_1#1_1k5sf&et7b#T~{%8@QW0nW2^b#Dq%r;q6$^jgU`}7~qJT4@VIN0w_#3i7yE^-!QiTAc^ zth?JjcSN39Ig7Af#NHp~FJ}9b*%zs$y1GEPV@Xd-Q9I7diPlm&wETwJIL&UD&=vE| zpJ=~6e9`Y1=p!UwojRSyfMYmYu;!FgJ4QlWv=hrV3@)N2xV_f|LK%ZAwXf<7jS!<> zJ^p@5RNmQN&ICGp1kPs>$vs1N1h|cmAWk^(n>y+^YpX&hJ@xUhBNm!n=~Dnt@~iUv zmQ{$v{h)t6q_I2%=e4`uLRe~#Sn|V6k51#Z*VXYGk8vj5I{Y~KKW9$jI&~w)JvN}w zCF2o=UQh}nfRC*`RS+0pc{hI~KEq-sqowucp50Z|SMd0f7*=NX4( zS)643*Xku=`oga2#pnD5(aPt0S*-^5G}dTFhW5J^Y8PQPR55D5gu)HTyhqoq*5u=t z%s8sD&QgoIV*S$CMpg$^w3t5CYOep<%!`4GyQI`xte2V0_x!fN+Bsj`!s=ukW2bEq zG=K-L9xs-l!Ep1{X%>OmtZz(pf4E7#109G3HAtAkS-xHQdWU~aey!j{p4p*Jcxqs@ zn3B*r+Pse5>V{2*UYwGJM|Ycg=@&pl6z7m+Ej+4pFld3L5jM>Df+&7#znt#^{KTS; zz2BaVEQ}B9t@8`jV=}3hHyG;+cEaPZh)O99*?hFk@$M+wKt~4sT}QBA-8LNRYn8Ibop&@YxdsTm?Tk z`{DP)4w)R0sHxR^zQBU1M`r~9(L)w?FMsaH{1fWqGQU60jYiKL)os;G!>dzmK}GB; ze2fMriqYDdI}#rLuiz?Gr#t2KcY%!Q&0h~!;rm-a1rev=lfg{lYH}3(faAgc3V(ad hS2MSn|F5RM&Duwcjjtzd^8lF7#?rx}$^1&%e*m0rNCW@? literal 0 HcmV?d00001 diff --git a/docs/proposal/001-关于paopao-ce的设计定位.md b/docs/proposal/001-关于paopao-ce的设计定位.md index 754a40b5..d5325bdd 100644 --- a/docs/proposal/001-关于paopao-ce的设计定位.md +++ b/docs/proposal/001-关于paopao-ce的设计定位.md @@ -1,14 +1,57 @@ | 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 | | ----- | ----- | ----- | ----- | ----- | ----- | -| 001| 北野 | 2022-11-04 | 2022-12-17 | v0.1 | 提议 | +| 001| 北野 | 2022-11-04 | 2022-12-18 | v0.2 | 提议 | ### 概述 -paopao-ce是一个清新文艺的微社区,提供类似Twiter/微博的推文分享服务。 +paopao-ce是一个清新文艺的微社区,提供类似Twiter/微博的推文分享服务。paopao-ce的运营形态有点类似Wordpress,只不过Wordpress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,在有限范围内形成一个友善的社交小圈子微社区。 ![](.assets/001-01.png) - + +### 实例部署 +部署paopao-ce实例 数据存储需要使用 关系数据库、对象存储、搜索引擎、缓存。 +![](.assets/001-02.png) + +#### 关系数据库 +* 本地(Native) - 部署 MySQL/PostgreSQL或者paopao-ce内嵌Sqlite3数据库 + MySQL/PostgreSQL 可以采用 一主多从+备、一主+备、多主+备 的模式部署,具体部署方式由运维者决定,paopao-ce本身不关心 关系数据库 的部署方式,仅仅使用标准的方式连接关系数据库使用其数据存储服务。 +* 云关系数据库 - 部署 云关系数据库 + 阿里云、腾讯云、华为云都提供云关系数据库服务,如何开启服务请参考相应文档进行部署。paopao-ce采用标准方式连接其相应的数据库使用数据存储服务。 + +#### 对象存储 +paopao-ce使用对象存储服务存储 图片/视频/附件 等推文资源。 + +* 本地(Native) - 部署OBS(Object Blob Storage System) + 目前开发环境可以使用`localoss`功能提供简单的OBS服务, 也可以自行部署[MinIO](https://github.com/minio/minio)来提供对象存储服务。 +* 云对象存储服务 + 阿里云、腾讯云、华为云都提供云对象存储服务,如何开启服务请参考相应文档进行部署。 + +#### 搜索引擎 +paopao-ce目前支持 使用[Zinc](https://github.com/zinclabs/zinc) /[Meilisearch](https://github.com/meilisearch/meilisearch) 提供推文搜索服务,搜索引擎实例的部署请参考相应官方文档。 + +#### 缓存 +paopao-ce目前支持Redis作为缓存存储引擎提供缓存服务,请参考Redis官方文档进行实例部署。 + +### 站点部署 +paopao-ce支持多实例部署,具体部署方式可以参考下图: +![](.assets/001-03.png) + +实例部署请参考[deploy](../deploy/)文档。 + +## 疑问 + +1. paopao-ce是一个清新文艺的微社区,微社区的 `微` 是如何界定的? +* 首先从站点用户流量层面,paopao-ce的部署一般针对的是小站点,注册用户不是很多,用户流量(QPS)也不会很高,这种情形本身很契合paopao-ce对自身微社区的服务定位; +* 从代码实现层面思考,在数据存储层面的架构设计中已经假定paopao-ce提供服务的QPS不会很高,因此不会考虑针对 快速数据获取的 数据库 **分库分表** 设计优化,对站点推文数据的总容量也假定是单个SQL数据库提供满足查询需求的数据容量极限。 +2. 如果一个paopao-ce部署站点运营一段时间后QPS逐渐提高到一定程度,目前架构的paopao-ce无法满足进一步的用户流量冲击,是否会采用分布式技术栈进行优化? +不会。paopao-ce将保守的采用目前的单体架构模式提供极致的QPS用户体验,如果确实需要超高QPS需求的实例部署,将另起炉灶开发另一款相应的产品,或许会采用云原生的分布式技术栈生态进行架构设计,这将是另一个paopao产品的故事序章了(前提是paopao能火出圈)。 +3. paopao-ce主要针对哪些站点运营者? +其实paopao-ce的运营形态有点类似Wordpress,只不过Wordpress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,有限范围内形成一个友善的社交小圈子微社区。 + ### 更新记录 #### v0.0(2022-11-04) - 北野 * 初始文档,先占个位置 #### v0.1(2022-12-17) - 北野 * 添加部署结构示意图 + +#### v0.2(2022-12-18) - 北野 +* 添加部分内容 From b225e7e1b7d498c3b06c72738c86a9070ff17d07 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sun, 18 Dec 2022 22:34:59 +0800 Subject: [PATCH 38/65] update proposal documents --- .../001-关于paopao-ce的设计定位.md | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/proposal/001-关于paopao-ce的设计定位.md b/docs/proposal/001-关于paopao-ce的设计定位.md index d5325bdd..0f6e9222 100644 --- a/docs/proposal/001-关于paopao-ce的设计定位.md +++ b/docs/proposal/001-关于paopao-ce的设计定位.md @@ -2,14 +2,17 @@ | ----- | ----- | ----- | ----- | ----- | ----- | | 001| 北野 | 2022-11-04 | 2022-12-18 | v0.2 | 提议 | -### 概述 +## 概述 paopao-ce是一个清新文艺的微社区,提供类似Twiter/微博的推文分享服务。paopao-ce的运营形态有点类似Wordpress,只不过Wordpress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,在有限范围内形成一个友善的社交小圈子微社区。 ![](.assets/001-01.png) -### 实例部署 -部署paopao-ce实例 数据存储需要使用 关系数据库、对象存储、搜索引擎、缓存。 -![](.assets/001-02.png) +## 从运维角度思考 +| 实例部署 | 站点部署 | +| ----- | ----- | +| ![](.assets/001-02.png)| ![](.assets/001-03.png) | + +部署paopao-ce实例 数据存储需要使用 关系数据库、对象存储、搜索引擎、缓存;paopao-ce支持多实例部署,具体文档请参考[deploy](../deploy/)。 #### 关系数据库 * 本地(Native) - 部署 MySQL/PostgreSQL或者paopao-ce内嵌Sqlite3数据库 MySQL/PostgreSQL 可以采用 一主多从+备、一主+备、多主+备 的模式部署,具体部署方式由运维者决定,paopao-ce本身不关心 关系数据库 的部署方式,仅仅使用标准的方式连接关系数据库使用其数据存储服务。 @@ -30,21 +33,22 @@ paopao-ce目前支持 使用[Zinc](https://github.com/zinclabs/zinc) /[Meilisear #### 缓存 paopao-ce目前支持Redis作为缓存存储引擎提供缓存服务,请参考Redis官方文档进行实例部署。 -### 站点部署 -paopao-ce支持多实例部署,具体部署方式可以参考下图: -![](.assets/001-03.png) +## 从人文角度思考 +现在的互联网世界已经非常精彩,各种社交媒体平台琳琅满目,使用体验也非常友好。每个社交平台都有自己的运营方式,都有自己的核心用户群体,也有自己的产品灵魂,都在不断的进行生态演进。比如Twitter、微博都已经从最初的推文分享服务演进到一个成熟的传媒平台,注册用户非常庞大,日均访问PV也是一个惊人的数字,这就注定了平台的运营思维是多维度考量均衡的结果,只能做到让用户群体的大多数人用户体验友好,并不能满足所有人的需求。大平台有大平台的运营模式,小站点有小站点的维系空间。对于类似Twitter这样的推文分享服务,paopao-ce提供一种小站点部署模式,采用类似WordPress的运维模式,让 **个人/小组织** 能快速、便捷的拥有一个提供推文分享服务的小站点,以填补那些在大平台下难以享受到的用户体验,享受小圈子内的自由空间。 + +就像许巍唱的「曾经的你」这首歌中所说:"曾梦想仗剑走天涯~ 看一看世界的繁华~ 年少的心总有些轻狂~ 如今你四海为家~ ......" 曾经的你我也在 疯狂刷朋友圈、狂奔微博空间、畅游Twitter世界,但是随着环境的改变、岁月的洗礼、心路的淬炼后,你我可能已经不复当年的热情,逐渐淡出朋友圈、沦为微博的稀客,或许Twitter世界还有点吸引力,但是总感觉表达的欲望不复从前了。是什么原因变成这样的呢,原因可能很多,也各自有自己的不同情形所至于此。但是总归一条,那就是 **自由**; 如果有那么一个有限空间内,可以自由的 *唠唠叨叨、怼天怼地亦或自言自语*,你我是否又能燃起表达的激情呢?!从这个角度来说,paopao-ce就很契合这种需求,曾经你我想拥有一个自己的博客小站点而使用WordPress,那么今天想拥有一个自己的类似Twitter的推文分享服务小站点,部署paopao-ce或许也是一个不错的选择。 -实例部署请参考[deploy](../deploy/)文档。 +一个产品应该有一个**属于自己的灵魂**,可以说 paopao-ce的宗旨就是 **打造一个清新文艺的微社区**。 ## 疑问 1. paopao-ce是一个清新文艺的微社区,微社区的 `微` 是如何界定的? * 首先从站点用户流量层面,paopao-ce的部署一般针对的是小站点,注册用户不是很多,用户流量(QPS)也不会很高,这种情形本身很契合paopao-ce对自身微社区的服务定位; -* 从代码实现层面思考,在数据存储层面的架构设计中已经假定paopao-ce提供服务的QPS不会很高,因此不会考虑针对 快速数据获取的 数据库 **分库分表** 设计优化,对站点推文数据的总容量也假定是单个SQL数据库提供满足查询需求的数据容量极限。 +* 从代码实现层面思考,在数据存储层面的架构设计中已经假定paopao-ce提供服务的QPS不会很高,因此不会考虑类似数据库 **分库分表** 这样的设计优化来应对数据库CRUD的流量冲击,对站点推文数据的总容量也假定是单个SQL数据库提供满足查询需求的数据容量极限。 2. 如果一个paopao-ce部署站点运营一段时间后QPS逐渐提高到一定程度,目前架构的paopao-ce无法满足进一步的用户流量冲击,是否会采用分布式技术栈进行优化? 不会。paopao-ce将保守的采用目前的单体架构模式提供极致的QPS用户体验,如果确实需要超高QPS需求的实例部署,将另起炉灶开发另一款相应的产品,或许会采用云原生的分布式技术栈生态进行架构设计,这将是另一个paopao产品的故事序章了(前提是paopao能火出圈)。 3. paopao-ce主要针对哪些站点运营者? -其实paopao-ce的运营形态有点类似Wordpress,只不过Wordpress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,有限范围内形成一个友善的社交小圈子微社区。 +其实paopao-ce的运营形态有点类似WordPress,只不过WordPress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,有限范围内形成一个友善的社交小圈子微社区。 ### 更新记录 #### v0.0(2022-11-04) - 北野 From f060439613ee0c5b461af9719d5d7b35a31419a5 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Mon, 19 Dec 2022 10:30:20 +0800 Subject: [PATCH 39/65] update proposal documents --- .../001-关于paopao-ce的设计定位.md | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/docs/proposal/001-关于paopao-ce的设计定位.md b/docs/proposal/001-关于paopao-ce的设计定位.md index 0f6e9222..be54b39e 100644 --- a/docs/proposal/001-关于paopao-ce的设计定位.md +++ b/docs/proposal/001-关于paopao-ce的设计定位.md @@ -1,16 +1,16 @@ | 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 | | ----- | ----- | ----- | ----- | ----- | ----- | -| 001| 北野 | 2022-11-04 | 2022-12-18 | v0.2 | 提议 | +| 001| 北野 | 2022-11-04 | 2022-12-19 | v1.0 | 提议 | ## 概述 -paopao-ce是一个清新文艺的微社区,提供类似Twiter/微博的推文分享服务。paopao-ce的运营形态有点类似Wordpress,只不过Wordpress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,在有限范围内形成一个友善的社交小圈子微社区。 +paopao-ce是一个清新文艺的微社区,提供类似Twiter/微博的推文分享服务。paopao-ce的运营形态有点类似WordPress,只不过WordPress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,在有限范围内形成一个友善的社交小圈子微社区。 ![](.assets/001-01.png) ## 从运维角度思考 -| 实例部署 | 站点部署 | -| ----- | ----- | -| ![](.assets/001-02.png)| ![](.assets/001-03.png) | +| 实例部署 | 站点部署 | +| ----- | ----- | +| ![](.assets/001-02.png)| ![](.assets/001-03.png) | 部署paopao-ce实例 数据存储需要使用 关系数据库、对象存储、搜索引擎、缓存;paopao-ce支持多实例部署,具体文档请参考[deploy](../deploy/)。 #### 关系数据库 @@ -33,24 +33,33 @@ paopao-ce目前支持 使用[Zinc](https://github.com/zinclabs/zinc) /[Meilisear #### 缓存 paopao-ce目前支持Redis作为缓存存储引擎提供缓存服务,请参考Redis官方文档进行实例部署。 +## 从代码实现角度思考 +paopao-ce在代码实现上采用 **单体架构模式、分层设计、功能模块化**,架构设计上可能略显保守,但是在使用新技术上却非常积极,比如搜索引擎就采用了近来新星[Zinc](https://github.com/zinclabs/zinc) /[Meilisearch](https://github.com/meilisearch/meilisearch),同时也不排斥各种云端服务,包括阿里云、腾讯云、华为云的对象存储服务、关系数据库服务等。paopao-ce始终秉持着 **包容并蓄、能用就上、去繁就简** 的架构思维,努力打造一个能 **稳定运行、代码清晰、功能可扩展** 的开源项目。 +![](.assets/006-01.png) + ## 从人文角度思考 现在的互联网世界已经非常精彩,各种社交媒体平台琳琅满目,使用体验也非常友好。每个社交平台都有自己的运营方式,都有自己的核心用户群体,也有自己的产品灵魂,都在不断的进行生态演进。比如Twitter、微博都已经从最初的推文分享服务演进到一个成熟的传媒平台,注册用户非常庞大,日均访问PV也是一个惊人的数字,这就注定了平台的运营思维是多维度考量均衡的结果,只能做到让用户群体的大多数人用户体验友好,并不能满足所有人的需求。大平台有大平台的运营模式,小站点有小站点的维系空间。对于类似Twitter这样的推文分享服务,paopao-ce提供一种小站点部署模式,采用类似WordPress的运维模式,让 **个人/小组织** 能快速、便捷的拥有一个提供推文分享服务的小站点,以填补那些在大平台下难以享受到的用户体验,享受小圈子内的自由空间。 -就像许巍唱的「曾经的你」这首歌中所说:"曾梦想仗剑走天涯~ 看一看世界的繁华~ 年少的心总有些轻狂~ 如今你四海为家~ ......" 曾经的你我也在 疯狂刷朋友圈、狂奔微博空间、畅游Twitter世界,但是随着环境的改变、岁月的洗礼、心路的淬炼后,你我可能已经不复当年的热情,逐渐淡出朋友圈、沦为微博的稀客,或许Twitter世界还有点吸引力,但是总感觉表达的欲望不复从前了。是什么原因变成这样的呢,原因可能很多,也各自有自己的不同情形所至于此。但是总归一条,那就是 **自由**; 如果有那么一个有限空间内,可以自由的 *唠唠叨叨、怼天怼地亦或自言自语*,你我是否又能燃起表达的激情呢?!从这个角度来说,paopao-ce就很契合这种需求,曾经你我想拥有一个自己的博客小站点而使用WordPress,那么今天想拥有一个自己的类似Twitter的推文分享服务小站点,部署paopao-ce或许也是一个不错的选择。 +就像许巍唱的「曾经的你」这首歌中所说:"曾梦想仗剑走天涯~ 看一看世界的繁华~ 年少的心总有些轻狂~ 如今你四海为家~ ......" 曾经的你我也在 疯狂刷朋友圈、狂奔微博空间、畅游Twitter世界,但是随着环境的改变、岁月的洗礼、心路的淬炼后,你我可能已经不复当年的热情,逐渐淡出朋友圈、沦为微博的稀客,或许Twitter世界还有点吸引力,但是总感觉表达的欲望不复从前了。是什么原因变成这样的呢,原因可能很多,也各自有自己的不同情形所至于此。但是总归一条,那就是 **自由**; 如果有那么一个有限空间内,可以自由的 *谈天说地、品头论足、唠唠叨叨亦或自言自语*,你我是否又能燃起表达的激情呢?!从这个角度来说,paopao-ce就很契合这种需求,曾经你我想拥有一个自己的博客小站点而使用WordPress,那么今天想拥有一个自己的类似Twitter的推文分享服务小站点,部署paopao-ce或许也是一个不错的选择。 一个产品应该有一个**属于自己的灵魂**,可以说 paopao-ce的宗旨就是 **打造一个清新文艺的微社区**。 ## 疑问 +1. paopao-ce主要针对哪些站点运营者? +其实paopao-ce的运营形态有点类似WordPress,只不过WordPress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,有限范围内形成一个友善的社交小圈子微社区。 1. paopao-ce是一个清新文艺的微社区,微社区的 `微` 是如何界定的? -* 首先从站点用户流量层面,paopao-ce的部署一般针对的是小站点,注册用户不是很多,用户流量(QPS)也不会很高,这种情形本身很契合paopao-ce对自身微社区的服务定位; -* 从代码实现层面思考,在数据存储层面的架构设计中已经假定paopao-ce提供服务的QPS不会很高,因此不会考虑类似数据库 **分库分表** 这样的设计优化来应对数据库CRUD的流量冲击,对站点推文数据的总容量也假定是单个SQL数据库提供满足查询需求的数据容量极限。 -2. 如果一个paopao-ce部署站点运营一段时间后QPS逐渐提高到一定程度,目前架构的paopao-ce无法满足进一步的用户流量冲击,是否会采用分布式技术栈进行优化? + * 首先从站点用户流量层面,paopao-ce的部署一般针对的是小站点,注册用户不是很多,用户流量(QPS)也不会很高,这种情形本身很契合paopao-ce对自身微社区的服务定位; + * 从代码实现层面思考,在数据存储层面的架构设计中已经假定paopao-ce提供服务的QPS不会很高,因此不会考虑类似数据库 **分库分表** 这样的设计优化来应对数据库CRUD的流量冲击,对站点推文数据的总容量也假定是单个SQL数据库提供满足查询需求的数据容量极限。 +1. paopao-ce在代码实现上为什么采用单体架构模式? +一个项目的架构设计是多方面考量均衡的结果,最终的目的是满足项目的需求与长远发展。 + * 从架构模式的角度来说,单体架构模式可以满足paopao-ce对自身服务定位的需求,完全有能力承载预期的用户流量QPS,所以采用单体模式架构设计是没有问题的; + * 从运营者的角度来说,在能保障服务质量的前提下,最看重的还是运营成本的考量。提供一项保质保量的服务,可持续性是评价一项服务的重要指标。单体架构模式的项目部署简单,成本相对于分布式架构模式的项目也更低,假设门槛也没有那么高。黑猫白猫,能抓老鼠就是好猫, 在什么阶段就用什么技术,根据部署运营场景选择适合的技术来支撑服务,才是运营者明智的选择。 + * 现在不管是单体架构模式亦或是云原生的分布式架构模式,相应的技术栈生态都已经非常成熟,技术本身没有优劣之分,需要根据具体环境来适配合适的技术,这样才能在你保证服务质量的同时保证服务的可持续性与经济性。说白了就是paopao-ce目前采用单体架构模式的设计,满足优质服务的同时性价比最高。 +1. 如果一个paopao-ce部署站点运营一段时间后QPS逐渐提高到一定程度,目前架构的paopao-ce无法满足进一步的用户流量冲击,是否会采用分布式技术栈进行优化? 不会。paopao-ce将保守的采用目前的单体架构模式提供极致的QPS用户体验,如果确实需要超高QPS需求的实例部署,将另起炉灶开发另一款相应的产品,或许会采用云原生的分布式技术栈生态进行架构设计,这将是另一个paopao产品的故事序章了(前提是paopao能火出圈)。 -3. paopao-ce主要针对哪些站点运营者? -其实paopao-ce的运营形态有点类似WordPress,只不过WordPress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,有限范围内形成一个友善的社交小圈子微社区。 -### 更新记录 +## 更新记录 #### v0.0(2022-11-04) - 北野 * 初始文档,先占个位置 @@ -59,3 +68,6 @@ paopao-ce目前支持Redis作为缓存存储引擎提供缓存服务,请参考 #### v0.2(2022-12-18) - 北野 * 添加部分内容 + +#### v1.0(2022-12-19) - 北野 +* 补充部分内容 From 850671d6bee037ce5953df7efea83b9cda2122fd Mon Sep 17 00:00:00 2001 From: Michael Li Date: Mon, 19 Dec 2022 10:50:54 +0800 Subject: [PATCH 40/65] just format proposal documents --- docs/proposal/001-关于paopao-ce的设计定位.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/proposal/001-关于paopao-ce的设计定位.md b/docs/proposal/001-关于paopao-ce的设计定位.md index be54b39e..a1d084cb 100644 --- a/docs/proposal/001-关于paopao-ce的设计定位.md +++ b/docs/proposal/001-关于paopao-ce的设计定位.md @@ -46,12 +46,12 @@ paopao-ce在代码实现上采用 **单体架构模式、分层设计、功能 ## 疑问 -1. paopao-ce主要针对哪些站点运营者? +1. paopao-ce主要针对哪些站点运营者? 其实paopao-ce的运营形态有点类似WordPress,只不过WordPress是使用PHP语言开发的博客平台,提供的是博客服务,而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,有限范围内形成一个友善的社交小圈子微社区。 -1. paopao-ce是一个清新文艺的微社区,微社区的 `微` 是如何界定的? +1. paopao-ce是一个清新文艺的微社区,微社区的 `微` 是如何界定的? * 首先从站点用户流量层面,paopao-ce的部署一般针对的是小站点,注册用户不是很多,用户流量(QPS)也不会很高,这种情形本身很契合paopao-ce对自身微社区的服务定位; * 从代码实现层面思考,在数据存储层面的架构设计中已经假定paopao-ce提供服务的QPS不会很高,因此不会考虑类似数据库 **分库分表** 这样的设计优化来应对数据库CRUD的流量冲击,对站点推文数据的总容量也假定是单个SQL数据库提供满足查询需求的数据容量极限。 -1. paopao-ce在代码实现上为什么采用单体架构模式? +1. paopao-ce在代码实现上为什么采用单体架构模式? 一个项目的架构设计是多方面考量均衡的结果,最终的目的是满足项目的需求与长远发展。 * 从架构模式的角度来说,单体架构模式可以满足paopao-ce对自身服务定位的需求,完全有能力承载预期的用户流量QPS,所以采用单体模式架构设计是没有问题的; * 从运营者的角度来说,在能保障服务质量的前提下,最看重的还是运营成本的考量。提供一项保质保量的服务,可持续性是评价一项服务的重要指标。单体架构模式的项目部署简单,成本相对于分布式架构模式的项目也更低,假设门槛也没有那么高。黑猫白猫,能抓老鼠就是好猫, 在什么阶段就用什么技术,根据部署运营场景选择适合的技术来支撑服务,才是运营者明智的选择。 From f287c825a6668aa2af9a43cc71c28ef3826c1e70 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 20 Dec 2022 11:25:09 +0800 Subject: [PATCH 41/65] add grpc service template code and optimize service initial logic --- Makefile | 26 +- {internal/mirc/auto => auto}/api/m/v1/user.go | 0 {internal/mirc/auto => auto}/api/r/v1/user.go | 0 {internal/mirc/auto => auto}/api/s/v1/user.go | 0 .../mirc/auto => auto}/api/v1/web_core.go | 0 {internal/mirc/auto => auto}/api/x/v1/user.go | 0 auto/rpc/v1/auth.pb.go | 371 ++++++++++++++++++ auto/rpc/v1/auth_grpc.pb.go | 177 +++++++++ buf.gen.yaml | 16 + buf.work.yaml | 3 + config.yaml.sample | 5 +- go.mod | 2 + go.sum | 2 + internal/conf/conf.go | 2 + internal/conf/config.yaml | 3 + internal/conf/settting.go | 5 + internal/ims/README.md | 2 + internal/{proto/gen.go => ims/ims.go} | 2 +- internal/obs/README.md | 2 + internal/obs/obs.go | 5 + internal/proto/tweets.proto | 10 - internal/servants/admin/admin.go | 2 +- internal/servants/admin/user.go | 2 +- internal/servants/bot/bot.go | 2 +- internal/servants/bot/user.go | 2 +- internal/servants/localoss/localoss.go | 2 +- internal/servants/localoss/user.go | 2 +- internal/servants/mobile/auth.go | 17 + internal/servants/mobile/mobile.go | 10 + internal/servants/servants.go | 7 + internal/servants/space/space.go | 2 +- internal/servants/space/user.go | 2 +- internal/servants/web/core.go | 2 +- internal/servants/web/web.go | 2 +- internal/service/admin.go | 2 +- internal/service/bot.go | 2 +- internal/service/grpc_server.go | 59 +++ internal/service/grpc_service.go | 32 ++ internal/service/http_server.go | 29 +- internal/service/http_service.go | 6 +- internal/service/localoss.go | 2 +- internal/service/mobile.go | 66 ++++ internal/service/server.go | 38 ++ internal/service/service.go | 11 +- internal/service/space.go | 2 +- internal/service/web.go | 2 +- internal/service/web_old.go | 2 +- main.go | 8 +- {internal/mirc => mirc}/README.md | 0 {internal/mirc => mirc}/main.go | 12 +- {internal/mirc => mirc}/routes/README.md | 0 .../mirc => mirc}/routes/admin/README.md | 0 .../mirc => mirc}/routes/admin/v1/user.go | 0 {internal/mirc => mirc}/routes/bot/README.md | 0 {internal/mirc => mirc}/routes/bot/v1/user.go | 0 .../mirc => mirc}/routes/localoss/README.md | 0 .../mirc => mirc}/routes/localoss/v1/user.go | 0 .../mirc => mirc}/routes/space/README.md | 0 .../mirc => mirc}/routes/space/v1/user.go | 0 {internal/mirc => mirc}/routes/v1/localoss.go | 0 .../mirc => mirc}/routes/v1/web_admin.go | 0 .../mirc => mirc}/routes/v1/web_alipay.go | 0 {internal/mirc => mirc}/routes/v1/web_core.go | 0 .../mirc => mirc}/routes/v1/web_followship.go | 0 .../mirc => mirc}/routes/v1/web_friendship.go | 0 .../mirc => mirc}/routes/v1/web_loose.go | 0 {internal/mirc => mirc}/routes/v1/web_priv.go | 0 {internal/mirc => mirc}/routes/v1/web_pub.go | 0 pkg/util/banner.go | 2 +- {internal/proto => proto}/RADME.md | 0 proto/buf.lock | 7 + proto/buf.yaml | 10 + proto/v1/auth.proto | 29 ++ 73 files changed, 933 insertions(+), 75 deletions(-) rename {internal/mirc/auto => auto}/api/m/v1/user.go (100%) rename {internal/mirc/auto => auto}/api/r/v1/user.go (100%) rename {internal/mirc/auto => auto}/api/s/v1/user.go (100%) rename {internal/mirc/auto => auto}/api/v1/web_core.go (100%) rename {internal/mirc/auto => auto}/api/x/v1/user.go (100%) create mode 100644 auto/rpc/v1/auth.pb.go create mode 100644 auto/rpc/v1/auth_grpc.pb.go create mode 100644 buf.gen.yaml create mode 100644 buf.work.yaml create mode 100644 internal/ims/README.md rename internal/{proto/gen.go => ims/ims.go} (91%) create mode 100644 internal/obs/README.md create mode 100644 internal/obs/obs.go delete mode 100644 internal/proto/tweets.proto create mode 100644 internal/servants/mobile/auth.go create mode 100644 internal/servants/mobile/mobile.go create mode 100644 internal/service/grpc_server.go create mode 100644 internal/service/grpc_service.go create mode 100644 internal/service/mobile.go create mode 100644 internal/service/server.go rename {internal/mirc => mirc}/README.md (100%) rename {internal/mirc => mirc}/main.go (61%) rename {internal/mirc => mirc}/routes/README.md (100%) rename {internal/mirc => mirc}/routes/admin/README.md (100%) rename {internal/mirc => mirc}/routes/admin/v1/user.go (100%) rename {internal/mirc => mirc}/routes/bot/README.md (100%) rename {internal/mirc => mirc}/routes/bot/v1/user.go (100%) rename {internal/mirc => mirc}/routes/localoss/README.md (100%) rename {internal/mirc => mirc}/routes/localoss/v1/user.go (100%) rename {internal/mirc => mirc}/routes/space/README.md (100%) rename {internal/mirc => mirc}/routes/space/v1/user.go (100%) rename {internal/mirc => mirc}/routes/v1/localoss.go (100%) rename {internal/mirc => mirc}/routes/v1/web_admin.go (100%) rename {internal/mirc => mirc}/routes/v1/web_alipay.go (100%) rename {internal/mirc => mirc}/routes/v1/web_core.go (100%) rename {internal/mirc => mirc}/routes/v1/web_followship.go (100%) rename {internal/mirc => mirc}/routes/v1/web_friendship.go (100%) rename {internal/mirc => mirc}/routes/v1/web_loose.go (100%) rename {internal/mirc => mirc}/routes/v1/web_priv.go (100%) rename {internal/mirc => mirc}/routes/v1/web_pub.go (100%) rename {internal/proto => proto}/RADME.md (100%) create mode 100644 proto/buf.lock create mode 100644 proto/buf.yaml create mode 100644 proto/v1/auth.proto diff --git a/Makefile b/Makefile index dd26e18c..3104045c 100644 --- a/Makefile +++ b/Makefile @@ -73,12 +73,22 @@ generate: gen-mir gen-grpc .PHONY: gen-mir gen-mir: - @go generate internal/mirc/main.go - @go fmt ./internal/mirc/... + @go generate mirc/main.go + @go fmt ./auto/api/... .PHONY: gen-grpc gen-grpc: - @go fmt ./internal/proto/... + @rm -rf auto/rpc + @buf generate proto + @go fmt ./auto/rpc/... + +.PHONY: proto-mod +proto-mod: + @cd proto/ && buf mod update + +.PHONY: proto-lint +proto-lint: + @cd proto/ && buf lint clean: @go clean @@ -95,7 +105,15 @@ test: @go test ./... pre-commit: fmt - go mod tidy + @go mod tidy + +.PHONY: install-protobuf-plugins +install-protobuf-plugins: + @go install github.com/bufbuild/buf/cmd/buf@v1.11.0 + @go install github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking@v1.11.0 + @go install github.com/bufbuild/buf/cmd/protoc-gen-buf-lint@v1.11.0 + @go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + @go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest help: @echo "make: make" diff --git a/internal/mirc/auto/api/m/v1/user.go b/auto/api/m/v1/user.go similarity index 100% rename from internal/mirc/auto/api/m/v1/user.go rename to auto/api/m/v1/user.go diff --git a/internal/mirc/auto/api/r/v1/user.go b/auto/api/r/v1/user.go similarity index 100% rename from internal/mirc/auto/api/r/v1/user.go rename to auto/api/r/v1/user.go diff --git a/internal/mirc/auto/api/s/v1/user.go b/auto/api/s/v1/user.go similarity index 100% rename from internal/mirc/auto/api/s/v1/user.go rename to auto/api/s/v1/user.go diff --git a/internal/mirc/auto/api/v1/web_core.go b/auto/api/v1/web_core.go similarity index 100% rename from internal/mirc/auto/api/v1/web_core.go rename to auto/api/v1/web_core.go diff --git a/internal/mirc/auto/api/x/v1/user.go b/auto/api/x/v1/user.go similarity index 100% rename from internal/mirc/auto/api/x/v1/user.go rename to auto/api/x/v1/user.go diff --git a/auto/rpc/v1/auth.pb.go b/auto/rpc/v1/auth.pb.go new file mode 100644 index 00000000..ab5109a6 --- /dev/null +++ b/auto/rpc/v1/auth.pb.go @@ -0,0 +1,371 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc (unknown) +// source: v1/auth.proto + +package v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type User struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PhoneNum string `protobuf:"bytes,1,opt,name=phoneNum,proto3" json:"phoneNum,omitempty"` +} + +func (x *User) Reset() { + *x = User{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_auth_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *User) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*User) ProtoMessage() {} + +func (x *User) ProtoReflect() protoreflect.Message { + mi := &file_v1_auth_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use User.ProtoReflect.Descriptor instead. +func (*User) Descriptor() ([]byte, []int) { + return file_v1_auth_proto_rawDescGZIP(), []int{0} +} + +func (x *User) GetPhoneNum() string { + if x != nil { + return x.PhoneNum + } + return "" +} + +type UserVerify struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PhoneNum string `protobuf:"bytes,1,opt,name=phoneNum,proto3" json:"phoneNum,omitempty"` + VerificationCode string `protobuf:"bytes,2,opt,name=VerificationCode,proto3" json:"VerificationCode,omitempty"` +} + +func (x *UserVerify) Reset() { + *x = UserVerify{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_auth_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserVerify) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserVerify) ProtoMessage() {} + +func (x *UserVerify) ProtoReflect() protoreflect.Message { + mi := &file_v1_auth_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserVerify.ProtoReflect.Descriptor instead. +func (*UserVerify) Descriptor() ([]byte, []int) { + return file_v1_auth_proto_rawDescGZIP(), []int{1} +} + +func (x *UserVerify) GetPhoneNum() string { + if x != nil { + return x.PhoneNum + } + return "" +} + +func (x *UserVerify) GetVerificationCode() string { + if x != nil { + return x.VerificationCode + } + return "" +} + +type LoginReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StatuCode int32 `protobuf:"varint,1,opt,name=statuCode,proto3" json:"statuCode,omitempty"` + Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"` +} + +func (x *LoginReply) Reset() { + *x = LoginReply{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_auth_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoginReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoginReply) ProtoMessage() {} + +func (x *LoginReply) ProtoReflect() protoreflect.Message { + mi := &file_v1_auth_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoginReply.ProtoReflect.Descriptor instead. +func (*LoginReply) Descriptor() ([]byte, []int) { + return file_v1_auth_proto_rawDescGZIP(), []int{2} +} + +func (x *LoginReply) GetStatuCode() int32 { + if x != nil { + return x.StatuCode + } + return 0 +} + +func (x *LoginReply) GetToken() string { + if x != nil { + return x.Token + } + return "" +} + +type ActionReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StatusCode int32 `protobuf:"varint,1,opt,name=statusCode,proto3" json:"statusCode,omitempty"` +} + +func (x *ActionReply) Reset() { + *x = ActionReply{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_auth_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ActionReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ActionReply) ProtoMessage() {} + +func (x *ActionReply) ProtoReflect() protoreflect.Message { + mi := &file_v1_auth_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ActionReply.ProtoReflect.Descriptor instead. +func (*ActionReply) Descriptor() ([]byte, []int) { + return file_v1_auth_proto_rawDescGZIP(), []int{3} +} + +func (x *ActionReply) GetStatusCode() int32 { + if x != nil { + return x.StatusCode + } + return 0 +} + +var File_v1_auth_proto protoreflect.FileDescriptor + +var file_v1_auth_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x04, 0x61, 0x75, 0x74, 0x68, 0x22, 0x22, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, + 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x22, 0x54, 0x0a, 0x0a, 0x55, 0x73, 0x65, + 0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, + 0x4e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, + 0x4e, 0x75, 0x6d, 0x12, 0x2a, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x22, + 0x40, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1c, 0x0a, + 0x09, 0x73, 0x74, 0x61, 0x74, 0x75, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x75, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x22, 0x2d, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, + 0x32, 0x89, 0x01, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x12, 0x29, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x0a, 0x2e, + 0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x11, 0x2e, 0x61, 0x75, 0x74, 0x68, + 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x05, + 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x0a, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x1a, 0x10, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x12, 0x27, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x0a, 0x2e, + 0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x11, 0x2e, 0x61, 0x75, 0x74, 0x68, + 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x42, 0x6f, 0x0a, 0x08, + 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x42, 0x09, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x72, 0x6f, 0x63, 0x62, 0x6f, 0x73, 0x73, 0x2f, 0x70, 0x61, 0x6f, 0x70, 0x61, 0x6f, + 0x2d, 0x63, 0x65, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, 0xa2, + 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x04, 0x41, 0x75, 0x74, 0x68, 0xca, 0x02, 0x04, 0x41, + 0x75, 0x74, 0x68, 0xe2, 0x02, 0x10, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x04, 0x41, 0x75, 0x74, 0x68, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_v1_auth_proto_rawDescOnce sync.Once + file_v1_auth_proto_rawDescData = file_v1_auth_proto_rawDesc +) + +func file_v1_auth_proto_rawDescGZIP() []byte { + file_v1_auth_proto_rawDescOnce.Do(func() { + file_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_v1_auth_proto_rawDescData) + }) + return file_v1_auth_proto_rawDescData +} + +var file_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_v1_auth_proto_goTypes = []interface{}{ + (*User)(nil), // 0: auth.User + (*UserVerify)(nil), // 1: auth.UserVerify + (*LoginReply)(nil), // 2: auth.LoginReply + (*ActionReply)(nil), // 3: auth.ActionReply +} +var file_v1_auth_proto_depIdxs = []int32{ + 0, // 0: auth.Authenticate.preLogin:input_type -> auth.User + 0, // 1: auth.Authenticate.login:input_type -> auth.User + 0, // 2: auth.Authenticate.logout:input_type -> auth.User + 3, // 3: auth.Authenticate.preLogin:output_type -> auth.ActionReply + 2, // 4: auth.Authenticate.login:output_type -> auth.LoginReply + 3, // 5: auth.Authenticate.logout:output_type -> auth.ActionReply + 3, // [3:6] is the sub-list for method output_type + 0, // [0:3] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_v1_auth_proto_init() } +func file_v1_auth_proto_init() { + if File_v1_auth_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_v1_auth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*User); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_auth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserVerify); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_auth_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_auth_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ActionReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_v1_auth_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_v1_auth_proto_goTypes, + DependencyIndexes: file_v1_auth_proto_depIdxs, + MessageInfos: file_v1_auth_proto_msgTypes, + }.Build() + File_v1_auth_proto = out.File + file_v1_auth_proto_rawDesc = nil + file_v1_auth_proto_goTypes = nil + file_v1_auth_proto_depIdxs = nil +} diff --git a/auto/rpc/v1/auth_grpc.pb.go b/auto/rpc/v1/auth_grpc.pb.go new file mode 100644 index 00000000..64fdc1d1 --- /dev/null +++ b/auto/rpc/v1/auth_grpc.pb.go @@ -0,0 +1,177 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc (unknown) +// source: v1/auth.proto + +package v1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// AuthenticateClient is the client API for Authenticate service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AuthenticateClient interface { + PreLogin(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) + Login(ctx context.Context, in *User, opts ...grpc.CallOption) (*LoginReply, error) + Logout(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) +} + +type authenticateClient struct { + cc grpc.ClientConnInterface +} + +func NewAuthenticateClient(cc grpc.ClientConnInterface) AuthenticateClient { + return &authenticateClient{cc} +} + +func (c *authenticateClient) PreLogin(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) { + out := new(ActionReply) + err := c.cc.Invoke(ctx, "/auth.Authenticate/preLogin", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authenticateClient) Login(ctx context.Context, in *User, opts ...grpc.CallOption) (*LoginReply, error) { + out := new(LoginReply) + err := c.cc.Invoke(ctx, "/auth.Authenticate/login", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *authenticateClient) Logout(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) { + out := new(ActionReply) + err := c.cc.Invoke(ctx, "/auth.Authenticate/logout", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AuthenticateServer is the server API for Authenticate service. +// All implementations must embed UnimplementedAuthenticateServer +// for forward compatibility +type AuthenticateServer interface { + PreLogin(context.Context, *User) (*ActionReply, error) + Login(context.Context, *User) (*LoginReply, error) + Logout(context.Context, *User) (*ActionReply, error) + mustEmbedUnimplementedAuthenticateServer() +} + +// UnimplementedAuthenticateServer must be embedded to have forward compatible implementations. +type UnimplementedAuthenticateServer struct { +} + +func (UnimplementedAuthenticateServer) PreLogin(context.Context, *User) (*ActionReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method PreLogin not implemented") +} +func (UnimplementedAuthenticateServer) Login(context.Context, *User) (*LoginReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") +} +func (UnimplementedAuthenticateServer) Logout(context.Context, *User) (*ActionReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented") +} +func (UnimplementedAuthenticateServer) mustEmbedUnimplementedAuthenticateServer() {} + +// UnsafeAuthenticateServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AuthenticateServer will +// result in compilation errors. +type UnsafeAuthenticateServer interface { + mustEmbedUnimplementedAuthenticateServer() +} + +func RegisterAuthenticateServer(s grpc.ServiceRegistrar, srv AuthenticateServer) { + s.RegisterService(&Authenticate_ServiceDesc, srv) +} + +func _Authenticate_PreLogin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(User) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthenticateServer).PreLogin(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/auth.Authenticate/preLogin", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthenticateServer).PreLogin(ctx, req.(*User)) + } + return interceptor(ctx, in, info, handler) +} + +func _Authenticate_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(User) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthenticateServer).Login(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/auth.Authenticate/login", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthenticateServer).Login(ctx, req.(*User)) + } + return interceptor(ctx, in, info, handler) +} + +func _Authenticate_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(User) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AuthenticateServer).Logout(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/auth.Authenticate/logout", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AuthenticateServer).Logout(ctx, req.(*User)) + } + return interceptor(ctx, in, info, handler) +} + +// Authenticate_ServiceDesc is the grpc.ServiceDesc for Authenticate service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Authenticate_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "auth.Authenticate", + HandlerType: (*AuthenticateServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "preLogin", + Handler: _Authenticate_PreLogin_Handler, + }, + { + MethodName: "login", + Handler: _Authenticate_Login_Handler, + }, + { + MethodName: "logout", + Handler: _Authenticate_Logout_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "v1/auth.proto", +} diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 00000000..bf9ba452 --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,16 @@ +version: v1 +managed: + enabled: true + go_package_prefix: + default: github.com/rocboss/paopao-ce/auto/rpc + except: + - buf.build/googleapis/googleapis +plugins: + - plugin: go + out: auto/rpc + opt: paths=source_relative + - plugin: go-grpc + out: auto/rpc + opt: + - paths=source_relative + - require_unimplemented_servers=true diff --git a/buf.work.yaml b/buf.work.yaml new file mode 100644 index 00000000..1878b341 --- /dev/null +++ b/buf.work.yaml @@ -0,0 +1,3 @@ +version: v1 +directories: + - proto diff --git a/config.yaml.sample b/config.yaml.sample index a3df0dd9..30535257 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -19,7 +19,7 @@ Features: Base: ["Redis", "PhoneBind"] Docs: ["Docs:OpenAPI"] Deprecated: ["Deprecated:OldWeb"] - Service: ["Admin", "SpaceX", "Bot", "LocalOSS"] + Service: ["Admin", "SpaceX", "Bot", "LocalOSS", "Mobile"] Option: ["SimpleCacheIndex"] Sms: "SmsJuhe" WebServer: # Web服务 @@ -52,6 +52,9 @@ DocsServer: # 开发文档服务 HttpPort: 8011 ReadTimeout: 60 WriteTimeout: 60 +MobileServer: # 移动端grpc api服务 + Host: 0.0.0.0 + Port: 8020 SmsJuhe: Gateway: https://v.juhe.cn/sms/send Key: diff --git a/go.mod b/go.mod index f5279d4d..eee36fdb 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/spf13/viper v1.14.0 github.com/tencentyun/cos-go-sdk-v5 v0.7.35 github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc + google.golang.org/grpc v1.50.1 google.golang.org/protobuf v1.28.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/resty.v1 v1.12.0 @@ -117,6 +118,7 @@ require ( golang.org/x/text v0.4.0 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect golang.org/x/tools v0.1.12 // indirect + google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 88972d10..ca0a32cb 100644 --- a/go.sum +++ b/go.sum @@ -2066,6 +2066,7 @@ google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2100,6 +2101,7 @@ google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5 google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/internal/conf/conf.go b/internal/conf/conf.go index bdadf5e4..35755f04 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -30,6 +30,7 @@ var ( BotServerSetting *HttpServerSettingS LocalossServerSetting *HttpServerSettingS DocsServerSetting *HttpServerSettingS + MobileServerSetting *GRPCServerSettingS AppSetting *AppSettingS CacheIndexSetting *CacheIndexSettingS SimpleCacheIndexSetting *SimpleCacheIndexSettingS @@ -72,6 +73,7 @@ func setupSetting(suite []string, noDefault bool) error { "BotServer": &BotServerSetting, "LocalossServer": &LocalossServerSetting, "DocsServer": &DocsServerSetting, + "MobileServer": &MobileServerSetting, "CacheIndex": &CacheIndexSetting, "SimpleCacheIndex": &SimpleCacheIndexSetting, "BigCacheIndex": &BigCacheIndexSetting, diff --git a/internal/conf/config.yaml b/internal/conf/config.yaml index 307e8451..6c642ed8 100644 --- a/internal/conf/config.yaml +++ b/internal/conf/config.yaml @@ -43,6 +43,9 @@ DocsServer: # 开发文档服务 HttpPort: 8011 ReadTimeout: 60 WriteTimeout: 60 +MobileServer: # 移动端grpc api服务 + Host: 0.0.0.0 + Port: 8020 SmsJuhe: Gateway: https://v.juhe.cn/sms/send Key: diff --git a/internal/conf/settting.go b/internal/conf/settting.go index 9fa232db..0c543706 100644 --- a/internal/conf/settting.go +++ b/internal/conf/settting.go @@ -57,6 +57,11 @@ type HttpServerSettingS struct { WriteTimeout time.Duration } +type GRPCServerSettingS struct { + Host string + Port string +} + type AppSettingS struct { RunMode string MaxCommentCount int64 diff --git a/internal/ims/README.md b/internal/ims/README.md new file mode 100644 index 00000000..d095421b --- /dev/null +++ b/internal/ims/README.md @@ -0,0 +1,2 @@ +### IMS(Instant Message Push System) +消息推送模块,用于优化@、私信、系统通知等消息服务,目前还没实现,先占个位置~ diff --git a/internal/proto/gen.go b/internal/ims/ims.go similarity index 91% rename from internal/proto/gen.go rename to internal/ims/ims.go index adb9c8db..1042e45d 100644 --- a/internal/proto/gen.go +++ b/internal/ims/ims.go @@ -2,4 +2,4 @@ // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. -package proto +package ims diff --git a/internal/obs/README.md b/internal/obs/README.md new file mode 100644 index 00000000..f56a1ef9 --- /dev/null +++ b/internal/obs/README.md @@ -0,0 +1,2 @@ +### OBS(Object Blob Storage System) +简单对象存储模块,目前还没实现,先占个位置~ diff --git a/internal/obs/obs.go b/internal/obs/obs.go new file mode 100644 index 00000000..13923b07 --- /dev/null +++ b/internal/obs/obs.go @@ -0,0 +1,5 @@ +// 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 obs diff --git a/internal/proto/tweets.proto b/internal/proto/tweets.proto deleted file mode 100644 index 1fcc9364..00000000 --- a/internal/proto/tweets.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto3"; - -package paopao; - -option go_package = "proto"; - -message Tag { - string name = 1; - int32 type = 2; -} diff --git a/internal/servants/admin/admin.go b/internal/servants/admin/admin.go index 3fa2a7cf..409bdd78 100644 --- a/internal/servants/admin/admin.go +++ b/internal/servants/admin/admin.go @@ -6,7 +6,7 @@ package admin import ( "github.com/gin-gonic/gin" - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/m/v1" + api "github.com/rocboss/paopao-ce/auto/api/m/v1" ) // RouteWeb register Manager route diff --git a/internal/servants/admin/user.go b/internal/servants/admin/user.go index 6c3f11ab..fef348cf 100644 --- a/internal/servants/admin/user.go +++ b/internal/servants/admin/user.go @@ -5,7 +5,7 @@ package admin import ( - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/m/v1" + api "github.com/rocboss/paopao-ce/auto/api/m/v1" "github.com/rocboss/paopao-ce/internal/servants/base" ) diff --git a/internal/servants/bot/bot.go b/internal/servants/bot/bot.go index 6ddd6846..a2e0e699 100644 --- a/internal/servants/bot/bot.go +++ b/internal/servants/bot/bot.go @@ -6,7 +6,7 @@ package bot import ( "github.com/gin-gonic/gin" - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/r/v1" + api "github.com/rocboss/paopao-ce/auto/api/r/v1" ) // RouteBot register Bot route diff --git a/internal/servants/bot/user.go b/internal/servants/bot/user.go index 9f17a6e8..aae9048c 100644 --- a/internal/servants/bot/user.go +++ b/internal/servants/bot/user.go @@ -5,7 +5,7 @@ package bot import ( - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/r/v1" + api "github.com/rocboss/paopao-ce/auto/api/r/v1" "github.com/rocboss/paopao-ce/internal/servants/base" ) diff --git a/internal/servants/localoss/localoss.go b/internal/servants/localoss/localoss.go index 721f0407..97fdafbe 100644 --- a/internal/servants/localoss/localoss.go +++ b/internal/servants/localoss/localoss.go @@ -8,8 +8,8 @@ import ( "path/filepath" "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/auto/api/s/v1" "github.com/rocboss/paopao-ce/internal/conf" - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/s/v1" "github.com/sirupsen/logrus" ) diff --git a/internal/servants/localoss/user.go b/internal/servants/localoss/user.go index b8d2309a..37fc715e 100644 --- a/internal/servants/localoss/user.go +++ b/internal/servants/localoss/user.go @@ -5,7 +5,7 @@ package localoss import ( - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/s/v1" + api "github.com/rocboss/paopao-ce/auto/api/s/v1" "github.com/rocboss/paopao-ce/internal/servants/base" ) diff --git a/internal/servants/mobile/auth.go b/internal/servants/mobile/auth.go new file mode 100644 index 00000000..00a9b747 --- /dev/null +++ b/internal/servants/mobile/auth.go @@ -0,0 +1,17 @@ +package mobile + +import ( + api "github.com/rocboss/paopao-ce/auto/rpc/v1" +) + +var ( + _ api.AuthenticateServer = (*authenticateServant)(nil) +) + +type authenticateServant struct { + api.UnimplementedAuthenticateServer +} + +func newAuthenticateServer() *authenticateServant { + return &authenticateServant{} +} diff --git a/internal/servants/mobile/mobile.go b/internal/servants/mobile/mobile.go new file mode 100644 index 00000000..425b71c1 --- /dev/null +++ b/internal/servants/mobile/mobile.go @@ -0,0 +1,10 @@ +package mobile + +import ( + api "github.com/rocboss/paopao-ce/auto/rpc/v1" + "google.golang.org/grpc" +) + +func RegisterServants(s *grpc.Server) { + api.RegisterAuthenticateServer(s, newAuthenticateServer()) +} diff --git a/internal/servants/servants.go b/internal/servants/servants.go index dd03b1de..74d7e8ce 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -11,9 +11,11 @@ import ( "github.com/rocboss/paopao-ce/internal/servants/bot" "github.com/rocboss/paopao-ce/internal/servants/docs" "github.com/rocboss/paopao-ce/internal/servants/localoss" + "github.com/rocboss/paopao-ce/internal/servants/mobile" "github.com/rocboss/paopao-ce/internal/servants/space" "github.com/rocboss/paopao-ce/internal/servants/statick" "github.com/rocboss/paopao-ce/internal/servants/web" + "google.golang.org/grpc" ) // RegisterWebServants register all the servants to gin.Engine @@ -47,3 +49,8 @@ func RegisterBotServants(e *gin.Engine) { func RegisterLocalossServants(e *gin.Engine) { localoss.RouteLocaloss(e) } + +// RegisterMobileServants register all the servants to grpc.Server +func RegisterMobileServants(s *grpc.Server) { + mobile.RegisterServants(s) +} diff --git a/internal/servants/space/space.go b/internal/servants/space/space.go index 311f76b0..c9952035 100644 --- a/internal/servants/space/space.go +++ b/internal/servants/space/space.go @@ -6,7 +6,7 @@ package space import ( "github.com/gin-gonic/gin" - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/x/v1" + api "github.com/rocboss/paopao-ce/auto/api/x/v1" ) // RouteWeb register SpaceX route diff --git a/internal/servants/space/user.go b/internal/servants/space/user.go index 2e6014a0..d0e5c632 100644 --- a/internal/servants/space/user.go +++ b/internal/servants/space/user.go @@ -5,7 +5,7 @@ package space import ( - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/x/v1" + api "github.com/rocboss/paopao-ce/auto/api/x/v1" "github.com/rocboss/paopao-ce/internal/servants/base" ) diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 085e5bcf..75c1409a 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -5,7 +5,7 @@ package web import ( - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" + api "github.com/rocboss/paopao-ce/auto/api/v1" "github.com/rocboss/paopao-ce/internal/servants/base" ) diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index 76ac9dd3..044440fa 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -6,7 +6,7 @@ package web import ( "github.com/gin-gonic/gin" - api "github.com/rocboss/paopao-ce/internal/mirc/auto/api/v1" + api "github.com/rocboss/paopao-ce/auto/api/v1" ) // RouteWeb register web route diff --git a/internal/service/admin.go b/internal/service/admin.go index 7acd408e..e91b68f5 100644 --- a/internal/service/admin.go +++ b/internal/service/admin.go @@ -32,7 +32,7 @@ func (s *adminService) Version() *semver.Version { return semver.MustParse("v0.1.0") } -func (s *adminService) Init() error { +func (s *adminService) OnInit() error { s.registerRoute(servants.RegisterAdminServants) return nil } diff --git a/internal/service/bot.go b/internal/service/bot.go index 38fd97c3..2b9eef20 100644 --- a/internal/service/bot.go +++ b/internal/service/bot.go @@ -32,7 +32,7 @@ func (s *botService) Version() *semver.Version { return semver.MustParse("v0.1.0") } -func (s *botService) Init() error { +func (s *botService) OnInit() error { s.registerRoute(servants.RegisterBotServants) return nil } diff --git a/internal/service/grpc_server.go b/internal/service/grpc_server.go new file mode 100644 index 00000000..3f0a3b94 --- /dev/null +++ b/internal/service/grpc_server.go @@ -0,0 +1,59 @@ +// 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 service + +import ( + "net" + "sync" + + "google.golang.org/grpc" +) + +// grpcServer wraper for grpc.Server +type grpcServer struct { + sync.RWMutex + + listener net.Listener + server *grpc.Server + serverStatus uint8 +} + +func (s *grpcServer) status() uint8 { + s.RLock() + defer s.RUnlock() + + return s.serverStatus +} + +func (s *grpcServer) start() error { + s.Lock() + if s.serverStatus == _statusServerStarted || s.serverStatus == _statusServerStoped { + return nil + } + oldStatus := s.serverStatus + s.serverStatus = _statusServerStarted + s.Unlock() + + if err := s.server.Serve(s.listener); err != nil { + s.Lock() + s.serverStatus = oldStatus + s.Unlock() + + return err + } + return nil +} + +func (s *grpcServer) stop() error { + s.Lock() + defer s.Unlock() + + if s.serverStatus == _statusServerStoped || s.serverStatus == _statusServerInitilized { + return nil + } + s.server.Stop() + s.serverStatus = _statusServerStoped + return nil +} diff --git a/internal/service/grpc_service.go b/internal/service/grpc_service.go new file mode 100644 index 00000000..ded7b507 --- /dev/null +++ b/internal/service/grpc_service.go @@ -0,0 +1,32 @@ +// 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 service + +import ( + "google.golang.org/grpc" +) + +type baseGRPCService struct { + baseService + + server *grpcServer +} + +func (s *baseGRPCService) registerServer(h func(s *grpc.Server)) { + if s.server.status() != _statusServerStarted { + h(s.server.server) + } +} + +func (s *baseGRPCService) OnStart() error { + if err := s.server.start(); err != nil { + return err + } + return nil +} + +func (s *baseGRPCService) OnStop() error { + return s.server.stop() +} diff --git a/internal/service/http_server.go b/internal/service/http_server.go index 4a8fdf3b..a7ca3879 100644 --- a/internal/service/http_server.go +++ b/internal/service/http_server.go @@ -12,16 +12,6 @@ import ( "github.com/gin-gonic/gin" ) -var ( - httpServers = make(map[string]*httpServer) -) - -const ( - httpServerInitilized uint8 = iota + 1 - httpServerStarted - httpServerStoped -) - // httpServer wraper for gin.engine and http.Server type httpServer struct { sync.RWMutex @@ -40,11 +30,11 @@ func (s *httpServer) status() uint8 { func (s *httpServer) start() error { s.Lock() - if s.serverStatus == httpServerStarted || s.serverStatus == httpServerStoped { + if s.serverStatus == _statusServerStarted || s.serverStatus == _statusServerStoped { return nil } oldStatus := s.serverStatus - s.serverStatus = httpServerStarted + s.serverStatus = _statusServerStarted s.Unlock() if err := s.server.ListenAndServe(); err != nil { @@ -61,23 +51,12 @@ func (s *httpServer) stop() error { s.Lock() defer s.Unlock() - if s.serverStatus == httpServerStoped || s.serverStatus == httpServerInitilized { + if s.serverStatus == _statusServerStoped || s.serverStatus == _statusServerInitilized { return nil } if err := s.server.Shutdown(context.Background()); err != nil { return err } - s.serverStatus = httpServerStoped + s.serverStatus = _statusServerStoped return nil } - -func httpServerFrom(addr string, newServer func() *httpServer) *httpServer { - s, exist := httpServers[addr] - if exist { - return s - } - s = newServer() - s.serverStatus = httpServerInitilized - httpServers[addr] = s - return s -} diff --git a/internal/service/http_service.go b/internal/service/http_service.go index fc7ce9b6..42f3f90c 100644 --- a/internal/service/http_service.go +++ b/internal/service/http_service.go @@ -15,18 +15,18 @@ type baseHttpService struct { } func (s *baseHttpService) registerRoute(h func(e *gin.Engine)) { - if s.server.status() != httpServerStarted { + if s.server.status() != _statusServerStarted { h(s.server.e) } } -func (s *baseHttpService) Start() error { +func (s *baseHttpService) OnStart() error { if err := s.server.start(); err != nil { return err } return nil } -func (s *baseHttpService) Stop() error { +func (s *baseHttpService) OnStop() error { return s.server.stop() } diff --git a/internal/service/localoss.go b/internal/service/localoss.go index 4c09412d..3f33e7ef 100644 --- a/internal/service/localoss.go +++ b/internal/service/localoss.go @@ -31,7 +31,7 @@ func (s *localossService) Version() *semver.Version { return semver.MustParse("v0.1.0") } -func (s *localossService) Init() error { +func (s *localossService) OnInit() error { s.registerRoute(servants.RegisterLocalossServants) return nil } diff --git a/internal/service/mobile.go b/internal/service/mobile.go new file mode 100644 index 00000000..262d35af --- /dev/null +++ b/internal/service/mobile.go @@ -0,0 +1,66 @@ +// 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 service + +import ( + "fmt" + "log" + "net" + + "github.com/Masterminds/semver/v3" + "github.com/fatih/color" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" + "google.golang.org/grpc" +) + +var ( + _ Service = (*mobileService)(nil) +) + +type mobileService struct { + *baseGRPCService +} + +func (s *mobileService) Name() string { + return "MobileService" +} + +func (s *mobileService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + +func (s *mobileService) OnInit() error { + s.registerServer(servants.RegisterMobileServants) + return nil +} + +func (s *mobileService) String() string { + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.MobileServerSetting.Host, conf.MobileServerSetting.Port)) +} + +func newMobileService() Service { + addr := conf.MobileServerSetting.Host + ":" + conf.MobileServerSetting.Port + server := grpcServerFrom(addr, func() *grpcServer { + l, err := net.Listen("tcp", addr) + if err != nil { + // TODO: optimize error process + log.Fatal(fmt.Errorf("failed to listen: %w", err)) + } + + // TODO: init grpc.Server + s := grpc.NewServer() + + return &grpcServer{ + listener: l, + server: s, + } + }) + return &mobileService{ + baseGRPCService: &baseGRPCService{ + server: server, + }, + } +} diff --git a/internal/service/server.go b/internal/service/server.go new file mode 100644 index 00000000..f2439777 --- /dev/null +++ b/internal/service/server.go @@ -0,0 +1,38 @@ +// 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 service + +var ( + httpServers = make(map[string]*httpServer) + grpcServers = make(map[string]*grpcServer) +) + +const ( + _statusServerInitilized uint8 = iota + 1 + _statusServerStarted + _statusServerStoped +) + +func httpServerFrom(addr string, newServer func() *httpServer) *httpServer { + s, exist := httpServers[addr] + if exist { + return s + } + s = newServer() + s.serverStatus = _statusServerInitilized + httpServers[addr] = s + return s +} + +func grpcServerFrom(addr string, newServer func() *grpcServer) *grpcServer { + s, exist := grpcServers[addr] + if exist { + return s + } + s = newServer() + s.serverStatus = _statusServerInitilized + grpcServers[addr] = s + return s +} diff --git a/internal/service/service.go b/internal/service/service.go index c1f8aa94..957979c3 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -15,9 +15,9 @@ import ( type Service interface { Name() string Version() *semver.Version - Init() error - Start() error - Stop() error + OnInit() error + OnStart() error + OnStop() error } type baseService types.Empty @@ -38,7 +38,7 @@ func (baseService) String() string { func InitService() []Service { ss := newService() for _, s := range ss { - if err := s.Init(); err != nil { + if err := s.OnInit(); err != nil { log.Fatalf("initial %s service error: %s", s.Name(), err) } } @@ -79,6 +79,9 @@ func newService() (ss []Service) { "NativeOBS": func() { ss = append(ss, newLocalossService()) }, + "Mobile": func() { + ss = append(ss, newMobileService()) + }, }) return } diff --git a/internal/service/space.go b/internal/service/space.go index 30dfeec0..fd6ee217 100644 --- a/internal/service/space.go +++ b/internal/service/space.go @@ -32,7 +32,7 @@ func (s *spaceXService) Version() *semver.Version { return semver.MustParse("v0.1.0") } -func (s *spaceXService) Init() error { +func (s *spaceXService) OnInit() error { s.registerRoute(servants.RegisterSpaceXServants) return nil } diff --git a/internal/service/web.go b/internal/service/web.go index e983e6c5..56b8ef3b 100644 --- a/internal/service/web.go +++ b/internal/service/web.go @@ -32,7 +32,7 @@ func (s *webService) Version() *semver.Version { return semver.MustParse("v0.1.0") } -func (s *webService) Init() error { +func (s *webService) OnInit() error { s.registerRoute(servants.RegisterWebServants) return nil } diff --git a/internal/service/web_old.go b/internal/service/web_old.go index de51c072..70e7ec37 100644 --- a/internal/service/web_old.go +++ b/internal/service/web_old.go @@ -30,7 +30,7 @@ func (s *oldWebService) Version() *semver.Version { return semver.MustParse("v0.1.0") } -func (s *oldWebService) Init() error { +func (s *oldWebService) OnInit() error { s.registerRoute(routers.RegisterRoute) return nil } diff --git a/main.go b/main.go index aafc14e3..5e0fcc01 100644 --- a/main.go +++ b/main.go @@ -61,7 +61,7 @@ func runService(wg *sync.WaitGroup, ss []service.Service) { for _, s := range ss { go func(s service.Service) { fmt.Fprintf(color.Output, "%s [start] - %s", util.SidStr(s.Name(), s.Version(), l), s) - if err := s.Start(); err != nil { + if err := s.OnStart(); err != nil { fmt.Fprintf(color.Output, "%s [start] - occurs on error: %s\n", util.SidStr(s.Name(), s.Version(), l), err) } wg.Done() @@ -79,10 +79,10 @@ func runManage(wg *sync.WaitGroup, ss []service.Service) { fmt.Fprintf(color.Output, "\nshutting down server...\n\n") l := service.MaxSidSize(ss) for _, s := range ss { - if err := s.Stop(); err != nil { - fmt.Fprintf(color.Output, "%s [stop] - occurs on error: %s\n", util.SidStr(s.Name(), s.Version(), l), err) + if err := s.OnStop(); err != nil { + fmt.Fprintf(color.Output, "%s [stop] - occurs on error: %s\n", util.SidStr(s.Name(), s.Version(), l), err) } - fmt.Fprintf(color.Output, "%s [stop] - finish...\n", util.SidStr(s.Name(), s.Version(), l)) + fmt.Fprintf(color.Output, "%s [stop] - finish...\n", util.SidStr(s.Name(), s.Version(), l)) } wg.Done() } diff --git a/internal/mirc/README.md b/mirc/README.md similarity index 100% rename from internal/mirc/README.md rename to mirc/README.md diff --git a/internal/mirc/main.go b/mirc/main.go similarity index 61% rename from internal/mirc/main.go rename to mirc/main.go index 05431a6c..a2c17cdd 100644 --- a/internal/mirc/main.go +++ b/mirc/main.go @@ -10,11 +10,11 @@ import ( . "github.com/alimy/mir/v3/core" . "github.com/alimy/mir/v3/engine" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/admin/v1" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/bot/v1" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/localoss/v1" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/space/v1" - _ "github.com/rocboss/paopao-ce/internal/mirc/routes/v1" + _ "github.com/rocboss/paopao-ce/mirc/routes/admin/v1" + _ "github.com/rocboss/paopao-ce/mirc/routes/bot/v1" + _ "github.com/rocboss/paopao-ce/mirc/routes/localoss/v1" + _ "github.com/rocboss/paopao-ce/mirc/routes/space/v1" + _ "github.com/rocboss/paopao-ce/mirc/routes/v1" ) //go:generate go run main.go @@ -24,7 +24,7 @@ func main() { RunMode(InSerialMode), GeneratorName(GeneratorGin), WatchCtxDone(true), - SinkPath("auto"), + SinkPath("../auto"), } if err := Generate(opts); err != nil { log.Fatal(err) diff --git a/internal/mirc/routes/README.md b/mirc/routes/README.md similarity index 100% rename from internal/mirc/routes/README.md rename to mirc/routes/README.md diff --git a/internal/mirc/routes/admin/README.md b/mirc/routes/admin/README.md similarity index 100% rename from internal/mirc/routes/admin/README.md rename to mirc/routes/admin/README.md diff --git a/internal/mirc/routes/admin/v1/user.go b/mirc/routes/admin/v1/user.go similarity index 100% rename from internal/mirc/routes/admin/v1/user.go rename to mirc/routes/admin/v1/user.go diff --git a/internal/mirc/routes/bot/README.md b/mirc/routes/bot/README.md similarity index 100% rename from internal/mirc/routes/bot/README.md rename to mirc/routes/bot/README.md diff --git a/internal/mirc/routes/bot/v1/user.go b/mirc/routes/bot/v1/user.go similarity index 100% rename from internal/mirc/routes/bot/v1/user.go rename to mirc/routes/bot/v1/user.go diff --git a/internal/mirc/routes/localoss/README.md b/mirc/routes/localoss/README.md similarity index 100% rename from internal/mirc/routes/localoss/README.md rename to mirc/routes/localoss/README.md diff --git a/internal/mirc/routes/localoss/v1/user.go b/mirc/routes/localoss/v1/user.go similarity index 100% rename from internal/mirc/routes/localoss/v1/user.go rename to mirc/routes/localoss/v1/user.go diff --git a/internal/mirc/routes/space/README.md b/mirc/routes/space/README.md similarity index 100% rename from internal/mirc/routes/space/README.md rename to mirc/routes/space/README.md diff --git a/internal/mirc/routes/space/v1/user.go b/mirc/routes/space/v1/user.go similarity index 100% rename from internal/mirc/routes/space/v1/user.go rename to mirc/routes/space/v1/user.go diff --git a/internal/mirc/routes/v1/localoss.go b/mirc/routes/v1/localoss.go similarity index 100% rename from internal/mirc/routes/v1/localoss.go rename to mirc/routes/v1/localoss.go diff --git a/internal/mirc/routes/v1/web_admin.go b/mirc/routes/v1/web_admin.go similarity index 100% rename from internal/mirc/routes/v1/web_admin.go rename to mirc/routes/v1/web_admin.go diff --git a/internal/mirc/routes/v1/web_alipay.go b/mirc/routes/v1/web_alipay.go similarity index 100% rename from internal/mirc/routes/v1/web_alipay.go rename to mirc/routes/v1/web_alipay.go diff --git a/internal/mirc/routes/v1/web_core.go b/mirc/routes/v1/web_core.go similarity index 100% rename from internal/mirc/routes/v1/web_core.go rename to mirc/routes/v1/web_core.go diff --git a/internal/mirc/routes/v1/web_followship.go b/mirc/routes/v1/web_followship.go similarity index 100% rename from internal/mirc/routes/v1/web_followship.go rename to mirc/routes/v1/web_followship.go diff --git a/internal/mirc/routes/v1/web_friendship.go b/mirc/routes/v1/web_friendship.go similarity index 100% rename from internal/mirc/routes/v1/web_friendship.go rename to mirc/routes/v1/web_friendship.go diff --git a/internal/mirc/routes/v1/web_loose.go b/mirc/routes/v1/web_loose.go similarity index 100% rename from internal/mirc/routes/v1/web_loose.go rename to mirc/routes/v1/web_loose.go diff --git a/internal/mirc/routes/v1/web_priv.go b/mirc/routes/v1/web_priv.go similarity index 100% rename from internal/mirc/routes/v1/web_priv.go rename to mirc/routes/v1/web_priv.go diff --git a/internal/mirc/routes/v1/web_pub.go b/mirc/routes/v1/web_pub.go similarity index 100% rename from internal/mirc/routes/v1/web_pub.go rename to mirc/routes/v1/web_pub.go diff --git a/pkg/util/banner.go b/pkg/util/banner.go index 5e9795c2..b8f16971 100644 --- a/pkg/util/banner.go +++ b/pkg/util/banner.go @@ -20,5 +20,5 @@ func PrintHelloBanner(text string) { } func SidStr(name string, version *semver.Version, size int) string { - return fmt.Sprintf(fmt.Sprintf("%%s%%-%ds", size-len(name+version.String())+4), name, version) + return fmt.Sprintf(fmt.Sprintf("%%s@%%-%ds", size-len(name+version.String())+4), name, version) } diff --git a/internal/proto/RADME.md b/proto/RADME.md similarity index 100% rename from internal/proto/RADME.md rename to proto/RADME.md diff --git a/proto/buf.lock b/proto/buf.lock new file mode 100644 index 00000000..19abf63f --- /dev/null +++ b/proto/buf.lock @@ -0,0 +1,7 @@ +# Generated by buf. DO NOT EDIT. +version: v1 +deps: + - remote: buf.build + owner: googleapis + repository: googleapis + commit: 75b4300737fb4efca0831636be94e517 diff --git a/proto/buf.yaml b/proto/buf.yaml new file mode 100644 index 00000000..eda8f330 --- /dev/null +++ b/proto/buf.yaml @@ -0,0 +1,10 @@ +version: v1 +lint: + use: + - DEFAULT +breaking: + use: + - FILE + +deps: + - buf.build/googleapis/googleapis diff --git a/proto/v1/auth.proto b/proto/v1/auth.proto new file mode 100644 index 00000000..bc18fae3 --- /dev/null +++ b/proto/v1/auth.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; + +package auth; + +option go_package = "github.com/rocboss/paopao-ce/auto/rpc"; + +message User { + string phoneNum = 1; +} + +message UserVerify { + string phoneNum = 1; + string VerificationCode = 2; +} + +message LoginReply { + int32 statuCode = 1; + string token = 2; +} + +message ActionReply { + int32 statusCode = 1; +} + +service Authenticate { + rpc preLogin(User) returns (ActionReply); + rpc login(User) returns (LoginReply); + rpc logout(User) returns (ActionReply); +} From db137b3c1c867ff844e937c94461bb9697e1b2c9 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 20 Dec 2022 11:28:52 +0800 Subject: [PATCH 42/65] change source code from mirc/routes/* => mirc/* --- mirc/README.md | 12 ++++++++++-- mirc/{routes => }/admin/README.md | 0 mirc/{routes => }/admin/v1/user.go | 0 mirc/{routes => }/bot/README.md | 0 mirc/{routes => }/bot/v1/user.go | 0 mirc/{routes => }/localoss/README.md | 0 mirc/{routes => }/localoss/v1/user.go | 0 mirc/main.go | 10 +++++----- mirc/routes/README.md | 10 ---------- mirc/{routes => }/space/README.md | 0 mirc/{routes => }/space/v1/user.go | 0 mirc/{routes => }/v1/localoss.go | 0 mirc/{routes => }/v1/web_admin.go | 0 mirc/{routes => }/v1/web_alipay.go | 0 mirc/{routes => }/v1/web_core.go | 0 mirc/{routes => }/v1/web_followship.go | 0 mirc/{routes => }/v1/web_friendship.go | 0 mirc/{routes => }/v1/web_loose.go | 0 mirc/{routes => }/v1/web_priv.go | 0 mirc/{routes => }/v1/web_pub.go | 0 20 files changed, 15 insertions(+), 17 deletions(-) rename mirc/{routes => }/admin/README.md (100%) rename mirc/{routes => }/admin/v1/user.go (100%) rename mirc/{routes => }/bot/README.md (100%) rename mirc/{routes => }/bot/v1/user.go (100%) rename mirc/{routes => }/localoss/README.md (100%) rename mirc/{routes => }/localoss/v1/user.go (100%) delete mode 100644 mirc/routes/README.md rename mirc/{routes => }/space/README.md (100%) rename mirc/{routes => }/space/v1/user.go (100%) rename mirc/{routes => }/v1/localoss.go (100%) rename mirc/{routes => }/v1/web_admin.go (100%) rename mirc/{routes => }/v1/web_alipay.go (100%) rename mirc/{routes => }/v1/web_core.go (100%) rename mirc/{routes => }/v1/web_followship.go (100%) rename mirc/{routes => }/v1/web_friendship.go (100%) rename mirc/{routes => }/v1/web_loose.go (100%) rename mirc/{routes => }/v1/web_priv.go (100%) rename mirc/{routes => }/v1/web_pub.go (100%) diff --git a/mirc/README.md b/mirc/README.md index 064cbe21..c592aa65 100644 --- a/mirc/README.md +++ b/mirc/README.md @@ -1,2 +1,10 @@ -### Mirc for paopao-ce -RESTful API for paopao-ce use [go-mir](https://github.com/alimy/mir) to generate service interface code automatic. +### RESTful API for paopao-ce +本目录包含所有RESTful API相关定义文件 + +|目录|系列API|备注| +| ----- | ----- | ----- | +|v1|/|Web v1版本RESTful API相关定义文件| +|admin|m|Admin后台运维系列相关RESTful API相关定义文件| +|space|x|SpaceX系列相关RESTful API相关定义文件| +|localoss|s| LocalOSS OBS系列RESTful API相关定义文件| +|bot|r| Bot系列相关RESTful API相关定义文件| diff --git a/mirc/routes/admin/README.md b/mirc/admin/README.md similarity index 100% rename from mirc/routes/admin/README.md rename to mirc/admin/README.md diff --git a/mirc/routes/admin/v1/user.go b/mirc/admin/v1/user.go similarity index 100% rename from mirc/routes/admin/v1/user.go rename to mirc/admin/v1/user.go diff --git a/mirc/routes/bot/README.md b/mirc/bot/README.md similarity index 100% rename from mirc/routes/bot/README.md rename to mirc/bot/README.md diff --git a/mirc/routes/bot/v1/user.go b/mirc/bot/v1/user.go similarity index 100% rename from mirc/routes/bot/v1/user.go rename to mirc/bot/v1/user.go diff --git a/mirc/routes/localoss/README.md b/mirc/localoss/README.md similarity index 100% rename from mirc/routes/localoss/README.md rename to mirc/localoss/README.md diff --git a/mirc/routes/localoss/v1/user.go b/mirc/localoss/v1/user.go similarity index 100% rename from mirc/routes/localoss/v1/user.go rename to mirc/localoss/v1/user.go diff --git a/mirc/main.go b/mirc/main.go index a2c17cdd..9136d986 100644 --- a/mirc/main.go +++ b/mirc/main.go @@ -10,11 +10,11 @@ import ( . "github.com/alimy/mir/v3/core" . "github.com/alimy/mir/v3/engine" - _ "github.com/rocboss/paopao-ce/mirc/routes/admin/v1" - _ "github.com/rocboss/paopao-ce/mirc/routes/bot/v1" - _ "github.com/rocboss/paopao-ce/mirc/routes/localoss/v1" - _ "github.com/rocboss/paopao-ce/mirc/routes/space/v1" - _ "github.com/rocboss/paopao-ce/mirc/routes/v1" + _ "github.com/rocboss/paopao-ce/mirc/admin/v1" + _ "github.com/rocboss/paopao-ce/mirc/bot/v1" + _ "github.com/rocboss/paopao-ce/mirc/localoss/v1" + _ "github.com/rocboss/paopao-ce/mirc/space/v1" + _ "github.com/rocboss/paopao-ce/mirc/v1" ) //go:generate go run main.go diff --git a/mirc/routes/README.md b/mirc/routes/README.md deleted file mode 100644 index c592aa65..00000000 --- a/mirc/routes/README.md +++ /dev/null @@ -1,10 +0,0 @@ -### RESTful API for paopao-ce -本目录包含所有RESTful API相关定义文件 - -|目录|系列API|备注| -| ----- | ----- | ----- | -|v1|/|Web v1版本RESTful API相关定义文件| -|admin|m|Admin后台运维系列相关RESTful API相关定义文件| -|space|x|SpaceX系列相关RESTful API相关定义文件| -|localoss|s| LocalOSS OBS系列RESTful API相关定义文件| -|bot|r| Bot系列相关RESTful API相关定义文件| diff --git a/mirc/routes/space/README.md b/mirc/space/README.md similarity index 100% rename from mirc/routes/space/README.md rename to mirc/space/README.md diff --git a/mirc/routes/space/v1/user.go b/mirc/space/v1/user.go similarity index 100% rename from mirc/routes/space/v1/user.go rename to mirc/space/v1/user.go diff --git a/mirc/routes/v1/localoss.go b/mirc/v1/localoss.go similarity index 100% rename from mirc/routes/v1/localoss.go rename to mirc/v1/localoss.go diff --git a/mirc/routes/v1/web_admin.go b/mirc/v1/web_admin.go similarity index 100% rename from mirc/routes/v1/web_admin.go rename to mirc/v1/web_admin.go diff --git a/mirc/routes/v1/web_alipay.go b/mirc/v1/web_alipay.go similarity index 100% rename from mirc/routes/v1/web_alipay.go rename to mirc/v1/web_alipay.go diff --git a/mirc/routes/v1/web_core.go b/mirc/v1/web_core.go similarity index 100% rename from mirc/routes/v1/web_core.go rename to mirc/v1/web_core.go diff --git a/mirc/routes/v1/web_followship.go b/mirc/v1/web_followship.go similarity index 100% rename from mirc/routes/v1/web_followship.go rename to mirc/v1/web_followship.go diff --git a/mirc/routes/v1/web_friendship.go b/mirc/v1/web_friendship.go similarity index 100% rename from mirc/routes/v1/web_friendship.go rename to mirc/v1/web_friendship.go diff --git a/mirc/routes/v1/web_loose.go b/mirc/v1/web_loose.go similarity index 100% rename from mirc/routes/v1/web_loose.go rename to mirc/v1/web_loose.go diff --git a/mirc/routes/v1/web_priv.go b/mirc/v1/web_priv.go similarity index 100% rename from mirc/routes/v1/web_priv.go rename to mirc/v1/web_priv.go diff --git a/mirc/routes/v1/web_pub.go b/mirc/v1/web_pub.go similarity index 100% rename from mirc/routes/v1/web_pub.go rename to mirc/v1/web_pub.go From fdcacec23533b0b5a3551378b47ff28561bfe846 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 20 Dec 2022 11:32:43 +0800 Subject: [PATCH 43/65] optimzie proto file define --- proto/v1/auth.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/v1/auth.proto b/proto/v1/auth.proto index bc18fae3..16c340ce 100644 --- a/proto/v1/auth.proto +++ b/proto/v1/auth.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package auth; -option go_package = "github.com/rocboss/paopao-ce/auto/rpc"; +option go_package = "github.com/rocboss/paopao-ce/auto/rpc/v1"; message User { string phoneNum = 1; From b164adec6b1b468ea526df492c547b1a27bb822b Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 20 Dec 2022 12:13:16 +0800 Subject: [PATCH 44/65] optimize service initial logic --- internal/servants/mobile/auth.go | 4 ++ internal/servants/mobile/mobile.go | 4 ++ internal/service/admin.go | 5 ++- internal/service/bot.go | 5 ++- internal/service/grpc_server.go | 19 ++++----- internal/service/http_server.go | 19 ++++----- internal/service/localoss.go | 5 ++- internal/service/mobile.go | 7 ++-- internal/service/server.go | 65 +++++++++++++++++++++++------- internal/service/space.go | 5 ++- internal/service/web.go | 5 ++- internal/service/web_old.go | 5 ++- 12 files changed, 94 insertions(+), 54 deletions(-) diff --git a/internal/servants/mobile/auth.go b/internal/servants/mobile/auth.go index 00a9b747..7b66794c 100644 --- a/internal/servants/mobile/auth.go +++ b/internal/servants/mobile/auth.go @@ -1,3 +1,7 @@ +// 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 mobile import ( diff --git a/internal/servants/mobile/mobile.go b/internal/servants/mobile/mobile.go index 425b71c1..5f9ed52c 100644 --- a/internal/servants/mobile/mobile.go +++ b/internal/servants/mobile/mobile.go @@ -1,3 +1,7 @@ +// 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 mobile import ( diff --git a/internal/service/admin.go b/internal/service/admin.go index e91b68f5..52bd120b 100644 --- a/internal/service/admin.go +++ b/internal/service/admin.go @@ -74,10 +74,11 @@ func newAdminEngine() *gin.Engine { func newAdminService() Service { addr := conf.AdminServerSetting.HttpIp + ":" + conf.AdminServerSetting.HttpPort - server := httpServerFrom(addr, func() *httpServer { + server := httpServers.from(addr, func() *httpServer { engine := newAdminEngine() return &httpServer{ - e: engine, + baseServer: newBaseServe(), + e: engine, server: &http.Server{ Addr: addr, Handler: engine, diff --git a/internal/service/bot.go b/internal/service/bot.go index 2b9eef20..d1cb4ea7 100644 --- a/internal/service/bot.go +++ b/internal/service/bot.go @@ -74,10 +74,11 @@ func newBotEngine() *gin.Engine { func newBotService() Service { addr := conf.BotServerSetting.HttpIp + ":" + conf.BotServerSetting.HttpPort - server := httpServerFrom(addr, func() *httpServer { + server := httpServers.from(addr, func() *httpServer { engine := newBotEngine() return &httpServer{ - e: engine, + baseServer: newBaseServe(), + e: engine, server: &http.Server{ Addr: addr, Handler: engine, diff --git a/internal/service/grpc_server.go b/internal/service/grpc_server.go index 3f0a3b94..47e870c9 100644 --- a/internal/service/grpc_server.go +++ b/internal/service/grpc_server.go @@ -6,25 +6,20 @@ package service import ( "net" - "sync" "google.golang.org/grpc" ) +var ( + _ server = (*grpcServer)(nil) +) + // grpcServer wraper for grpc.Server type grpcServer struct { - sync.RWMutex - - listener net.Listener - server *grpc.Server - serverStatus uint8 -} - -func (s *grpcServer) status() uint8 { - s.RLock() - defer s.RUnlock() + *baseServer - return s.serverStatus + listener net.Listener + server *grpc.Server } func (s *grpcServer) start() error { diff --git a/internal/service/http_server.go b/internal/service/http_server.go index a7ca3879..105df1a2 100644 --- a/internal/service/http_server.go +++ b/internal/service/http_server.go @@ -7,25 +7,20 @@ package service import ( "context" "net/http" - "sync" "github.com/gin-gonic/gin" ) +var ( + _ server = (*httpServer)(nil) +) + // httpServer wraper for gin.engine and http.Server type httpServer struct { - sync.RWMutex - - e *gin.Engine - server *http.Server - serverStatus uint8 -} - -func (s *httpServer) status() uint8 { - s.RLock() - defer s.RUnlock() + *baseServer - return s.serverStatus + e *gin.Engine + server *http.Server } func (s *httpServer) start() error { diff --git a/internal/service/localoss.go b/internal/service/localoss.go index 3f33e7ef..7d70291d 100644 --- a/internal/service/localoss.go +++ b/internal/service/localoss.go @@ -49,10 +49,11 @@ func newLocalossEngine() *gin.Engine { func newLocalossService() Service { addr := conf.LocalossServerSetting.HttpIp + ":" + conf.LocalossServerSetting.HttpPort - server := httpServerFrom(addr, func() *httpServer { + server := httpServers.from(addr, func() *httpServer { engine := newLocalossEngine() return &httpServer{ - e: engine, + baseServer: newBaseServe(), + e: engine, server: &http.Server{ Addr: addr, Handler: engine, diff --git a/internal/service/mobile.go b/internal/service/mobile.go index 262d35af..9fa3cb64 100644 --- a/internal/service/mobile.go +++ b/internal/service/mobile.go @@ -43,7 +43,7 @@ func (s *mobileService) String() string { func newMobileService() Service { addr := conf.MobileServerSetting.Host + ":" + conf.MobileServerSetting.Port - server := grpcServerFrom(addr, func() *grpcServer { + server := grpcServers.from(addr, func() *grpcServer { l, err := net.Listen("tcp", addr) if err != nil { // TODO: optimize error process @@ -54,8 +54,9 @@ func newMobileService() Service { s := grpc.NewServer() return &grpcServer{ - listener: l, - server: s, + baseServer: newBaseServe(), + listener: l, + server: s, } }) return &mobileService{ diff --git a/internal/service/server.go b/internal/service/server.go index f2439777..336e96af 100644 --- a/internal/service/server.go +++ b/internal/service/server.go @@ -4,35 +4,70 @@ package service +import "sync" + var ( - httpServers = make(map[string]*httpServer) - grpcServers = make(map[string]*grpcServer) + httpServers = newServerPool[*httpServer]() + grpcServers = newServerPool[*grpcServer]() ) const ( - _statusServerInitilized uint8 = iota + 1 + _statusServerUnknow uint8 = iota + _statusServerInitilized _statusServerStarted _statusServerStoped ) -func httpServerFrom(addr string, newServer func() *httpServer) *httpServer { - s, exist := httpServers[addr] +type server interface { + status() uint8 + setStatus(uint8) + start() error + stop() error +} + +type serverPool[T server] struct { + servers map[string]T +} + +type baseServer struct { + sync.RWMutex + serverStatus uint8 +} + +func (p *serverPool[T]) from(addr string, newServer func() T) T { + s, exist := p.servers[addr] if exist { return s } s = newServer() - s.serverStatus = _statusServerInitilized - httpServers[addr] = s + s.setStatus(_statusServerInitilized) + p.servers[addr] = s return s } -func grpcServerFrom(addr string, newServer func() *grpcServer) *grpcServer { - s, exist := grpcServers[addr] - if exist { - return s +func (s *baseServer) setStatus(status uint8) { + s.RLock() + defer s.RUnlock() + + s.serverStatus = status +} + +func (s *baseServer) status() uint8 { + s.RLock() + defer s.RUnlock() + + return s.serverStatus +} + +func newServerPool[T server]() *serverPool[T] { + return &serverPool[T]{ + servers: make(map[string]T), + } +} + +func newBaseServe() *baseServer { + return &baseServer{ + RWMutex: sync.RWMutex{}, + serverStatus: _statusServerUnknow, } - s = newServer() - s.serverStatus = _statusServerInitilized - grpcServers[addr] = s - return s } diff --git a/internal/service/space.go b/internal/service/space.go index fd6ee217..2d5ff1ff 100644 --- a/internal/service/space.go +++ b/internal/service/space.go @@ -74,10 +74,11 @@ func newSpaceXEngine() *gin.Engine { func newSpaceXService() Service { addr := conf.SpaceXServerSetting.HttpIp + ":" + conf.SpaceXServerSetting.HttpPort - server := httpServerFrom(addr, func() *httpServer { + server := httpServers.from(addr, func() *httpServer { engine := newSpaceXEngine() return &httpServer{ - e: engine, + baseServer: newBaseServe(), + e: engine, server: &http.Server{ Addr: addr, Handler: engine, diff --git a/internal/service/web.go b/internal/service/web.go index 56b8ef3b..0d1b9f12 100644 --- a/internal/service/web.go +++ b/internal/service/web.go @@ -74,10 +74,11 @@ func newWebEngine() *gin.Engine { func newWebService() Service { addr := conf.WebServerSetting.HttpIp + ":" + conf.WebServerSetting.HttpPort - server := httpServerFrom(addr, func() *httpServer { + server := httpServers.from(addr, func() *httpServer { engine := newWebEngine() return &httpServer{ - e: engine, + baseServer: newBaseServe(), + e: engine, server: &http.Server{ Addr: addr, Handler: engine, diff --git a/internal/service/web_old.go b/internal/service/web_old.go index 70e7ec37..bcef11cd 100644 --- a/internal/service/web_old.go +++ b/internal/service/web_old.go @@ -41,10 +41,11 @@ func (s *oldWebService) String() string { func newOldWebService() Service { addr := conf.ServerSetting.HttpIp + ":" + conf.ServerSetting.HttpPort - server := httpServerFrom(addr, func() *httpServer { + server := httpServers.from(addr, func() *httpServer { engine := newWebEngine() return &httpServer{ - e: engine, + baseServer: newBaseServe(), + e: engine, server: &http.Server{ Addr: addr, Handler: engine, From 3e0c38d15fc30edb138dda8d0c7f246478322c1c Mon Sep 17 00:00:00 2001 From: Michael Li Date: Thu, 22 Dec 2022 09:53:42 +0800 Subject: [PATCH 45/65] upgrade github.com/alimy/mir/v3 => v3.0.0-beta.1 --- go.mod | 2 +- go.sum | 4 ++-- mirc/main.go | 2 +- mirc/{ => web}/v1/localoss.go | 0 mirc/{ => web}/v1/web_admin.go | 0 mirc/{ => web}/v1/web_alipay.go | 0 mirc/{ => web}/v1/web_core.go | 0 mirc/{ => web}/v1/web_followship.go | 0 mirc/{ => web}/v1/web_friendship.go | 0 mirc/{ => web}/v1/web_loose.go | 0 mirc/{ => web}/v1/web_priv.go | 0 mirc/{ => web}/v1/web_pub.go | 0 12 files changed, 4 insertions(+), 4 deletions(-) rename mirc/{ => web}/v1/localoss.go (100%) rename mirc/{ => web}/v1/web_admin.go (100%) rename mirc/{ => web}/v1/web_alipay.go (100%) rename mirc/{ => web}/v1/web_core.go (100%) rename mirc/{ => web}/v1/web_followship.go (100%) rename mirc/{ => web}/v1/web_friendship.go (100%) rename mirc/{ => web}/v1/web_loose.go (100%) rename mirc/{ => web}/v1/web_priv.go (100%) rename mirc/{ => web}/v1/web_pub.go (100%) diff --git a/go.mod b/go.mod index eee36fdb..6c7efd3b 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/cfg v0.3.0 - github.com/alimy/mir/v3 v3.0.0-alpha.7 + github.com/alimy/mir/v3 v3.0.0-beta.1 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index ca0a32cb..d6798787 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= -github.com/alimy/mir/v3 v3.0.0-alpha.7 h1:CuT+wx8KuwgPjzNz5AUDlobqSgFOWNvyzF2tBXm7Hek= -github.com/alimy/mir/v3 v3.0.0-alpha.7/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= +github.com/alimy/mir/v3 v3.0.0-beta.1 h1:ZSbclyf9XRw1nMrndLnyCvDUqHvWvBx2Z1XSsHllvoQ= +github.com/alimy/mir/v3 v3.0.0-beta.1/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/mirc/main.go b/mirc/main.go index 9136d986..1ec56e76 100644 --- a/mirc/main.go +++ b/mirc/main.go @@ -14,7 +14,7 @@ import ( _ "github.com/rocboss/paopao-ce/mirc/bot/v1" _ "github.com/rocboss/paopao-ce/mirc/localoss/v1" _ "github.com/rocboss/paopao-ce/mirc/space/v1" - _ "github.com/rocboss/paopao-ce/mirc/v1" + _ "github.com/rocboss/paopao-ce/mirc/web/v1" ) //go:generate go run main.go diff --git a/mirc/v1/localoss.go b/mirc/web/v1/localoss.go similarity index 100% rename from mirc/v1/localoss.go rename to mirc/web/v1/localoss.go diff --git a/mirc/v1/web_admin.go b/mirc/web/v1/web_admin.go similarity index 100% rename from mirc/v1/web_admin.go rename to mirc/web/v1/web_admin.go diff --git a/mirc/v1/web_alipay.go b/mirc/web/v1/web_alipay.go similarity index 100% rename from mirc/v1/web_alipay.go rename to mirc/web/v1/web_alipay.go diff --git a/mirc/v1/web_core.go b/mirc/web/v1/web_core.go similarity index 100% rename from mirc/v1/web_core.go rename to mirc/web/v1/web_core.go diff --git a/mirc/v1/web_followship.go b/mirc/web/v1/web_followship.go similarity index 100% rename from mirc/v1/web_followship.go rename to mirc/web/v1/web_followship.go diff --git a/mirc/v1/web_friendship.go b/mirc/web/v1/web_friendship.go similarity index 100% rename from mirc/v1/web_friendship.go rename to mirc/web/v1/web_friendship.go diff --git a/mirc/v1/web_loose.go b/mirc/web/v1/web_loose.go similarity index 100% rename from mirc/v1/web_loose.go rename to mirc/web/v1/web_loose.go diff --git a/mirc/v1/web_priv.go b/mirc/web/v1/web_priv.go similarity index 100% rename from mirc/v1/web_priv.go rename to mirc/web/v1/web_priv.go diff --git a/mirc/v1/web_pub.go b/mirc/web/v1/web_pub.go similarity index 100% rename from mirc/v1/web_pub.go rename to mirc/web/v1/web_pub.go From 8139e4dbe214aeab400039ee8f56535a3d128e43 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Thu, 22 Dec 2022 13:22:21 +0800 Subject: [PATCH 46/65] upgrade github.com/alimy/mir/v3 => v3.0.0-alpha.8 --- auto/api/v1/web_core.go | 8 +++++- go.mod | 2 +- go.sum | 4 +-- internal/servants/base/base.go | 45 ++++++++++++---------------------- mirc/README.md | 2 +- mirc/web/README.md | 4 +++ mirc/web/v1/base.go | 9 +++++++ mirc/web/v1/web_core.go | 1 + 8 files changed, 41 insertions(+), 34 deletions(-) create mode 100644 mirc/web/README.md create mode 100644 mirc/web/v1/base.go diff --git a/auto/api/v1/web_core.go b/auto/api/v1/web_core.go index 613977fe..8b61e383 100644 --- a/auto/api/v1/web_core.go +++ b/auto/api/v1/web_core.go @@ -7,9 +7,11 @@ import ( "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" ) type LoginReq struct { + BaseInfo `json:"-"` AgentInfo AgentInfo `json:"agent_info"` Name string `json:"name"` Passwd string `json:"passwd"` @@ -20,6 +22,10 @@ type AgentInfo struct { UserAgent string `json:"user_agent"` } +type BaseInfo struct { + User *dbr.User +} + type LoginResp struct { UserInfo ServerInfo ServerInfo `json:"server_info"` @@ -105,8 +111,8 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor r.RenderArticles(c, s.Articles()) } - router.Handle("HEAD", "/articles/:category/", h) router.Handle("GET", "/articles/:category/", h) + router.Handle("HEAD", "/articles/:category/", h) } router.Handle("GET", "/index/", func(c *gin.Context) { diff --git a/go.mod b/go.mod index 6c7efd3b..50fb6bea 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/cfg v0.3.0 - github.com/alimy/mir/v3 v3.0.0-beta.1 + github.com/alimy/mir/v3 v3.0.0-alpha.8 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index d6798787..7debc8ba 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= -github.com/alimy/mir/v3 v3.0.0-beta.1 h1:ZSbclyf9XRw1nMrndLnyCvDUqHvWvBx2Z1XSsHllvoQ= -github.com/alimy/mir/v3 v3.0.0-beta.1/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= +github.com/alimy/mir/v3 v3.0.0-alpha.8 h1:Zz94oefYkYXA/IuXrjRT7LrQ6LdsZi5z9+IWmXuPdUw= +github.com/alimy/mir/v3 v3.0.0-alpha.8/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index 6c204e7e..d2c30329 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -6,7 +6,6 @@ package base import ( "net/http" - "os" "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" @@ -26,7 +25,13 @@ type BaseRender struct { // TODO } -func (BaseServant) userFrom(c *gin.Context) (*core.User, bool) { +type JsonResp struct { + Code int `json:"code"` + Msg string `json:"msg,omitempty"` + Data any `json:",omitempty"` +} + +func (BaseServant) UserFrom(c *gin.Context) (*core.User, bool) { if u, exists := c.Get("USER"); exists { user, ok := u.(*core.User) return user, ok @@ -45,33 +50,15 @@ func BindAny(c *gin.Context, obj any) mir.Error { func RenderAny(c *gin.Context, data any, err mir.Error) { if err == nil { - hostname, _ := os.Hostname() - if data == nil { - data = gin.H{ - "code": 0, - "msg": "success", - "tracehost": hostname, - } - } else { - data = gin.H{ - "code": 0, - "msg": "success", - "data": data, - "tracehost": hostname, - } - } - c.JSON(http.StatusOK, data) + c.JSON(http.StatusOK, &JsonResp{ + Code: 0, + Msg: "success", + Data: data, + }) } else { - // TODO: error process logic - resp := gin.H{"code": err.StatusCode(), "msg": err.Error()} - // xerr := &xerror.Error{} - // if errors.As(err, xerr) { - // resp["code"], resp["msg"] = xerr.Code(), xerr.Msg() - // details := xerr.Details() - // if len(details) > 0 { - // resp["details"] = details - // } - // } - c.JSON(http.StatusInternalServerError, resp) + c.JSON(http.StatusInternalServerError, &JsonResp{ + Code: err.StatusCode(), + Msg: err.Error(), + }) } } diff --git a/mirc/README.md b/mirc/README.md index c592aa65..81c88517 100644 --- a/mirc/README.md +++ b/mirc/README.md @@ -3,7 +3,7 @@ |目录|系列API|备注| | ----- | ----- | ----- | -|v1|/|Web v1版本RESTful API相关定义文件| +|web|/|Web v1版本RESTful API相关定义文件| |admin|m|Admin后台运维系列相关RESTful API相关定义文件| |space|x|SpaceX系列相关RESTful API相关定义文件| |localoss|s| LocalOSS OBS系列RESTful API相关定义文件| diff --git a/mirc/web/README.md b/mirc/web/README.md new file mode 100644 index 00000000..f8690712 --- /dev/null +++ b/mirc/web/README.md @@ -0,0 +1,4 @@ +### Web系列RESTful API +本目录包含Web系列RESTful API相关定义文件 + +* v1 - v1版本API diff --git a/mirc/web/v1/base.go b/mirc/web/v1/base.go new file mode 100644 index 00000000..ee279a39 --- /dev/null +++ b/mirc/web/v1/base.go @@ -0,0 +1,9 @@ +package v1 + +import ( + "github.com/rocboss/paopao-ce/internal/core" +) + +type BaseInfo struct { + User *core.User +} diff --git a/mirc/web/v1/web_core.go b/mirc/web/v1/web_core.go index 83193986..f87338d7 100644 --- a/mirc/web/v1/web_core.go +++ b/mirc/web/v1/web_core.go @@ -23,6 +23,7 @@ type UserInfo struct { } type LoginReq struct { + BaseInfo `json:"-"` AgentInfo AgentInfo `json:"agent_info"` Name string `json:"name"` Passwd string `json:"passwd"` From 989d79080e5a2ed61587659719a48b8a763cd466 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 23 Dec 2022 12:40:19 +0800 Subject: [PATCH 47/65] add simple go-mir define file for web api --- auto/api/v1/web_admin.go | 95 ++++++++ auto/api/v1/web_alipay_priv.go | 136 ++++++++++++ auto/api/v1/web_alipay_pub.go | 85 ++++++++ auto/api/v1/web_core.go | 363 +++++++++++++++++++++++++------ auto/api/v1/web_followship.go | 156 +++++++++++++ auto/api/v1/web_friendship.go | 176 +++++++++++++++ auto/api/v1/web_loose.go | 136 ++++++++++++ auto/api/v1/web_priv.go | 356 ++++++++++++++++++++++++++++++ auto/api/v1/web_pub.go | 226 +++++++++++++++++++ go.mod | 4 +- go.sum | 2 - internal/model/model.go | 5 + internal/model/web/admin.go | 5 + internal/model/web/alipay.go | 13 ++ internal/model/web/core.go | 17 ++ internal/model/web/followship.go | 13 ++ internal/model/web/friendship.go | 13 ++ internal/model/web/loose.go | 9 + internal/model/web/priv.go | 9 + internal/model/web/pub.go | 9 + internal/model/web/web.go | 13 ++ internal/servants/base/base.go | 2 +- internal/servants/web/admin.go | 50 ++++- internal/servants/web/core.go | 6 + internal/servants/web/web.go | 1 + mirc/web/v1/admin.go | 22 ++ mirc/web/v1/alipay.go | 45 ++++ mirc/web/v1/base.go | 9 - mirc/web/v1/core.go | 97 +++++++++ mirc/web/v1/followship.go | 25 +++ mirc/web/v1/friendship.go | 49 +++++ mirc/web/v1/localoss.go | 15 -- mirc/web/v1/loose.go | 36 +++ mirc/web/v1/priv.go | 87 ++++++++ mirc/web/v1/pub.go | 63 ++++++ mirc/web/v1/web_admin.go | 15 -- mirc/web/v1/web_alipay.go | 15 -- mirc/web/v1/web_core.go | 45 ---- mirc/web/v1/web_followship.go | 15 -- mirc/web/v1/web_friendship.go | 15 -- mirc/web/v1/web_loose.go | 15 -- mirc/web/v1/web_priv.go | 15 -- mirc/web/v1/web_pub.go | 15 -- 43 files changed, 2247 insertions(+), 251 deletions(-) create mode 100644 auto/api/v1/web_admin.go create mode 100644 auto/api/v1/web_alipay_priv.go create mode 100644 auto/api/v1/web_alipay_pub.go create mode 100644 auto/api/v1/web_followship.go create mode 100644 auto/api/v1/web_friendship.go create mode 100644 auto/api/v1/web_loose.go create mode 100644 auto/api/v1/web_priv.go create mode 100644 auto/api/v1/web_pub.go create mode 100644 internal/model/model.go create mode 100644 internal/model/web/admin.go create mode 100644 internal/model/web/alipay.go create mode 100644 internal/model/web/core.go create mode 100644 internal/model/web/followship.go create mode 100644 internal/model/web/friendship.go create mode 100644 internal/model/web/loose.go create mode 100644 internal/model/web/priv.go create mode 100644 internal/model/web/pub.go create mode 100644 internal/model/web/web.go create mode 100644 mirc/web/v1/admin.go create mode 100644 mirc/web/v1/alipay.go delete mode 100644 mirc/web/v1/base.go create mode 100644 mirc/web/v1/core.go create mode 100644 mirc/web/v1/followship.go create mode 100644 mirc/web/v1/friendship.go delete mode 100644 mirc/web/v1/localoss.go create mode 100644 mirc/web/v1/loose.go create mode 100644 mirc/web/v1/priv.go create mode 100644 mirc/web/v1/pub.go delete mode 100644 mirc/web/v1/web_admin.go delete mode 100644 mirc/web/v1/web_alipay.go delete mode 100644 mirc/web/v1/web_core.go delete mode 100644 mirc/web/v1/web_followship.go delete mode 100644 mirc/web/v1/web_friendship.go delete mode 100644 mirc/web/v1/web_loose.go delete mode 100644 mirc/web/v1/web_priv.go delete mode 100644 mirc/web/v1/web_pub.go diff --git a/auto/api/v1/web_admin.go b/auto/api/v1/web_admin.go new file mode 100644 index 00000000..1e2f721d --- /dev/null +++ b/auto/api/v1/web_admin.go @@ -0,0 +1,95 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type WebAdmin interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + ChangeUserStatus(*web.ChangeUserStatusReq) mir.Error + + mustEmbedUnimplementedWebAdminServant() +} + +type WebAdminBinding interface { + BindChangeUserStatus(*gin.Context) (*web.ChangeUserStatusReq, mir.Error) + + mustEmbedUnimplementedWebAdminBinding() +} + +type WebAdminRender interface { + RenderChangeUserStatus(*gin.Context, mir.Error) + + mustEmbedUnimplementedWebAdminRender() +} + +// RegisterWebAdminServant register WebAdmin servant to gin +func RegisterWebAdminServant(e *gin.Engine, s WebAdmin, b WebAdminBinding, r WebAdminRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("POST", "/admin/user/status", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindChangeUserStatus(c) + if err != nil { + r.RenderChangeUserStatus(c, err) + return + } + r.RenderChangeUserStatus(c, s.ChangeUserStatus(req)) + }) + +} + +// UnimplementedWebAdminServant can be embedded to have forward compatible implementations. +type UnimplementedWebAdminServant struct { +} + +func (UnimplementedWebAdminServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedWebAdminServant) ChangeUserStatus(req *web.ChangeUserStatusReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebAdminServant) mustEmbedUnimplementedWebAdminServant() {} + +// UnimplementedWebAdminRender can be embedded to have forward compatible implementations. +type UnimplementedWebAdminRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedWebAdminRender) RenderChangeUserStatus(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebAdminRender) mustEmbedUnimplementedWebAdminRender() {} + +// UnimplementedWebAdminBinding can be embedded to have forward compatible implementations. +type UnimplementedWebAdminBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebAdminBinding) BindChangeUserStatus(c *gin.Context) (*web.ChangeUserStatusReq, mir.Error) { + obj := new(web.ChangeUserStatusReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebAdminBinding) mustEmbedUnimplementedWebAdminBinding() {} diff --git a/auto/api/v1/web_alipay_priv.go b/auto/api/v1/web_alipay_priv.go new file mode 100644 index 00000000..20a5d562 --- /dev/null +++ b/auto/api/v1/web_alipay_priv.go @@ -0,0 +1,136 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type WebAlipayPriv interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + UserWalletBills(*web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) + UserRechargeResult() mir.Error + UserRechargeLink() mir.Error + + mustEmbedUnimplementedWebAlipayPrivServant() +} + +type WebAlipayPrivBinding interface { + BindUserWalletBills(*gin.Context) (*web.UserWalletBillsReq, mir.Error) + + mustEmbedUnimplementedWebAlipayPrivBinding() +} + +type WebAlipayPrivRender interface { + RenderUserWalletBills(*gin.Context, *web.UserWalletBillsResp, mir.Error) + RenderUserRechargeResult(*gin.Context, mir.Error) + RenderUserRechargeLink(*gin.Context, mir.Error) + + mustEmbedUnimplementedWebAlipayPrivRender() +} + +// RegisterWebAlipayPrivServant register WebAlipayPriv servant to gin +func RegisterWebAlipayPrivServant(e *gin.Engine, s WebAlipayPriv, b WebAlipayPrivBinding, r WebAlipayPrivRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("GET", "/user/wallet/bills", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindUserWalletBills(c) + if err != nil { + r.RenderUserWalletBills(c, nil, err) + return + } + resp, err := s.UserWalletBills(req) + r.RenderUserWalletBills(c, resp, err) + }) + + router.Handle("GET", "/user/recharge", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderUserRechargeResult(c, s.UserRechargeResult()) + }) + + router.Handle("POST", "/user/recharge", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderUserRechargeLink(c, s.UserRechargeLink()) + }) + +} + +// UnimplementedWebAlipayPrivServant can be embedded to have forward compatible implementations. +type UnimplementedWebAlipayPrivServant struct { +} + +func (UnimplementedWebAlipayPrivServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedWebAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebAlipayPrivServant) UserRechargeResult() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebAlipayPrivServant) UserRechargeLink() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebAlipayPrivServant) mustEmbedUnimplementedWebAlipayPrivServant() {} + +// UnimplementedWebAlipayPrivRender can be embedded to have forward compatible implementations. +type UnimplementedWebAlipayPrivRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedWebAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *web.UserWalletBillsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedWebAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebAlipayPrivRender) mustEmbedUnimplementedWebAlipayPrivRender() {} + +// UnimplementedWebAlipayPrivBinding can be embedded to have forward compatible implementations. +type UnimplementedWebAlipayPrivBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebAlipayPrivBinding) BindUserWalletBills(c *gin.Context) (*web.UserWalletBillsReq, mir.Error) { + obj := new(web.UserWalletBillsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebAlipayPrivBinding) mustEmbedUnimplementedWebAlipayPrivBinding() {} diff --git a/auto/api/v1/web_alipay_pub.go b/auto/api/v1/web_alipay_pub.go new file mode 100644 index 00000000..d4917af7 --- /dev/null +++ b/auto/api/v1/web_alipay_pub.go @@ -0,0 +1,85 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type WebAlipayPub interface { + AlipayNotify(*web.AlipayNotifyReq) mir.Error + + mustEmbedUnimplementedWebAlipayPubServant() +} + +type WebAlipayPubBinding interface { + BindAlipayNotify(*gin.Context) (*web.AlipayNotifyReq, mir.Error) + + mustEmbedUnimplementedWebAlipayPubBinding() +} + +type WebAlipayPubRender interface { + RenderAlipayNotify(*gin.Context, mir.Error) + + mustEmbedUnimplementedWebAlipayPubRender() +} + +// RegisterWebAlipayPubServant register WebAlipayPub servant to gin +func RegisterWebAlipayPubServant(e *gin.Engine, s WebAlipayPub, b WebAlipayPubBinding, r WebAlipayPubRender) { + router := e.Group("v1") + + // register routes info to router + router.Handle("POST", "/alipay/notify", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindAlipayNotify(c) + if err != nil { + r.RenderAlipayNotify(c, err) + return + } + r.RenderAlipayNotify(c, s.AlipayNotify(req)) + }) + +} + +// UnimplementedWebAlipayPubServant can be embedded to have forward compatible implementations. +type UnimplementedWebAlipayPubServant struct { +} + +func (UnimplementedWebAlipayPubServant) AlipayNotify(req *web.AlipayNotifyReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebAlipayPubServant) mustEmbedUnimplementedWebAlipayPubServant() {} + +// UnimplementedWebAlipayPubRender can be embedded to have forward compatible implementations. +type UnimplementedWebAlipayPubRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedWebAlipayPubRender) RenderAlipayNotify(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebAlipayPubRender) mustEmbedUnimplementedWebAlipayPubRender() {} + +// UnimplementedWebAlipayPubBinding can be embedded to have forward compatible implementations. +type UnimplementedWebAlipayPubBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebAlipayPubBinding) BindAlipayNotify(c *gin.Context) (*web.AlipayNotifyReq, mir.Error) { + obj := new(web.AlipayNotifyReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebAlipayPubBinding) mustEmbedUnimplementedWebAlipayPubBinding() {} diff --git a/auto/api/v1/web_core.go b/auto/api/v1/web_core.go index 8b61e383..dee50533 100644 --- a/auto/api/v1/web_core.go +++ b/auto/api/v1/web_core.go @@ -7,62 +7,58 @@ import ( "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" + "github.com/rocboss/paopao-ce/internal/model/web" ) -type LoginReq struct { - BaseInfo `json:"-"` - AgentInfo AgentInfo `json:"agent_info"` - Name string `json:"name"` - Passwd string `json:"passwd"` -} - -type AgentInfo struct { - Platform string `json:"platform"` - UserAgent string `json:"user_agent"` -} - -type BaseInfo struct { - User *dbr.User -} - -type LoginResp struct { - UserInfo - ServerInfo ServerInfo `json:"server_info"` - JwtToken string `json:"jwt_token"` -} - -type ServerInfo struct { - ApiVer string `json:"api_ver"` -} - -type UserInfo struct { - Name string `json:"name"` -} - type WebCore interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - Logout() mir.Error - Login(*LoginReq) (*LoginResp, mir.Error) - Articles() mir.Error - Index() mir.Error + TweetCollectionStatus() mir.Error + TweetStarStatus() mir.Error + SuggestTags() mir.Error + SuggestUsers() mir.Error + ChangeAvatar(*web.ChangeAvatarReq) mir.Error + ChangeNickname() mir.Error + ChangePassword() mir.Error + UserPhoneBind() mir.Error + GetStars() mir.Error + GetCollections() mir.Error + SendUserWhisper() mir.Error + ReadMessage() mir.Error + GetMessages() mir.Error + GetUnreadMsgCount() mir.Error + GetUserInfo(*web.UserInfoReq) (*web.UserInfoResp, mir.Error) + SyncSearchIndex() mir.Error mustEmbedUnimplementedWebCoreServant() } type WebCoreBinding interface { - BindLogin(*gin.Context) (*LoginReq, mir.Error) + BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error) + + BindGetUserInfo(*gin.Context) (*web.UserInfoReq, mir.Error) mustEmbedUnimplementedWebCoreBinding() } type WebCoreRender interface { - RenderLogout(*gin.Context, mir.Error) - RenderLogin(*gin.Context, *LoginResp, mir.Error) - RenderArticles(*gin.Context, mir.Error) - RenderIndex(*gin.Context, mir.Error) + RenderTweetCollectionStatus(*gin.Context, mir.Error) + RenderTweetStarStatus(*gin.Context, mir.Error) + RenderSuggestTags(*gin.Context, mir.Error) + RenderSuggestUsers(*gin.Context, mir.Error) + RenderChangeAvatar(*gin.Context, mir.Error) + RenderChangeNickname(*gin.Context, mir.Error) + RenderChangePassword(*gin.Context, mir.Error) + RenderUserPhoneBind(*gin.Context, mir.Error) + RenderGetStars(*gin.Context, mir.Error) + RenderGetCollections(*gin.Context, mir.Error) + RenderSendUserWhisper(*gin.Context, mir.Error) + RenderReadMessage(*gin.Context, mir.Error) + RenderGetMessages(*gin.Context, mir.Error) + RenderGetUnreadMsgCount(*gin.Context, mir.Error) + RenderGetUserInfo(*gin.Context, *web.UserInfoResp, mir.Error) + RenderSyncSearchIndex(*gin.Context, mir.Error) mustEmbedUnimplementedWebCoreRender() } @@ -75,54 +71,175 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor router.Use(middlewares...) // register routes info to router - router.Handle("POST", "/user/logout/", func(c *gin.Context) { + router.Handle("GET", "/post/collection", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderTweetCollectionStatus(c, s.TweetCollectionStatus()) + }) + + router.Handle("GET", "/post/star", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderTweetStarStatus(c, s.TweetStarStatus()) + }) + + router.Handle("GET", "/suggest/tags", func(c *gin.Context) { select { case <-c.Request.Context().Done(): return default: } - r.RenderLogout(c, s.Logout()) + r.RenderSuggestTags(c, s.SuggestTags()) }) - router.Handle("POST", "/user/login/", func(c *gin.Context) { + router.Handle("GET", "/suggest/users", func(c *gin.Context) { select { case <-c.Request.Context().Done(): return default: } - req, err := b.BindLogin(c) + r.RenderSuggestUsers(c, s.SuggestUsers()) + }) + + router.Handle("POST", "/user/avatar", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindChangeAvatar(c) if err != nil { - r.RenderLogin(c, nil, err) + r.RenderChangeAvatar(c, err) return } - resp, err := s.Login(req) - r.RenderLogin(c, resp, err) + r.RenderChangeAvatar(c, s.ChangeAvatar(req)) }) - { - h := func(c *gin.Context) { - select { - case <-c.Request.Context().Done(): - return - default: - } + router.Handle("POST", "/user/nickname", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderChangeNickname(c, s.ChangeNickname()) + }) - r.RenderArticles(c, s.Articles()) + router.Handle("POST", "/user/password", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: } - router.Handle("GET", "/articles/:category/", h) - router.Handle("HEAD", "/articles/:category/", h) - } - router.Handle("GET", "/index/", func(c *gin.Context) { + r.RenderChangePassword(c, s.ChangePassword()) + }) + + router.Handle("POST", "/user/phone", func(c *gin.Context) { select { case <-c.Request.Context().Done(): return default: } - r.RenderIndex(c, s.Index()) + r.RenderUserPhoneBind(c, s.UserPhoneBind()) + }) + + router.Handle("GET", "/user/stars", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderGetStars(c, s.GetStars()) + }) + + router.Handle("GET", "/user/collections", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderGetCollections(c, s.GetCollections()) + }) + + router.Handle("POST", "/user/whisper", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderSendUserWhisper(c, s.SendUserWhisper()) + }) + + router.Handle("POST", "/user/message/read", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderReadMessage(c, s.ReadMessage()) + }) + + router.Handle("GET", "/user/messages", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderGetMessages(c, s.GetMessages()) + }) + + router.Handle("GET", "/user/msgcount/unread", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderGetUnreadMsgCount(c, s.GetUnreadMsgCount()) + }) + + router.Handle("GET", "/user/info", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindGetUserInfo(c) + if err != nil { + r.RenderGetUserInfo(c, nil, err) + return + } + resp, err := s.GetUserInfo(req) + r.RenderGetUserInfo(c, resp, err) + }) + + router.Handle("GET", "/sync/index", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderSyncSearchIndex(c, s.SyncSearchIndex()) }) } @@ -135,19 +252,67 @@ func (UnimplementedWebCoreServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebCoreServant) Logout() mir.Error { +func (UnimplementedWebCoreServant) TweetCollectionStatus() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Login(req *LoginReq) (*LoginResp, mir.Error) { - return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedWebCoreServant) TweetStarStatus() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) SuggestTags() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) SuggestUsers() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) ChangeAvatar(req *web.ChangeAvatarReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) ChangeNickname() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) ChangePassword() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) UserPhoneBind() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) GetStars() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) GetCollections() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) SendUserWhisper() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) ReadMessage() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) GetMessages() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Articles() mir.Error { +func (UnimplementedWebCoreServant) GetUnreadMsgCount() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) Index() mir.Error { +func (UnimplementedWebCoreServant) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebCoreServant) SyncSearchIndex() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -158,19 +323,67 @@ type UnimplementedWebCoreRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err mir.Error) { +func (r *UnimplementedWebCoreRender) RenderTweetCollectionStatus(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) { - r.RenderAny(c, data, err) +func (r *UnimplementedWebCoreRender) RenderTweetStarStatus(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderSuggestTags(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err mir.Error) { +func (r *UnimplementedWebCoreRender) RenderSuggestUsers(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err mir.Error) { +func (r *UnimplementedWebCoreRender) RenderChangeAvatar(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderChangeNickname(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderChangePassword(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderUserPhoneBind(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderGetStars(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderGetCollections(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderSendUserWhisper(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderReadMessage(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderGetMessages(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderGetUnreadMsgCount(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebCoreRender) RenderGetUserInfo(c *gin.Context, data *web.UserInfoResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedWebCoreRender) RenderSyncSearchIndex(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } @@ -181,8 +394,14 @@ type UnimplementedWebCoreBinding struct { BindAny func(*gin.Context, any) mir.Error } -func (b *UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) { - obj := new(LoginReq) +func (b *UnimplementedWebCoreBinding) BindChangeAvatar(c *gin.Context) (*web.ChangeAvatarReq, mir.Error) { + obj := new(web.ChangeAvatarReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebCoreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) { + obj := new(web.UserInfoReq) err := b.BindAny(c, obj) return obj, err } diff --git a/auto/api/v1/web_followship.go b/auto/api/v1/web_followship.go new file mode 100644 index 00000000..a308bc40 --- /dev/null +++ b/auto/api/v1/web_followship.go @@ -0,0 +1,156 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type WebFollowship interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + ListFollowers(*web.ListFollowersReq) (*web.ListFollowersResp, mir.Error) + ListFollowings() mir.Error + DeleteFollowing() mir.Error + AddFollowing() mir.Error + + mustEmbedUnimplementedWebFollowshipServant() +} + +type WebFollowshipBinding interface { + BindListFollowers(*gin.Context) (*web.ListFollowersReq, mir.Error) + + mustEmbedUnimplementedWebFollowshipBinding() +} + +type WebFollowshipRender interface { + RenderListFollowers(*gin.Context, *web.ListFollowersResp, mir.Error) + RenderListFollowings(*gin.Context, mir.Error) + RenderDeleteFollowing(*gin.Context, mir.Error) + RenderAddFollowing(*gin.Context, mir.Error) + + mustEmbedUnimplementedWebFollowshipRender() +} + +// RegisterWebFollowshipServant register WebFollowship servant to gin +func RegisterWebFollowshipServant(e *gin.Engine, s WebFollowship, b WebFollowshipBinding, r WebFollowshipRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("GET", "/follower/list", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindListFollowers(c) + if err != nil { + r.RenderListFollowers(c, nil, err) + return + } + resp, err := s.ListFollowers(req) + r.RenderListFollowers(c, resp, err) + }) + + router.Handle("GET", "/following/list", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderListFollowings(c, s.ListFollowings()) + }) + + router.Handle("POST", "/following/delete", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderDeleteFollowing(c, s.DeleteFollowing()) + }) + + router.Handle("POST", "/following/add", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderAddFollowing(c, s.AddFollowing()) + }) + +} + +// UnimplementedWebFollowshipServant can be embedded to have forward compatible implementations. +type UnimplementedWebFollowshipServant struct { +} + +func (UnimplementedWebFollowshipServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedWebFollowshipServant) ListFollowers(req *web.ListFollowersReq) (*web.ListFollowersResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFollowshipServant) ListFollowings() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFollowshipServant) DeleteFollowing() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFollowshipServant) AddFollowing() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFollowshipServant) mustEmbedUnimplementedWebFollowshipServant() {} + +// UnimplementedWebFollowshipRender can be embedded to have forward compatible implementations. +type UnimplementedWebFollowshipRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedWebFollowshipRender) RenderListFollowers(c *gin.Context, data *web.ListFollowersResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedWebFollowshipRender) RenderListFollowings(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebFollowshipRender) RenderDeleteFollowing(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebFollowshipRender) RenderAddFollowing(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebFollowshipRender) mustEmbedUnimplementedWebFollowshipRender() {} + +// UnimplementedWebFollowshipBinding can be embedded to have forward compatible implementations. +type UnimplementedWebFollowshipBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebFollowshipBinding) BindListFollowers(c *gin.Context) (*web.ListFollowersReq, mir.Error) { + obj := new(web.ListFollowersReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebFollowshipBinding) mustEmbedUnimplementedWebFollowshipBinding() {} diff --git a/auto/api/v1/web_friendship.go b/auto/api/v1/web_friendship.go new file mode 100644 index 00000000..2e558ea5 --- /dev/null +++ b/auto/api/v1/web_friendship.go @@ -0,0 +1,176 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type WebFriendship interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + GetContacts(*web.GetContactsReq) (*web.GetContactsResp, mir.Error) + DeleteFriend() mir.Error + RejectFriend() mir.Error + AddFriend() mir.Error + RequestingFriend() mir.Error + + mustEmbedUnimplementedWebFriendshipServant() +} + +type WebFriendshipBinding interface { + BindGetContacts(*gin.Context) (*web.GetContactsReq, mir.Error) + + mustEmbedUnimplementedWebFriendshipBinding() +} + +type WebFriendshipRender interface { + RenderGetContacts(*gin.Context, *web.GetContactsResp, mir.Error) + RenderDeleteFriend(*gin.Context, mir.Error) + RenderRejectFriend(*gin.Context, mir.Error) + RenderAddFriend(*gin.Context, mir.Error) + RenderRequestingFriend(*gin.Context, mir.Error) + + mustEmbedUnimplementedWebFriendshipRender() +} + +// RegisterWebFriendshipServant register WebFriendship servant to gin +func RegisterWebFriendshipServant(e *gin.Engine, s WebFriendship, b WebFriendshipBinding, r WebFriendshipRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("GET", "/user/contacts", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindGetContacts(c) + if err != nil { + r.RenderGetContacts(c, nil, err) + return + } + resp, err := s.GetContacts(req) + r.RenderGetContacts(c, resp, err) + }) + + router.Handle("POST", "/friend/delete", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderDeleteFriend(c, s.DeleteFriend()) + }) + + router.Handle("POST", "/friend/reject", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderRejectFriend(c, s.RejectFriend()) + }) + + router.Handle("POST", "/friend/add", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderAddFriend(c, s.AddFriend()) + }) + + router.Handle("POST", "/friend/requesting", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderRequestingFriend(c, s.RequestingFriend()) + }) + +} + +// UnimplementedWebFriendshipServant can be embedded to have forward compatible implementations. +type UnimplementedWebFriendshipServant struct { +} + +func (UnimplementedWebFriendshipServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedWebFriendshipServant) GetContacts(req *web.GetContactsReq) (*web.GetContactsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFriendshipServant) DeleteFriend() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFriendshipServant) RejectFriend() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFriendshipServant) AddFriend() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFriendshipServant) RequestingFriend() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebFriendshipServant) mustEmbedUnimplementedWebFriendshipServant() {} + +// UnimplementedWebFriendshipRender can be embedded to have forward compatible implementations. +type UnimplementedWebFriendshipRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedWebFriendshipRender) RenderGetContacts(c *gin.Context, data *web.GetContactsResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedWebFriendshipRender) RenderDeleteFriend(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebFriendshipRender) RenderRejectFriend(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebFriendshipRender) RenderAddFriend(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebFriendshipRender) RenderRequestingFriend(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebFriendshipRender) mustEmbedUnimplementedWebFriendshipRender() {} + +// UnimplementedWebFriendshipBinding can be embedded to have forward compatible implementations. +type UnimplementedWebFriendshipBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebFriendshipBinding) BindGetContacts(c *gin.Context) (*web.GetContactsReq, mir.Error) { + obj := new(web.GetContactsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebFriendshipBinding) mustEmbedUnimplementedWebFriendshipBinding() {} diff --git a/auto/api/v1/web_loose.go b/auto/api/v1/web_loose.go new file mode 100644 index 00000000..d42c83a7 --- /dev/null +++ b/auto/api/v1/web_loose.go @@ -0,0 +1,136 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type WebLoose interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + GetUserProfile() mir.Error + GetUserTweets() mir.Error + Timeline(*web.TimelineReq) (*web.TimelineResp, mir.Error) + + mustEmbedUnimplementedWebLooseServant() +} + +type WebLooseBinding interface { + BindTimeline(*gin.Context) (*web.TimelineReq, mir.Error) + + mustEmbedUnimplementedWebLooseBinding() +} + +type WebLooseRender interface { + RenderGetUserProfile(*gin.Context, mir.Error) + RenderGetUserTweets(*gin.Context, mir.Error) + RenderTimeline(*gin.Context, *web.TimelineResp, mir.Error) + + mustEmbedUnimplementedWebLooseRender() +} + +// RegisterWebLooseServant register WebLoose servant to gin +func RegisterWebLooseServant(e *gin.Engine, s WebLoose, b WebLooseBinding, r WebLooseRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("GET", "/user/profile", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderGetUserProfile(c, s.GetUserProfile()) + }) + + router.Handle("GET", "/user/posts", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderGetUserTweets(c, s.GetUserTweets()) + }) + + router.Handle("GET", "/Posts", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindTimeline(c) + if err != nil { + r.RenderTimeline(c, nil, err) + return + } + resp, err := s.Timeline(req) + r.RenderTimeline(c, resp, err) + }) + +} + +// UnimplementedWebLooseServant can be embedded to have forward compatible implementations. +type UnimplementedWebLooseServant struct { +} + +func (UnimplementedWebLooseServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedWebLooseServant) GetUserProfile() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebLooseServant) GetUserTweets() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebLooseServant) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebLooseServant) mustEmbedUnimplementedWebLooseServant() {} + +// UnimplementedWebLooseRender can be embedded to have forward compatible implementations. +type UnimplementedWebLooseRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedWebLooseRender) RenderGetUserProfile(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebLooseRender) RenderGetUserTweets(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebLooseRender) RenderTimeline(c *gin.Context, data *web.TimelineResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedWebLooseRender) mustEmbedUnimplementedWebLooseRender() {} + +// UnimplementedWebLooseBinding can be embedded to have forward compatible implementations. +type UnimplementedWebLooseBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebLooseBinding) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) { + obj := new(web.TimelineReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebLooseBinding) mustEmbedUnimplementedWebLooseBinding() {} diff --git a/auto/api/v1/web_priv.go b/auto/api/v1/web_priv.go new file mode 100644 index 00000000..039ac706 --- /dev/null +++ b/auto/api/v1/web_priv.go @@ -0,0 +1,356 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type WebPriv interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + DeleteCommentReply() mir.Error + CreateCommentReply() mir.Error + DeleteComment() mir.Error + CreateComment() mir.Error + VisiblePost() mir.Error + StickTweet() mir.Error + LockTweet() mir.Error + CollectionTweet() mir.Error + StarTweet() mir.Error + DeleteTweet() mir.Error + CreateTweet(*web.CreateTweetReq) (*web.CreateTweetResp, mir.Error) + DownloadAttachment() mir.Error + DownloadAttachmentPrecheck() mir.Error + UploadAttachment() mir.Error + + mustEmbedUnimplementedWebPrivServant() +} + +type WebPrivBinding interface { + BindCreateTweet(*gin.Context) (*web.CreateTweetReq, mir.Error) + + mustEmbedUnimplementedWebPrivBinding() +} + +type WebPrivRender interface { + RenderDeleteCommentReply(*gin.Context, mir.Error) + RenderCreateCommentReply(*gin.Context, mir.Error) + RenderDeleteComment(*gin.Context, mir.Error) + RenderCreateComment(*gin.Context, mir.Error) + RenderVisiblePost(*gin.Context, mir.Error) + RenderStickTweet(*gin.Context, mir.Error) + RenderLockTweet(*gin.Context, mir.Error) + RenderCollectionTweet(*gin.Context, mir.Error) + RenderStarTweet(*gin.Context, mir.Error) + RenderDeleteTweet(*gin.Context, mir.Error) + RenderCreateTweet(*gin.Context, *web.CreateTweetResp, mir.Error) + RenderDownloadAttachment(*gin.Context, mir.Error) + RenderDownloadAttachmentPrecheck(*gin.Context, mir.Error) + RenderUploadAttachment(*gin.Context, mir.Error) + + mustEmbedUnimplementedWebPrivRender() +} + +// RegisterWebPrivServant register WebPriv servant to gin +func RegisterWebPrivServant(e *gin.Engine, s WebPriv, b WebPrivBinding, r WebPrivRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("DELETE", "/post/comment/reply", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderDeleteCommentReply(c, s.DeleteCommentReply()) + }) + + router.Handle("POST", "/post/comment/reply", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderCreateCommentReply(c, s.CreateCommentReply()) + }) + + router.Handle("DELETE", "/post/comment", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderDeleteComment(c, s.DeleteComment()) + }) + + router.Handle("POST", "/post/comment", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderCreateComment(c, s.CreateComment()) + }) + + router.Handle("POST", "/post/visibility", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderVisiblePost(c, s.VisiblePost()) + }) + + router.Handle("POST", "/post/stick", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderStickTweet(c, s.StickTweet()) + }) + + router.Handle("POST", "/post/lock", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderLockTweet(c, s.LockTweet()) + }) + + router.Handle("POST", "/post/collection", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderCollectionTweet(c, s.CollectionTweet()) + }) + + router.Handle("POST", "/post/start", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderStarTweet(c, s.StarTweet()) + }) + + router.Handle("DELETE", "/post", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderDeleteTweet(c, s.DeleteTweet()) + }) + + router.Handle("POST", "/post", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindCreateTweet(c) + if err != nil { + r.RenderCreateTweet(c, nil, err) + return + } + resp, err := s.CreateTweet(req) + r.RenderCreateTweet(c, resp, err) + }) + + router.Handle("GET", "/attachment", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderDownloadAttachment(c, s.DownloadAttachment()) + }) + + router.Handle("GET", "/attachment/precheck", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderDownloadAttachmentPrecheck(c, s.DownloadAttachmentPrecheck()) + }) + + router.Handle("POST", "/attachment", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderUploadAttachment(c, s.UploadAttachment()) + }) + +} + +// UnimplementedWebPrivServant can be embedded to have forward compatible implementations. +type UnimplementedWebPrivServant struct { +} + +func (UnimplementedWebPrivServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedWebPrivServant) DeleteCommentReply() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) CreateCommentReply() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) DeleteComment() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) CreateComment() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) VisiblePost() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) StickTweet() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) LockTweet() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) CollectionTweet() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) StarTweet() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) DeleteTweet() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) CreateTweet(req *web.CreateTweetReq) (*web.CreateTweetResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) DownloadAttachment() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) DownloadAttachmentPrecheck() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) UploadAttachment() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPrivServant) mustEmbedUnimplementedWebPrivServant() {} + +// UnimplementedWebPrivRender can be embedded to have forward compatible implementations. +type UnimplementedWebPrivRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedWebPrivRender) RenderDeleteCommentReply(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderCreateCommentReply(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderDeleteComment(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderCreateComment(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderVisiblePost(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderStickTweet(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderLockTweet(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderCollectionTweet(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderStarTweet(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderDeleteTweet(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderCreateTweet(c *gin.Context, data *web.CreateTweetResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedWebPrivRender) RenderDownloadAttachment(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderDownloadAttachmentPrecheck(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) RenderUploadAttachment(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPrivRender) mustEmbedUnimplementedWebPrivRender() {} + +// UnimplementedWebPrivBinding can be embedded to have forward compatible implementations. +type UnimplementedWebPrivBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebPrivBinding) BindCreateTweet(c *gin.Context) (*web.CreateTweetReq, mir.Error) { + obj := new(web.CreateTweetReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebPrivBinding) mustEmbedUnimplementedWebPrivBinding() {} diff --git a/auto/api/v1/web_pub.go b/auto/api/v1/web_pub.go new file mode 100644 index 00000000..b1e2f591 --- /dev/null +++ b/auto/api/v1/web_pub.go @@ -0,0 +1,226 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type WebPub interface { + TopicList() mir.Error + TweetComments() mir.Error + TweetDetail(*web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) + SendCaptcha() mir.Error + GetCaptcha() mir.Error + Register() mir.Error + Login() mir.Error + Version() mir.Error + + mustEmbedUnimplementedWebPubServant() +} + +type WebPubBinding interface { + BindTweetDetail(*gin.Context) (*web.TweetDetailReq, mir.Error) + + mustEmbedUnimplementedWebPubBinding() +} + +type WebPubRender interface { + RenderTopicList(*gin.Context, mir.Error) + RenderTweetComments(*gin.Context, mir.Error) + RenderTweetDetail(*gin.Context, *web.TweetDetailResp, mir.Error) + RenderSendCaptcha(*gin.Context, mir.Error) + RenderGetCaptcha(*gin.Context, mir.Error) + RenderRegister(*gin.Context, mir.Error) + RenderLogin(*gin.Context, mir.Error) + RenderVersion(*gin.Context, mir.Error) + + mustEmbedUnimplementedWebPubRender() +} + +// RegisterWebPubServant register WebPub servant to gin +func RegisterWebPubServant(e *gin.Engine, s WebPub, b WebPubBinding, r WebPubRender) { + router := e.Group("v1") + + // register routes info to router + router.Handle("GET", "/tags", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderTopicList(c, s.TopicList()) + }) + + router.Handle("GET", "/post/comments", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderTweetComments(c, s.TweetComments()) + }) + + router.Handle("GET", "/post", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindTweetDetail(c) + if err != nil { + r.RenderTweetDetail(c, nil, err) + return + } + resp, err := s.TweetDetail(req) + r.RenderTweetDetail(c, resp, err) + }) + + router.Handle("POST", "/captcha", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderSendCaptcha(c, s.SendCaptcha()) + }) + + router.Handle("GET", "/captcha", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderGetCaptcha(c, s.GetCaptcha()) + }) + + router.Handle("POST", "/auth/register", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderRegister(c, s.Register()) + }) + + router.Handle("POST", "/auth/login", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderLogin(c, s.Login()) + }) + + router.Handle("GET", "/", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + r.RenderVersion(c, s.Version()) + }) + +} + +// UnimplementedWebPubServant can be embedded to have forward compatible implementations. +type UnimplementedWebPubServant struct { +} + +func (UnimplementedWebPubServant) TopicList() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPubServant) TweetComments() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPubServant) TweetDetail(req *web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPubServant) SendCaptcha() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPubServant) GetCaptcha() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPubServant) Register() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPubServant) Login() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPubServant) Version() mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedWebPubServant) mustEmbedUnimplementedWebPubServant() {} + +// UnimplementedWebPubRender can be embedded to have forward compatible implementations. +type UnimplementedWebPubRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedWebPubRender) RenderTopicList(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPubRender) RenderTweetComments(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPubRender) RenderTweetDetail(c *gin.Context, data *web.TweetDetailResp, err mir.Error) { + r.RenderAny(c, data, err) +} + +func (r *UnimplementedWebPubRender) RenderSendCaptcha(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPubRender) RenderGetCaptcha(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPubRender) RenderRegister(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPubRender) RenderLogin(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPubRender) RenderVersion(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedWebPubRender) mustEmbedUnimplementedWebPubRender() {} + +// UnimplementedWebPubBinding can be embedded to have forward compatible implementations. +type UnimplementedWebPubBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedWebPubBinding) BindTweetDetail(c *gin.Context) (*web.TweetDetailReq, mir.Error) { + obj := new(web.TweetDetailReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedWebPubBinding) mustEmbedUnimplementedWebPubBinding() {} diff --git a/go.mod b/go.mod index 50fb6bea..2fed525e 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/cfg v0.3.0 - github.com/alimy/mir/v3 v3.0.0-alpha.8 + github.com/alimy/mir/v3 v3.0.0-beta.2 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 @@ -132,3 +132,5 @@ require ( modernc.org/strutil v1.1.1 // indirect modernc.org/token v1.0.0 // indirect ) + +replace github.com/alimy/mir/v3 => ../../alimy/mir diff --git a/go.sum b/go.sum index 7debc8ba..c7d92f0d 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,6 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= -github.com/alimy/mir/v3 v3.0.0-alpha.8 h1:Zz94oefYkYXA/IuXrjRT7LrQ6LdsZi5z9+IWmXuPdUw= -github.com/alimy/mir/v3 v3.0.0-alpha.8/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/model/model.go b/internal/model/model.go new file mode 100644 index 00000000..12cc4fbb --- /dev/null +++ b/internal/model/model.go @@ -0,0 +1,5 @@ +// 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 model diff --git a/internal/model/web/admin.go b/internal/model/web/admin.go new file mode 100644 index 00000000..ab4747fd --- /dev/null +++ b/internal/model/web/admin.go @@ -0,0 +1,5 @@ +package web + +type ChangeUserStatusReq struct { + *BaseInfo +} diff --git a/internal/model/web/alipay.go b/internal/model/web/alipay.go new file mode 100644 index 00000000..4b4549bd --- /dev/null +++ b/internal/model/web/alipay.go @@ -0,0 +1,13 @@ +package web + +type UserWalletBillsReq struct { + *BaseInfo +} + +type UserWalletBillsResp struct { + // TODO +} + +type AlipayNotifyReq struct { + // TODO +} diff --git a/internal/model/web/core.go b/internal/model/web/core.go new file mode 100644 index 00000000..ca989990 --- /dev/null +++ b/internal/model/web/core.go @@ -0,0 +1,17 @@ +// 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 + +type ChangeAvatarReq struct { + *BaseInfo +} + +type UserInfoReq struct { + *BaseInfo +} + +type UserInfoResp struct { + // TODO +} diff --git a/internal/model/web/followship.go b/internal/model/web/followship.go new file mode 100644 index 00000000..dc51409e --- /dev/null +++ b/internal/model/web/followship.go @@ -0,0 +1,13 @@ +// 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 + +type ListFollowersReq struct { + *BaseInfo +} + +type ListFollowersResp struct { + // TODO +} diff --git a/internal/model/web/friendship.go b/internal/model/web/friendship.go new file mode 100644 index 00000000..79612078 --- /dev/null +++ b/internal/model/web/friendship.go @@ -0,0 +1,13 @@ +// 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 + +type GetContactsReq struct { + *BaseInfo +} + +type GetContactsResp struct { + // TODO +} diff --git a/internal/model/web/loose.go b/internal/model/web/loose.go new file mode 100644 index 00000000..cd9d3fe4 --- /dev/null +++ b/internal/model/web/loose.go @@ -0,0 +1,9 @@ +package web + +type TimelineReq struct { + *BaseInfo +} + +type TimelineResp struct { + // TODO +} diff --git a/internal/model/web/priv.go b/internal/model/web/priv.go new file mode 100644 index 00000000..7e8efd65 --- /dev/null +++ b/internal/model/web/priv.go @@ -0,0 +1,9 @@ +package web + +type CreateTweetReq struct { + *BaseInfo +} + +type CreateTweetResp struct { + // TODO +} diff --git a/internal/model/web/pub.go b/internal/model/web/pub.go new file mode 100644 index 00000000..ac482fc0 --- /dev/null +++ b/internal/model/web/pub.go @@ -0,0 +1,9 @@ +package web + +type TweetDetailReq struct { + // TODO +} + +type TweetDetailResp struct { + // TODO +} diff --git a/internal/model/web/web.go b/internal/model/web/web.go new file mode 100644 index 00000000..8ac4236d --- /dev/null +++ b/internal/model/web/web.go @@ -0,0 +1,13 @@ +// 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 ( + "github.com/rocboss/paopao-ce/internal/core" +) + +type BaseInfo struct { + User *core.User +} diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index d2c30329..3a1c3382 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -31,7 +31,7 @@ type JsonResp struct { Data any `json:",omitempty"` } -func (BaseServant) UserFrom(c *gin.Context) (*core.User, bool) { +func UserFrom(c *gin.Context) (*core.User, bool) { if u, exists := c.Get("USER"); exists { user, ok := u.(*core.User) return user, ok diff --git a/internal/servants/web/admin.go b/internal/servants/web/admin.go index e4f2ef6e..2618746a 100644 --- a/internal/servants/web/admin.go +++ b/internal/servants/web/admin.go @@ -4,6 +4,54 @@ package web +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/internal/servants/chain" +) + +var ( + _ api.WebAdmin = (*webAdminSrv)(nil) + _ api.WebAdminBinding = (*webAdminBinding)(nil) + _ api.WebAdminRender = (*webAdminRender)(nil) +) + type webAdminSrv struct { - // TODO + base.BaseServant + api.UnimplementedWebAdminServant +} + +type webAdminBinding struct { + base.BaseBinding + *api.UnimplementedWebAdminBinding +} + +type webAdminRender struct { + base.BaseRender + *api.UnimplementedWebAdminRender +} + +func (s *webAdminSrv) Chain() gin.HandlersChain { + return gin.HandlersChain{chain.JWT(), chain.Admin()} +} + +func newWebAdminSrv() api.WebAdmin { + return &webAdminSrv{} +} + +func newWebAdminBinding() api.WebAdminBinding { + return &webAdminBinding{ + UnimplementedWebAdminBinding: &api.UnimplementedWebAdminBinding{ + BindAny: base.BindAny, + }, + } +} + +func newWebAdminRender() api.WebAdminRender { + return &webAdminRender{ + UnimplementedWebAdminRender: &api.UnimplementedWebAdminRender{ + RenderAny: base.RenderAny, + }, + } } diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 75c1409a..1c40cdfe 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -5,8 +5,10 @@ package web import ( + "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/internal/servants/chain" ) var ( @@ -30,6 +32,10 @@ type webCoreRender struct { *api.UnimplementedWebCoreRender } +func (s *webCoreSrv) Chain() gin.HandlersChain { + return gin.HandlersChain{chain.JWT()} +} + func newWebCoreSrv() api.WebCore { return &webCoreSrv{} } diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index 044440fa..12cd6937 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -12,4 +12,5 @@ import ( // RouteWeb register web route func RouteWeb(e *gin.Engine) { api.RegisterWebCoreServant(e, newWebCoreSrv(), newWebCoreBinding(), newWebCoreRender()) + api.RegisterWebAdminServant(e, newWebAdminSrv(), newWebAdminBinding(), newWebAdminRender()) } diff --git a/mirc/web/v1/admin.go b/mirc/web/v1/admin.go new file mode 100644 index 00000000..a67e946a --- /dev/null +++ b/mirc/web/v1/admin.go @@ -0,0 +1,22 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +func init() { + AddEntry(new(WebAdmin)) +} + +// // 管理·禁言/解封用户 +// adminApi.POST("/admin/user/status", api.ChangeUserStatus) + +type WebAdmin struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + + // ChangeUserStatus 管理·禁言/解封用户 + ChangeUserStatus func(Post, web.ChangeUserStatusReq) `mir:"/admin/user/status"` +} diff --git a/mirc/web/v1/alipay.go b/mirc/web/v1/alipay.go new file mode 100644 index 00000000..e23212a5 --- /dev/null +++ b/mirc/web/v1/alipay.go @@ -0,0 +1,45 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +func init() { + AddEntries(new(WebAlipayPub), new(WebAlipayPriv)) +} + +// // routeAlipay register Alipay feature releated route if needed +// func routeAlipay(public gin.IRoutes, authApi gin.IRoutes) { +// // 支付宝回调 +// public.POST("/alipay/notify", api.AlipayNotify) + +// // 用户充值 +// authApi.POST("/user/recharge", api.GetUserRechargeLink) + +// // 获取钱包余额 +// authApi.GET("/user/recharge", api.GetUserRechargeResult) + +// // 获取用户账单 +// authApi.GET("/user/wallet/bills", api.GetUserWalletBills) +// } + +type WebAlipayPub struct { + Group Group `mir:"v1"` + + // AlipayNotify 支付宝回调 + AlipayNotify func(Post, web.AlipayNotifyReq) `mir:"/alipay/notify"` +} + +type WebAlipayPriv struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + + // UserRechargeLink 用户充值 + UserRechargeLink func(Post) `mir:"/user/recharge"` + // UserRechargeResult 获取钱包余额 + UserRechargeResult func(Get) `mir:"/user/recharge"` + // UserWalletBills 获取用户账单 + UserWalletBills func(Get, web.UserWalletBillsReq) web.UserWalletBillsResp `mir:"/user/wallet/bills"` +} diff --git a/mirc/web/v1/base.go b/mirc/web/v1/base.go deleted file mode 100644 index ee279a39..00000000 --- a/mirc/web/v1/base.go +++ /dev/null @@ -1,9 +0,0 @@ -package v1 - -import ( - "github.com/rocboss/paopao-ce/internal/core" -) - -type BaseInfo struct { - User *core.User -} diff --git a/mirc/web/v1/core.go b/mirc/web/v1/core.go new file mode 100644 index 00000000..8592c59c --- /dev/null +++ b/mirc/web/v1/core.go @@ -0,0 +1,97 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +func init() { + AddEntry(new(WebCore)) +} + +// // 同步索引 +// authApi.GET("/sync/index", api.SyncSearchIndex) + +// // 获取当前用户信息 +// authApi.GET("/user/info", api.GetUserInfo) + +// // 获取当前用户未读消息数量 +// authApi.GET("/user/msgcount/unread", api.GetUnreadMsgCount) + +// // 获取消息列表 +// authApi.GET("/user/messages", api.GetMessages) + +// // 标记消息已读 +// authApi.POST("/user/message/read", api.ReadMessage) + +// // 发送用户私信 +// authApi.POST("/user/whisper", api.SendUserWhisper) + +// // 获取用户收藏列表 +// authApi.GET("/user/collections", api.GetUserCollections) + +// // 获取用户点赞列表 +// authApi.GET("/user/stars", api.GetUserStars) + +// // 绑定用户手机号 +// authApi.POST("/user/phone", api.BindUserPhone) + +// // 修改密码 +// authApi.POST("/user/password", api.ChangeUserPassword) + +// // 修改昵称 +// authApi.POST("/user/nickname", api.ChangeNickname) + +// // 修改头像 +// authApi.POST("/user/avatar", api.ChangeAvatar) + +// // 检索用户 +// authApi.GET("/suggest/users", api.GetSuggestUsers) + +// // 检索标签 +// authApi.GET("/suggest/tags", api.GetSuggestTags) + +// // 获取动态点赞状态 +// authApi.GET("/post/star", api.GetPostStar) + +// // 获取动态收藏状态 +// authApi.GET("/post/collection", api.GetPostCollection) + +type WebCore struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + + // SyncSearchIndex 同步索引 + SyncSearchIndex func(Get) `mir:"/sync/index"` + // GetUserInfo 获取当前用户信息 + GetUserInfo func(Get, web.UserInfoReq) web.UserInfoResp `mir:"/user/info"` + // GetUnreadMsgCount 获取当前用户未读消息数量 + GetUnreadMsgCount func(Get) `mir:"/user/msgcount/unread"` + // GetMessages 获取消息列表 + GetMessages func(Get) `mir:"/user/messages"` + // ReadMessage 标记消息已读 + ReadMessage func(Post) `mir:"/user/message/read"` + // SendUserWhisper 发送用户私信 + SendUserWhisper func(Post) `mir:"/user/whisper"` + // GetCollections 获取用户收藏列表 + GetCollections func(Get) `mir:"/user/collections"` + // GetStars 获取用户点赞列表 + GetStars func(Get) `mir:"/user/stars"` + // UserPhoneBind 绑定用户手机号 + UserPhoneBind func(Post) `mir:"/user/phone"` + // ChangePassword 修改密码 + ChangePassword func(Post) `mir:"/user/password"` + // ChangeNickname 修改昵称 + ChangeNickname func(Post) `mir:"/user/nickname"` + // ChangeAvatar 修改头像 + ChangeAvatar func(Post, web.ChangeAvatarReq) `mir:"/user/avatar"` + // SuggestUsers 检索用户 + SuggestUsers func(Get) `mir:"/suggest/users"` + // SuggestTags 检索标签 + SuggestTags func(Get) `mir:"/suggest/tags"` + // TweetStarStatus 获取动态点赞状态 + TweetStarStatus func(Get) `mir:"/post/star"` + // TweetCollectionStatus 获取动态收藏状态 + TweetCollectionStatus func(Get) `mir:"/post/collection"` +} diff --git a/mirc/web/v1/followship.go b/mirc/web/v1/followship.go new file mode 100644 index 00000000..d9dfc56d --- /dev/null +++ b/mirc/web/v1/followship.go @@ -0,0 +1,25 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +func init() { + AddEntry(new(WebFollowship)) +} + +type WebFollowship struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + + // AddFollowing 添加关注 + AddFollowing func(Post) `mir:"/following/add"` + // DeleteFollowing 取消关注 + DeleteFollowing func(Post) `mir:"/following/delete"` + // ListFollowings 获取用户的关注列表 + ListFollowings func(Get) `mir:"/following/list"` + // ListFollowers 获取用户的追随者列表 + ListFollowers func(Get, web.ListFollowersReq) web.ListFollowersResp `mir:"/follower/list"` +} diff --git a/mirc/web/v1/friendship.go b/mirc/web/v1/friendship.go new file mode 100644 index 00000000..aab12767 --- /dev/null +++ b/mirc/web/v1/friendship.go @@ -0,0 +1,49 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +func init() { + AddEntry(new(WebFriendship)) +} + +// // routeFriendship register Friendship feature releated routes +// func routeFriendship(authApi gin.IRoutes) { +// // 请求添加朋友 +// authApi.POST("/friend/requesting", api.RequestingFriend) + +// // 同意添加好友 +// authApi.POST("/friend/add", api.AddFriend) + +// // 拒绝添加好友 +// authApi.POST("/friend/reject", api.RejectFriend) + +// // 删除好友 +// authApi.POST("/friend/delete", api.DeleteFriend) + +// // 获取好友列表 +// authApi.GET("/user/contacts", api.GetContacts) +// } + +type WebFriendship struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + + // RequestingFriend 请求添加朋友 + RequestingFriend func(Post) `mir:"/friend/requesting"` + + // AddFriend 同意添加好友 + AddFriend func(Post) `mir:"/friend/add"` + + // RejectFriend 拒绝添加好友 + RejectFriend func(Post) `mir:"/friend/reject"` + + // DeleteFriend 删除好友 + DeleteFriend func(Post) `mir:"/friend/delete"` + + // GetContacts 获取好友列表 + GetContacts func(Get, web.GetContactsReq) web.GetContactsResp `mir:"/user/contacts"` +} diff --git a/mirc/web/v1/localoss.go b/mirc/web/v1/localoss.go deleted file mode 100644 index bf2d09d8..00000000 --- a/mirc/web/v1/localoss.go +++ /dev/null @@ -1,15 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(LocalOSS)) -} - -type LocalOSS struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` -} diff --git a/mirc/web/v1/loose.go b/mirc/web/v1/loose.go new file mode 100644 index 00000000..36bdfff9 --- /dev/null +++ b/mirc/web/v1/loose.go @@ -0,0 +1,36 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +func init() { + AddEntry(new(WebLoose)) +} + +// // 宽松鉴权路由组 +// looseApi := r.Group("/").Use(chain.JwtLoose()) +// { +// // 获取广场流 +// looseApi.GET("/posts", api.GetPostList) + +// // 获取用户动态列表 +// looseApi.GET("/user/posts", api.GetUserPosts) + +// // 获取用户基本信息 +// looseApi.GET("/user/profile", api.GetUserProfile) +// } + +type WebLoose struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + + // Timeline 获取广场流 + Timeline func(Get, web.TimelineReq) web.TimelineResp `mir:"/Posts"` + // GetUserTweets 获取用户动态列表 + GetUserTweets func(Get) `mir:"/user/posts"` + // GetUserProfile 获取用户基本信息 + GetUserProfile func(Get) `mir:"/user/profile"` +} diff --git a/mirc/web/v1/priv.go b/mirc/web/v1/priv.go new file mode 100644 index 00000000..76001a9e --- /dev/null +++ b/mirc/web/v1/priv.go @@ -0,0 +1,87 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +func init() { + AddEntry(new(WebPriv)) +} + +// // 上传资源 +// privApi.POST("/attachment", api.UploadAttachment) + +// // 下载资源预检 +// privApi.GET("/attachment/precheck", api.DownloadAttachmentPrecheck) + +// // 下载资源 +// privApi.GET("/attachment", api.DownloadAttachment) + +// // 发布动态 +// privApi.POST("/post", api.CreatePost) + +// // 删除动态 +// privApi.DELETE("/post", api.DeletePost) + +// // 动态点赞操作 +// privApi.POST("/post/star", api.PostStar) + +// // 动态收藏操作 +// privApi.POST("/post/collection", api.PostCollection) + +// // 锁定动态 +// privApi.POST("/post/lock", api.LockPost) + +// // 置顶动态 +// privApi.POST("/post/stick", api.StickPost) + +// // 修改动态可见度 +// privApi.POST("/post/visibility", api.VisiblePost) + +// // 发布动态评论 +// privApi.POST("/post/comment", api.CreatePostComment) + +// // 删除动态评论 +// privApi.DELETE("/post/comment", api.DeletePostComment) + +// // 发布评论回复 +// privApi.POST("/post/comment/reply", api.CreatePostCommentReply) + +// // 删除评论回复 +// privApi.DELETE("/post/comment/reply", api.DeletePostCommentReply) + +type WebPriv struct { + Chain Chain `mir:"-"` + Group Group `mir:"v1"` + + // UploadAttachment 上传资源 + UploadAttachment func(Post) `mir:"/attachment"` + // DownloadAttachmentPrecheck 下载资源预检 + DownloadAttachmentPrecheck func(Get) `mir:"/attachment/precheck"` + // DownloadAttachment 下载资源 + DownloadAttachment func(Get) `mir:"/attachment"` + // CreateTweet 发布动态 + CreateTweet func(Post, web.CreateTweetReq)web.CreateTweetResp `mir:"/post"` + // DeleteTweet 删除动态 + DeleteTweet func(Delete) `mir:"/post"` + // StarTweet 动态点赞操作 + StarTweet func(Post) `mir:"/post/start"` + // CollectionTweet 动态收藏操作 + CollectionTweet func(Post) `mir:"/post/collection"` + // LockTweet 锁定动态 + LockTweet func(Post) `mir:"/post/lock"` + // StickTweet 置顶动态 + StickTweet func(Post) `mir:"/post/stick"` + // VisiblePost 修改动态可见度 + VisiblePost func(Post) `mir:"/post/visibility"` + // CreateTweetComment 发布动态评论 + CreateComment func(Post) `mir:"/post/comment"` + // DeletePostComment 删除动态评论 + DeleteComment func(Delete) `mir:"/post/comment"` + // CreateCommentReply 发布评论回复 + CreateCommentReply func(Post) `mir:"/post/comment/reply"` + // DeleteCommentReply 删除评论回复 + DeleteCommentReply func(Delete) `mir:"/post/comment/reply"` +} diff --git a/mirc/web/v1/pub.go b/mirc/web/v1/pub.go new file mode 100644 index 00000000..d128efd5 --- /dev/null +++ b/mirc/web/v1/pub.go @@ -0,0 +1,63 @@ +package v1 + +import ( + . "github.com/alimy/mir/v3" + . "github.com/alimy/mir/v3/engine" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +func init() { + AddEntry(new(WebPub)) +} + +// // v1 group api +// r := e.Group("/v1") + +// // 获取version +// r.GET("/", api.Version) + +// // 用户登录 +// r.POST("/auth/login", api.Login) + +// // 用户注册 +// r.POST("/auth/register", api.Register) + +// // 获取验证码 +// r.GET("/captcha", api.GetCaptcha) + +// // 发送验证码 +// r.POST("/captcha", api.PostCaptcha) + +// // 无鉴权路由组 +// noAuthApi := r.Group("/") +// { +// // 获取动态详情 +// noAuthApi.GET("/post", api.GetPost) + +// // 获取动态评论 +// noAuthApi.GET("/post/comments", api.GetPostComments) + +// // 获取话题列表 +// noAuthApi.GET("/tags", api.GetPostTags) +// } + +type WebPub struct { + Group Group `mir:"v1"` + + // Version 获取后台版本信息 + Version func(Get) `mir:"/"` + // Login 用户登录 + Login func(Post) `mir:"/auth/login"` + // Register 用户注册 + Register func(Post) `mir:"/auth/register"` + // GetCaptcha 获取验证码 + GetCaptcha func(Get) `mir:"/captcha"` + // PostCaptcha 发送验证码 + SendCaptcha func(Post) `mir:"/captcha"` + // TweetDetail 获取动态详情 + TweetDetail func(Get, web.TweetDetailReq) web.TweetDetailResp `mir:"/post"` + // TweetComments 获取动态评论 + TweetComments func(Get) `mir:"/post/comments"` + // TopicList 获取话题列表 + TopicList func(Get) `mir:"/tags"` +} diff --git a/mirc/web/v1/web_admin.go b/mirc/web/v1/web_admin.go deleted file mode 100644 index db95fc86..00000000 --- a/mirc/web/v1/web_admin.go +++ /dev/null @@ -1,15 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(WebAdmin)) -} - -type WebAdmin struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` -} diff --git a/mirc/web/v1/web_alipay.go b/mirc/web/v1/web_alipay.go deleted file mode 100644 index 61de0906..00000000 --- a/mirc/web/v1/web_alipay.go +++ /dev/null @@ -1,15 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(WebAlipay)) -} - -type WebAlipay struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` -} diff --git a/mirc/web/v1/web_core.go b/mirc/web/v1/web_core.go deleted file mode 100644 index f87338d7..00000000 --- a/mirc/web/v1/web_core.go +++ /dev/null @@ -1,45 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(WebCore)) -} - -type AgentInfo struct { - Platform string `json:"platform"` - UserAgent string `json:"user_agent"` -} - -type ServerInfo struct { - ApiVer string `json:"api_ver"` -} - -type UserInfo struct { - Name string `json:"name"` -} - -type LoginReq struct { - BaseInfo `json:"-"` - AgentInfo AgentInfo `json:"agent_info"` - Name string `json:"name"` - Passwd string `json:"passwd"` -} - -type LoginResp struct { - UserInfo - ServerInfo ServerInfo `json:"server_info"` - JwtToken string `json:"jwt_token"` -} - -type WebCore struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` - Index func(Get) `mir:"/index/"` - Articles func(Get, Head) `mir:"/articles/:category/"` - Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` - Logout func(Post) `mir:"/user/logout/"` -} diff --git a/mirc/web/v1/web_followship.go b/mirc/web/v1/web_followship.go deleted file mode 100644 index 1dd9de82..00000000 --- a/mirc/web/v1/web_followship.go +++ /dev/null @@ -1,15 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(WebFollowship)) -} - -type WebFollowship struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` -} diff --git a/mirc/web/v1/web_friendship.go b/mirc/web/v1/web_friendship.go deleted file mode 100644 index e1276e99..00000000 --- a/mirc/web/v1/web_friendship.go +++ /dev/null @@ -1,15 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(WebFriendship)) -} - -type WebFriendship struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` -} diff --git a/mirc/web/v1/web_loose.go b/mirc/web/v1/web_loose.go deleted file mode 100644 index 7eff7d44..00000000 --- a/mirc/web/v1/web_loose.go +++ /dev/null @@ -1,15 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(WebLoose)) -} - -type WebLoose struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` -} diff --git a/mirc/web/v1/web_priv.go b/mirc/web/v1/web_priv.go deleted file mode 100644 index 3d73eb1b..00000000 --- a/mirc/web/v1/web_priv.go +++ /dev/null @@ -1,15 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(WebPriv)) -} - -type WebPriv struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` -} diff --git a/mirc/web/v1/web_pub.go b/mirc/web/v1/web_pub.go deleted file mode 100644 index 7bfe2e3a..00000000 --- a/mirc/web/v1/web_pub.go +++ /dev/null @@ -1,15 +0,0 @@ -package v1 - -import ( - . "github.com/alimy/mir/v3" - . "github.com/alimy/mir/v3/engine" -) - -func init() { - AddEntry(new(WebPub)) -} - -type WebPub struct { - Chain Chain `mir:"-"` - Group Group `mir:"v1"` -} From 3a1626efb4917c02ffe09fec38ff28e8bcf8b883 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 23 Dec 2022 12:55:22 +0800 Subject: [PATCH 48/65] mir: remove reduce comment in mirc/web/v1 and go mod tidy --- go.mod | 2 -- go.sum | 2 ++ mirc/web/v1/admin.go | 3 -- mirc/web/v1/alipay.go | 17 ++--------- mirc/web/v1/core.go | 63 ++++++++++----------------------------- mirc/web/v1/followship.go | 3 ++ mirc/web/v1/friendship.go | 18 ----------- mirc/web/v1/loose.go | 17 ++--------- mirc/web/v1/priv.go | 57 +++++++++-------------------------- mirc/web/v1/pub.go | 38 +++++------------------ 10 files changed, 46 insertions(+), 174 deletions(-) diff --git a/go.mod b/go.mod index 2fed525e..2377b980 100644 --- a/go.mod +++ b/go.mod @@ -132,5 +132,3 @@ require ( modernc.org/strutil v1.1.1 // indirect modernc.org/token v1.0.0 // indirect ) - -replace github.com/alimy/mir/v3 => ../../alimy/mir diff --git a/go.sum b/go.sum index c7d92f0d..69ac6d38 100644 --- a/go.sum +++ b/go.sum @@ -147,6 +147,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= +github.com/alimy/mir/v3 v3.0.0-beta.2 h1:qpg0l4FEUafkpzGXlBIJtJbFjQfzbK9lDP5FJjjgOrA= +github.com/alimy/mir/v3 v3.0.0-beta.2/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/mirc/web/v1/admin.go b/mirc/web/v1/admin.go index a67e946a..97d89ea8 100644 --- a/mirc/web/v1/admin.go +++ b/mirc/web/v1/admin.go @@ -10,9 +10,6 @@ func init() { AddEntry(new(WebAdmin)) } -// // 管理·禁言/解封用户 -// adminApi.POST("/admin/user/status", api.ChangeUserStatus) - type WebAdmin struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/alipay.go b/mirc/web/v1/alipay.go index e23212a5..55397a08 100644 --- a/mirc/web/v1/alipay.go +++ b/mirc/web/v1/alipay.go @@ -10,21 +10,6 @@ func init() { AddEntries(new(WebAlipayPub), new(WebAlipayPriv)) } -// // routeAlipay register Alipay feature releated route if needed -// func routeAlipay(public gin.IRoutes, authApi gin.IRoutes) { -// // 支付宝回调 -// public.POST("/alipay/notify", api.AlipayNotify) - -// // 用户充值 -// authApi.POST("/user/recharge", api.GetUserRechargeLink) - -// // 获取钱包余额 -// authApi.GET("/user/recharge", api.GetUserRechargeResult) - -// // 获取用户账单 -// authApi.GET("/user/wallet/bills", api.GetUserWalletBills) -// } - type WebAlipayPub struct { Group Group `mir:"v1"` @@ -38,8 +23,10 @@ type WebAlipayPriv struct { // UserRechargeLink 用户充值 UserRechargeLink func(Post) `mir:"/user/recharge"` + // UserRechargeResult 获取钱包余额 UserRechargeResult func(Get) `mir:"/user/recharge"` + // UserWalletBills 获取用户账单 UserWalletBills func(Get, web.UserWalletBillsReq) web.UserWalletBillsResp `mir:"/user/wallet/bills"` } diff --git a/mirc/web/v1/core.go b/mirc/web/v1/core.go index 8592c59c..4d9e5ba4 100644 --- a/mirc/web/v1/core.go +++ b/mirc/web/v1/core.go @@ -10,88 +10,55 @@ func init() { AddEntry(new(WebCore)) } -// // 同步索引 -// authApi.GET("/sync/index", api.SyncSearchIndex) - -// // 获取当前用户信息 -// authApi.GET("/user/info", api.GetUserInfo) - -// // 获取当前用户未读消息数量 -// authApi.GET("/user/msgcount/unread", api.GetUnreadMsgCount) - -// // 获取消息列表 -// authApi.GET("/user/messages", api.GetMessages) - -// // 标记消息已读 -// authApi.POST("/user/message/read", api.ReadMessage) - -// // 发送用户私信 -// authApi.POST("/user/whisper", api.SendUserWhisper) - -// // 获取用户收藏列表 -// authApi.GET("/user/collections", api.GetUserCollections) - -// // 获取用户点赞列表 -// authApi.GET("/user/stars", api.GetUserStars) - -// // 绑定用户手机号 -// authApi.POST("/user/phone", api.BindUserPhone) - -// // 修改密码 -// authApi.POST("/user/password", api.ChangeUserPassword) - -// // 修改昵称 -// authApi.POST("/user/nickname", api.ChangeNickname) - -// // 修改头像 -// authApi.POST("/user/avatar", api.ChangeAvatar) - -// // 检索用户 -// authApi.GET("/suggest/users", api.GetSuggestUsers) - -// // 检索标签 -// authApi.GET("/suggest/tags", api.GetSuggestTags) - -// // 获取动态点赞状态 -// authApi.GET("/post/star", api.GetPostStar) - -// // 获取动态收藏状态 -// authApi.GET("/post/collection", api.GetPostCollection) - type WebCore struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` // SyncSearchIndex 同步索引 SyncSearchIndex func(Get) `mir:"/sync/index"` + // GetUserInfo 获取当前用户信息 GetUserInfo func(Get, web.UserInfoReq) web.UserInfoResp `mir:"/user/info"` + // GetUnreadMsgCount 获取当前用户未读消息数量 GetUnreadMsgCount func(Get) `mir:"/user/msgcount/unread"` + // GetMessages 获取消息列表 GetMessages func(Get) `mir:"/user/messages"` + // ReadMessage 标记消息已读 ReadMessage func(Post) `mir:"/user/message/read"` + // SendUserWhisper 发送用户私信 SendUserWhisper func(Post) `mir:"/user/whisper"` + // GetCollections 获取用户收藏列表 GetCollections func(Get) `mir:"/user/collections"` + // GetStars 获取用户点赞列表 GetStars func(Get) `mir:"/user/stars"` + // UserPhoneBind 绑定用户手机号 UserPhoneBind func(Post) `mir:"/user/phone"` + // ChangePassword 修改密码 ChangePassword func(Post) `mir:"/user/password"` + // ChangeNickname 修改昵称 ChangeNickname func(Post) `mir:"/user/nickname"` + // ChangeAvatar 修改头像 ChangeAvatar func(Post, web.ChangeAvatarReq) `mir:"/user/avatar"` + // SuggestUsers 检索用户 SuggestUsers func(Get) `mir:"/suggest/users"` + // SuggestTags 检索标签 SuggestTags func(Get) `mir:"/suggest/tags"` + // TweetStarStatus 获取动态点赞状态 TweetStarStatus func(Get) `mir:"/post/star"` + // TweetCollectionStatus 获取动态收藏状态 TweetCollectionStatus func(Get) `mir:"/post/collection"` } diff --git a/mirc/web/v1/followship.go b/mirc/web/v1/followship.go index d9dfc56d..a3ff76a3 100644 --- a/mirc/web/v1/followship.go +++ b/mirc/web/v1/followship.go @@ -16,10 +16,13 @@ type WebFollowship struct { // AddFollowing 添加关注 AddFollowing func(Post) `mir:"/following/add"` + // DeleteFollowing 取消关注 DeleteFollowing func(Post) `mir:"/following/delete"` + // ListFollowings 获取用户的关注列表 ListFollowings func(Get) `mir:"/following/list"` + // ListFollowers 获取用户的追随者列表 ListFollowers func(Get, web.ListFollowersReq) web.ListFollowersResp `mir:"/follower/list"` } diff --git a/mirc/web/v1/friendship.go b/mirc/web/v1/friendship.go index aab12767..409513ec 100644 --- a/mirc/web/v1/friendship.go +++ b/mirc/web/v1/friendship.go @@ -10,24 +10,6 @@ func init() { AddEntry(new(WebFriendship)) } -// // routeFriendship register Friendship feature releated routes -// func routeFriendship(authApi gin.IRoutes) { -// // 请求添加朋友 -// authApi.POST("/friend/requesting", api.RequestingFriend) - -// // 同意添加好友 -// authApi.POST("/friend/add", api.AddFriend) - -// // 拒绝添加好友 -// authApi.POST("/friend/reject", api.RejectFriend) - -// // 删除好友 -// authApi.POST("/friend/delete", api.DeleteFriend) - -// // 获取好友列表 -// authApi.GET("/user/contacts", api.GetContacts) -// } - type WebFriendship struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/loose.go b/mirc/web/v1/loose.go index 36bdfff9..804d33a2 100644 --- a/mirc/web/v1/loose.go +++ b/mirc/web/v1/loose.go @@ -10,27 +10,16 @@ func init() { AddEntry(new(WebLoose)) } -// // 宽松鉴权路由组 -// looseApi := r.Group("/").Use(chain.JwtLoose()) -// { -// // 获取广场流 -// looseApi.GET("/posts", api.GetPostList) - -// // 获取用户动态列表 -// looseApi.GET("/user/posts", api.GetUserPosts) - -// // 获取用户基本信息 -// looseApi.GET("/user/profile", api.GetUserProfile) -// } - type WebLoose struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` // Timeline 获取广场流 - Timeline func(Get, web.TimelineReq) web.TimelineResp `mir:"/Posts"` + Timeline func(Get, web.TimelineReq) web.TimelineResp `mir:"/posts"` + // GetUserTweets 获取用户动态列表 GetUserTweets func(Get) `mir:"/user/posts"` + // GetUserProfile 获取用户基本信息 GetUserProfile func(Get) `mir:"/user/profile"` } diff --git a/mirc/web/v1/priv.go b/mirc/web/v1/priv.go index 76001a9e..43ec13b2 100644 --- a/mirc/web/v1/priv.go +++ b/mirc/web/v1/priv.go @@ -10,78 +10,49 @@ func init() { AddEntry(new(WebPriv)) } -// // 上传资源 -// privApi.POST("/attachment", api.UploadAttachment) - -// // 下载资源预检 -// privApi.GET("/attachment/precheck", api.DownloadAttachmentPrecheck) - -// // 下载资源 -// privApi.GET("/attachment", api.DownloadAttachment) - -// // 发布动态 -// privApi.POST("/post", api.CreatePost) - -// // 删除动态 -// privApi.DELETE("/post", api.DeletePost) - -// // 动态点赞操作 -// privApi.POST("/post/star", api.PostStar) - -// // 动态收藏操作 -// privApi.POST("/post/collection", api.PostCollection) - -// // 锁定动态 -// privApi.POST("/post/lock", api.LockPost) - -// // 置顶动态 -// privApi.POST("/post/stick", api.StickPost) - -// // 修改动态可见度 -// privApi.POST("/post/visibility", api.VisiblePost) - -// // 发布动态评论 -// privApi.POST("/post/comment", api.CreatePostComment) - -// // 删除动态评论 -// privApi.DELETE("/post/comment", api.DeletePostComment) - -// // 发布评论回复 -// privApi.POST("/post/comment/reply", api.CreatePostCommentReply) - -// // 删除评论回复 -// privApi.DELETE("/post/comment/reply", api.DeletePostCommentReply) - type WebPriv struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` // UploadAttachment 上传资源 UploadAttachment func(Post) `mir:"/attachment"` + // DownloadAttachmentPrecheck 下载资源预检 DownloadAttachmentPrecheck func(Get) `mir:"/attachment/precheck"` + // DownloadAttachment 下载资源 DownloadAttachment func(Get) `mir:"/attachment"` + // CreateTweet 发布动态 - CreateTweet func(Post, web.CreateTweetReq)web.CreateTweetResp `mir:"/post"` + CreateTweet func(Post, web.CreateTweetReq) web.CreateTweetResp `mir:"/post"` + // DeleteTweet 删除动态 DeleteTweet func(Delete) `mir:"/post"` + // StarTweet 动态点赞操作 StarTweet func(Post) `mir:"/post/start"` + // CollectionTweet 动态收藏操作 CollectionTweet func(Post) `mir:"/post/collection"` + // LockTweet 锁定动态 LockTweet func(Post) `mir:"/post/lock"` + // StickTweet 置顶动态 StickTweet func(Post) `mir:"/post/stick"` + // VisiblePost 修改动态可见度 VisiblePost func(Post) `mir:"/post/visibility"` + // CreateTweetComment 发布动态评论 CreateComment func(Post) `mir:"/post/comment"` + // DeletePostComment 删除动态评论 DeleteComment func(Delete) `mir:"/post/comment"` + // CreateCommentReply 发布评论回复 CreateCommentReply func(Post) `mir:"/post/comment/reply"` + // DeleteCommentReply 删除评论回复 DeleteCommentReply func(Delete) `mir:"/post/comment/reply"` } diff --git a/mirc/web/v1/pub.go b/mirc/web/v1/pub.go index d128efd5..73491b44 100644 --- a/mirc/web/v1/pub.go +++ b/mirc/web/v1/pub.go @@ -10,54 +10,30 @@ func init() { AddEntry(new(WebPub)) } -// // v1 group api -// r := e.Group("/v1") - -// // 获取version -// r.GET("/", api.Version) - -// // 用户登录 -// r.POST("/auth/login", api.Login) - -// // 用户注册 -// r.POST("/auth/register", api.Register) - -// // 获取验证码 -// r.GET("/captcha", api.GetCaptcha) - -// // 发送验证码 -// r.POST("/captcha", api.PostCaptcha) - -// // 无鉴权路由组 -// noAuthApi := r.Group("/") -// { -// // 获取动态详情 -// noAuthApi.GET("/post", api.GetPost) - -// // 获取动态评论 -// noAuthApi.GET("/post/comments", api.GetPostComments) - -// // 获取话题列表 -// noAuthApi.GET("/tags", api.GetPostTags) -// } - type WebPub struct { Group Group `mir:"v1"` // Version 获取后台版本信息 Version func(Get) `mir:"/"` + // Login 用户登录 Login func(Post) `mir:"/auth/login"` + // Register 用户注册 Register func(Post) `mir:"/auth/register"` + // GetCaptcha 获取验证码 GetCaptcha func(Get) `mir:"/captcha"` + // PostCaptcha 发送验证码 SendCaptcha func(Post) `mir:"/captcha"` + // TweetDetail 获取动态详情 TweetDetail func(Get, web.TweetDetailReq) web.TweetDetailResp `mir:"/post"` + // TweetComments 获取动态评论 TweetComments func(Get) `mir:"/post/comments"` + // TopicList 获取话题列表 TopicList func(Get) `mir:"/tags"` } From 63bc1c57e6d9ea70cde945d84496bddfa4f2d044 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 23 Dec 2022 14:29:32 +0800 Subject: [PATCH 49/65] add internal/servants/web servants init logic --- internal/model/web/admin.go | 2 +- internal/model/web/alipay.go | 2 +- internal/model/web/core.go | 4 +- internal/model/web/followship.go | 2 +- internal/model/web/friendship.go | 2 +- internal/model/web/loose.go | 2 +- internal/model/web/priv.go | 2 +- internal/model/web/web.go | 4 ++ internal/servants/base/base.go | 9 +++ internal/servants/web/alipay.go | 90 ++++++++++++++++++++++++++++- internal/servants/web/followship.go | 50 +++++++++++++++- internal/servants/web/friendship.go | 50 +++++++++++++++- internal/servants/web/loose.go | 50 +++++++++++++++- internal/servants/web/priv.go | 50 +++++++++++++++- internal/servants/web/pub.go | 50 +++++++++++++++- internal/servants/web/web.go | 19 +++++- internal/servants/web/xerror.go | 69 +++++++++++----------- 17 files changed, 407 insertions(+), 50 deletions(-) diff --git a/internal/model/web/admin.go b/internal/model/web/admin.go index ab4747fd..765d507a 100644 --- a/internal/model/web/admin.go +++ b/internal/model/web/admin.go @@ -1,5 +1,5 @@ package web type ChangeUserStatusReq struct { - *BaseInfo + *BaseInfo `json:"-"` } diff --git a/internal/model/web/alipay.go b/internal/model/web/alipay.go index 4b4549bd..15fc2321 100644 --- a/internal/model/web/alipay.go +++ b/internal/model/web/alipay.go @@ -1,7 +1,7 @@ package web type UserWalletBillsReq struct { - *BaseInfo + *BaseInfo `json:"-"` } type UserWalletBillsResp struct { diff --git a/internal/model/web/core.go b/internal/model/web/core.go index ca989990..12243a1e 100644 --- a/internal/model/web/core.go +++ b/internal/model/web/core.go @@ -5,11 +5,11 @@ package web type ChangeAvatarReq struct { - *BaseInfo + *BaseInfo `json:"-"` } type UserInfoReq struct { - *BaseInfo + *BaseInfo `json:"-"` } type UserInfoResp struct { diff --git a/internal/model/web/followship.go b/internal/model/web/followship.go index dc51409e..1b1f0428 100644 --- a/internal/model/web/followship.go +++ b/internal/model/web/followship.go @@ -5,7 +5,7 @@ package web type ListFollowersReq struct { - *BaseInfo + *BaseInfo `json:"-"` } type ListFollowersResp struct { diff --git a/internal/model/web/friendship.go b/internal/model/web/friendship.go index 79612078..1cece059 100644 --- a/internal/model/web/friendship.go +++ b/internal/model/web/friendship.go @@ -5,7 +5,7 @@ package web type GetContactsReq struct { - *BaseInfo + *BaseInfo `json:"-"` } type GetContactsResp struct { diff --git a/internal/model/web/loose.go b/internal/model/web/loose.go index cd9d3fe4..26a3aa6e 100644 --- a/internal/model/web/loose.go +++ b/internal/model/web/loose.go @@ -1,7 +1,7 @@ package web type TimelineReq struct { - *BaseInfo + *BaseInfo `json:"-"` } type TimelineResp struct { diff --git a/internal/model/web/priv.go b/internal/model/web/priv.go index 7e8efd65..d6ced02e 100644 --- a/internal/model/web/priv.go +++ b/internal/model/web/priv.go @@ -1,7 +1,7 @@ package web type CreateTweetReq struct { - *BaseInfo + *BaseInfo `json:"-"` } type CreateTweetResp struct { diff --git a/internal/model/web/web.go b/internal/model/web/web.go index 8ac4236d..dd04971a 100644 --- a/internal/model/web/web.go +++ b/internal/model/web/web.go @@ -11,3 +11,7 @@ import ( type BaseInfo struct { User *core.User } + +func (b *BaseInfo) SetUser(user *core.User) { + b.User = user +} diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index 3a1c3382..eac975ed 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -31,6 +31,10 @@ type JsonResp struct { Data any `json:",omitempty"` } +type UserSetter interface { + SetUser(*core.User) +} + func UserFrom(c *gin.Context) (*core.User, bool) { if u, exists := c.Get("USER"); exists { user, ok := u.(*core.User) @@ -45,6 +49,11 @@ func BindAny(c *gin.Context, obj any) mir.Error { if err != nil { return mir.NewError(xerror.InvalidParams.Code(), xerror.InvalidParams.WithDetails(errs.Error())) } + // setup *core.User if needed + if setter, ok := obj.(UserSetter); ok { + user, _ := UserFrom(c) + setter.SetUser(user) + } return nil } diff --git a/internal/servants/web/alipay.go b/internal/servants/web/alipay.go index 80cfd7b7..d8c143eb 100644 --- a/internal/servants/web/alipay.go +++ b/internal/servants/web/alipay.go @@ -4,6 +4,92 @@ package web -type webAlipaySrv struct { - // TODO +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/internal/servants/chain" +) + +var ( + _ api.WebAlipayPub = (*webAlipayPubSrv)(nil) + _ api.WebAlipayPubBinding = (*webAlipayPubBinding)(nil) + _ api.WebAlipayPubRender = (*webAlipayPubRender)(nil) + _ api.WebAlipayPriv = (*webAlipayPrivSrv)(nil) + _ api.WebAlipayPrivBinding = (*webAlipayPrivBinding)(nil) + _ api.WebAlipayPrivRender = (*webAlipayPrivRender)(nil) +) + +type webAlipayPubSrv struct { + base.BaseServant + api.UnimplementedWebAlipayPubServant +} + +type webAlipayPubBinding struct { + base.BaseBinding + *api.UnimplementedWebAlipayPubBinding +} + +type webAlipayPubRender struct { + base.BaseRender + *api.UnimplementedWebAlipayPubRender +} + +type webAlipayPrivSrv struct { + base.BaseServant + api.UnimplementedWebAlipayPrivServant +} + +type webAlipayPrivBinding struct { + base.BaseBinding + *api.UnimplementedWebAlipayPrivBinding +} + +type webAlipayPrivRender struct { + base.BaseRender + *api.UnimplementedWebAlipayPrivRender +} + +func (s *webAlipayPrivSrv) Chain() gin.HandlersChain { + return gin.HandlersChain{chain.JWT()} +} + +func newWebAlipayPubSrv() api.WebAlipayPub { + return &webAlipayPubSrv{} +} + +func newWebAlipayPubBinding() api.WebAlipayPubBinding { + return &webAlipayPubBinding{ + UnimplementedWebAlipayPubBinding: &api.UnimplementedWebAlipayPubBinding{ + BindAny: base.BindAny, + }, + } +} + +func newWebAlipayPubRender() api.WebAlipayPubRender { + return &webAlipayPubRender{ + UnimplementedWebAlipayPubRender: &api.UnimplementedWebAlipayPubRender{ + RenderAny: base.RenderAny, + }, + } +} + +func newWebAlipayPrivSrv() api.WebAlipayPriv { + return &webAlipayPrivSrv{} +} + +func newWebAlipayPrivBinding() api.WebAlipayPrivBinding { + return &webAlipayPrivBinding{ + UnimplementedWebAlipayPrivBinding: &api.UnimplementedWebAlipayPrivBinding{ + BindAny: base.BindAny, + }, + } +} + +func newWebAlipayPrivRender() api.WebAlipayPrivRender { + return &webAlipayPrivRender{ + UnimplementedWebAlipayPrivRender: &api.UnimplementedWebAlipayPrivRender{ + RenderAny: base.RenderAny, + }, + } } diff --git a/internal/servants/web/followship.go b/internal/servants/web/followship.go index 4158de39..a9c077f3 100644 --- a/internal/servants/web/followship.go +++ b/internal/servants/web/followship.go @@ -4,6 +4,54 @@ package web +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/internal/servants/chain" +) + +var ( + _ api.WebFollowship = (*webFollowshipSrv)(nil) + _ api.WebFollowshipBinding = (*webFollowshipBinding)(nil) + _ api.WebFollowshipRender = (*webFollowshipRender)(nil) +) + type webFollowshipSrv struct { - // TODO + base.BaseServant + api.UnimplementedWebFollowshipServant +} + +type webFollowshipBinding struct { + base.BaseBinding + *api.UnimplementedWebFollowshipBinding +} + +type webFollowshipRender struct { + base.BaseRender + *api.UnimplementedWebFollowshipRender +} + +func (s *webFollowshipSrv) Chain() gin.HandlersChain { + return gin.HandlersChain{chain.JWT()} +} + +func newWebFollowshipSrv() api.WebFollowship { + return &webFollowshipSrv{} +} + +func newWebFollowshipBinding() api.WebFollowshipBinding { + return &webFollowshipBinding{ + UnimplementedWebFollowshipBinding: &api.UnimplementedWebFollowshipBinding{ + BindAny: base.BindAny, + }, + } +} + +func newWebFollowshipRender() api.WebFollowshipRender { + return &webFollowshipRender{ + UnimplementedWebFollowshipRender: &api.UnimplementedWebFollowshipRender{ + RenderAny: base.RenderAny, + }, + } } diff --git a/internal/servants/web/friendship.go b/internal/servants/web/friendship.go index a4fb3d59..042bf0a5 100644 --- a/internal/servants/web/friendship.go +++ b/internal/servants/web/friendship.go @@ -4,6 +4,54 @@ package web +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/internal/servants/chain" +) + +var ( + _ api.WebFriendship = (*webFriendshipSrv)(nil) + _ api.WebFriendshipBinding = (*webFriendshipBinding)(nil) + _ api.WebFriendshipRender = (*webFriendshipRender)(nil) +) + type webFriendshipSrv struct { - // TODO + base.BaseServant + api.UnimplementedWebFriendshipServant +} + +type webFriendshipBinding struct { + base.BaseBinding + *api.UnimplementedWebFriendshipBinding +} + +type webFriendshipRender struct { + base.BaseRender + *api.UnimplementedWebFriendshipRender +} + +func (s *webFriendshipSrv) Chain() gin.HandlersChain { + return gin.HandlersChain{chain.JWT()} +} + +func newWebFriendshipSrv() api.WebFriendship { + return &webFriendshipSrv{} +} + +func newWebFriendshipBinding() api.WebFriendshipBinding { + return &webFriendshipBinding{ + UnimplementedWebFriendshipBinding: &api.UnimplementedWebFriendshipBinding{ + BindAny: base.BindAny, + }, + } +} + +func newWebFriendshipRender() api.WebFriendshipRender { + return &webFriendshipRender{ + UnimplementedWebFriendshipRender: &api.UnimplementedWebFriendshipRender{ + RenderAny: base.RenderAny, + }, + } } diff --git a/internal/servants/web/loose.go b/internal/servants/web/loose.go index 51a309a1..04a75faa 100644 --- a/internal/servants/web/loose.go +++ b/internal/servants/web/loose.go @@ -4,6 +4,54 @@ package web +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/internal/servants/chain" +) + +var ( + _ api.WebLoose = (*webLooseSrv)(nil) + _ api.WebLooseBinding = (*webLooseBinding)(nil) + _ api.WebLooseRender = (*webLooseRender)(nil) +) + type webLooseSrv struct { - // TODO + base.BaseServant + api.UnimplementedWebLooseServant +} + +type webLooseBinding struct { + base.BaseBinding + *api.UnimplementedWebLooseBinding +} + +type webLooseRender struct { + base.BaseRender + *api.UnimplementedWebLooseRender +} + +func (s *webLooseSrv) Chain() gin.HandlersChain { + return gin.HandlersChain{chain.JwtLoose()} +} + +func newWebLooseSrv() api.WebLoose { + return &webLooseSrv{} +} + +func newWebLooseBinding() api.WebLooseBinding { + return &webLooseBinding{ + UnimplementedWebLooseBinding: &api.UnimplementedWebLooseBinding{ + BindAny: base.BindAny, + }, + } +} + +func newWebLooseRender() api.WebLooseRender { + return &webLooseRender{ + UnimplementedWebLooseRender: &api.UnimplementedWebLooseRender{ + RenderAny: base.RenderAny, + }, + } } diff --git a/internal/servants/web/priv.go b/internal/servants/web/priv.go index 51f0f486..96485fec 100644 --- a/internal/servants/web/priv.go +++ b/internal/servants/web/priv.go @@ -4,6 +4,54 @@ package web +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/internal/servants/chain" +) + +var ( + _ api.WebPriv = (*webPrivSrv)(nil) + _ api.WebPrivBinding = (*webPrivBinding)(nil) + _ api.WebPrivRender = (*webPrivRender)(nil) +) + type webPrivSrv struct { - // TODO + base.BaseServant + api.UnimplementedWebPrivServant +} + +type webPrivBinding struct { + base.BaseBinding + *api.UnimplementedWebPrivBinding +} + +type webPrivRender struct { + base.BaseRender + *api.UnimplementedWebPrivRender +} + +func (s *webPrivSrv) Chain() gin.HandlersChain { + return gin.HandlersChain{chain.JWT(), chain.Priv()} +} + +func newWebPrivSrv() api.WebPriv { + return &webPrivSrv{} +} + +func newWebPrivBinding() api.WebPrivBinding { + return &webPrivBinding{ + UnimplementedWebPrivBinding: &api.UnimplementedWebPrivBinding{ + BindAny: base.BindAny, + }, + } +} + +func newWebPrivRender() api.WebPrivRender { + return &webPrivRender{ + UnimplementedWebPrivRender: &api.UnimplementedWebPrivRender{ + RenderAny: base.RenderAny, + }, + } } diff --git a/internal/servants/web/pub.go b/internal/servants/web/pub.go index d7c68ec5..689cbc32 100644 --- a/internal/servants/web/pub.go +++ b/internal/servants/web/pub.go @@ -4,6 +4,54 @@ package web +import ( + "github.com/gin-gonic/gin" + api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/internal/servants/chain" +) + +var ( + _ api.WebPub = (*webPubSrv)(nil) + _ api.WebPubBinding = (*webPubBinding)(nil) + _ api.WebPubRender = (*webPubRender)(nil) +) + type webPubSrv struct { - // TODO + base.BaseServant + api.UnimplementedWebPubServant +} + +type webPubBinding struct { + base.BaseBinding + *api.UnimplementedWebPubBinding +} + +type webPubRender struct { + base.BaseRender + *api.UnimplementedWebPubRender +} + +func (s *webPubSrv) Chain() gin.HandlersChain { + return gin.HandlersChain{chain.JwtLoose()} +} + +func newWebPubSrv() api.WebPub { + return &webPubSrv{} +} + +func newWebPubBinding() api.WebPubBinding { + return &webPubBinding{ + UnimplementedWebPubBinding: &api.UnimplementedWebPubBinding{ + BindAny: base.BindAny, + }, + } +} + +func newWebPubRender() api.WebPubRender { + return &webPubRender{ + UnimplementedWebPubRender: &api.UnimplementedWebPubRender{ + RenderAny: base.RenderAny, + }, + } } diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index 12cd6937..d19444a7 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -5,12 +5,29 @@ package web import ( + "github.com/alimy/cfg" "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" ) // RouteWeb register web route func RouteWeb(e *gin.Engine) { - api.RegisterWebCoreServant(e, newWebCoreSrv(), newWebCoreBinding(), newWebCoreRender()) api.RegisterWebAdminServant(e, newWebAdminSrv(), newWebAdminBinding(), newWebAdminRender()) + api.RegisterWebCoreServant(e, newWebCoreSrv(), newWebCoreBinding(), newWebCoreRender()) + api.RegisterWebLooseServant(e, newWebLooseSrv(), newWebLooseBinding(), newWebLooseRender()) + api.RegisterWebPrivServant(e, newWebPrivSrv(), newWebPrivBinding(), newWebPrivRender()) + api.RegisterWebPubServant(e, newWebPubSrv(), newWebPubBinding(), newWebPubRender()) + + cfg.In(cfg.Actions{ + "Alipay": func() { + api.RegisterWebAlipayPubServant(e, newWebAlipayPubSrv(), newWebAlipayPubBinding(), newWebAlipayPubRender()) + api.RegisterWebAlipayPrivServant(e, newWebAlipayPrivSrv(), newWebAlipayPrivBinding(), newWebAlipayPrivRender()) + }, + "Followship": func() { + api.RegisterWebFollowshipServant(e, newWebFollowshipSrv(), newWebFollowshipBinding(), newWebFollowshipRender()) + }, + "Friendship": func() { + api.RegisterWebFriendshipServant(e, newWebFriendshipSrv(), newWebFriendshipBinding(), newWebFriendshipRender()) + }, + }) } diff --git a/internal/servants/web/xerror.go b/internal/servants/web/xerror.go index ecc0355e..f5c9aeb3 100644 --- a/internal/servants/web/xerror.go +++ b/internal/servants/web/xerror.go @@ -8,42 +8,43 @@ import ( "github.com/rocboss/paopao-ce/pkg/xerror" ) +// nolint var ( - errUsernameHasExisted = xerror.NewError(20001, "用户名已存在") - errUsernameLengthLimit = xerror.NewError(20002, "用户名长度3~12") - errUsernameCharLimit = xerror.NewError(20003, "用户名只能包含字母、数字") - errPasswordLengthLimit = xerror.NewError(20004, "密码长度6~16") - errUserRegisterFailed = xerror.NewError(20005, "用户注册失败") - errUserHasBeenBanned = xerror.NewError(20006, "该账户已被封停") - errNoPermission = xerror.NewError(20007, "无权限执行该请求") - errUserHasBindOTP = xerror.NewError(20008, "当前用户已绑定二次验证") - errUserOTPInvalid = xerror.NewError(20009, "二次验证码验证失败") - errUserNoBindOTP = xerror.NewError(20010, "当前用户未绑定二次验证") - errErrorOldPassword = xerror.NewError(20011, "当前用户密码验证失败") - errErrorCaptchaPassword = xerror.NewError(20012, "图形验证码验证失败") - errAccountNoPhoneBind = xerror.NewError(20013, "拒绝操作: 账户未绑定手机号") - errTooManyLoginError = xerror.NewError(20014, "登录失败次数过多,请稍后再试") - errGetPhoneCaptchaError = xerror.NewError(20015, "短信验证码获取失败") - errTooManyPhoneCaptchaSend = xerror.NewError(20016, "短信验证码获取次数已达今日上限") - errExistedUserPhone = xerror.NewError(20017, "该手机号已被绑定") - errErrorPhoneCaptcha = xerror.NewError(20018, "手机验证码不正确") - errMaxPhoneCaptchaUseTimes = xerror.NewError(20019, "手机验证码已达最大使用次数") - errNicknameLengthLimit = xerror.NewError(20020, "昵称长度2~12") - errNoExistUsername = xerror.NewError(20021, "用户不存在") - errNoAdminPermission = xerror.NewError(20022, "无管理权限") + _errUsernameHasExisted = xerror.NewError(20001, "用户名已存在") + _errUsernameLengthLimit = xerror.NewError(20002, "用户名长度3~12") + _errUsernameCharLimit = xerror.NewError(20003, "用户名只能包含字母、数字") + _errPasswordLengthLimit = xerror.NewError(20004, "密码长度6~16") + _errUserRegisterFailed = xerror.NewError(20005, "用户注册失败") + _errUserHasBeenBanned = xerror.NewError(20006, "该账户已被封停") + _errNoPermission = xerror.NewError(20007, "无权限执行该请求") + _errUserHasBindOTP = xerror.NewError(20008, "当前用户已绑定二次验证") + _errUserOTPInvalid = xerror.NewError(20009, "二次验证码验证失败") + _errUserNoBindOTP = xerror.NewError(20010, "当前用户未绑定二次验证") + _errErrorOldPassword = xerror.NewError(20011, "当前用户密码验证失败") + _errErrorCaptchaPassword = xerror.NewError(20012, "图形验证码验证失败") + _errAccountNoPhoneBind = xerror.NewError(20013, "拒绝操作: 账户未绑定手机号") + _errTooManyLoginError = xerror.NewError(20014, "登录失败次数过多,请稍后再试") + _errGetPhoneCaptchaError = xerror.NewError(20015, "短信验证码获取失败") + _errTooManyPhoneCaptchaSend = xerror.NewError(20016, "短信验证码获取次数已达今日上限") + _errExistedUserPhone = xerror.NewError(20017, "该手机号已被绑定") + _errErrorPhoneCaptcha = xerror.NewError(20018, "手机验证码不正确") + _errMaxPhoneCaptchaUseTimes = xerror.NewError(20019, "手机验证码已达最大使用次数") + _errNicknameLengthLimit = xerror.NewError(20020, "昵称长度2~12") + _errNoExistUsername = xerror.NewError(20021, "用户不存在") + _errNoAdminPermission = xerror.NewError(20022, "无管理权限") - errGetPostsFailed = xerror.NewError(30001, "获取动态列表失败") - errCreatePostFailed = xerror.NewError(30002, "动态发布失败") - errGetPostFailed = xerror.NewError(30003, "获取动态详情失败") - errDeletePostFailed = xerror.NewError(30004, "动态删除失败") - errLockPostFailed = xerror.NewError(30005, "动态锁定失败") - errGetPostTagsFailed = xerror.NewError(30006, "获取话题列表失败") - errInvalidDownloadReq = xerror.NewError(30007, "附件下载请求不合法") - errDownloadReqError = xerror.NewError(30008, "附件下载请求失败") - errInsuffientDownloadMoney = xerror.NewError(30009, "附件下载失败:账户资金不足") - errDownloadExecFail = xerror.NewError(30010, "附件下载失败:扣费失败") - errStickPostFailed = xerror.NewError(30011, "动态置顶失败") - errVisblePostFailed = xerror.NewError(30012, "更新可见性失败") + _errGetPostsFailed = xerror.NewError(30001, "获取动态列表失败") + _errCreatePostFailed = xerror.NewError(30002, "动态发布失败") + _errGetPostFailed = xerror.NewError(30003, "获取动态详情失败") + _errDeletePostFailed = xerror.NewError(30004, "动态删除失败") + _errLockPostFailed = xerror.NewError(30005, "动态锁定失败") + _errGetPostTagsFailed = xerror.NewError(30006, "获取话题列表失败") + _errInvalidDownloadReq = xerror.NewError(30007, "附件下载请求不合法") + _errDownloadReqError = xerror.NewError(30008, "附件下载请求失败") + _errInsuffientDownloadMoney = xerror.NewError(30009, "附件下载失败:账户资金不足") + _errDownloadExecFail = xerror.NewError(30010, "附件下载失败:扣费失败") + _errStickPostFailed = xerror.NewError(30011, "动态置顶失败") + _errVisblePostFailed = xerror.NewError(30012, "更新可见性失败") errGetCommentsFailed = xerror.NewError(40001, "获取评论列表失败") errCreateCommentFailed = xerror.NewError(40002, "评论发布失败") From f3bb188ee4bd2b4740fc17558204cc7c098ea882 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 23 Dec 2022 14:32:27 +0800 Subject: [PATCH 50/65] mir: change error variable names --- internal/servants/web/xerror.go | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/internal/servants/web/xerror.go b/internal/servants/web/xerror.go index f5c9aeb3..bda13caf 100644 --- a/internal/servants/web/xerror.go +++ b/internal/servants/web/xerror.go @@ -46,33 +46,33 @@ var ( _errStickPostFailed = xerror.NewError(30011, "动态置顶失败") _errVisblePostFailed = xerror.NewError(30012, "更新可见性失败") - errGetCommentsFailed = xerror.NewError(40001, "获取评论列表失败") - errCreateCommentFailed = xerror.NewError(40002, "评论发布失败") - errGetCommentFailed = xerror.NewError(40003, "获取评论详情失败") - errDeleteCommentFailed = xerror.NewError(40004, "评论删除失败") - errCreateReplyFailed = xerror.NewError(40005, "评论回复失败") - errGetReplyFailed = xerror.NewError(40006, "获取评论详情失败") - errMaxCommentCount = xerror.NewError(40007, "评论数已达最大限制") + _errGetCommentsFailed = xerror.NewError(40001, "获取评论列表失败") + _errCreateCommentFailed = xerror.NewError(40002, "评论发布失败") + _errGetCommentFailed = xerror.NewError(40003, "获取评论详情失败") + _errDeleteCommentFailed = xerror.NewError(40004, "评论删除失败") + _errCreateReplyFailed = xerror.NewError(40005, "评论回复失败") + _errGetReplyFailed = xerror.NewError(40006, "获取评论详情失败") + _errMaxCommentCount = xerror.NewError(40007, "评论数已达最大限制") - errGetMessagesFailed = xerror.NewError(50001, "获取消息列表失败") - errReadMessageFailed = xerror.NewError(50002, "标记消息已读失败") - errSendWhisperFailed = xerror.NewError(50003, "私信发送失败") - errNoWhisperToSelf = xerror.NewError(50004, "不允许给自己发送私信") - errTooManyWhisperNum = xerror.NewError(50005, "今日私信次数已达上限") + _errGetMessagesFailed = xerror.NewError(50001, "获取消息列表失败") + _errReadMessageFailed = xerror.NewError(50002, "标记消息已读失败") + _errSendWhisperFailed = xerror.NewError(50003, "私信发送失败") + _errNoWhisperToSelf = xerror.NewError(50004, "不允许给自己发送私信") + _errTooManyWhisperNum = xerror.NewError(50005, "今日私信次数已达上限") - errGetCollectionsFailed = xerror.NewError(60001, "获取收藏列表失败") - errGetStarsFailed = xerror.NewError(60002, "获取点赞列表失败") + _errGetCollectionsFailed = xerror.NewError(60001, "获取收藏列表失败") + _errGetStarsFailed = xerror.NewError(60002, "获取点赞列表失败") - errRechargeReqFail = xerror.NewError(70001, "充值请求失败") - errRechargeNotifyError = xerror.NewError(70002, "充值回调失败") - errGetRechargeFailed = xerror.NewError(70003, "充值详情获取失败") + _errRechargeReqFail = xerror.NewError(70001, "充值请求失败") + _errRechargeNotifyError = xerror.NewError(70002, "充值回调失败") + _errGetRechargeFailed = xerror.NewError(70003, "充值详情获取失败") - errNoRequestingFriendToSelf = xerror.NewError(80001, "不允许添加自己为好友") - errNotExistFriendId = xerror.NewError(80002, "好友id不存在") - errSendRequestingFriendFailed = xerror.NewError(80003, "申请添加朋友请求发送失败") - errAddFriendFailed = xerror.NewError(80004, "添加好友失败") - errRejectFriendFailed = xerror.NewError(80005, "拒绝好友失败") - errDeleteFriendFailed = xerror.NewError(80006, "删除好友失败") - errGetContactsFailed = xerror.NewError(80007, "获取联系人列表失败") - errNoActionToSelf = xerror.NewError(80008, "不允许对自己操作") + _errNoRequestingFriendToSelf = xerror.NewError(80001, "不允许添加自己为好友") + _errNotExistFriendId = xerror.NewError(80002, "好友id不存在") + _errSendRequestingFriendFailed = xerror.NewError(80003, "申请添加朋友请求发送失败") + _errAddFriendFailed = xerror.NewError(80004, "添加好友失败") + _errRejectFriendFailed = xerror.NewError(80005, "拒绝好友失败") + _errDeleteFriendFailed = xerror.NewError(80006, "删除好友失败") + _errGetContactsFailed = xerror.NewError(80007, "获取联系人列表失败") + _errNoActionToSelf = xerror.NewError(80008, "不允许对自己操作") ) From fc4e79662d64e73034dd1ed19a55680bb1e2ade3 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 23 Dec 2022 14:57:41 +0800 Subject: [PATCH 51/65] mir: optimize api defined service names --- auto/api/v1/admin.go | 95 ++++++++++++++++ .../v1/{web_alipay_priv.go => alipay_priv.go} | 50 ++++----- auto/api/v1/alipay_pub.go | 85 ++++++++++++++ auto/api/v1/{web_core.go => core.go} | 104 +++++++++--------- .../v1/{web_followship.go => followship.go} | 54 ++++----- .../v1/{web_friendship.go => friendship.go} | 58 +++++----- auto/api/v1/{web_loose.go => loose.go} | 52 ++++----- auto/api/v1/{web_priv.go => priv.go} | 94 ++++++++-------- auto/api/v1/{web_pub.go => pub.go} | 68 ++++++------ auto/api/v1/web_admin.go | 95 ---------------- auto/api/v1/web_alipay_pub.go | 85 -------------- internal/model/web/admin.go | 4 + internal/model/web/alipay.go | 4 + internal/model/web/loose.go | 4 + internal/model/web/priv.go | 4 + internal/model/web/pub.go | 4 + internal/servants/web/admin.go | 36 +++--- internal/servants/web/alipay.go | 70 ++++++------ internal/servants/web/core.go | 36 +++--- internal/servants/web/followship.go | 36 +++--- internal/servants/web/friendship.go | 36 +++--- internal/servants/web/loose.go | 36 +++--- internal/servants/web/priv.go | 36 +++--- internal/servants/web/pub.go | 36 +++--- internal/servants/web/web.go | 18 +-- mirc/web/v1/admin.go | 5 +- mirc/web/v1/alipay.go | 8 +- mirc/web/v1/core.go | 5 +- mirc/web/v1/followship.go | 5 +- mirc/web/v1/friendship.go | 5 +- mirc/web/v1/loose.go | 5 +- mirc/web/v1/priv.go | 5 +- mirc/web/v1/pub.go | 5 +- 33 files changed, 636 insertions(+), 607 deletions(-) create mode 100644 auto/api/v1/admin.go rename auto/api/v1/{web_alipay_priv.go => alipay_priv.go} (52%) create mode 100644 auto/api/v1/alipay_pub.go rename auto/api/v1/{web_core.go => core.go} (67%) rename auto/api/v1/{web_followship.go => followship.go} (54%) rename auto/api/v1/{web_friendship.go => friendship.go} (56%) rename auto/api/v1/{web_loose.go => loose.go} (52%) rename auto/api/v1/{web_priv.go => priv.go} (65%) rename auto/api/v1/{web_pub.go => pub.go} (62%) delete mode 100644 auto/api/v1/web_admin.go delete mode 100644 auto/api/v1/web_alipay_pub.go diff --git a/auto/api/v1/admin.go b/auto/api/v1/admin.go new file mode 100644 index 00000000..6872d123 --- /dev/null +++ b/auto/api/v1/admin.go @@ -0,0 +1,95 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type Admin interface { + // Chain provide handlers chain for gin + Chain() gin.HandlersChain + + ChangeUserStatus(*web.ChangeUserStatusReq) mir.Error + + mustEmbedUnimplementedAdminServant() +} + +type AdminBinding interface { + BindChangeUserStatus(*gin.Context) (*web.ChangeUserStatusReq, mir.Error) + + mustEmbedUnimplementedAdminBinding() +} + +type AdminRender interface { + RenderChangeUserStatus(*gin.Context, mir.Error) + + mustEmbedUnimplementedAdminRender() +} + +// RegisterAdminServant register Admin servant to gin +func RegisterAdminServant(e *gin.Engine, s Admin, b AdminBinding, r AdminRender) { + router := e.Group("v1") + // use chain for router + middlewares := s.Chain() + router.Use(middlewares...) + + // register routes info to router + router.Handle("POST", "/admin/user/status", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindChangeUserStatus(c) + if err != nil { + r.RenderChangeUserStatus(c, err) + return + } + r.RenderChangeUserStatus(c, s.ChangeUserStatus(req)) + }) + +} + +// UnimplementedAdminServant can be embedded to have forward compatible implementations. +type UnimplementedAdminServant struct { +} + +func (UnimplementedAdminServant) Chain() gin.HandlersChain { + return nil +} + +func (UnimplementedAdminServant) ChangeUserStatus(req *web.ChangeUserStatusReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedAdminServant) mustEmbedUnimplementedAdminServant() {} + +// UnimplementedAdminRender can be embedded to have forward compatible implementations. +type UnimplementedAdminRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedAdminRender) RenderChangeUserStatus(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedAdminRender) mustEmbedUnimplementedAdminRender() {} + +// UnimplementedAdminBinding can be embedded to have forward compatible implementations. +type UnimplementedAdminBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedAdminBinding) BindChangeUserStatus(c *gin.Context) (*web.ChangeUserStatusReq, mir.Error) { + obj := new(web.ChangeUserStatusReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedAdminBinding) mustEmbedUnimplementedAdminBinding() {} diff --git a/auto/api/v1/web_alipay_priv.go b/auto/api/v1/alipay_priv.go similarity index 52% rename from auto/api/v1/web_alipay_priv.go rename to auto/api/v1/alipay_priv.go index 20a5d562..2c95604c 100644 --- a/auto/api/v1/web_alipay_priv.go +++ b/auto/api/v1/alipay_priv.go @@ -10,7 +10,7 @@ import ( "github.com/rocboss/paopao-ce/internal/model/web" ) -type WebAlipayPriv interface { +type AlipayPriv interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain @@ -18,25 +18,25 @@ type WebAlipayPriv interface { UserRechargeResult() mir.Error UserRechargeLink() mir.Error - mustEmbedUnimplementedWebAlipayPrivServant() + mustEmbedUnimplementedAlipayPrivServant() } -type WebAlipayPrivBinding interface { +type AlipayPrivBinding interface { BindUserWalletBills(*gin.Context) (*web.UserWalletBillsReq, mir.Error) - mustEmbedUnimplementedWebAlipayPrivBinding() + mustEmbedUnimplementedAlipayPrivBinding() } -type WebAlipayPrivRender interface { +type AlipayPrivRender interface { RenderUserWalletBills(*gin.Context, *web.UserWalletBillsResp, mir.Error) RenderUserRechargeResult(*gin.Context, mir.Error) RenderUserRechargeLink(*gin.Context, mir.Error) - mustEmbedUnimplementedWebAlipayPrivRender() + mustEmbedUnimplementedAlipayPrivRender() } -// RegisterWebAlipayPrivServant register WebAlipayPriv servant to gin -func RegisterWebAlipayPrivServant(e *gin.Engine, s WebAlipayPriv, b WebAlipayPrivBinding, r WebAlipayPrivRender) { +// RegisterAlipayPrivServant register AlipayPriv servant to gin +func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv, b AlipayPrivBinding, r AlipayPrivRender) { router := e.Group("v1") // use chain for router middlewares := s.Chain() @@ -81,56 +81,56 @@ func RegisterWebAlipayPrivServant(e *gin.Engine, s WebAlipayPriv, b WebAlipayPri } -// UnimplementedWebAlipayPrivServant can be embedded to have forward compatible implementations. -type UnimplementedWebAlipayPrivServant struct { +// UnimplementedAlipayPrivServant can be embedded to have forward compatible implementations. +type UnimplementedAlipayPrivServant struct { } -func (UnimplementedWebAlipayPrivServant) Chain() gin.HandlersChain { +func (UnimplementedAlipayPrivServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { +func (UnimplementedAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebAlipayPrivServant) UserRechargeResult() mir.Error { +func (UnimplementedAlipayPrivServant) UserRechargeResult() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebAlipayPrivServant) UserRechargeLink() mir.Error { +func (UnimplementedAlipayPrivServant) UserRechargeLink() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebAlipayPrivServant) mustEmbedUnimplementedWebAlipayPrivServant() {} +func (UnimplementedAlipayPrivServant) mustEmbedUnimplementedAlipayPrivServant() {} -// UnimplementedWebAlipayPrivRender can be embedded to have forward compatible implementations. -type UnimplementedWebAlipayPrivRender struct { +// UnimplementedAlipayPrivRender can be embedded to have forward compatible implementations. +type UnimplementedAlipayPrivRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *web.UserWalletBillsResp, err mir.Error) { +func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *web.UserWalletBillsResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedWebAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, err mir.Error) { +func (r *UnimplementedAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, err mir.Error) { +func (r *UnimplementedAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebAlipayPrivRender) mustEmbedUnimplementedWebAlipayPrivRender() {} +func (r *UnimplementedAlipayPrivRender) mustEmbedUnimplementedAlipayPrivRender() {} -// UnimplementedWebAlipayPrivBinding can be embedded to have forward compatible implementations. -type UnimplementedWebAlipayPrivBinding struct { +// UnimplementedAlipayPrivBinding can be embedded to have forward compatible implementations. +type UnimplementedAlipayPrivBinding struct { BindAny func(*gin.Context, any) mir.Error } -func (b *UnimplementedWebAlipayPrivBinding) BindUserWalletBills(c *gin.Context) (*web.UserWalletBillsReq, mir.Error) { +func (b *UnimplementedAlipayPrivBinding) BindUserWalletBills(c *gin.Context) (*web.UserWalletBillsReq, mir.Error) { obj := new(web.UserWalletBillsReq) err := b.BindAny(c, obj) return obj, err } -func (b *UnimplementedWebAlipayPrivBinding) mustEmbedUnimplementedWebAlipayPrivBinding() {} +func (b *UnimplementedAlipayPrivBinding) mustEmbedUnimplementedAlipayPrivBinding() {} diff --git a/auto/api/v1/alipay_pub.go b/auto/api/v1/alipay_pub.go new file mode 100644 index 00000000..3119119e --- /dev/null +++ b/auto/api/v1/alipay_pub.go @@ -0,0 +1,85 @@ +// Code generated by go-mir. DO NOT EDIT. + +package v1 + +import ( + "net/http" + + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type AlipayPub interface { + AlipayNotify(*web.AlipayNotifyReq) mir.Error + + mustEmbedUnimplementedAlipayPubServant() +} + +type AlipayPubBinding interface { + BindAlipayNotify(*gin.Context) (*web.AlipayNotifyReq, mir.Error) + + mustEmbedUnimplementedAlipayPubBinding() +} + +type AlipayPubRender interface { + RenderAlipayNotify(*gin.Context, mir.Error) + + mustEmbedUnimplementedAlipayPubRender() +} + +// RegisterAlipayPubServant register AlipayPub servant to gin +func RegisterAlipayPubServant(e *gin.Engine, s AlipayPub, b AlipayPubBinding, r AlipayPubRender) { + router := e.Group("v1") + + // register routes info to router + router.Handle("POST", "/alipay/notify", func(c *gin.Context) { + select { + case <-c.Request.Context().Done(): + return + default: + } + + req, err := b.BindAlipayNotify(c) + if err != nil { + r.RenderAlipayNotify(c, err) + return + } + r.RenderAlipayNotify(c, s.AlipayNotify(req)) + }) + +} + +// UnimplementedAlipayPubServant can be embedded to have forward compatible implementations. +type UnimplementedAlipayPubServant struct { +} + +func (UnimplementedAlipayPubServant) AlipayNotify(req *web.AlipayNotifyReq) mir.Error { + return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +} + +func (UnimplementedAlipayPubServant) mustEmbedUnimplementedAlipayPubServant() {} + +// UnimplementedAlipayPubRender can be embedded to have forward compatible implementations. +type UnimplementedAlipayPubRender struct { + RenderAny func(*gin.Context, any, mir.Error) +} + +func (r *UnimplementedAlipayPubRender) RenderAlipayNotify(c *gin.Context, err mir.Error) { + r.RenderAny(c, nil, err) +} + +func (r *UnimplementedAlipayPubRender) mustEmbedUnimplementedAlipayPubRender() {} + +// UnimplementedAlipayPubBinding can be embedded to have forward compatible implementations. +type UnimplementedAlipayPubBinding struct { + BindAny func(*gin.Context, any) mir.Error +} + +func (b *UnimplementedAlipayPubBinding) BindAlipayNotify(c *gin.Context) (*web.AlipayNotifyReq, mir.Error) { + obj := new(web.AlipayNotifyReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedAlipayPubBinding) mustEmbedUnimplementedAlipayPubBinding() {} diff --git a/auto/api/v1/web_core.go b/auto/api/v1/core.go similarity index 67% rename from auto/api/v1/web_core.go rename to auto/api/v1/core.go index dee50533..50b9576a 100644 --- a/auto/api/v1/web_core.go +++ b/auto/api/v1/core.go @@ -10,7 +10,7 @@ import ( "github.com/rocboss/paopao-ce/internal/model/web" ) -type WebCore interface { +type Core interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain @@ -31,18 +31,18 @@ type WebCore interface { GetUserInfo(*web.UserInfoReq) (*web.UserInfoResp, mir.Error) SyncSearchIndex() mir.Error - mustEmbedUnimplementedWebCoreServant() + mustEmbedUnimplementedCoreServant() } -type WebCoreBinding interface { +type CoreBinding interface { BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error) BindGetUserInfo(*gin.Context) (*web.UserInfoReq, mir.Error) - mustEmbedUnimplementedWebCoreBinding() + mustEmbedUnimplementedCoreBinding() } -type WebCoreRender interface { +type CoreRender interface { RenderTweetCollectionStatus(*gin.Context, mir.Error) RenderTweetStarStatus(*gin.Context, mir.Error) RenderSuggestTags(*gin.Context, mir.Error) @@ -60,11 +60,11 @@ type WebCoreRender interface { RenderGetUserInfo(*gin.Context, *web.UserInfoResp, mir.Error) RenderSyncSearchIndex(*gin.Context, mir.Error) - mustEmbedUnimplementedWebCoreRender() + mustEmbedUnimplementedCoreRender() } -// RegisterWebCoreServant register WebCore servant to gin -func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCoreRender) { +// RegisterCoreServant register Core servant to gin +func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { router := e.Group("v1") // use chain for router middlewares := s.Chain() @@ -244,166 +244,166 @@ func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCor } -// UnimplementedWebCoreServant can be embedded to have forward compatible implementations. -type UnimplementedWebCoreServant struct { +// UnimplementedCoreServant can be embedded to have forward compatible implementations. +type UnimplementedCoreServant struct { } -func (UnimplementedWebCoreServant) Chain() gin.HandlersChain { +func (UnimplementedCoreServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebCoreServant) TweetCollectionStatus() mir.Error { +func (UnimplementedCoreServant) TweetCollectionStatus() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) TweetStarStatus() mir.Error { +func (UnimplementedCoreServant) TweetStarStatus() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) SuggestTags() mir.Error { +func (UnimplementedCoreServant) SuggestTags() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) SuggestUsers() mir.Error { +func (UnimplementedCoreServant) SuggestUsers() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) ChangeAvatar(req *web.ChangeAvatarReq) mir.Error { +func (UnimplementedCoreServant) ChangeAvatar(req *web.ChangeAvatarReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) ChangeNickname() mir.Error { +func (UnimplementedCoreServant) ChangeNickname() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) ChangePassword() mir.Error { +func (UnimplementedCoreServant) ChangePassword() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) UserPhoneBind() mir.Error { +func (UnimplementedCoreServant) UserPhoneBind() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) GetStars() mir.Error { +func (UnimplementedCoreServant) GetStars() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) GetCollections() mir.Error { +func (UnimplementedCoreServant) GetCollections() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) SendUserWhisper() mir.Error { +func (UnimplementedCoreServant) SendUserWhisper() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) ReadMessage() mir.Error { +func (UnimplementedCoreServant) ReadMessage() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) GetMessages() mir.Error { +func (UnimplementedCoreServant) GetMessages() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) GetUnreadMsgCount() mir.Error { +func (UnimplementedCoreServant) GetUnreadMsgCount() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Error) { +func (UnimplementedCoreServant) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) SyncSearchIndex() mir.Error { +func (UnimplementedCoreServant) SyncSearchIndex() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebCoreServant) mustEmbedUnimplementedWebCoreServant() {} +func (UnimplementedCoreServant) mustEmbedUnimplementedCoreServant() {} -// UnimplementedWebCoreRender can be embedded to have forward compatible implementations. -type UnimplementedWebCoreRender struct { +// UnimplementedCoreRender can be embedded to have forward compatible implementations. +type UnimplementedCoreRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebCoreRender) RenderTweetCollectionStatus(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderTweetCollectionStatus(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderTweetStarStatus(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderTweetStarStatus(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderSuggestTags(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderSuggestTags(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderSuggestUsers(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderSuggestUsers(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderChangeAvatar(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderChangeAvatar(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderChangeNickname(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderChangeNickname(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderChangePassword(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderChangePassword(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderUserPhoneBind(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderUserPhoneBind(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderGetStars(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderGetStars(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderGetCollections(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderGetCollections(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderSendUserWhisper(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderSendUserWhisper(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderReadMessage(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderReadMessage(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderGetMessages(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderGetMessages(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderGetUnreadMsgCount(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderGetUnreadMsgCount(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) RenderGetUserInfo(c *gin.Context, data *web.UserInfoResp, err mir.Error) { +func (r *UnimplementedCoreRender) RenderGetUserInfo(c *gin.Context, data *web.UserInfoResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedWebCoreRender) RenderSyncSearchIndex(c *gin.Context, err mir.Error) { +func (r *UnimplementedCoreRender) RenderSyncSearchIndex(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebCoreRender) mustEmbedUnimplementedWebCoreRender() {} +func (r *UnimplementedCoreRender) mustEmbedUnimplementedCoreRender() {} -// UnimplementedWebCoreBinding can be embedded to have forward compatible implementations. -type UnimplementedWebCoreBinding struct { +// UnimplementedCoreBinding can be embedded to have forward compatible implementations. +type UnimplementedCoreBinding struct { BindAny func(*gin.Context, any) mir.Error } -func (b *UnimplementedWebCoreBinding) BindChangeAvatar(c *gin.Context) (*web.ChangeAvatarReq, mir.Error) { +func (b *UnimplementedCoreBinding) BindChangeAvatar(c *gin.Context) (*web.ChangeAvatarReq, mir.Error) { obj := new(web.ChangeAvatarReq) err := b.BindAny(c, obj) return obj, err } -func (b *UnimplementedWebCoreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) { +func (b *UnimplementedCoreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) { obj := new(web.UserInfoReq) err := b.BindAny(c, obj) return obj, err } -func (b *UnimplementedWebCoreBinding) mustEmbedUnimplementedWebCoreBinding() {} +func (b *UnimplementedCoreBinding) mustEmbedUnimplementedCoreBinding() {} diff --git a/auto/api/v1/web_followship.go b/auto/api/v1/followship.go similarity index 54% rename from auto/api/v1/web_followship.go rename to auto/api/v1/followship.go index a308bc40..13f94946 100644 --- a/auto/api/v1/web_followship.go +++ b/auto/api/v1/followship.go @@ -10,7 +10,7 @@ import ( "github.com/rocboss/paopao-ce/internal/model/web" ) -type WebFollowship interface { +type Followship interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain @@ -19,26 +19,26 @@ type WebFollowship interface { DeleteFollowing() mir.Error AddFollowing() mir.Error - mustEmbedUnimplementedWebFollowshipServant() + mustEmbedUnimplementedFollowshipServant() } -type WebFollowshipBinding interface { +type FollowshipBinding interface { BindListFollowers(*gin.Context) (*web.ListFollowersReq, mir.Error) - mustEmbedUnimplementedWebFollowshipBinding() + mustEmbedUnimplementedFollowshipBinding() } -type WebFollowshipRender interface { +type FollowshipRender interface { RenderListFollowers(*gin.Context, *web.ListFollowersResp, mir.Error) RenderListFollowings(*gin.Context, mir.Error) RenderDeleteFollowing(*gin.Context, mir.Error) RenderAddFollowing(*gin.Context, mir.Error) - mustEmbedUnimplementedWebFollowshipRender() + mustEmbedUnimplementedFollowshipRender() } -// RegisterWebFollowshipServant register WebFollowship servant to gin -func RegisterWebFollowshipServant(e *gin.Engine, s WebFollowship, b WebFollowshipBinding, r WebFollowshipRender) { +// RegisterFollowshipServant register Followship servant to gin +func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding, r FollowshipRender) { router := e.Group("v1") // use chain for router middlewares := s.Chain() @@ -93,64 +93,64 @@ func RegisterWebFollowshipServant(e *gin.Engine, s WebFollowship, b WebFollowshi } -// UnimplementedWebFollowshipServant can be embedded to have forward compatible implementations. -type UnimplementedWebFollowshipServant struct { +// UnimplementedFollowshipServant can be embedded to have forward compatible implementations. +type UnimplementedFollowshipServant struct { } -func (UnimplementedWebFollowshipServant) Chain() gin.HandlersChain { +func (UnimplementedFollowshipServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebFollowshipServant) ListFollowers(req *web.ListFollowersReq) (*web.ListFollowersResp, mir.Error) { +func (UnimplementedFollowshipServant) ListFollowers(req *web.ListFollowersReq) (*web.ListFollowersResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFollowshipServant) ListFollowings() mir.Error { +func (UnimplementedFollowshipServant) ListFollowings() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFollowshipServant) DeleteFollowing() mir.Error { +func (UnimplementedFollowshipServant) DeleteFollowing() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFollowshipServant) AddFollowing() mir.Error { +func (UnimplementedFollowshipServant) AddFollowing() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFollowshipServant) mustEmbedUnimplementedWebFollowshipServant() {} +func (UnimplementedFollowshipServant) mustEmbedUnimplementedFollowshipServant() {} -// UnimplementedWebFollowshipRender can be embedded to have forward compatible implementations. -type UnimplementedWebFollowshipRender struct { +// UnimplementedFollowshipRender can be embedded to have forward compatible implementations. +type UnimplementedFollowshipRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebFollowshipRender) RenderListFollowers(c *gin.Context, data *web.ListFollowersResp, err mir.Error) { +func (r *UnimplementedFollowshipRender) RenderListFollowers(c *gin.Context, data *web.ListFollowersResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedWebFollowshipRender) RenderListFollowings(c *gin.Context, err mir.Error) { +func (r *UnimplementedFollowshipRender) RenderListFollowings(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebFollowshipRender) RenderDeleteFollowing(c *gin.Context, err mir.Error) { +func (r *UnimplementedFollowshipRender) RenderDeleteFollowing(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebFollowshipRender) RenderAddFollowing(c *gin.Context, err mir.Error) { +func (r *UnimplementedFollowshipRender) RenderAddFollowing(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebFollowshipRender) mustEmbedUnimplementedWebFollowshipRender() {} +func (r *UnimplementedFollowshipRender) mustEmbedUnimplementedFollowshipRender() {} -// UnimplementedWebFollowshipBinding can be embedded to have forward compatible implementations. -type UnimplementedWebFollowshipBinding struct { +// UnimplementedFollowshipBinding can be embedded to have forward compatible implementations. +type UnimplementedFollowshipBinding struct { BindAny func(*gin.Context, any) mir.Error } -func (b *UnimplementedWebFollowshipBinding) BindListFollowers(c *gin.Context) (*web.ListFollowersReq, mir.Error) { +func (b *UnimplementedFollowshipBinding) BindListFollowers(c *gin.Context) (*web.ListFollowersReq, mir.Error) { obj := new(web.ListFollowersReq) err := b.BindAny(c, obj) return obj, err } -func (b *UnimplementedWebFollowshipBinding) mustEmbedUnimplementedWebFollowshipBinding() {} +func (b *UnimplementedFollowshipBinding) mustEmbedUnimplementedFollowshipBinding() {} diff --git a/auto/api/v1/web_friendship.go b/auto/api/v1/friendship.go similarity index 56% rename from auto/api/v1/web_friendship.go rename to auto/api/v1/friendship.go index 2e558ea5..f0bc6208 100644 --- a/auto/api/v1/web_friendship.go +++ b/auto/api/v1/friendship.go @@ -10,7 +10,7 @@ import ( "github.com/rocboss/paopao-ce/internal/model/web" ) -type WebFriendship interface { +type Friendship interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain @@ -20,27 +20,27 @@ type WebFriendship interface { AddFriend() mir.Error RequestingFriend() mir.Error - mustEmbedUnimplementedWebFriendshipServant() + mustEmbedUnimplementedFriendshipServant() } -type WebFriendshipBinding interface { +type FriendshipBinding interface { BindGetContacts(*gin.Context) (*web.GetContactsReq, mir.Error) - mustEmbedUnimplementedWebFriendshipBinding() + mustEmbedUnimplementedFriendshipBinding() } -type WebFriendshipRender interface { +type FriendshipRender interface { RenderGetContacts(*gin.Context, *web.GetContactsResp, mir.Error) RenderDeleteFriend(*gin.Context, mir.Error) RenderRejectFriend(*gin.Context, mir.Error) RenderAddFriend(*gin.Context, mir.Error) RenderRequestingFriend(*gin.Context, mir.Error) - mustEmbedUnimplementedWebFriendshipRender() + mustEmbedUnimplementedFriendshipRender() } -// RegisterWebFriendshipServant register WebFriendship servant to gin -func RegisterWebFriendshipServant(e *gin.Engine, s WebFriendship, b WebFriendshipBinding, r WebFriendshipRender) { +// RegisterFriendshipServant register Friendship servant to gin +func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding, r FriendshipRender) { router := e.Group("v1") // use chain for router middlewares := s.Chain() @@ -105,72 +105,72 @@ func RegisterWebFriendshipServant(e *gin.Engine, s WebFriendship, b WebFriendshi } -// UnimplementedWebFriendshipServant can be embedded to have forward compatible implementations. -type UnimplementedWebFriendshipServant struct { +// UnimplementedFriendshipServant can be embedded to have forward compatible implementations. +type UnimplementedFriendshipServant struct { } -func (UnimplementedWebFriendshipServant) Chain() gin.HandlersChain { +func (UnimplementedFriendshipServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebFriendshipServant) GetContacts(req *web.GetContactsReq) (*web.GetContactsResp, mir.Error) { +func (UnimplementedFriendshipServant) GetContacts(req *web.GetContactsReq) (*web.GetContactsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFriendshipServant) DeleteFriend() mir.Error { +func (UnimplementedFriendshipServant) DeleteFriend() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFriendshipServant) RejectFriend() mir.Error { +func (UnimplementedFriendshipServant) RejectFriend() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFriendshipServant) AddFriend() mir.Error { +func (UnimplementedFriendshipServant) AddFriend() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFriendshipServant) RequestingFriend() mir.Error { +func (UnimplementedFriendshipServant) RequestingFriend() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebFriendshipServant) mustEmbedUnimplementedWebFriendshipServant() {} +func (UnimplementedFriendshipServant) mustEmbedUnimplementedFriendshipServant() {} -// UnimplementedWebFriendshipRender can be embedded to have forward compatible implementations. -type UnimplementedWebFriendshipRender struct { +// UnimplementedFriendshipRender can be embedded to have forward compatible implementations. +type UnimplementedFriendshipRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebFriendshipRender) RenderGetContacts(c *gin.Context, data *web.GetContactsResp, err mir.Error) { +func (r *UnimplementedFriendshipRender) RenderGetContacts(c *gin.Context, data *web.GetContactsResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedWebFriendshipRender) RenderDeleteFriend(c *gin.Context, err mir.Error) { +func (r *UnimplementedFriendshipRender) RenderDeleteFriend(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebFriendshipRender) RenderRejectFriend(c *gin.Context, err mir.Error) { +func (r *UnimplementedFriendshipRender) RenderRejectFriend(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebFriendshipRender) RenderAddFriend(c *gin.Context, err mir.Error) { +func (r *UnimplementedFriendshipRender) RenderAddFriend(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebFriendshipRender) RenderRequestingFriend(c *gin.Context, err mir.Error) { +func (r *UnimplementedFriendshipRender) RenderRequestingFriend(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebFriendshipRender) mustEmbedUnimplementedWebFriendshipRender() {} +func (r *UnimplementedFriendshipRender) mustEmbedUnimplementedFriendshipRender() {} -// UnimplementedWebFriendshipBinding can be embedded to have forward compatible implementations. -type UnimplementedWebFriendshipBinding struct { +// UnimplementedFriendshipBinding can be embedded to have forward compatible implementations. +type UnimplementedFriendshipBinding struct { BindAny func(*gin.Context, any) mir.Error } -func (b *UnimplementedWebFriendshipBinding) BindGetContacts(c *gin.Context) (*web.GetContactsReq, mir.Error) { +func (b *UnimplementedFriendshipBinding) BindGetContacts(c *gin.Context) (*web.GetContactsReq, mir.Error) { obj := new(web.GetContactsReq) err := b.BindAny(c, obj) return obj, err } -func (b *UnimplementedWebFriendshipBinding) mustEmbedUnimplementedWebFriendshipBinding() {} +func (b *UnimplementedFriendshipBinding) mustEmbedUnimplementedFriendshipBinding() {} diff --git a/auto/api/v1/web_loose.go b/auto/api/v1/loose.go similarity index 52% rename from auto/api/v1/web_loose.go rename to auto/api/v1/loose.go index d42c83a7..02d12831 100644 --- a/auto/api/v1/web_loose.go +++ b/auto/api/v1/loose.go @@ -10,7 +10,7 @@ import ( "github.com/rocboss/paopao-ce/internal/model/web" ) -type WebLoose interface { +type Loose interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain @@ -18,25 +18,25 @@ type WebLoose interface { GetUserTweets() mir.Error Timeline(*web.TimelineReq) (*web.TimelineResp, mir.Error) - mustEmbedUnimplementedWebLooseServant() + mustEmbedUnimplementedLooseServant() } -type WebLooseBinding interface { +type LooseBinding interface { BindTimeline(*gin.Context) (*web.TimelineReq, mir.Error) - mustEmbedUnimplementedWebLooseBinding() + mustEmbedUnimplementedLooseBinding() } -type WebLooseRender interface { +type LooseRender interface { RenderGetUserProfile(*gin.Context, mir.Error) RenderGetUserTweets(*gin.Context, mir.Error) RenderTimeline(*gin.Context, *web.TimelineResp, mir.Error) - mustEmbedUnimplementedWebLooseRender() + mustEmbedUnimplementedLooseRender() } -// RegisterWebLooseServant register WebLoose servant to gin -func RegisterWebLooseServant(e *gin.Engine, s WebLoose, b WebLooseBinding, r WebLooseRender) { +// RegisterLooseServant register Loose servant to gin +func RegisterLooseServant(e *gin.Engine, s Loose, b LooseBinding, r LooseRender) { router := e.Group("v1") // use chain for router middlewares := s.Chain() @@ -63,7 +63,7 @@ func RegisterWebLooseServant(e *gin.Engine, s WebLoose, b WebLooseBinding, r Web r.RenderGetUserTweets(c, s.GetUserTweets()) }) - router.Handle("GET", "/Posts", func(c *gin.Context) { + router.Handle("GET", "/posts", func(c *gin.Context) { select { case <-c.Request.Context().Done(): return @@ -81,56 +81,56 @@ func RegisterWebLooseServant(e *gin.Engine, s WebLoose, b WebLooseBinding, r Web } -// UnimplementedWebLooseServant can be embedded to have forward compatible implementations. -type UnimplementedWebLooseServant struct { +// UnimplementedLooseServant can be embedded to have forward compatible implementations. +type UnimplementedLooseServant struct { } -func (UnimplementedWebLooseServant) Chain() gin.HandlersChain { +func (UnimplementedLooseServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebLooseServant) GetUserProfile() mir.Error { +func (UnimplementedLooseServant) GetUserProfile() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebLooseServant) GetUserTweets() mir.Error { +func (UnimplementedLooseServant) GetUserTweets() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebLooseServant) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error) { +func (UnimplementedLooseServant) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebLooseServant) mustEmbedUnimplementedWebLooseServant() {} +func (UnimplementedLooseServant) mustEmbedUnimplementedLooseServant() {} -// UnimplementedWebLooseRender can be embedded to have forward compatible implementations. -type UnimplementedWebLooseRender struct { +// UnimplementedLooseRender can be embedded to have forward compatible implementations. +type UnimplementedLooseRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebLooseRender) RenderGetUserProfile(c *gin.Context, err mir.Error) { +func (r *UnimplementedLooseRender) RenderGetUserProfile(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebLooseRender) RenderGetUserTweets(c *gin.Context, err mir.Error) { +func (r *UnimplementedLooseRender) RenderGetUserTweets(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebLooseRender) RenderTimeline(c *gin.Context, data *web.TimelineResp, err mir.Error) { +func (r *UnimplementedLooseRender) RenderTimeline(c *gin.Context, data *web.TimelineResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedWebLooseRender) mustEmbedUnimplementedWebLooseRender() {} +func (r *UnimplementedLooseRender) mustEmbedUnimplementedLooseRender() {} -// UnimplementedWebLooseBinding can be embedded to have forward compatible implementations. -type UnimplementedWebLooseBinding struct { +// UnimplementedLooseBinding can be embedded to have forward compatible implementations. +type UnimplementedLooseBinding struct { BindAny func(*gin.Context, any) mir.Error } -func (b *UnimplementedWebLooseBinding) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) { +func (b *UnimplementedLooseBinding) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) { obj := new(web.TimelineReq) err := b.BindAny(c, obj) return obj, err } -func (b *UnimplementedWebLooseBinding) mustEmbedUnimplementedWebLooseBinding() {} +func (b *UnimplementedLooseBinding) mustEmbedUnimplementedLooseBinding() {} diff --git a/auto/api/v1/web_priv.go b/auto/api/v1/priv.go similarity index 65% rename from auto/api/v1/web_priv.go rename to auto/api/v1/priv.go index 039ac706..e5c19fd2 100644 --- a/auto/api/v1/web_priv.go +++ b/auto/api/v1/priv.go @@ -10,7 +10,7 @@ import ( "github.com/rocboss/paopao-ce/internal/model/web" ) -type WebPriv interface { +type Priv interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain @@ -29,16 +29,16 @@ type WebPriv interface { DownloadAttachmentPrecheck() mir.Error UploadAttachment() mir.Error - mustEmbedUnimplementedWebPrivServant() + mustEmbedUnimplementedPrivServant() } -type WebPrivBinding interface { +type PrivBinding interface { BindCreateTweet(*gin.Context) (*web.CreateTweetReq, mir.Error) - mustEmbedUnimplementedWebPrivBinding() + mustEmbedUnimplementedPrivBinding() } -type WebPrivRender interface { +type PrivRender interface { RenderDeleteCommentReply(*gin.Context, mir.Error) RenderCreateCommentReply(*gin.Context, mir.Error) RenderDeleteComment(*gin.Context, mir.Error) @@ -54,11 +54,11 @@ type WebPrivRender interface { RenderDownloadAttachmentPrecheck(*gin.Context, mir.Error) RenderUploadAttachment(*gin.Context, mir.Error) - mustEmbedUnimplementedWebPrivRender() + mustEmbedUnimplementedPrivRender() } -// RegisterWebPrivServant register WebPriv servant to gin -func RegisterWebPrivServant(e *gin.Engine, s WebPriv, b WebPrivBinding, r WebPrivRender) { +// RegisterPrivServant register Priv servant to gin +func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { router := e.Group("v1") // use chain for router middlewares := s.Chain() @@ -213,144 +213,144 @@ func RegisterWebPrivServant(e *gin.Engine, s WebPriv, b WebPrivBinding, r WebPri } -// UnimplementedWebPrivServant can be embedded to have forward compatible implementations. -type UnimplementedWebPrivServant struct { +// UnimplementedPrivServant can be embedded to have forward compatible implementations. +type UnimplementedPrivServant struct { } -func (UnimplementedWebPrivServant) Chain() gin.HandlersChain { +func (UnimplementedPrivServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedWebPrivServant) DeleteCommentReply() mir.Error { +func (UnimplementedPrivServant) DeleteCommentReply() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) CreateCommentReply() mir.Error { +func (UnimplementedPrivServant) CreateCommentReply() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) DeleteComment() mir.Error { +func (UnimplementedPrivServant) DeleteComment() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) CreateComment() mir.Error { +func (UnimplementedPrivServant) CreateComment() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) VisiblePost() mir.Error { +func (UnimplementedPrivServant) VisiblePost() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) StickTweet() mir.Error { +func (UnimplementedPrivServant) StickTweet() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) LockTweet() mir.Error { +func (UnimplementedPrivServant) LockTweet() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) CollectionTweet() mir.Error { +func (UnimplementedPrivServant) CollectionTweet() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) StarTweet() mir.Error { +func (UnimplementedPrivServant) StarTweet() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) DeleteTweet() mir.Error { +func (UnimplementedPrivServant) DeleteTweet() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) CreateTweet(req *web.CreateTweetReq) (*web.CreateTweetResp, mir.Error) { +func (UnimplementedPrivServant) CreateTweet(req *web.CreateTweetReq) (*web.CreateTweetResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) DownloadAttachment() mir.Error { +func (UnimplementedPrivServant) DownloadAttachment() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) DownloadAttachmentPrecheck() mir.Error { +func (UnimplementedPrivServant) DownloadAttachmentPrecheck() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) UploadAttachment() mir.Error { +func (UnimplementedPrivServant) UploadAttachment() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPrivServant) mustEmbedUnimplementedWebPrivServant() {} +func (UnimplementedPrivServant) mustEmbedUnimplementedPrivServant() {} -// UnimplementedWebPrivRender can be embedded to have forward compatible implementations. -type UnimplementedWebPrivRender struct { +// UnimplementedPrivRender can be embedded to have forward compatible implementations. +type UnimplementedPrivRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebPrivRender) RenderDeleteCommentReply(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderDeleteCommentReply(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderCreateCommentReply(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderCreateCommentReply(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderDeleteComment(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderDeleteComment(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderCreateComment(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderCreateComment(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderVisiblePost(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderVisiblePost(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderStickTweet(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderStickTweet(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderLockTweet(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderLockTweet(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderCollectionTweet(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderCollectionTweet(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderStarTweet(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderStarTweet(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderDeleteTweet(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderDeleteTweet(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderCreateTweet(c *gin.Context, data *web.CreateTweetResp, err mir.Error) { +func (r *UnimplementedPrivRender) RenderCreateTweet(c *gin.Context, data *web.CreateTweetResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedWebPrivRender) RenderDownloadAttachment(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderDownloadAttachment(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderDownloadAttachmentPrecheck(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderDownloadAttachmentPrecheck(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) RenderUploadAttachment(c *gin.Context, err mir.Error) { +func (r *UnimplementedPrivRender) RenderUploadAttachment(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPrivRender) mustEmbedUnimplementedWebPrivRender() {} +func (r *UnimplementedPrivRender) mustEmbedUnimplementedPrivRender() {} -// UnimplementedWebPrivBinding can be embedded to have forward compatible implementations. -type UnimplementedWebPrivBinding struct { +// UnimplementedPrivBinding can be embedded to have forward compatible implementations. +type UnimplementedPrivBinding struct { BindAny func(*gin.Context, any) mir.Error } -func (b *UnimplementedWebPrivBinding) BindCreateTweet(c *gin.Context) (*web.CreateTweetReq, mir.Error) { +func (b *UnimplementedPrivBinding) BindCreateTweet(c *gin.Context) (*web.CreateTweetReq, mir.Error) { obj := new(web.CreateTweetReq) err := b.BindAny(c, obj) return obj, err } -func (b *UnimplementedWebPrivBinding) mustEmbedUnimplementedWebPrivBinding() {} +func (b *UnimplementedPrivBinding) mustEmbedUnimplementedPrivBinding() {} diff --git a/auto/api/v1/web_pub.go b/auto/api/v1/pub.go similarity index 62% rename from auto/api/v1/web_pub.go rename to auto/api/v1/pub.go index b1e2f591..b783393a 100644 --- a/auto/api/v1/web_pub.go +++ b/auto/api/v1/pub.go @@ -10,7 +10,7 @@ import ( "github.com/rocboss/paopao-ce/internal/model/web" ) -type WebPub interface { +type Pub interface { TopicList() mir.Error TweetComments() mir.Error TweetDetail(*web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) @@ -20,16 +20,16 @@ type WebPub interface { Login() mir.Error Version() mir.Error - mustEmbedUnimplementedWebPubServant() + mustEmbedUnimplementedPubServant() } -type WebPubBinding interface { +type PubBinding interface { BindTweetDetail(*gin.Context) (*web.TweetDetailReq, mir.Error) - mustEmbedUnimplementedWebPubBinding() + mustEmbedUnimplementedPubBinding() } -type WebPubRender interface { +type PubRender interface { RenderTopicList(*gin.Context, mir.Error) RenderTweetComments(*gin.Context, mir.Error) RenderTweetDetail(*gin.Context, *web.TweetDetailResp, mir.Error) @@ -39,11 +39,11 @@ type WebPubRender interface { RenderLogin(*gin.Context, mir.Error) RenderVersion(*gin.Context, mir.Error) - mustEmbedUnimplementedWebPubRender() + mustEmbedUnimplementedPubRender() } -// RegisterWebPubServant register WebPub servant to gin -func RegisterWebPubServant(e *gin.Engine, s WebPub, b WebPubBinding, r WebPubRender) { +// RegisterPubServant register Pub servant to gin +func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { router := e.Group("v1") // register routes info to router @@ -135,92 +135,92 @@ func RegisterWebPubServant(e *gin.Engine, s WebPub, b WebPubBinding, r WebPubRen } -// UnimplementedWebPubServant can be embedded to have forward compatible implementations. -type UnimplementedWebPubServant struct { +// UnimplementedPubServant can be embedded to have forward compatible implementations. +type UnimplementedPubServant struct { } -func (UnimplementedWebPubServant) TopicList() mir.Error { +func (UnimplementedPubServant) TopicList() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPubServant) TweetComments() mir.Error { +func (UnimplementedPubServant) TweetComments() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPubServant) TweetDetail(req *web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) { +func (UnimplementedPubServant) TweetDetail(req *web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPubServant) SendCaptcha() mir.Error { +func (UnimplementedPubServant) SendCaptcha() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPubServant) GetCaptcha() mir.Error { +func (UnimplementedPubServant) GetCaptcha() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPubServant) Register() mir.Error { +func (UnimplementedPubServant) Register() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPubServant) Login() mir.Error { +func (UnimplementedPubServant) Login() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPubServant) Version() mir.Error { +func (UnimplementedPubServant) Version() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedWebPubServant) mustEmbedUnimplementedWebPubServant() {} +func (UnimplementedPubServant) mustEmbedUnimplementedPubServant() {} -// UnimplementedWebPubRender can be embedded to have forward compatible implementations. -type UnimplementedWebPubRender struct { +// UnimplementedPubRender can be embedded to have forward compatible implementations. +type UnimplementedPubRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedWebPubRender) RenderTopicList(c *gin.Context, err mir.Error) { +func (r *UnimplementedPubRender) RenderTopicList(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPubRender) RenderTweetComments(c *gin.Context, err mir.Error) { +func (r *UnimplementedPubRender) RenderTweetComments(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPubRender) RenderTweetDetail(c *gin.Context, data *web.TweetDetailResp, err mir.Error) { +func (r *UnimplementedPubRender) RenderTweetDetail(c *gin.Context, data *web.TweetDetailResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedWebPubRender) RenderSendCaptcha(c *gin.Context, err mir.Error) { +func (r *UnimplementedPubRender) RenderSendCaptcha(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPubRender) RenderGetCaptcha(c *gin.Context, err mir.Error) { +func (r *UnimplementedPubRender) RenderGetCaptcha(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPubRender) RenderRegister(c *gin.Context, err mir.Error) { +func (r *UnimplementedPubRender) RenderRegister(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPubRender) RenderLogin(c *gin.Context, err mir.Error) { +func (r *UnimplementedPubRender) RenderLogin(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPubRender) RenderVersion(c *gin.Context, err mir.Error) { +func (r *UnimplementedPubRender) RenderVersion(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedWebPubRender) mustEmbedUnimplementedWebPubRender() {} +func (r *UnimplementedPubRender) mustEmbedUnimplementedPubRender() {} -// UnimplementedWebPubBinding can be embedded to have forward compatible implementations. -type UnimplementedWebPubBinding struct { +// UnimplementedPubBinding can be embedded to have forward compatible implementations. +type UnimplementedPubBinding struct { BindAny func(*gin.Context, any) mir.Error } -func (b *UnimplementedWebPubBinding) BindTweetDetail(c *gin.Context) (*web.TweetDetailReq, mir.Error) { +func (b *UnimplementedPubBinding) BindTweetDetail(c *gin.Context) (*web.TweetDetailReq, mir.Error) { obj := new(web.TweetDetailReq) err := b.BindAny(c, obj) return obj, err } -func (b *UnimplementedWebPubBinding) mustEmbedUnimplementedWebPubBinding() {} +func (b *UnimplementedPubBinding) mustEmbedUnimplementedPubBinding() {} diff --git a/auto/api/v1/web_admin.go b/auto/api/v1/web_admin.go deleted file mode 100644 index 1e2f721d..00000000 --- a/auto/api/v1/web_admin.go +++ /dev/null @@ -1,95 +0,0 @@ -// Code generated by go-mir. DO NOT EDIT. - -package v1 - -import ( - "net/http" - - "github.com/alimy/mir/v3" - "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model/web" -) - -type WebAdmin interface { - // Chain provide handlers chain for gin - Chain() gin.HandlersChain - - ChangeUserStatus(*web.ChangeUserStatusReq) mir.Error - - mustEmbedUnimplementedWebAdminServant() -} - -type WebAdminBinding interface { - BindChangeUserStatus(*gin.Context) (*web.ChangeUserStatusReq, mir.Error) - - mustEmbedUnimplementedWebAdminBinding() -} - -type WebAdminRender interface { - RenderChangeUserStatus(*gin.Context, mir.Error) - - mustEmbedUnimplementedWebAdminRender() -} - -// RegisterWebAdminServant register WebAdmin servant to gin -func RegisterWebAdminServant(e *gin.Engine, s WebAdmin, b WebAdminBinding, r WebAdminRender) { - router := e.Group("v1") - // use chain for router - middlewares := s.Chain() - router.Use(middlewares...) - - // register routes info to router - router.Handle("POST", "/admin/user/status", func(c *gin.Context) { - select { - case <-c.Request.Context().Done(): - return - default: - } - - req, err := b.BindChangeUserStatus(c) - if err != nil { - r.RenderChangeUserStatus(c, err) - return - } - r.RenderChangeUserStatus(c, s.ChangeUserStatus(req)) - }) - -} - -// UnimplementedWebAdminServant can be embedded to have forward compatible implementations. -type UnimplementedWebAdminServant struct { -} - -func (UnimplementedWebAdminServant) Chain() gin.HandlersChain { - return nil -} - -func (UnimplementedWebAdminServant) ChangeUserStatus(req *web.ChangeUserStatusReq) mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) -} - -func (UnimplementedWebAdminServant) mustEmbedUnimplementedWebAdminServant() {} - -// UnimplementedWebAdminRender can be embedded to have forward compatible implementations. -type UnimplementedWebAdminRender struct { - RenderAny func(*gin.Context, any, mir.Error) -} - -func (r *UnimplementedWebAdminRender) RenderChangeUserStatus(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) -} - -func (r *UnimplementedWebAdminRender) mustEmbedUnimplementedWebAdminRender() {} - -// UnimplementedWebAdminBinding can be embedded to have forward compatible implementations. -type UnimplementedWebAdminBinding struct { - BindAny func(*gin.Context, any) mir.Error -} - -func (b *UnimplementedWebAdminBinding) BindChangeUserStatus(c *gin.Context) (*web.ChangeUserStatusReq, mir.Error) { - obj := new(web.ChangeUserStatusReq) - err := b.BindAny(c, obj) - return obj, err -} - -func (b *UnimplementedWebAdminBinding) mustEmbedUnimplementedWebAdminBinding() {} diff --git a/auto/api/v1/web_alipay_pub.go b/auto/api/v1/web_alipay_pub.go deleted file mode 100644 index d4917af7..00000000 --- a/auto/api/v1/web_alipay_pub.go +++ /dev/null @@ -1,85 +0,0 @@ -// Code generated by go-mir. DO NOT EDIT. - -package v1 - -import ( - "net/http" - - "github.com/alimy/mir/v3" - "github.com/gin-gonic/gin" - "github.com/rocboss/paopao-ce/internal/model/web" -) - -type WebAlipayPub interface { - AlipayNotify(*web.AlipayNotifyReq) mir.Error - - mustEmbedUnimplementedWebAlipayPubServant() -} - -type WebAlipayPubBinding interface { - BindAlipayNotify(*gin.Context) (*web.AlipayNotifyReq, mir.Error) - - mustEmbedUnimplementedWebAlipayPubBinding() -} - -type WebAlipayPubRender interface { - RenderAlipayNotify(*gin.Context, mir.Error) - - mustEmbedUnimplementedWebAlipayPubRender() -} - -// RegisterWebAlipayPubServant register WebAlipayPub servant to gin -func RegisterWebAlipayPubServant(e *gin.Engine, s WebAlipayPub, b WebAlipayPubBinding, r WebAlipayPubRender) { - router := e.Group("v1") - - // register routes info to router - router.Handle("POST", "/alipay/notify", func(c *gin.Context) { - select { - case <-c.Request.Context().Done(): - return - default: - } - - req, err := b.BindAlipayNotify(c) - if err != nil { - r.RenderAlipayNotify(c, err) - return - } - r.RenderAlipayNotify(c, s.AlipayNotify(req)) - }) - -} - -// UnimplementedWebAlipayPubServant can be embedded to have forward compatible implementations. -type UnimplementedWebAlipayPubServant struct { -} - -func (UnimplementedWebAlipayPubServant) AlipayNotify(req *web.AlipayNotifyReq) mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) -} - -func (UnimplementedWebAlipayPubServant) mustEmbedUnimplementedWebAlipayPubServant() {} - -// UnimplementedWebAlipayPubRender can be embedded to have forward compatible implementations. -type UnimplementedWebAlipayPubRender struct { - RenderAny func(*gin.Context, any, mir.Error) -} - -func (r *UnimplementedWebAlipayPubRender) RenderAlipayNotify(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) -} - -func (r *UnimplementedWebAlipayPubRender) mustEmbedUnimplementedWebAlipayPubRender() {} - -// UnimplementedWebAlipayPubBinding can be embedded to have forward compatible implementations. -type UnimplementedWebAlipayPubBinding struct { - BindAny func(*gin.Context, any) mir.Error -} - -func (b *UnimplementedWebAlipayPubBinding) BindAlipayNotify(c *gin.Context) (*web.AlipayNotifyReq, mir.Error) { - obj := new(web.AlipayNotifyReq) - err := b.BindAny(c, obj) - return obj, err -} - -func (b *UnimplementedWebAlipayPubBinding) mustEmbedUnimplementedWebAlipayPubBinding() {} diff --git a/internal/model/web/admin.go b/internal/model/web/admin.go index 765d507a..d0c3b46e 100644 --- a/internal/model/web/admin.go +++ b/internal/model/web/admin.go @@ -1,3 +1,7 @@ +// 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 type ChangeUserStatusReq struct { diff --git a/internal/model/web/alipay.go b/internal/model/web/alipay.go index 15fc2321..9260725f 100644 --- a/internal/model/web/alipay.go +++ b/internal/model/web/alipay.go @@ -1,3 +1,7 @@ +// 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 type UserWalletBillsReq struct { diff --git a/internal/model/web/loose.go b/internal/model/web/loose.go index 26a3aa6e..6115e2cc 100644 --- a/internal/model/web/loose.go +++ b/internal/model/web/loose.go @@ -1,3 +1,7 @@ +// 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 type TimelineReq struct { diff --git a/internal/model/web/priv.go b/internal/model/web/priv.go index d6ced02e..9184a437 100644 --- a/internal/model/web/priv.go +++ b/internal/model/web/priv.go @@ -1,3 +1,7 @@ +// 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 type CreateTweetReq struct { diff --git a/internal/model/web/pub.go b/internal/model/web/pub.go index ac482fc0..f0df15e2 100644 --- a/internal/model/web/pub.go +++ b/internal/model/web/pub.go @@ -1,3 +1,7 @@ +// 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 type TweetDetailReq struct { diff --git a/internal/servants/web/admin.go b/internal/servants/web/admin.go index 2618746a..d00f63c9 100644 --- a/internal/servants/web/admin.go +++ b/internal/servants/web/admin.go @@ -12,45 +12,45 @@ import ( ) var ( - _ api.WebAdmin = (*webAdminSrv)(nil) - _ api.WebAdminBinding = (*webAdminBinding)(nil) - _ api.WebAdminRender = (*webAdminRender)(nil) + _ api.Admin = (*adminSrv)(nil) + _ api.AdminBinding = (*adminBinding)(nil) + _ api.AdminRender = (*adminRender)(nil) ) -type webAdminSrv struct { +type adminSrv struct { base.BaseServant - api.UnimplementedWebAdminServant + api.UnimplementedAdminServant } -type webAdminBinding struct { +type adminBinding struct { base.BaseBinding - *api.UnimplementedWebAdminBinding + *api.UnimplementedAdminBinding } -type webAdminRender struct { +type adminRender struct { base.BaseRender - *api.UnimplementedWebAdminRender + *api.UnimplementedAdminRender } -func (s *webAdminSrv) Chain() gin.HandlersChain { +func (s *adminSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT(), chain.Admin()} } -func newWebAdminSrv() api.WebAdmin { - return &webAdminSrv{} +func newAdminSrv() api.Admin { + return &adminSrv{} } -func newWebAdminBinding() api.WebAdminBinding { - return &webAdminBinding{ - UnimplementedWebAdminBinding: &api.UnimplementedWebAdminBinding{ +func newAdminBinding() api.AdminBinding { + return &adminBinding{ + UnimplementedAdminBinding: &api.UnimplementedAdminBinding{ BindAny: base.BindAny, }, } } -func newWebAdminRender() api.WebAdminRender { - return &webAdminRender{ - UnimplementedWebAdminRender: &api.UnimplementedWebAdminRender{ +func newAdminRender() api.AdminRender { + return &adminRender{ + UnimplementedAdminRender: &api.UnimplementedAdminRender{ RenderAny: base.RenderAny, }, } diff --git a/internal/servants/web/alipay.go b/internal/servants/web/alipay.go index d8c143eb..a6bc97f6 100644 --- a/internal/servants/web/alipay.go +++ b/internal/servants/web/alipay.go @@ -12,83 +12,83 @@ import ( ) var ( - _ api.WebAlipayPub = (*webAlipayPubSrv)(nil) - _ api.WebAlipayPubBinding = (*webAlipayPubBinding)(nil) - _ api.WebAlipayPubRender = (*webAlipayPubRender)(nil) - _ api.WebAlipayPriv = (*webAlipayPrivSrv)(nil) - _ api.WebAlipayPrivBinding = (*webAlipayPrivBinding)(nil) - _ api.WebAlipayPrivRender = (*webAlipayPrivRender)(nil) + _ api.AlipayPub = (*alipayPubSrv)(nil) + _ api.AlipayPubBinding = (*alipayPubBinding)(nil) + _ api.AlipayPubRender = (*alipayPubRender)(nil) + _ api.AlipayPriv = (*alipayPrivSrv)(nil) + _ api.AlipayPrivBinding = (*alipayPrivBinding)(nil) + _ api.AlipayPrivRender = (*alipayPrivRender)(nil) ) -type webAlipayPubSrv struct { +type alipayPubSrv struct { base.BaseServant - api.UnimplementedWebAlipayPubServant + api.UnimplementedAlipayPubServant } -type webAlipayPubBinding struct { +type alipayPubBinding struct { base.BaseBinding - *api.UnimplementedWebAlipayPubBinding + *api.UnimplementedAlipayPubBinding } -type webAlipayPubRender struct { +type alipayPubRender struct { base.BaseRender - *api.UnimplementedWebAlipayPubRender + *api.UnimplementedAlipayPubRender } -type webAlipayPrivSrv struct { +type alipayPrivSrv struct { base.BaseServant - api.UnimplementedWebAlipayPrivServant + api.UnimplementedAlipayPrivServant } -type webAlipayPrivBinding struct { +type alipayPrivBinding struct { base.BaseBinding - *api.UnimplementedWebAlipayPrivBinding + *api.UnimplementedAlipayPrivBinding } -type webAlipayPrivRender struct { +type alipayPrivRender struct { base.BaseRender - *api.UnimplementedWebAlipayPrivRender + *api.UnimplementedAlipayPrivRender } -func (s *webAlipayPrivSrv) Chain() gin.HandlersChain { +func (s *alipayPrivSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func newWebAlipayPubSrv() api.WebAlipayPub { - return &webAlipayPubSrv{} +func newAlipayPubSrv() api.AlipayPub { + return &alipayPubSrv{} } -func newWebAlipayPubBinding() api.WebAlipayPubBinding { - return &webAlipayPubBinding{ - UnimplementedWebAlipayPubBinding: &api.UnimplementedWebAlipayPubBinding{ +func newAlipayPubBinding() api.AlipayPubBinding { + return &alipayPubBinding{ + UnimplementedAlipayPubBinding: &api.UnimplementedAlipayPubBinding{ BindAny: base.BindAny, }, } } -func newWebAlipayPubRender() api.WebAlipayPubRender { - return &webAlipayPubRender{ - UnimplementedWebAlipayPubRender: &api.UnimplementedWebAlipayPubRender{ +func newAlipayPubRender() api.AlipayPubRender { + return &alipayPubRender{ + UnimplementedAlipayPubRender: &api.UnimplementedAlipayPubRender{ RenderAny: base.RenderAny, }, } } -func newWebAlipayPrivSrv() api.WebAlipayPriv { - return &webAlipayPrivSrv{} +func newAlipayPrivSrv() api.AlipayPriv { + return &alipayPrivSrv{} } -func newWebAlipayPrivBinding() api.WebAlipayPrivBinding { - return &webAlipayPrivBinding{ - UnimplementedWebAlipayPrivBinding: &api.UnimplementedWebAlipayPrivBinding{ +func newAlipayPrivBinding() api.AlipayPrivBinding { + return &alipayPrivBinding{ + UnimplementedAlipayPrivBinding: &api.UnimplementedAlipayPrivBinding{ BindAny: base.BindAny, }, } } -func newWebAlipayPrivRender() api.WebAlipayPrivRender { - return &webAlipayPrivRender{ - UnimplementedWebAlipayPrivRender: &api.UnimplementedWebAlipayPrivRender{ +func newAlipayPrivRender() api.AlipayPrivRender { + return &alipayPrivRender{ + UnimplementedAlipayPrivRender: &api.UnimplementedAlipayPrivRender{ RenderAny: base.RenderAny, }, } diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 1c40cdfe..30bbe7e5 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -12,45 +12,45 @@ import ( ) var ( - _ api.WebCore = (*webCoreSrv)(nil) - _ api.WebCoreBinding = (*webCoreBinding)(nil) - _ api.WebCoreRender = (*webCoreRender)(nil) + _ api.Core = (*coreSrv)(nil) + _ api.CoreBinding = (*coreBinding)(nil) + _ api.CoreRender = (*coreRender)(nil) ) -type webCoreSrv struct { +type coreSrv struct { base.BaseServant - api.UnimplementedWebCoreServant + api.UnimplementedCoreServant } -type webCoreBinding struct { +type coreBinding struct { base.BaseBinding - *api.UnimplementedWebCoreBinding + *api.UnimplementedCoreBinding } -type webCoreRender struct { +type coreRender struct { base.BaseRender - *api.UnimplementedWebCoreRender + *api.UnimplementedCoreRender } -func (s *webCoreSrv) Chain() gin.HandlersChain { +func (s *coreSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func newWebCoreSrv() api.WebCore { - return &webCoreSrv{} +func newCoreSrv() api.Core { + return &coreSrv{} } -func newWebCoreBinding() api.WebCoreBinding { - return &webCoreBinding{ - UnimplementedWebCoreBinding: &api.UnimplementedWebCoreBinding{ +func newCoreBinding() api.CoreBinding { + return &coreBinding{ + UnimplementedCoreBinding: &api.UnimplementedCoreBinding{ BindAny: base.BindAny, }, } } -func newWebCoreRender() api.WebCoreRender { - return &webCoreRender{ - UnimplementedWebCoreRender: &api.UnimplementedWebCoreRender{ +func newCoreRender() api.CoreRender { + return &coreRender{ + UnimplementedCoreRender: &api.UnimplementedCoreRender{ RenderAny: base.RenderAny, }, } diff --git a/internal/servants/web/followship.go b/internal/servants/web/followship.go index a9c077f3..fc9d6788 100644 --- a/internal/servants/web/followship.go +++ b/internal/servants/web/followship.go @@ -12,45 +12,45 @@ import ( ) var ( - _ api.WebFollowship = (*webFollowshipSrv)(nil) - _ api.WebFollowshipBinding = (*webFollowshipBinding)(nil) - _ api.WebFollowshipRender = (*webFollowshipRender)(nil) + _ api.Followship = (*followshipSrv)(nil) + _ api.FollowshipBinding = (*followshipBinding)(nil) + _ api.FollowshipRender = (*followshipRender)(nil) ) -type webFollowshipSrv struct { +type followshipSrv struct { base.BaseServant - api.UnimplementedWebFollowshipServant + api.UnimplementedFollowshipServant } -type webFollowshipBinding struct { +type followshipBinding struct { base.BaseBinding - *api.UnimplementedWebFollowshipBinding + *api.UnimplementedFollowshipBinding } -type webFollowshipRender struct { +type followshipRender struct { base.BaseRender - *api.UnimplementedWebFollowshipRender + *api.UnimplementedFollowshipRender } -func (s *webFollowshipSrv) Chain() gin.HandlersChain { +func (s *followshipSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func newWebFollowshipSrv() api.WebFollowship { - return &webFollowshipSrv{} +func newFollowshipSrv() api.Followship { + return &followshipSrv{} } -func newWebFollowshipBinding() api.WebFollowshipBinding { - return &webFollowshipBinding{ - UnimplementedWebFollowshipBinding: &api.UnimplementedWebFollowshipBinding{ +func newFollowshipBinding() api.FollowshipBinding { + return &followshipBinding{ + UnimplementedFollowshipBinding: &api.UnimplementedFollowshipBinding{ BindAny: base.BindAny, }, } } -func newWebFollowshipRender() api.WebFollowshipRender { - return &webFollowshipRender{ - UnimplementedWebFollowshipRender: &api.UnimplementedWebFollowshipRender{ +func newFollowshipRender() api.FollowshipRender { + return &followshipRender{ + UnimplementedFollowshipRender: &api.UnimplementedFollowshipRender{ RenderAny: base.RenderAny, }, } diff --git a/internal/servants/web/friendship.go b/internal/servants/web/friendship.go index 042bf0a5..3813763b 100644 --- a/internal/servants/web/friendship.go +++ b/internal/servants/web/friendship.go @@ -12,45 +12,45 @@ import ( ) var ( - _ api.WebFriendship = (*webFriendshipSrv)(nil) - _ api.WebFriendshipBinding = (*webFriendshipBinding)(nil) - _ api.WebFriendshipRender = (*webFriendshipRender)(nil) + _ api.Friendship = (*friendshipSrv)(nil) + _ api.FriendshipBinding = (*friendshipBinding)(nil) + _ api.FriendshipRender = (*friendshipRender)(nil) ) -type webFriendshipSrv struct { +type friendshipSrv struct { base.BaseServant - api.UnimplementedWebFriendshipServant + api.UnimplementedFriendshipServant } -type webFriendshipBinding struct { +type friendshipBinding struct { base.BaseBinding - *api.UnimplementedWebFriendshipBinding + *api.UnimplementedFriendshipBinding } -type webFriendshipRender struct { +type friendshipRender struct { base.BaseRender - *api.UnimplementedWebFriendshipRender + *api.UnimplementedFriendshipRender } -func (s *webFriendshipSrv) Chain() gin.HandlersChain { +func (s *friendshipSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func newWebFriendshipSrv() api.WebFriendship { - return &webFriendshipSrv{} +func newFriendshipSrv() api.Friendship { + return &friendshipSrv{} } -func newWebFriendshipBinding() api.WebFriendshipBinding { - return &webFriendshipBinding{ - UnimplementedWebFriendshipBinding: &api.UnimplementedWebFriendshipBinding{ +func newFriendshipBinding() api.FriendshipBinding { + return &friendshipBinding{ + UnimplementedFriendshipBinding: &api.UnimplementedFriendshipBinding{ BindAny: base.BindAny, }, } } -func newWebFriendshipRender() api.WebFriendshipRender { - return &webFriendshipRender{ - UnimplementedWebFriendshipRender: &api.UnimplementedWebFriendshipRender{ +func newFriendshipRender() api.FriendshipRender { + return &friendshipRender{ + UnimplementedFriendshipRender: &api.UnimplementedFriendshipRender{ RenderAny: base.RenderAny, }, } diff --git a/internal/servants/web/loose.go b/internal/servants/web/loose.go index 04a75faa..3b6e37a7 100644 --- a/internal/servants/web/loose.go +++ b/internal/servants/web/loose.go @@ -12,45 +12,45 @@ import ( ) var ( - _ api.WebLoose = (*webLooseSrv)(nil) - _ api.WebLooseBinding = (*webLooseBinding)(nil) - _ api.WebLooseRender = (*webLooseRender)(nil) + _ api.Loose = (*looseSrv)(nil) + _ api.LooseBinding = (*looseBinding)(nil) + _ api.LooseRender = (*looseRender)(nil) ) -type webLooseSrv struct { +type looseSrv struct { base.BaseServant - api.UnimplementedWebLooseServant + api.UnimplementedLooseServant } -type webLooseBinding struct { +type looseBinding struct { base.BaseBinding - *api.UnimplementedWebLooseBinding + *api.UnimplementedLooseBinding } -type webLooseRender struct { +type looseRender struct { base.BaseRender - *api.UnimplementedWebLooseRender + *api.UnimplementedLooseRender } -func (s *webLooseSrv) Chain() gin.HandlersChain { +func (s *looseSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JwtLoose()} } -func newWebLooseSrv() api.WebLoose { - return &webLooseSrv{} +func newLooseSrv() api.Loose { + return &looseSrv{} } -func newWebLooseBinding() api.WebLooseBinding { - return &webLooseBinding{ - UnimplementedWebLooseBinding: &api.UnimplementedWebLooseBinding{ +func newLooseBinding() api.LooseBinding { + return &looseBinding{ + UnimplementedLooseBinding: &api.UnimplementedLooseBinding{ BindAny: base.BindAny, }, } } -func newWebLooseRender() api.WebLooseRender { - return &webLooseRender{ - UnimplementedWebLooseRender: &api.UnimplementedWebLooseRender{ +func newLooseRender() api.LooseRender { + return &looseRender{ + UnimplementedLooseRender: &api.UnimplementedLooseRender{ RenderAny: base.RenderAny, }, } diff --git a/internal/servants/web/priv.go b/internal/servants/web/priv.go index 96485fec..5e4890f0 100644 --- a/internal/servants/web/priv.go +++ b/internal/servants/web/priv.go @@ -12,45 +12,45 @@ import ( ) var ( - _ api.WebPriv = (*webPrivSrv)(nil) - _ api.WebPrivBinding = (*webPrivBinding)(nil) - _ api.WebPrivRender = (*webPrivRender)(nil) + _ api.Priv = (*privSrv)(nil) + _ api.PrivBinding = (*privBinding)(nil) + _ api.PrivRender = (*privRender)(nil) ) -type webPrivSrv struct { +type privSrv struct { base.BaseServant - api.UnimplementedWebPrivServant + api.UnimplementedPrivServant } -type webPrivBinding struct { +type privBinding struct { base.BaseBinding - *api.UnimplementedWebPrivBinding + *api.UnimplementedPrivBinding } -type webPrivRender struct { +type privRender struct { base.BaseRender - *api.UnimplementedWebPrivRender + *api.UnimplementedPrivRender } -func (s *webPrivSrv) Chain() gin.HandlersChain { +func (s *privSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT(), chain.Priv()} } -func newWebPrivSrv() api.WebPriv { - return &webPrivSrv{} +func newPrivSrv() api.Priv { + return &privSrv{} } -func newWebPrivBinding() api.WebPrivBinding { - return &webPrivBinding{ - UnimplementedWebPrivBinding: &api.UnimplementedWebPrivBinding{ +func newPrivBinding() api.PrivBinding { + return &privBinding{ + UnimplementedPrivBinding: &api.UnimplementedPrivBinding{ BindAny: base.BindAny, }, } } -func newWebPrivRender() api.WebPrivRender { - return &webPrivRender{ - UnimplementedWebPrivRender: &api.UnimplementedWebPrivRender{ +func newPrivRender() api.PrivRender { + return &privRender{ + UnimplementedPrivRender: &api.UnimplementedPrivRender{ RenderAny: base.RenderAny, }, } diff --git a/internal/servants/web/pub.go b/internal/servants/web/pub.go index 689cbc32..f072a6b2 100644 --- a/internal/servants/web/pub.go +++ b/internal/servants/web/pub.go @@ -12,45 +12,45 @@ import ( ) var ( - _ api.WebPub = (*webPubSrv)(nil) - _ api.WebPubBinding = (*webPubBinding)(nil) - _ api.WebPubRender = (*webPubRender)(nil) + _ api.Pub = (*pubSrv)(nil) + _ api.PubBinding = (*pubBinding)(nil) + _ api.PubRender = (*pubRender)(nil) ) -type webPubSrv struct { +type pubSrv struct { base.BaseServant - api.UnimplementedWebPubServant + api.UnimplementedPubServant } -type webPubBinding struct { +type pubBinding struct { base.BaseBinding - *api.UnimplementedWebPubBinding + *api.UnimplementedPubBinding } -type webPubRender struct { +type pubRender struct { base.BaseRender - *api.UnimplementedWebPubRender + *api.UnimplementedPubRender } -func (s *webPubSrv) Chain() gin.HandlersChain { +func (s *pubSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JwtLoose()} } -func newWebPubSrv() api.WebPub { - return &webPubSrv{} +func newPubSrv() api.Pub { + return &pubSrv{} } -func newWebPubBinding() api.WebPubBinding { - return &webPubBinding{ - UnimplementedWebPubBinding: &api.UnimplementedWebPubBinding{ +func newPubBinding() api.PubBinding { + return &pubBinding{ + UnimplementedPubBinding: &api.UnimplementedPubBinding{ BindAny: base.BindAny, }, } } -func newWebPubRender() api.WebPubRender { - return &webPubRender{ - UnimplementedWebPubRender: &api.UnimplementedWebPubRender{ +func newPubRender() api.PubRender { + return &pubRender{ + UnimplementedPubRender: &api.UnimplementedPubRender{ RenderAny: base.RenderAny, }, } diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index d19444a7..b735f5a7 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -12,22 +12,22 @@ import ( // RouteWeb register web route func RouteWeb(e *gin.Engine) { - api.RegisterWebAdminServant(e, newWebAdminSrv(), newWebAdminBinding(), newWebAdminRender()) - api.RegisterWebCoreServant(e, newWebCoreSrv(), newWebCoreBinding(), newWebCoreRender()) - api.RegisterWebLooseServant(e, newWebLooseSrv(), newWebLooseBinding(), newWebLooseRender()) - api.RegisterWebPrivServant(e, newWebPrivSrv(), newWebPrivBinding(), newWebPrivRender()) - api.RegisterWebPubServant(e, newWebPubSrv(), newWebPubBinding(), newWebPubRender()) + api.RegisterAdminServant(e, newAdminSrv(), newAdminBinding(), newAdminRender()) + api.RegisterCoreServant(e, newCoreSrv(), newCoreBinding(), newCoreRender()) + api.RegisterLooseServant(e, newLooseSrv(), newLooseBinding(), newLooseRender()) + api.RegisterPrivServant(e, newPrivSrv(), newPrivBinding(), newPrivRender()) + api.RegisterPubServant(e, newPubSrv(), newPubBinding(), newPubRender()) cfg.In(cfg.Actions{ "Alipay": func() { - api.RegisterWebAlipayPubServant(e, newWebAlipayPubSrv(), newWebAlipayPubBinding(), newWebAlipayPubRender()) - api.RegisterWebAlipayPrivServant(e, newWebAlipayPrivSrv(), newWebAlipayPrivBinding(), newWebAlipayPrivRender()) + api.RegisterAlipayPubServant(e, newAlipayPubSrv(), newAlipayPubBinding(), newAlipayPubRender()) + api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(), newAlipayPrivBinding(), newAlipayPrivRender()) }, "Followship": func() { - api.RegisterWebFollowshipServant(e, newWebFollowshipSrv(), newWebFollowshipBinding(), newWebFollowshipRender()) + api.RegisterFollowshipServant(e, newFollowshipSrv(), newFollowshipBinding(), newFollowshipRender()) }, "Friendship": func() { - api.RegisterWebFriendshipServant(e, newWebFriendshipSrv(), newWebFriendshipBinding(), newWebFriendshipRender()) + api.RegisterFriendshipServant(e, newFriendshipSrv(), newFriendshipBinding(), newFriendshipRender()) }, }) } diff --git a/mirc/web/v1/admin.go b/mirc/web/v1/admin.go index 97d89ea8..4a1d8655 100644 --- a/mirc/web/v1/admin.go +++ b/mirc/web/v1/admin.go @@ -7,10 +7,11 @@ import ( ) func init() { - AddEntry(new(WebAdmin)) + AddEntry(new(Admin)) } -type WebAdmin struct { +// Admin 运维相关服务 +type Admin struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/alipay.go b/mirc/web/v1/alipay.go index 55397a08..c4a34111 100644 --- a/mirc/web/v1/alipay.go +++ b/mirc/web/v1/alipay.go @@ -7,17 +7,19 @@ import ( ) func init() { - AddEntries(new(WebAlipayPub), new(WebAlipayPriv)) + AddEntries(new(AlipayPub), new(AlipayPriv)) } -type WebAlipayPub struct { +// AlipayPub 支付宝相关不用授权的服务 +type AlipayPub struct { Group Group `mir:"v1"` // AlipayNotify 支付宝回调 AlipayNotify func(Post, web.AlipayNotifyReq) `mir:"/alipay/notify"` } -type WebAlipayPriv struct { +// AlipayPub 支付宝相关授权的服务 +type AlipayPriv struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/core.go b/mirc/web/v1/core.go index 4d9e5ba4..1500e3db 100644 --- a/mirc/web/v1/core.go +++ b/mirc/web/v1/core.go @@ -7,10 +7,11 @@ import ( ) func init() { - AddEntry(new(WebCore)) + AddEntry(new(Core)) } -type WebCore struct { +// Core 核心服务,需要授权访问 +type Core struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/followship.go b/mirc/web/v1/followship.go index a3ff76a3..8c4e81fe 100644 --- a/mirc/web/v1/followship.go +++ b/mirc/web/v1/followship.go @@ -7,10 +7,11 @@ import ( ) func init() { - AddEntry(new(WebFollowship)) + AddEntry(new(Followship)) } -type WebFollowship struct { +// Followship 关注者模式 服务 +type Followship struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/friendship.go b/mirc/web/v1/friendship.go index 409513ec..ae29910a 100644 --- a/mirc/web/v1/friendship.go +++ b/mirc/web/v1/friendship.go @@ -7,10 +7,11 @@ import ( ) func init() { - AddEntry(new(WebFriendship)) + AddEntry(new(Friendship)) } -type WebFriendship struct { +// Friendship 好友模式 服务 +type Friendship struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/loose.go b/mirc/web/v1/loose.go index 804d33a2..665a9837 100644 --- a/mirc/web/v1/loose.go +++ b/mirc/web/v1/loose.go @@ -7,10 +7,11 @@ import ( ) func init() { - AddEntry(new(WebLoose)) + AddEntry(new(Loose)) } -type WebLoose struct { +// Loose 宽松授权的服务 +type Loose struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/priv.go b/mirc/web/v1/priv.go index 43ec13b2..86321a4e 100644 --- a/mirc/web/v1/priv.go +++ b/mirc/web/v1/priv.go @@ -7,10 +7,11 @@ import ( ) func init() { - AddEntry(new(WebPriv)) + AddEntry(new(Priv)) } -type WebPriv struct { +// Priv 私有授权的服务 +type Priv struct { Chain Chain `mir:"-"` Group Group `mir:"v1"` diff --git a/mirc/web/v1/pub.go b/mirc/web/v1/pub.go index 73491b44..b69bc47b 100644 --- a/mirc/web/v1/pub.go +++ b/mirc/web/v1/pub.go @@ -7,10 +7,11 @@ import ( ) func init() { - AddEntry(new(WebPub)) + AddEntry(new(Pub)) } -type WebPub struct { +// Pub 不用授权的公开服务 +type Pub struct { Group Group `mir:"v1"` // Version 获取后台版本信息 From 9feb1a5a0b70e711b27f5cec5912e9facf900352 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 23 Dec 2022 22:58:11 +0800 Subject: [PATCH 52/65] mir:update proposal documents --- .../006-关于paopao-ce的结构设计.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/proposal/006-关于paopao-ce的结构设计.md b/docs/proposal/006-关于paopao-ce的结构设计.md index d60999a5..953c1741 100644 --- a/docs/proposal/006-关于paopao-ce的结构设计.md +++ b/docs/proposal/006-关于paopao-ce的结构设计.md @@ -1,17 +1,19 @@ | 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 | | ----- | ----- | ----- | ----- | ----- | ----- | -| 006| 北野 | 2022-11-23 | 2022-11-23 | v0.0 | 提议 | +| 006| 北野 | 2022-11-23 | 2022-12-23 | v0.1 | 提议 | ### 关于paopao-ce的结构设计 ![](.assets/06-01.png) ### 疑问 -1. 为什么要引入[go-mir](https://github.com/alimy/mir)? -TODO; -1. 为什么要兼容RESTful服务与gRPC服务? -TODO; +1. 为什么要引入[go-mir](https://github.com/alimy/mir)? +工欲善其事,必先利其器。为了RESTFul API的后端开发体验可以媲美gRPC,本人特意打造[go-mir](https://github.com/alimy/mir) v3版本来满足需求。[go-mir](https://github.com/alimy/mir)是一套使用golang自身语言生态实现的RESTFul API从接口定义到代码自动生成的脚手架辅助工具集,便捷的实现快速后端开发体验,颇有“程咬金的三板斧,简单抡着就完事”的韵味。而从[go-mir](https://github.com/alimy/mir)的官方文档参考也可以看出,其生成的代码也确实就将一个HTTP的请求/响应简单分成 `请求绑定`->`业务逻辑`->`结果渲染`三个步骤去完成,生成的代码结构简单清晰,与gRPC的生成代码有点类似。 +1. 为什么要兼容RESTful服务与gRPC服务? +RESTful服务与gRPC服务各自有擅长的场景,在合适的场景使用最适合的技术去做相应的适配,这是paopao-ce秉持的代码开发原则之一。 ### 更新记录 -#### v0.0(2022-11-23) - 北野 -* 初始文档, 先占个位置 \ No newline at end of file +#### v0.0(2022-11-23) - 北野 +* 初始文档, 先占个位置 +#### v0.1(2022-12-23) - 北野 +* 添加部分内容 \ No newline at end of file From da939f7c7368c8023c65a88439b7c8248b9279d4 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 27 Dec 2022 12:14:17 +0800 Subject: [PATCH 53/65] mir: add partital interface implement for new web service --- internal/model/web/admin.go | 4 +- internal/model/web/alipay.go | 13 ++++++- internal/servants/base/base.go | 10 ++++- internal/servants/web/admin.go | 26 ++++++++++--- internal/servants/web/alipay.go | 65 ++++++++++++++++++++++++++++----- internal/servants/web/core.go | 16 +++++--- internal/servants/web/web.go | 43 ++++++++++++++++++++-- pkg/xerror/xerror.go | 31 +++++++++------- 8 files changed, 166 insertions(+), 42 deletions(-) diff --git a/internal/model/web/admin.go b/internal/model/web/admin.go index d0c3b46e..ec312f2c 100644 --- a/internal/model/web/admin.go +++ b/internal/model/web/admin.go @@ -5,5 +5,7 @@ package web type ChangeUserStatusReq struct { - *BaseInfo `json:"-"` + *BaseInfo `json:"-" binding:"-"` + ID int64 `json:"id" form:"id" binding:"required"` + Status int `json:"status" form:"status" binding:"required,oneof=1 2"` } diff --git a/internal/model/web/alipay.go b/internal/model/web/alipay.go index 9260725f..2063e88c 100644 --- a/internal/model/web/alipay.go +++ b/internal/model/web/alipay.go @@ -4,8 +4,14 @@ package web +import ( + "context" + + "github.com/smartwalle/alipay/v3" +) + type UserWalletBillsReq struct { - *BaseInfo `json:"-"` + *BaseInfo `json:"-" binding:"-"` } type UserWalletBillsResp struct { @@ -13,5 +19,8 @@ type UserWalletBillsResp struct { } type AlipayNotifyReq struct { - // TODO + Ctx context.Context + ID int64 + TradeNo string + TradeStatus alipay.TradeStatus } diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index eac975ed..301753f6 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -9,6 +9,7 @@ import ( "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" + "github.com/go-redis/redis/v8" "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/pkg/xerror" ) @@ -17,6 +18,11 @@ type BaseServant struct { // TODO } +type DaoServant struct { + Redis *redis.Client + Ds core.DataService +} + type BaseBinding struct { // TODO } @@ -47,7 +53,7 @@ func BindAny(c *gin.Context, obj any) mir.Error { var errs xerror.ValidErrors err := c.ShouldBind(obj) if err != nil { - return mir.NewError(xerror.InvalidParams.Code(), xerror.InvalidParams.WithDetails(errs.Error())) + return mir.NewError(xerror.InvalidParams.StatusCode(), xerror.InvalidParams.WithDetails(errs.Error())) } // setup *core.User if needed if setter, ok := obj.(UserSetter); ok { @@ -65,7 +71,7 @@ func RenderAny(c *gin.Context, data any, err mir.Error) { Data: data, }) } else { - c.JSON(http.StatusInternalServerError, &JsonResp{ + c.JSON(xerror.HttpStatusCode(err), &JsonResp{ Code: err.StatusCode(), Msg: err.Error(), }) diff --git a/internal/servants/web/admin.go b/internal/servants/web/admin.go index d00f63c9..6a6dc2ec 100644 --- a/internal/servants/web/admin.go +++ b/internal/servants/web/admin.go @@ -5,10 +5,13 @@ package web import ( + "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" + "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/rocboss/paopao-ce/pkg/xerror" ) var ( @@ -18,17 +21,15 @@ var ( ) type adminSrv struct { - base.BaseServant api.UnimplementedAdminServant + *base.DaoServant } type adminBinding struct { - base.BaseBinding *api.UnimplementedAdminBinding } type adminRender struct { - base.BaseRender *api.UnimplementedAdminRender } @@ -36,8 +37,23 @@ func (s *adminSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT(), chain.Admin()} } -func newAdminSrv() api.Admin { - return &adminSrv{} +func (s *adminSrv) ChangeUserStatus(req *web.ChangeUserStatusReq) mir.Error { + user, err := s.Ds.GetUserByID(req.ID) + if err != nil || user.Model == nil || user.ID <= 0 { + return _errNoExistUsername + } + // 执行更新 + user.Status = req.Status + if err := s.Ds.UpdateUser(user); err != nil { + return xerror.ServerError + } + return nil +} + +func newAdminSrv(s *base.DaoServant) api.Admin { + return &adminSrv{ + DaoServant: s, + } } func newAdminBinding() api.AdminBinding { diff --git a/internal/servants/web/alipay.go b/internal/servants/web/alipay.go index a6bc97f6..36fc6f60 100644 --- a/internal/servants/web/alipay.go +++ b/internal/servants/web/alipay.go @@ -5,10 +5,17 @@ package web import ( + "time" + + "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" + "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/rocboss/paopao-ce/pkg/convert" + "github.com/sirupsen/logrus" + "github.com/smartwalle/alipay/v3" ) var ( @@ -21,48 +28,88 @@ var ( ) type alipayPubSrv struct { - base.BaseServant api.UnimplementedAlipayPubServant + *base.DaoServant } type alipayPubBinding struct { - base.BaseBinding *api.UnimplementedAlipayPubBinding + + alipayClient *alipay.Client } type alipayPubRender struct { - base.BaseRender *api.UnimplementedAlipayPubRender } type alipayPrivSrv struct { - base.BaseServant api.UnimplementedAlipayPrivServant } type alipayPrivBinding struct { - base.BaseBinding *api.UnimplementedAlipayPrivBinding } type alipayPrivRender struct { - base.BaseRender *api.UnimplementedAlipayPrivRender } +func (b *alipayPubBinding) BindAlipayNotify(c *gin.Context) (*web.AlipayNotifyReq, mir.Error) { + if err := c.Request.ParseForm(); err != nil { + logrus.Errorf("parse form err: %s", err) + return nil, _errRechargeNotifyError + } + noti, err := b.alipayClient.GetTradeNotification(c.Request) + if err != nil { + logrus.Errorf("alipayClient.GetTradeNotification err: %s form: %v", err, c.Request.Form) + return nil, _errRechargeNotifyError + } + return &web.AlipayNotifyReq{ + Ctx: c.Request.Context(), + ID: convert.StrTo(noti.OutTradeNo).MustInt64(), + TradeNo: noti.TradeNo, + TradeStatus: noti.TradeStatus, + }, nil +} + +func (s *alipayPubSrv) AlipayNotify(req *web.AlipayNotifyReq) mir.Error { + if req.TradeStatus == alipay.TradeStatusSuccess { + if ok, _ := s.Redis.SetNX(req.Ctx, "PaoPaoRecharge:"+req.TradeNo, 1, time.Second*5).Result(); ok { + recharge, err := s.Ds.GetRechargeByID(req.ID) + if err != nil { + logrus.Errorf("GetRechargeByID id:%d err: %s", req.ID, err) + return _errRechargeNotifyError + } + if recharge.TradeStatus != "TRADE_SUCCESS" { + // 标记为已付款 + err := s.Ds.HandleRechargeSuccess(recharge, req.TradeNo) + defer s.Redis.Del(req.Ctx, "PaoPaoRecharge:"+req.TradeNo) + if err != nil { + logrus.Errorf("HandleRechargeSuccess id:%d err: %s", req.ID, err) + return _errRechargeNotifyError + } + } + } + } + return nil +} + func (s *alipayPrivSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func newAlipayPubSrv() api.AlipayPub { - return &alipayPubSrv{} +func newAlipayPubSrv(s *base.DaoServant) api.AlipayPub { + return &alipayPubSrv{ + DaoServant: s, + } } -func newAlipayPubBinding() api.AlipayPubBinding { +func newAlipayPubBinding(alipayClient *alipay.Client) api.AlipayPubBinding { return &alipayPubBinding{ UnimplementedAlipayPubBinding: &api.UnimplementedAlipayPubBinding{ BindAny: base.BindAny, }, + alipayClient: alipayClient, } } diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 30bbe7e5..f4eef6e9 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -7,6 +7,7 @@ package web import ( "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/servants/base" "github.com/rocboss/paopao-ce/internal/servants/chain" ) @@ -18,17 +19,18 @@ var ( ) type coreSrv struct { - base.BaseServant api.UnimplementedCoreServant + *base.DaoServant + + ts core.TweetSearchService + oss core.ObjectStorageService } type coreBinding struct { - base.BaseBinding *api.UnimplementedCoreBinding } type coreRender struct { - base.BaseRender *api.UnimplementedCoreRender } @@ -36,8 +38,12 @@ func (s *coreSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func newCoreSrv() api.Core { - return &coreSrv{} +func newCoreSrv(s *base.DaoServant, ts core.TweetSearchService, oss core.ObjectStorageService) api.Core { + return &coreSrv{ + DaoServant: s, + ts: ts, + oss: oss, + } } func newCoreBinding() api.CoreBinding { diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index b735f5a7..22fc71a7 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -8,19 +8,32 @@ import ( "github.com/alimy/cfg" "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/dao" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/sirupsen/logrus" + "github.com/smartwalle/alipay/v3" ) // RouteWeb register web route func RouteWeb(e *gin.Engine) { - api.RegisterAdminServant(e, newAdminSrv(), newAdminBinding(), newAdminRender()) - api.RegisterCoreServant(e, newCoreSrv(), newCoreBinding(), newCoreRender()) + ts := dao.TweetSearchService() + oss := dao.ObjectStorageService() + ds := &base.DaoServant{ + Redis: conf.Redis, + Ds: dao.DataService(), + } + // aways register servants + api.RegisterAdminServant(e, newAdminSrv(ds), newAdminBinding(), newAdminRender()) + api.RegisterCoreServant(e, newCoreSrv(ds, ts, oss), newCoreBinding(), newCoreRender()) api.RegisterLooseServant(e, newLooseSrv(), newLooseBinding(), newLooseRender()) api.RegisterPrivServant(e, newPrivSrv(), newPrivBinding(), newPrivRender()) api.RegisterPubServant(e, newPubSrv(), newPubBinding(), newPubRender()) - + // regster servants if needed by configure cfg.In(cfg.Actions{ "Alipay": func() { - api.RegisterAlipayPubServant(e, newAlipayPubSrv(), newAlipayPubBinding(), newAlipayPubRender()) + client := mustAlipayClient() + api.RegisterAlipayPubServant(e, newAlipayPubSrv(ds), newAlipayPubBinding(client), newAlipayPubRender()) api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(), newAlipayPrivBinding(), newAlipayPrivRender()) }, "Followship": func() { @@ -31,3 +44,25 @@ func RouteWeb(e *gin.Engine) { }, }) } + +func mustAlipayClient() *alipay.Client { + s := conf.AlipaySetting + // 将 key 的验证调整到初始化阶段 + client, err := alipay.New(s.AppID, s.PrivateKey, s.InProduction) + if err != nil { + logrus.Fatalf("alipay.New err: %s", err) + } + // 加载应用公钥证书 + if err = client.LoadAppPublicCertFromFile(s.AppPublicCertFile); err != nil { + logrus.Fatalf("client.LoadAppPublicCertFromFile err: %s\n", err) + } + // 加载支付宝根证书 + if err = client.LoadAliPayRootCertFromFile(s.RootCertFile); err != nil { + logrus.Fatalf("client.LoadAliPayRootCertFromFile err: %s\n", err) + } + // 加载支付宝公钥证书 + if err = client.LoadAliPayPublicCertFromFile(s.PublicCertFile); err != nil { + logrus.Fatalf("client.LoadAliPayPublicCertFromFile err: %s\n", err) + } + return client +} diff --git a/pkg/xerror/xerror.go b/pkg/xerror/xerror.go index f614d18e..0fc7878c 100644 --- a/pkg/xerror/xerror.go +++ b/pkg/xerror/xerror.go @@ -8,9 +8,13 @@ import ( "fmt" "net/http" "strings" + + "github.com/alimy/mir/v3" ) var ( + _ mir.Error = (*Error)(nil) + codes = map[int]string{} ) @@ -51,10 +55,10 @@ func NewError(code int, msg string) *Error { } func (e *Error) Error() string { - return fmt.Sprintf("错误码: %d, 错误信息: %s", e.Code(), e.Msg()) + return fmt.Sprintf("错误码: %d, 错误信息: %s", e.StatusCode(), e.Msg()) } -func (e *Error) Code() int { +func (e *Error) StatusCode() int { return e.code } @@ -78,27 +82,26 @@ func (e *Error) WithDetails(details ...string) *Error { return &newError } -func (e *Error) StatusCode() int { - switch e.Code() { - case Success.Code(): +func HttpStatusCode(e mir.Error) int { + switch e.StatusCode() { + case Success.StatusCode(): return http.StatusOK - case ServerError.Code(): + case ServerError.StatusCode(): return http.StatusInternalServerError - case InvalidParams.Code(): + case InvalidParams.StatusCode(): return http.StatusBadRequest - case UnauthorizedAuthNotExist.Code(): + case UnauthorizedAuthNotExist.StatusCode(): fallthrough - case UnauthorizedAuthFailed.Code(): + case UnauthorizedAuthFailed.StatusCode(): fallthrough - case UnauthorizedTokenError.Code(): + case UnauthorizedTokenError.StatusCode(): fallthrough - case UnauthorizedTokenGenerate.Code(): + case UnauthorizedTokenGenerate.StatusCode(): fallthrough - case UnauthorizedTokenTimeout.Code(): + case UnauthorizedTokenTimeout.StatusCode(): return http.StatusUnauthorized - case TooManyRequests.Code(): + case TooManyRequests.StatusCode(): return http.StatusTooManyRequests } - return http.StatusInternalServerError } From dee07b6184788430ba975d4427048eed744afdb6 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Wed, 28 Dec 2022 00:03:06 +0800 Subject: [PATCH 54/65] mir: add alipay api implement for new web service --- auto/api/v1/alipay_priv.go | 63 ++++++++++++++------ auto/api/v1/core.go | 1 - go.mod | 2 +- go.sum | 4 +- internal/model/web/alipay.go | 28 ++++++++- internal/servants/base/base.go | 13 ++++- internal/servants/base/page.go | 27 +++++++++ internal/servants/web/alipay.go | 100 +++++++++++++++++++++++++++++++- internal/servants/web/web.go | 2 +- internal/servants/web/xerror.go | 7 ++- mirc/web/v1/alipay.go | 6 +- 11 files changed, 218 insertions(+), 35 deletions(-) create mode 100644 internal/servants/base/page.go diff --git a/auto/api/v1/alipay_priv.go b/auto/api/v1/alipay_priv.go index 2c95604c..152465a0 100644 --- a/auto/api/v1/alipay_priv.go +++ b/auto/api/v1/alipay_priv.go @@ -8,29 +8,32 @@ import ( "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/model/web" + "github.com/rocboss/paopao-ce/internal/servants/base" ) type AlipayPriv interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - UserWalletBills(*web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) - UserRechargeResult() mir.Error - UserRechargeLink() mir.Error + UserWalletBills(*web.UserWalletBillsReq) (*base.PageResp, mir.Error) + UserRechargeResult(*web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error) + UserRechargeLink(*web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error) mustEmbedUnimplementedAlipayPrivServant() } type AlipayPrivBinding interface { BindUserWalletBills(*gin.Context) (*web.UserWalletBillsReq, mir.Error) + BindUserRechargeResult(*gin.Context) (*web.UserRechargeResultReq, mir.Error) + BindUserRechargeLink(*gin.Context) (*web.UserRechargeLinkReq, mir.Error) mustEmbedUnimplementedAlipayPrivBinding() } type AlipayPrivRender interface { - RenderUserWalletBills(*gin.Context, *web.UserWalletBillsResp, mir.Error) - RenderUserRechargeResult(*gin.Context, mir.Error) - RenderUserRechargeLink(*gin.Context, mir.Error) + RenderUserWalletBills(*gin.Context, *base.PageResp, mir.Error) + RenderUserRechargeResult(*gin.Context, *web.UserRechargeResultResp, mir.Error) + RenderUserRechargeLink(*gin.Context, *web.UserRechargeLinkResp, mir.Error) mustEmbedUnimplementedAlipayPrivRender() } @@ -66,7 +69,13 @@ func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv, b AlipayPrivBinding, default: } - r.RenderUserRechargeResult(c, s.UserRechargeResult()) + req, err := b.BindUserRechargeResult(c) + if err != nil { + r.RenderUserRechargeResult(c, nil, err) + return + } + resp, err := s.UserRechargeResult(req) + r.RenderUserRechargeResult(c, resp, err) }) router.Handle("POST", "/user/recharge", func(c *gin.Context) { @@ -76,7 +85,13 @@ func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv, b AlipayPrivBinding, default: } - r.RenderUserRechargeLink(c, s.UserRechargeLink()) + req, err := b.BindUserRechargeLink(c) + if err != nil { + r.RenderUserRechargeLink(c, nil, err) + return + } + resp, err := s.UserRechargeLink(req) + r.RenderUserRechargeLink(c, resp, err) }) } @@ -89,16 +104,16 @@ func (UnimplementedAlipayPrivServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { +func (UnimplementedAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*base.PageResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedAlipayPrivServant) UserRechargeResult() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedAlipayPrivServant) UserRechargeResult(req *web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedAlipayPrivServant) UserRechargeLink() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedAlipayPrivServant) UserRechargeLink(req *web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedAlipayPrivServant) mustEmbedUnimplementedAlipayPrivServant() {} @@ -108,16 +123,16 @@ type UnimplementedAlipayPrivRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *web.UserWalletBillsResp, err mir.Error) { +func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *base.PageResp, err mir.Error) { r.RenderAny(c, data, err) } -func (r *UnimplementedAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, data *web.UserRechargeResultResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, data *web.UserRechargeLinkResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedAlipayPrivRender) mustEmbedUnimplementedAlipayPrivRender() {} @@ -133,4 +148,16 @@ func (b *UnimplementedAlipayPrivBinding) BindUserWalletBills(c *gin.Context) (*w return obj, err } +func (b *UnimplementedAlipayPrivBinding) BindUserRechargeResult(c *gin.Context) (*web.UserRechargeResultReq, mir.Error) { + obj := new(web.UserRechargeResultReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedAlipayPrivBinding) BindUserRechargeLink(c *gin.Context) (*web.UserRechargeLinkReq, mir.Error) { + obj := new(web.UserRechargeLinkReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedAlipayPrivBinding) mustEmbedUnimplementedAlipayPrivBinding() {} diff --git a/auto/api/v1/core.go b/auto/api/v1/core.go index 50b9576a..bffc2879 100644 --- a/auto/api/v1/core.go +++ b/auto/api/v1/core.go @@ -36,7 +36,6 @@ type Core interface { type CoreBinding interface { BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error) - BindGetUserInfo(*gin.Context) (*web.UserInfoReq, mir.Error) mustEmbedUnimplementedCoreBinding() diff --git a/go.mod b/go.mod index 2377b980..23b5d680 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/cfg v0.3.0 - github.com/alimy/mir/v3 v3.0.0-beta.2 + github.com/alimy/mir/v3 v3.0.0-beta.3 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index 69ac6d38..588a3b56 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= -github.com/alimy/mir/v3 v3.0.0-beta.2 h1:qpg0l4FEUafkpzGXlBIJtJbFjQfzbK9lDP5FJjjgOrA= -github.com/alimy/mir/v3 v3.0.0-beta.2/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= +github.com/alimy/mir/v3 v3.0.0-beta.3 h1:b+2C9rvZg2ssZ0+gMUf9aYwhuJFKExO611ybXRP+/30= +github.com/alimy/mir/v3 v3.0.0-beta.3/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/model/web/alipay.go b/internal/model/web/alipay.go index 2063e88c..b431f8d2 100644 --- a/internal/model/web/alipay.go +++ b/internal/model/web/alipay.go @@ -7,15 +7,37 @@ package web import ( "context" + "github.com/rocboss/paopao-ce/internal/servants/base" "github.com/smartwalle/alipay/v3" ) type UserWalletBillsReq struct { - *BaseInfo `json:"-" binding:"-"` + UserId int64 + Page int + PageSize int } -type UserWalletBillsResp struct { - // TODO +type UserWalletBillsResp = base.PageResp + +type UserRechargeLinkReq struct { + *BaseInfo `json:"-" form:"-" binding:"-"` + Host string `json:"-" form:"-" binding:"-"` + Amount int64 `json:"amount" form:"amount" binding:"required"` +} + +type UserRechargeLinkResp struct { + Id int64 `json:"id"` + Pay string `json:"pay"` +} + +type UserRechargeResultReq struct { + UserId int64 + Id int64 +} + +type UserRechargeResultResp struct { + Id int64 `json:"id"` + Status string `json:"status"` } type AlipayNotifyReq struct { diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index 301753f6..b6f244f1 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -49,6 +49,14 @@ func UserFrom(c *gin.Context) (*core.User, bool) { return nil, false } +func UserIdFrom(c *gin.Context) (int64, bool) { + if u, exists := c.Get("UID"); exists { + uid, ok := u.(int64) + return uid, ok + } + return -1, false +} + func BindAny(c *gin.Context, obj any) mir.Error { var errs xerror.ValidErrors err := c.ShouldBind(obj) @@ -57,7 +65,10 @@ func BindAny(c *gin.Context, obj any) mir.Error { } // setup *core.User if needed if setter, ok := obj.(UserSetter); ok { - user, _ := UserFrom(c) + user, exist := UserFrom(c) + if !exist { + return xerror.UnauthorizedTokenError + } setter.SetUser(user) } return nil diff --git a/internal/servants/base/page.go b/internal/servants/base/page.go new file mode 100644 index 00000000..6e3b4d05 --- /dev/null +++ b/internal/servants/base/page.go @@ -0,0 +1,27 @@ +// 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 base + +type Pager struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + TotalRows int64 `json:"total_rows"` +} + +type PageResp struct { + List any `json:"list"` + Pager Pager `json:"pager"` +} + +func PageRespFrom(list any, page int, pageSize int, totalRows int64) *PageResp { + return &PageResp{ + List: list, + Pager: Pager{ + Page: page, + PageSize: pageSize, + TotalRows: totalRows, + }, + } +} diff --git a/internal/servants/web/alipay.go b/internal/servants/web/alipay.go index 36fc6f60..ccbf00bc 100644 --- a/internal/servants/web/alipay.go +++ b/internal/servants/web/alipay.go @@ -5,6 +5,7 @@ package web import ( + "fmt" "time" "github.com/alimy/mir/v3" @@ -13,7 +14,9 @@ import ( "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/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/convert" + "github.com/rocboss/paopao-ce/pkg/xerror" "github.com/sirupsen/logrus" "github.com/smartwalle/alipay/v3" ) @@ -44,6 +47,9 @@ type alipayPubRender struct { type alipayPrivSrv struct { api.UnimplementedAlipayPrivServant + *base.DaoServant + + alipayClient *alipay.Client } type alipayPrivBinding struct { @@ -94,10 +100,97 @@ func (s *alipayPubSrv) AlipayNotify(req *web.AlipayNotifyReq) mir.Error { return nil } +func (b *alipayPrivBinding) BindUserWalletBills(c *gin.Context) (*web.UserWalletBillsReq, mir.Error) { + uid, ok := base.UserIdFrom(c) + if !ok { + return nil, xerror.UnauthorizedTokenError + } + page, pageSize := app.GetPageOffset(c) + return &web.UserWalletBillsReq{ + UserId: uid, + Page: page, + PageSize: pageSize, + }, nil +} + +func (b *alipayPrivBinding) BindUserRechargeLink(c *gin.Context) (*web.UserRechargeLinkReq, mir.Error) { + v := &web.UserRechargeLinkReq{ + Host: c.Request.Host, + } + err := b.BindAny(c, v) + return v, err +} + +func (b *alipayPrivBinding) BindUserRechargeResult(c *gin.Context) (*web.UserRechargeResultReq, mir.Error) { + uid, exist := base.UserIdFrom(c) + if !exist { + return nil, xerror.UnauthorizedTokenError + } + return &web.UserRechargeResultReq{ + UserId: uid, + Id: convert.StrTo(c.Query("id")).MustInt64(), + }, nil +} + func (s *alipayPrivSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } +func (s *alipayPrivSrv) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { + bills, err := s.Ds.GetUserWalletBills(req.UserId, (req.Page-1)*req.PageSize, req.PageSize) + if err != nil { + logrus.Errorf("GetUserWalletBills err: %s", err) + return nil, _errUserWalletBillsFailed + } + totalRows, err := s.Ds.GetUserWalletBillCount(req.UserId) + if err != nil { + logrus.Errorf("GetUserWalletBillCount err: %s", err) + return nil, _errUserWalletBillsFailed + } + return base.PageRespFrom(bills, req.Page, req.PageSize, totalRows), nil +} + +func (s *alipayPrivSrv) UserRechargeLink(req *web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error) { + recharge, err := s.Ds.CreateRecharge(req.User.ID, req.Amount) + if err != nil { + logrus.Errorf("Ds.CreateRecharge err: %v", err) + return nil, _errRechargeReqFail + } + p := alipay.TradePreCreate{} + p.OutTradeNo = fmt.Sprintf("%d", recharge.ID) + p.Subject = "PaoPao用户钱包充值" + p.TotalAmount = fmt.Sprintf("%.2f", float64(recharge.Amount)/100.0) + p.NotifyURL = "https://" + req.Host + "/v1/alipay/notify" + rsp, err := s.alipayClient.TradePreCreate(p) + if err != nil { + logrus.Errorf("client.TradePreCreate err: %v\n", err) + return nil, _errRechargeReqFail + } + if rsp.Content.Code != alipay.CodeSuccess { + return nil, _errRechargeReqFail + } + return &web.UserRechargeLinkResp{ + Id: recharge.ID, + Pay: rsp.Content.QRCode, + }, nil +} + +func (s *alipayPrivSrv) UserRechargeResult(req *web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error) { + recharge, err := s.Ds.GetRechargeByID(req.Id) + if err != nil { + logrus.Errorf("Ds.GetRechargeByID err: %v", err) + return nil, _errGetRechargeFailed + } + if recharge.UserID != req.UserId { + logrus.Errorf("Ds.GetRechargeByID userId not equel recharge.UserID: %d req.UserId %d", recharge.UserID, req.UserId) + return nil, _errGetRechargeFailed + } + return &web.UserRechargeResultResp{ + Id: recharge.ID, + Status: recharge.TradeStatus, + }, nil +} + func newAlipayPubSrv(s *base.DaoServant) api.AlipayPub { return &alipayPubSrv{ DaoServant: s, @@ -121,8 +214,11 @@ func newAlipayPubRender() api.AlipayPubRender { } } -func newAlipayPrivSrv() api.AlipayPriv { - return &alipayPrivSrv{} +func newAlipayPrivSrv(s *base.DaoServant, client *alipay.Client) api.AlipayPriv { + return &alipayPrivSrv{ + DaoServant: s, + alipayClient: client, + } } func newAlipayPrivBinding() api.AlipayPrivBinding { diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index 22fc71a7..f9f3127b 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -34,7 +34,7 @@ func RouteWeb(e *gin.Engine) { "Alipay": func() { client := mustAlipayClient() api.RegisterAlipayPubServant(e, newAlipayPubSrv(ds), newAlipayPubBinding(client), newAlipayPubRender()) - api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(), newAlipayPrivBinding(), newAlipayPrivRender()) + api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(ds, client), newAlipayPrivBinding(), newAlipayPrivRender()) }, "Followship": func() { api.RegisterFollowshipServant(e, newFollowshipSrv(), newFollowshipBinding(), newFollowshipRender()) diff --git a/internal/servants/web/xerror.go b/internal/servants/web/xerror.go index bda13caf..544053b2 100644 --- a/internal/servants/web/xerror.go +++ b/internal/servants/web/xerror.go @@ -63,9 +63,10 @@ var ( _errGetCollectionsFailed = xerror.NewError(60001, "获取收藏列表失败") _errGetStarsFailed = xerror.NewError(60002, "获取点赞列表失败") - _errRechargeReqFail = xerror.NewError(70001, "充值请求失败") - _errRechargeNotifyError = xerror.NewError(70002, "充值回调失败") - _errGetRechargeFailed = xerror.NewError(70003, "充值详情获取失败") + _errRechargeReqFail = xerror.NewError(70001, "充值请求失败") + _errRechargeNotifyError = xerror.NewError(70002, "充值回调失败") + _errGetRechargeFailed = xerror.NewError(70003, "充值详情获取失败") + _errUserWalletBillsFailed = xerror.NewError(70004, "用户钱包账单获取失败") _errNoRequestingFriendToSelf = xerror.NewError(80001, "不允许添加自己为好友") _errNotExistFriendId = xerror.NewError(80002, "好友id不存在") diff --git a/mirc/web/v1/alipay.go b/mirc/web/v1/alipay.go index c4a34111..86ab6936 100644 --- a/mirc/web/v1/alipay.go +++ b/mirc/web/v1/alipay.go @@ -24,10 +24,10 @@ type AlipayPriv struct { Group Group `mir:"v1"` // UserRechargeLink 用户充值 - UserRechargeLink func(Post) `mir:"/user/recharge"` + UserRechargeLink func(Post, web.UserRechargeLinkReq) web.UserRechargeLinkResp `mir:"/user/recharge"` - // UserRechargeResult 获取钱包余额 - UserRechargeResult func(Get) `mir:"/user/recharge"` + // UserRechargeResult 获取充值结果 + UserRechargeResult func(Get, web.UserRechargeResultReq) web.UserRechargeResultResp `mir:"/user/recharge"` // UserWalletBills 获取用户账单 UserWalletBills func(Get, web.UserWalletBillsReq) web.UserWalletBillsResp `mir:"/user/wallet/bills"` From 2d2c245ca1725e5abd44af7c661b35e76a55897b Mon Sep 17 00:00:00 2001 From: Michael Li Date: Wed, 28 Dec 2022 12:10:57 +0800 Subject: [PATCH 55/65] mir: partial api implement for new web service --- auto/api/v1/core.go | 91 ++++++++++++---- go.mod | 2 +- go.sum | 4 +- internal/model/web/core.go | 48 +++++++- internal/model/web/web.go | 8 ++ internal/servants/base/base.go | 54 +++++++-- internal/servants/web/alipay.go | 2 +- internal/servants/web/core.go | 187 ++++++++++++++++++++++++++++++++ mirc/web/v1/core.go | 8 +- 9 files changed, 366 insertions(+), 38 deletions(-) diff --git a/auto/api/v1/core.go b/auto/api/v1/core.go index bffc2879..b49f480b 100644 --- a/auto/api/v1/core.go +++ b/auto/api/v1/core.go @@ -8,6 +8,7 @@ import ( "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/model/web" + "github.com/rocboss/paopao-ce/internal/servants/base" ) type Core interface { @@ -25,18 +26,22 @@ type Core interface { GetStars() mir.Error GetCollections() mir.Error SendUserWhisper() mir.Error - ReadMessage() mir.Error - GetMessages() mir.Error - GetUnreadMsgCount() mir.Error + ReadMessage(*web.ReadMessageReq) mir.Error + GetMessages(*web.GetMessagesReq) (*base.PageResp, mir.Error) + GetUnreadMsgCount(*web.GetUnreadMsgCountReq) (*web.GetUnreadMsgCountResp, mir.Error) GetUserInfo(*web.UserInfoReq) (*web.UserInfoResp, mir.Error) - SyncSearchIndex() mir.Error + SyncSearchIndex(*web.SyncSearchIndexReq) mir.Error mustEmbedUnimplementedCoreServant() } type CoreBinding interface { BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error) + BindReadMessage(*gin.Context) (*web.ReadMessageReq, mir.Error) + BindGetMessages(*gin.Context) (*web.GetMessagesReq, mir.Error) + BindGetUnreadMsgCount(*gin.Context) (*web.GetUnreadMsgCountReq, mir.Error) BindGetUserInfo(*gin.Context) (*web.UserInfoReq, mir.Error) + BindSyncSearchIndex(*gin.Context) (*web.SyncSearchIndexReq, mir.Error) mustEmbedUnimplementedCoreBinding() } @@ -54,8 +59,8 @@ type CoreRender interface { RenderGetCollections(*gin.Context, mir.Error) RenderSendUserWhisper(*gin.Context, mir.Error) RenderReadMessage(*gin.Context, mir.Error) - RenderGetMessages(*gin.Context, mir.Error) - RenderGetUnreadMsgCount(*gin.Context, mir.Error) + RenderGetMessages(*gin.Context, *base.PageResp, mir.Error) + RenderGetUnreadMsgCount(*gin.Context, *web.GetUnreadMsgCountResp, mir.Error) RenderGetUserInfo(*gin.Context, *web.UserInfoResp, mir.Error) RenderSyncSearchIndex(*gin.Context, mir.Error) @@ -192,7 +197,12 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderReadMessage(c, s.ReadMessage()) + req, err := b.BindReadMessage(c) + if err != nil { + r.RenderReadMessage(c, err) + return + } + r.RenderReadMessage(c, s.ReadMessage(req)) }) router.Handle("GET", "/user/messages", func(c *gin.Context) { @@ -202,7 +212,13 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderGetMessages(c, s.GetMessages()) + req, err := b.BindGetMessages(c) + if err != nil { + r.RenderGetMessages(c, nil, err) + return + } + resp, err := s.GetMessages(req) + r.RenderGetMessages(c, resp, err) }) router.Handle("GET", "/user/msgcount/unread", func(c *gin.Context) { @@ -212,7 +228,13 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderGetUnreadMsgCount(c, s.GetUnreadMsgCount()) + req, err := b.BindGetUnreadMsgCount(c) + if err != nil { + r.RenderGetUnreadMsgCount(c, nil, err) + return + } + resp, err := s.GetUnreadMsgCount(req) + r.RenderGetUnreadMsgCount(c, resp, err) }) router.Handle("GET", "/user/info", func(c *gin.Context) { @@ -238,7 +260,12 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderSyncSearchIndex(c, s.SyncSearchIndex()) + req, err := b.BindSyncSearchIndex(c) + if err != nil { + r.RenderSyncSearchIndex(c, err) + return + } + r.RenderSyncSearchIndex(c, s.SyncSearchIndex(req)) }) } @@ -295,23 +322,23 @@ func (UnimplementedCoreServant) SendUserWhisper() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) ReadMessage() mir.Error { +func (UnimplementedCoreServant) ReadMessage(req *web.ReadMessageReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) GetMessages() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedCoreServant) GetMessages(req *web.GetMessagesReq) (*base.PageResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) GetUnreadMsgCount() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedCoreServant) GetUnreadMsgCount(req *web.GetUnreadMsgCountReq) (*web.GetUnreadMsgCountResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedCoreServant) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) SyncSearchIndex() mir.Error { +func (UnimplementedCoreServant) SyncSearchIndex(req *web.SyncSearchIndexReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -370,12 +397,12 @@ func (r *UnimplementedCoreRender) RenderReadMessage(c *gin.Context, err mir.Erro r.RenderAny(c, nil, err) } -func (r *UnimplementedCoreRender) RenderGetMessages(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedCoreRender) RenderGetMessages(c *gin.Context, data *base.PageResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedCoreRender) RenderGetUnreadMsgCount(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedCoreRender) RenderGetUnreadMsgCount(c *gin.Context, data *web.GetUnreadMsgCountResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedCoreRender) RenderGetUserInfo(c *gin.Context, data *web.UserInfoResp, err mir.Error) { @@ -399,10 +426,34 @@ func (b *UnimplementedCoreBinding) BindChangeAvatar(c *gin.Context) (*web.Change return obj, err } +func (b *UnimplementedCoreBinding) BindReadMessage(c *gin.Context) (*web.ReadMessageReq, mir.Error) { + obj := new(web.ReadMessageReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindGetMessages(c *gin.Context) (*web.GetMessagesReq, mir.Error) { + obj := new(web.GetMessagesReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindGetUnreadMsgCount(c *gin.Context) (*web.GetUnreadMsgCountReq, mir.Error) { + obj := new(web.GetUnreadMsgCountReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedCoreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) { obj := new(web.UserInfoReq) err := b.BindAny(c, obj) return obj, err } +func (b *UnimplementedCoreBinding) BindSyncSearchIndex(c *gin.Context) (*web.SyncSearchIndexReq, mir.Error) { + obj := new(web.SyncSearchIndexReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedCoreBinding) mustEmbedUnimplementedCoreBinding() {} diff --git a/go.mod b/go.mod index 23b5d680..7bd04004 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/cfg v0.3.0 - github.com/alimy/mir/v3 v3.0.0-beta.3 + github.com/alimy/mir/v3 v3.0.0-beta.4 github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/allegro/bigcache/v3 v3.0.2 github.com/bytedance/sonic v1.5.0 diff --git a/go.sum b/go.sum index 588a3b56..bb2a4603 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY= github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= -github.com/alimy/mir/v3 v3.0.0-beta.3 h1:b+2C9rvZg2ssZ0+gMUf9aYwhuJFKExO611ybXRP+/30= -github.com/alimy/mir/v3 v3.0.0-beta.3/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= +github.com/alimy/mir/v3 v3.0.0-beta.4 h1:4++lea7OWmykHRVbF1nCnKOJXCvBifmnhe47e91aV6c= +github.com/alimy/mir/v3 v3.0.0-beta.4/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= diff --git a/internal/model/web/core.go b/internal/model/web/core.go index 12243a1e..3da85471 100644 --- a/internal/model/web/core.go +++ b/internal/model/web/core.go @@ -4,14 +4,56 @@ package web +import ( + "context" + + "github.com/rocboss/paopao-ce/internal/servants/base" +) + type ChangeAvatarReq struct { - *BaseInfo `json:"-"` + *BaseInfo `json:"-" binding:"-"` +} + +type SyncSearchIndexReq struct { + *BaseInfo `json:"-" binding:"-"` + + Ctx context.Context `json:"-" binding:"-"` } type UserInfoReq struct { - *BaseInfo `json:"-"` + *BaseInfo `json:"-" binding:"-"` + Username string `json:"username" form:"username" binding:"required"` } type UserInfoResp struct { - // TODO + Id int64 `json:"id"` + Nickname string `json:"nickname"` + Username string `json:"username"` + Status int `json:"status"` + Avatar string `json:"avatar"` + Balance int64 `json:"balance"` + Phone string `json:"phone"` + IsAdmin bool `json:"is_admin"` +} + +type GetUnreadMsgCountReq struct { + *SimpleInfo `json:"-" binding:"-"` +} + +type GetUnreadMsgCountResp struct { + Count int64 `json:"count"` +} + +type GetMessagesReq struct { + UserId int64 + Page int + PageSize int +} + +type GetMessagesResp = base.PageResp + +type ReadMessageReq struct { + *SimpleInfo `json:"-" binding:"-"` + + ID int64 `json:"id" binding:"required"` } diff --git a/internal/model/web/web.go b/internal/model/web/web.go index dd04971a..bcddea3a 100644 --- a/internal/model/web/web.go +++ b/internal/model/web/web.go @@ -12,6 +12,14 @@ type BaseInfo struct { User *core.User } +type SimpleInfo struct { + Uid int64 +} + func (b *BaseInfo) SetUser(user *core.User) { b.User = user } + +func (s *SimpleInfo) SetUserId(id int64) { + s.Uid = id +} diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index b6f244f1..abbe8944 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -41,6 +41,10 @@ type UserSetter interface { SetUser(*core.User) } +type UserIdSetter interface { + SetUserId(int64) +} + func UserFrom(c *gin.Context) (*core.User, bool) { if u, exists := c.Get("USER"); exists { user, ok := u.(*core.User) @@ -50,13 +54,21 @@ func UserFrom(c *gin.Context) (*core.User, bool) { } func UserIdFrom(c *gin.Context) (int64, bool) { - if u, exists := c.Get("UID"); exists { - uid, ok := u.(int64) - return uid, ok + if uid, exists := c.Get("UID"); exists { + v, ok := uid.(int64) + return v, ok } return -1, false } +func UserNameFrom(c *gin.Context) (string, bool) { + if username, exists := c.Get("USERNAME"); exists { + v, ok := username.(string) + return v, ok + } + return "", false +} + func BindAny(c *gin.Context, obj any) mir.Error { var errs xerror.ValidErrors err := c.ShouldBind(obj) @@ -65,12 +77,14 @@ func BindAny(c *gin.Context, obj any) mir.Error { } // setup *core.User if needed if setter, ok := obj.(UserSetter); ok { - user, exist := UserFrom(c) - if !exist { - return xerror.UnauthorizedTokenError - } + user, _ := UserFrom(c) setter.SetUser(user) } + // setup UserId if needed + if setter, ok := obj.(UserIdSetter); ok { + uid, _ := UserIdFrom(c) + setter.SetUserId(uid) + } return nil } @@ -88,3 +102,29 @@ func RenderAny(c *gin.Context, data any, err mir.Error) { }) } } + +func (s *DaoServant) GetTweetBy(id int64) (*core.PostFormated, error) { + post, err := s.Ds.GetPostByID(id) + if err != nil { + return nil, err + } + postContents, err := s.Ds.GetPostContentsByIDs([]int64{post.ID}) + if err != nil { + return nil, err + } + users, err := s.Ds.GetUsersByIDs([]int64{post.UserID}) + if err != nil { + return nil, err + } + // 数据整合 + postFormated := post.Format() + for _, user := range users { + postFormated.User = user.Format() + } + for _, content := range postContents { + if content.PostID == post.ID { + postFormated.Contents = append(postFormated.Contents, content.Format()) + } + } + return postFormated, nil +} diff --git a/internal/servants/web/alipay.go b/internal/servants/web/alipay.go index ccbf00bc..9420ffe4 100644 --- a/internal/servants/web/alipay.go +++ b/internal/servants/web/alipay.go @@ -136,7 +136,7 @@ func (s *alipayPrivSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func (s *alipayPrivSrv) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { +func (s *alipayPrivSrv) UserWalletBills(req *web.UserWalletBillsReq) (*base.PageResp, mir.Error) { bills, err := s.Ds.GetUserWalletBills(req.UserId, (req.Page-1)*req.PageSize, req.PageSize) if err != nil { logrus.Errorf("GetUserWalletBills err: %s", err) diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index f4eef6e9..102a7554 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -5,11 +5,21 @@ package web import ( + "context" + "fmt" + "math" + "time" + + "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" "github.com/rocboss/paopao-ce/internal/core" + "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/rocboss/paopao-ce/pkg/app" + "github.com/rocboss/paopao-ce/pkg/xerror" + "github.com/sirupsen/logrus" ) var ( @@ -34,10 +44,187 @@ type coreRender struct { *api.UnimplementedCoreRender } +func (b *coreBinding) BindSyncSearchIndex(c *gin.Context) (*web.SyncSearchIndexReq, mir.Error) { + user, _ := base.UserFrom(c) + return &web.SyncSearchIndexReq{ + BaseInfo: &web.BaseInfo{ + User: user, + }, + Ctx: c.Request.Context(), + }, nil +} + +func (b *coreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) { + username, exists := base.UserNameFrom(c) + if !exists { + return nil, xerror.UnauthorizedAuthNotExist + } + return &web.UserInfoReq{ + Username: username, + }, nil +} + +func (b *coreBinding) BindGetMessages(c *gin.Context) (*web.GetMessagesReq, mir.Error) { + uid, ok := base.UserIdFrom(c) + if !ok { + return nil, xerror.UnauthorizedTokenError + } + page, pageSize := app.GetPageOffset(c) + return &web.GetMessagesReq{ + UserId: uid, + Page: page, + PageSize: pageSize, + }, nil +} + func (s *coreSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } +func (s *coreSrv) SyncSearchIndex(req *web.SyncSearchIndexReq) mir.Error { + if req.User != nil && req.User.IsAdmin { + go s.pushPostsToSearch(req.Ctx) + } + return nil +} + +func (s *coreSrv) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Error) { + user, err := s.Ds.GetUserByUsername(req.Username) + if err != nil { + return nil, xerror.UnauthorizedAuthNotExist + } + if user.Model == nil || user.ID < 0 { + return nil, xerror.UnauthorizedAuthNotExist + } + resp := &web.UserInfoResp{ + Id: user.ID, + Nickname: user.Nickname, + Username: user.Username, + Status: user.Status, + Avatar: user.Avatar, + Balance: user.Balance, + IsAdmin: user.IsAdmin, + } + if user.Phone != "" && len(user.Phone) == 11 { + resp.Phone = user.Phone[0:3] + "****" + user.Phone[7:] + } + return resp, nil +} + +func (s *coreSrv) GetUnreadMsgCount(req *web.GetUnreadMsgCountReq) (*web.GetUnreadMsgCountResp, mir.Error) { + count, err := s.Ds.GetUnreadCount(req.Uid) + if err != nil { + return nil, xerror.ServerError + } + return &web.GetUnreadMsgCountResp{ + Count: count, + }, nil +} + +func (s *coreSrv) GetMessages(req *web.GetMessagesReq) (*base.PageResp, mir.Error) { + conditions := &core.ConditionsT{ + "receiver_user_id": req.UserId, + "ORDER": "id DESC", + } + messages, err := s.Ds.GetMessages(conditions, (req.Page-1)*req.PageSize, req.PageSize) + for _, mf := range messages { + if mf.SenderUserID > 0 { + user, err := s.Ds.GetUserByID(mf.SenderUserID) + if err == nil { + mf.SenderUser = user.Format() + } + } + // 好友申请消息不需要获取其他信息 + if mf.Type == core.MsgTypeRequestingFriend { + continue + } + if mf.PostID > 0 { + post, err := s.GetTweetBy(mf.PostID) + if err == nil { + mf.Post = post + if mf.CommentID > 0 { + comment, err := s.Ds.GetCommentByID(mf.CommentID) + if err == nil { + mf.Comment = comment + if mf.ReplyID > 0 { + reply, err := s.Ds.GetCommentReplyByID(mf.ReplyID) + if err == nil { + mf.Reply = reply + } + } + } + } + } + } + } + if err != nil { + logrus.Errorf("Ds.GetMessages err: %v\n", err) + return nil, _errGetMessagesFailed + } + totalRows, _ := s.Ds.GetMessageCount(conditions) + return base.PageRespFrom(messages, req.Page, req.PageSize, totalRows), nil +} + +func (s *coreSrv) ReadMessage(req *web.ReadMessageReq) mir.Error { + message, err := s.Ds.GetMessageByID(req.ID) + if err != nil { + return _errReadMessageFailed + } + if message.ReceiverUserID != req.Uid { + return _errNoPermission + } + if err = s.Ds.ReadMessage(message); err != nil { + logrus.Errorf("Ds.ReadMessage err: %s", err) + return _errReadMessageFailed + } + return nil +} + +func (s *coreSrv) pushPostsToSearch(c context.Context) { + if ok, _ := s.Redis.SetNX(c, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok { + defer s.Redis.Del(c, "JOB_PUSH_TO_SEARCH") + + splitNum := 1000 + totalRows, _ := s.Ds.GetPostCount(&core.ConditionsT{ + "visibility IN ?": []core.PostVisibleT{core.PostVisitPublic, core.PostVisitFriend}, + }) + pages := math.Ceil(float64(totalRows) / float64(splitNum)) + nums := int(pages) + for i := 0; i < nums; i++ { + posts, postsFormated, err := s.getTweetList(&core.ConditionsT{}, i*splitNum, splitNum) + if err != nil || len(posts) != len(postsFormated) { + continue + } + for i, pf := range postsFormated { + contentFormated := "" + for _, content := range pf.Contents { + if content.Type == core.ContentTypeText || content.Type == core.ContentTypeTitle { + contentFormated = contentFormated + content.Content + "\n" + } + } + docs := []core.TsDocItem{{ + Post: posts[i], + Content: contentFormated, + }} + s.ts.AddDocuments(docs, fmt.Sprintf("%d", posts[i].ID)) + } + } + } +} + +func (s *coreSrv) deleteSearchPost(post *core.Post) error { + return s.ts.DeleteDocuments([]string{fmt.Sprintf("%d", post.ID)}) +} + +func (s *coreSrv) getTweetList(conditions *core.ConditionsT, offset, limit int) ([]*core.Post, []*core.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 newCoreSrv(s *base.DaoServant, ts core.TweetSearchService, oss core.ObjectStorageService) api.Core { return &coreSrv{ DaoServant: s, diff --git a/mirc/web/v1/core.go b/mirc/web/v1/core.go index 1500e3db..529f15de 100644 --- a/mirc/web/v1/core.go +++ b/mirc/web/v1/core.go @@ -16,19 +16,19 @@ type Core struct { Group Group `mir:"v1"` // SyncSearchIndex 同步索引 - SyncSearchIndex func(Get) `mir:"/sync/index"` + SyncSearchIndex func(Get, web.SyncSearchIndexReq) `mir:"/sync/index"` // GetUserInfo 获取当前用户信息 GetUserInfo func(Get, web.UserInfoReq) web.UserInfoResp `mir:"/user/info"` // GetUnreadMsgCount 获取当前用户未读消息数量 - GetUnreadMsgCount func(Get) `mir:"/user/msgcount/unread"` + GetUnreadMsgCount func(Get, web.GetUnreadMsgCountReq) web.GetUnreadMsgCountResp `mir:"/user/msgcount/unread"` // GetMessages 获取消息列表 - GetMessages func(Get) `mir:"/user/messages"` + GetMessages func(Get, web.GetMessagesReq) web.GetMessagesResp `mir:"/user/messages"` // ReadMessage 标记消息已读 - ReadMessage func(Post) `mir:"/user/message/read"` + ReadMessage func(Post, web.ReadMessageReq) `mir:"/user/message/read"` // SendUserWhisper 发送用户私信 SendUserWhisper func(Post) `mir:"/user/whisper"` From 64527ec6b206cd8de3f3852c7b45a06ac5b53a4b Mon Sep 17 00:00:00 2001 From: Michael Li Date: Thu, 29 Dec 2022 12:09:46 +0800 Subject: [PATCH 56/65] mir:add core api implement for new web service --- auto/api/v1/alipay_priv.go | 9 +- auto/api/v1/core.go | 243 ++++++++++++++++++------ internal/model/web/admin.go | 6 +- internal/model/web/alipay.go | 8 +- internal/model/web/core.go | 87 +++++++-- internal/model/web/web.go | 24 +++ internal/servants/base/base.go | 9 +- internal/servants/web/alipay.go | 5 +- internal/servants/web/core.go | 317 ++++++++++++++++++++++++++++++-- internal/servants/web/utils.go | 47 +++++ mirc/web/v1/core.go | 20 +- 11 files changed, 656 insertions(+), 119 deletions(-) create mode 100644 internal/servants/web/utils.go diff --git a/auto/api/v1/alipay_priv.go b/auto/api/v1/alipay_priv.go index 152465a0..4cb3fe0a 100644 --- a/auto/api/v1/alipay_priv.go +++ b/auto/api/v1/alipay_priv.go @@ -8,14 +8,13 @@ import ( "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/model/web" - "github.com/rocboss/paopao-ce/internal/servants/base" ) type AlipayPriv interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - UserWalletBills(*web.UserWalletBillsReq) (*base.PageResp, mir.Error) + UserWalletBills(*web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) UserRechargeResult(*web.UserRechargeResultReq) (*web.UserRechargeResultResp, mir.Error) UserRechargeLink(*web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error) @@ -31,7 +30,7 @@ type AlipayPrivBinding interface { } type AlipayPrivRender interface { - RenderUserWalletBills(*gin.Context, *base.PageResp, mir.Error) + RenderUserWalletBills(*gin.Context, *web.UserWalletBillsResp, mir.Error) RenderUserRechargeResult(*gin.Context, *web.UserRechargeResultResp, mir.Error) RenderUserRechargeLink(*gin.Context, *web.UserRechargeLinkResp, mir.Error) @@ -104,7 +103,7 @@ func (UnimplementedAlipayPrivServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*base.PageResp, mir.Error) { +func (UnimplementedAlipayPrivServant) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -123,7 +122,7 @@ type UnimplementedAlipayPrivRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *base.PageResp, err mir.Error) { +func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *web.UserWalletBillsResp, err mir.Error) { r.RenderAny(c, data, err) } diff --git a/auto/api/v1/core.go b/auto/api/v1/core.go index b49f480b..8e633c53 100644 --- a/auto/api/v1/core.go +++ b/auto/api/v1/core.go @@ -8,26 +8,25 @@ import ( "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/model/web" - "github.com/rocboss/paopao-ce/internal/servants/base" ) type Core interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - TweetCollectionStatus() mir.Error - TweetStarStatus() mir.Error - SuggestTags() mir.Error - SuggestUsers() mir.Error + TweetCollectionStatus(*web.TweetCollectionStatusReq) (*web.TweetCollectionStatusResp, mir.Error) + TweetStarStatus(*web.TweetStarStatusReq) (*web.TweetStarStatusResp, mir.Error) + SuggestTags(*web.SuggestTagsReq) (*web.SuggestTagsResp, mir.Error) + SuggestUsers(*web.SuggestUsersReq) (*web.SuggestUsersResp, mir.Error) ChangeAvatar(*web.ChangeAvatarReq) mir.Error - ChangeNickname() mir.Error - ChangePassword() mir.Error - UserPhoneBind() mir.Error - GetStars() mir.Error - GetCollections() mir.Error - SendUserWhisper() mir.Error + ChangeNickname(*web.ChangeNicknameReq) mir.Error + ChangePassword(*web.ChangePasswordReq) mir.Error + UserPhoneBind(*web.UserPhoneBindReq) mir.Error + GetStars(*web.GetStarsReq) (*web.GetStarsResp, mir.Error) + GetCollections(*web.GetCollectionsReq) (*web.GetCollectionsResp, mir.Error) + SendUserWhisper(*web.SendWhisperReq) mir.Error ReadMessage(*web.ReadMessageReq) mir.Error - GetMessages(*web.GetMessagesReq) (*base.PageResp, mir.Error) + GetMessages(*web.GetMessagesReq) (*web.GetMessagesResp, mir.Error) GetUnreadMsgCount(*web.GetUnreadMsgCountReq) (*web.GetUnreadMsgCountResp, mir.Error) GetUserInfo(*web.UserInfoReq) (*web.UserInfoResp, mir.Error) SyncSearchIndex(*web.SyncSearchIndexReq) mir.Error @@ -36,7 +35,17 @@ type Core interface { } type CoreBinding interface { + BindTweetCollectionStatus(*gin.Context) (*web.TweetCollectionStatusReq, mir.Error) + BindTweetStarStatus(*gin.Context) (*web.TweetStarStatusReq, mir.Error) + BindSuggestTags(*gin.Context) (*web.SuggestTagsReq, mir.Error) + BindSuggestUsers(*gin.Context) (*web.SuggestUsersReq, mir.Error) BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error) + BindChangeNickname(*gin.Context) (*web.ChangeNicknameReq, mir.Error) + BindChangePassword(*gin.Context) (*web.ChangePasswordReq, mir.Error) + BindUserPhoneBind(*gin.Context) (*web.UserPhoneBindReq, mir.Error) + BindGetStars(*gin.Context) (*web.GetStarsReq, mir.Error) + BindGetCollections(*gin.Context) (*web.GetCollectionsReq, mir.Error) + BindSendUserWhisper(*gin.Context) (*web.SendWhisperReq, mir.Error) BindReadMessage(*gin.Context) (*web.ReadMessageReq, mir.Error) BindGetMessages(*gin.Context) (*web.GetMessagesReq, mir.Error) BindGetUnreadMsgCount(*gin.Context) (*web.GetUnreadMsgCountReq, mir.Error) @@ -47,19 +56,19 @@ type CoreBinding interface { } type CoreRender interface { - RenderTweetCollectionStatus(*gin.Context, mir.Error) - RenderTweetStarStatus(*gin.Context, mir.Error) - RenderSuggestTags(*gin.Context, mir.Error) - RenderSuggestUsers(*gin.Context, mir.Error) + RenderTweetCollectionStatus(*gin.Context, *web.TweetCollectionStatusResp, mir.Error) + RenderTweetStarStatus(*gin.Context, *web.TweetStarStatusResp, mir.Error) + RenderSuggestTags(*gin.Context, *web.SuggestTagsResp, mir.Error) + RenderSuggestUsers(*gin.Context, *web.SuggestUsersResp, mir.Error) RenderChangeAvatar(*gin.Context, mir.Error) RenderChangeNickname(*gin.Context, mir.Error) RenderChangePassword(*gin.Context, mir.Error) RenderUserPhoneBind(*gin.Context, mir.Error) - RenderGetStars(*gin.Context, mir.Error) - RenderGetCollections(*gin.Context, mir.Error) + RenderGetStars(*gin.Context, *web.GetStarsResp, mir.Error) + RenderGetCollections(*gin.Context, *web.GetCollectionsResp, mir.Error) RenderSendUserWhisper(*gin.Context, mir.Error) RenderReadMessage(*gin.Context, mir.Error) - RenderGetMessages(*gin.Context, *base.PageResp, mir.Error) + RenderGetMessages(*gin.Context, *web.GetMessagesResp, mir.Error) RenderGetUnreadMsgCount(*gin.Context, *web.GetUnreadMsgCountResp, mir.Error) RenderGetUserInfo(*gin.Context, *web.UserInfoResp, mir.Error) RenderSyncSearchIndex(*gin.Context, mir.Error) @@ -82,7 +91,13 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderTweetCollectionStatus(c, s.TweetCollectionStatus()) + req, err := b.BindTweetCollectionStatus(c) + if err != nil { + r.RenderTweetCollectionStatus(c, nil, err) + return + } + resp, err := s.TweetCollectionStatus(req) + r.RenderTweetCollectionStatus(c, resp, err) }) router.Handle("GET", "/post/star", func(c *gin.Context) { @@ -92,7 +107,13 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderTweetStarStatus(c, s.TweetStarStatus()) + req, err := b.BindTweetStarStatus(c) + if err != nil { + r.RenderTweetStarStatus(c, nil, err) + return + } + resp, err := s.TweetStarStatus(req) + r.RenderTweetStarStatus(c, resp, err) }) router.Handle("GET", "/suggest/tags", func(c *gin.Context) { @@ -102,7 +123,13 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderSuggestTags(c, s.SuggestTags()) + req, err := b.BindSuggestTags(c) + if err != nil { + r.RenderSuggestTags(c, nil, err) + return + } + resp, err := s.SuggestTags(req) + r.RenderSuggestTags(c, resp, err) }) router.Handle("GET", "/suggest/users", func(c *gin.Context) { @@ -112,7 +139,13 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderSuggestUsers(c, s.SuggestUsers()) + req, err := b.BindSuggestUsers(c) + if err != nil { + r.RenderSuggestUsers(c, nil, err) + return + } + resp, err := s.SuggestUsers(req) + r.RenderSuggestUsers(c, resp, err) }) router.Handle("POST", "/user/avatar", func(c *gin.Context) { @@ -137,7 +170,12 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderChangeNickname(c, s.ChangeNickname()) + req, err := b.BindChangeNickname(c) + if err != nil { + r.RenderChangeNickname(c, err) + return + } + r.RenderChangeNickname(c, s.ChangeNickname(req)) }) router.Handle("POST", "/user/password", func(c *gin.Context) { @@ -147,7 +185,12 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderChangePassword(c, s.ChangePassword()) + req, err := b.BindChangePassword(c) + if err != nil { + r.RenderChangePassword(c, err) + return + } + r.RenderChangePassword(c, s.ChangePassword(req)) }) router.Handle("POST", "/user/phone", func(c *gin.Context) { @@ -157,7 +200,12 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderUserPhoneBind(c, s.UserPhoneBind()) + req, err := b.BindUserPhoneBind(c) + if err != nil { + r.RenderUserPhoneBind(c, err) + return + } + r.RenderUserPhoneBind(c, s.UserPhoneBind(req)) }) router.Handle("GET", "/user/stars", func(c *gin.Context) { @@ -167,7 +215,13 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderGetStars(c, s.GetStars()) + req, err := b.BindGetStars(c) + if err != nil { + r.RenderGetStars(c, nil, err) + return + } + resp, err := s.GetStars(req) + r.RenderGetStars(c, resp, err) }) router.Handle("GET", "/user/collections", func(c *gin.Context) { @@ -177,7 +231,13 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderGetCollections(c, s.GetCollections()) + req, err := b.BindGetCollections(c) + if err != nil { + r.RenderGetCollections(c, nil, err) + return + } + resp, err := s.GetCollections(req) + r.RenderGetCollections(c, resp, err) }) router.Handle("POST", "/user/whisper", func(c *gin.Context) { @@ -187,7 +247,12 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) { default: } - r.RenderSendUserWhisper(c, s.SendUserWhisper()) + req, err := b.BindSendUserWhisper(c) + if err != nil { + r.RenderSendUserWhisper(c, err) + return + } + r.RenderSendUserWhisper(c, s.SendUserWhisper(req)) }) router.Handle("POST", "/user/message/read", func(c *gin.Context) { @@ -278,47 +343,47 @@ func (UnimplementedCoreServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedCoreServant) TweetCollectionStatus() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedCoreServant) TweetCollectionStatus(req *web.TweetCollectionStatusReq) (*web.TweetCollectionStatusResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) TweetStarStatus() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedCoreServant) TweetStarStatus(req *web.TweetStarStatusReq) (*web.TweetStarStatusResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) SuggestTags() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedCoreServant) SuggestTags(req *web.SuggestTagsReq) (*web.SuggestTagsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) SuggestUsers() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedCoreServant) SuggestUsers(req *web.SuggestUsersReq) (*web.SuggestUsersResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedCoreServant) ChangeAvatar(req *web.ChangeAvatarReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) ChangeNickname() mir.Error { +func (UnimplementedCoreServant) ChangeNickname(req *web.ChangeNicknameReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) ChangePassword() mir.Error { +func (UnimplementedCoreServant) ChangePassword(req *web.ChangePasswordReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) UserPhoneBind() mir.Error { +func (UnimplementedCoreServant) UserPhoneBind(req *web.UserPhoneBindReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) GetStars() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedCoreServant) GetStars(req *web.GetStarsReq) (*web.GetStarsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) GetCollections() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedCoreServant) GetCollections(req *web.GetCollectionsReq) (*web.GetCollectionsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) SendUserWhisper() mir.Error { +func (UnimplementedCoreServant) SendUserWhisper(req *web.SendWhisperReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -326,7 +391,7 @@ func (UnimplementedCoreServant) ReadMessage(req *web.ReadMessageReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedCoreServant) GetMessages(req *web.GetMessagesReq) (*base.PageResp, mir.Error) { +func (UnimplementedCoreServant) GetMessages(req *web.GetMessagesReq) (*web.GetMessagesResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -349,20 +414,20 @@ type UnimplementedCoreRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedCoreRender) RenderTweetCollectionStatus(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedCoreRender) RenderTweetCollectionStatus(c *gin.Context, data *web.TweetCollectionStatusResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedCoreRender) RenderTweetStarStatus(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedCoreRender) RenderTweetStarStatus(c *gin.Context, data *web.TweetStarStatusResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedCoreRender) RenderSuggestTags(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedCoreRender) RenderSuggestTags(c *gin.Context, data *web.SuggestTagsResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedCoreRender) RenderSuggestUsers(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedCoreRender) RenderSuggestUsers(c *gin.Context, data *web.SuggestUsersResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedCoreRender) RenderChangeAvatar(c *gin.Context, err mir.Error) { @@ -381,12 +446,12 @@ func (r *UnimplementedCoreRender) RenderUserPhoneBind(c *gin.Context, err mir.Er r.RenderAny(c, nil, err) } -func (r *UnimplementedCoreRender) RenderGetStars(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedCoreRender) RenderGetStars(c *gin.Context, data *web.GetStarsResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedCoreRender) RenderGetCollections(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedCoreRender) RenderGetCollections(c *gin.Context, data *web.GetCollectionsResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedCoreRender) RenderSendUserWhisper(c *gin.Context, err mir.Error) { @@ -397,7 +462,7 @@ func (r *UnimplementedCoreRender) RenderReadMessage(c *gin.Context, err mir.Erro r.RenderAny(c, nil, err) } -func (r *UnimplementedCoreRender) RenderGetMessages(c *gin.Context, data *base.PageResp, err mir.Error) { +func (r *UnimplementedCoreRender) RenderGetMessages(c *gin.Context, data *web.GetMessagesResp, err mir.Error) { r.RenderAny(c, data, err) } @@ -420,12 +485,72 @@ type UnimplementedCoreBinding struct { BindAny func(*gin.Context, any) mir.Error } +func (b *UnimplementedCoreBinding) BindTweetCollectionStatus(c *gin.Context) (*web.TweetCollectionStatusReq, mir.Error) { + obj := new(web.TweetCollectionStatusReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindTweetStarStatus(c *gin.Context) (*web.TweetStarStatusReq, mir.Error) { + obj := new(web.TweetStarStatusReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindSuggestTags(c *gin.Context) (*web.SuggestTagsReq, mir.Error) { + obj := new(web.SuggestTagsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindSuggestUsers(c *gin.Context) (*web.SuggestUsersReq, mir.Error) { + obj := new(web.SuggestUsersReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedCoreBinding) BindChangeAvatar(c *gin.Context) (*web.ChangeAvatarReq, mir.Error) { obj := new(web.ChangeAvatarReq) err := b.BindAny(c, obj) return obj, err } +func (b *UnimplementedCoreBinding) BindChangeNickname(c *gin.Context) (*web.ChangeNicknameReq, mir.Error) { + obj := new(web.ChangeNicknameReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindChangePassword(c *gin.Context) (*web.ChangePasswordReq, mir.Error) { + obj := new(web.ChangePasswordReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindUserPhoneBind(c *gin.Context) (*web.UserPhoneBindReq, mir.Error) { + obj := new(web.UserPhoneBindReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindGetStars(c *gin.Context) (*web.GetStarsReq, mir.Error) { + obj := new(web.GetStarsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindGetCollections(c *gin.Context) (*web.GetCollectionsReq, mir.Error) { + obj := new(web.GetCollectionsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedCoreBinding) BindSendUserWhisper(c *gin.Context) (*web.SendWhisperReq, mir.Error) { + obj := new(web.SendWhisperReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedCoreBinding) BindReadMessage(c *gin.Context) (*web.ReadMessageReq, mir.Error) { obj := new(web.ReadMessageReq) err := b.BindAny(c, obj) diff --git a/internal/model/web/admin.go b/internal/model/web/admin.go index ec312f2c..6b1980ca 100644 --- a/internal/model/web/admin.go +++ b/internal/model/web/admin.go @@ -5,7 +5,7 @@ package web type ChangeUserStatusReq struct { - *BaseInfo `json:"-" binding:"-"` - ID int64 `json:"id" form:"id" binding:"required"` - Status int `json:"status" form:"status" binding:"required,oneof=1 2"` + BaseInfo `json:"-" binding:"-"` + ID int64 `json:"id" form:"id" binding:"required"` + Status int `json:"status" form:"status" binding:"required,oneof=1 2"` } diff --git a/internal/model/web/alipay.go b/internal/model/web/alipay.go index b431f8d2..84746309 100644 --- a/internal/model/web/alipay.go +++ b/internal/model/web/alipay.go @@ -17,12 +17,12 @@ type UserWalletBillsReq struct { PageSize int } -type UserWalletBillsResp = base.PageResp +type UserWalletBillsResp base.PageResp type UserRechargeLinkReq struct { - *BaseInfo `json:"-" form:"-" binding:"-"` - Host string `json:"-" form:"-" binding:"-"` - Amount int64 `json:"amount" form:"amount" binding:"required"` + BaseInfo `json:"-" form:"-" binding:"-"` + Host string `json:"-" form:"-" binding:"-"` + Amount int64 `json:"amount" form:"amount" binding:"required"` } type UserRechargeLinkResp struct { diff --git a/internal/model/web/core.go b/internal/model/web/core.go index 3da85471..c0e44e85 100644 --- a/internal/model/web/core.go +++ b/internal/model/web/core.go @@ -11,18 +11,18 @@ import ( ) type ChangeAvatarReq struct { - *BaseInfo `json:"-" binding:"-"` + BaseInfo `json:"-" binding:"-"` + Avatar string `json:"avatar" form:"avatar" binding:"required"` } type SyncSearchIndexReq struct { - *BaseInfo `json:"-" binding:"-"` - - Ctx context.Context `json:"-" binding:"-"` + BaseInfo `json:"-" binding:"-"` + Ctx context.Context `json:"-" binding:"-"` } type UserInfoReq struct { - *BaseInfo `json:"-" binding:"-"` - Username string `json:"username" form:"username" binding:"required"` + BaseInfo `json:"-" binding:"-"` + Username string `json:"username" form:"username" binding:"required"` } type UserInfoResp struct { @@ -37,23 +37,80 @@ type UserInfoResp struct { } type GetUnreadMsgCountReq struct { - *SimpleInfo `json:"-" binding:"-"` + SimpleInfo `json:"-" binding:"-"` } type GetUnreadMsgCountResp struct { Count int64 `json:"count"` } -type GetMessagesReq struct { - UserId int64 - Page int - PageSize int -} +type GetMessagesReq BasePageReq -type GetMessagesResp = base.PageResp +type GetMessagesResp base.PageResp type ReadMessageReq struct { - *SimpleInfo `json:"-" binding:"-"` + SimpleInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` +} +type SendWhisperReq struct { + SimpleInfo `json:"-" binding:"-"` + UserID int64 `json:"user_id" binding:"required"` + Content string `json:"content" binding:"required"` +} + +type GetCollectionsReq BasePageReq +type GetCollectionsResp base.PageResp + +type GetStarsReq BasePageReq +type GetStarsResp base.PageResp + +type UserPhoneBindReq struct { + BaseInfo `json:"-" binding:"-"` + Phone string `json:"phone" form:"phone" binding:"required"` + Captcha string `json:"captcha" form:"captcha" binding:"required"` +} + +type ChangePasswordReq struct { + BaseInfo `json:"-" binding:"-"` + Password string `json:"password" form:"password" binding:"required"` + OldPassword string `json:"old_password" form:"old_password" binding:"required"` +} + +type ChangeNicknameReq struct { + BaseInfo `json:"-" binding:"-"` + Nickname string `json:"nickname" form:"nickname" binding:"required"` +} + +type SuggestUsersReq struct { + Keyword string +} + +type SuggestUsersResp struct { + Suggests []string `json:"suggests"` +} + +type SuggestTagsReq struct { + Keyword string +} + +type SuggestTagsResp struct { + Suggests []string `json:"suggests"` +} + +type TweetStarStatusReq struct { + SimpleInfo `json:"-" binding:"-"` + TweetId int64 `form:"id"` +} + +type TweetStarStatusResp struct { + Status bool `json:"status"` +} + +type TweetCollectionStatusReq struct { + SimpleInfo `json:"-" binding:"-"` + TweetId int64 `form:"id"` +} - ID int64 `json:"id" binding:"required"` +type TweetCollectionStatusResp struct { + Status bool `json:"status"` } diff --git a/internal/model/web/web.go b/internal/model/web/web.go index bcddea3a..a4a8941f 100644 --- a/internal/model/web/web.go +++ b/internal/model/web/web.go @@ -5,7 +5,12 @@ package web import ( + "github.com/alimy/mir/v3" + "github.com/gin-gonic/gin" "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/pkg/app" + "github.com/rocboss/paopao-ce/pkg/xerror" ) type BaseInfo struct { @@ -16,6 +21,12 @@ type SimpleInfo struct { Uid int64 } +type BasePageReq struct { + UserId int64 + Page int + PageSize int +} + func (b *BaseInfo) SetUser(user *core.User) { b.User = user } @@ -23,3 +34,16 @@ func (b *BaseInfo) SetUser(user *core.User) { func (s *SimpleInfo) SetUserId(id int64) { s.Uid = id } + +func BasePageReqFrom(c *gin.Context) (*BasePageReq, mir.Error) { + uid, ok := base.UserIdFrom(c) + if !ok { + return nil, xerror.UnauthorizedTokenError + } + page, pageSize := app.GetPageOffset(c) + return &BasePageReq{ + UserId: uid, + Page: page, + PageSize: pageSize, + }, nil +} diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index abbe8944..dc1bbb9e 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -11,6 +11,7 @@ import ( "github.com/gin-gonic/gin" "github.com/go-redis/redis/v8" "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/pkg/types" "github.com/rocboss/paopao-ce/pkg/xerror" ) @@ -23,13 +24,9 @@ type DaoServant struct { Ds core.DataService } -type BaseBinding struct { - // TODO -} +type BaseBinding types.Empty -type BaseRender struct { - // TODO -} +type BaseRender types.Empty type JsonResp struct { Code int `json:"code"` diff --git a/internal/servants/web/alipay.go b/internal/servants/web/alipay.go index 9420ffe4..ab8401f7 100644 --- a/internal/servants/web/alipay.go +++ b/internal/servants/web/alipay.go @@ -136,7 +136,7 @@ func (s *alipayPrivSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func (s *alipayPrivSrv) UserWalletBills(req *web.UserWalletBillsReq) (*base.PageResp, mir.Error) { +func (s *alipayPrivSrv) UserWalletBills(req *web.UserWalletBillsReq) (*web.UserWalletBillsResp, mir.Error) { bills, err := s.Ds.GetUserWalletBills(req.UserId, (req.Page-1)*req.PageSize, req.PageSize) if err != nil { logrus.Errorf("GetUserWalletBills err: %s", err) @@ -147,7 +147,8 @@ func (s *alipayPrivSrv) UserWalletBills(req *web.UserWalletBillsReq) (*base.Page logrus.Errorf("GetUserWalletBillCount err: %s", err) return nil, _errUserWalletBillsFailed } - return base.PageRespFrom(bills, req.Page, req.PageSize, totalRows), nil + resp := base.PageRespFrom(bills, req.Page, req.PageSize, totalRows) + return (*web.UserWalletBillsResp)(resp), nil } func (s *alipayPrivSrv) UserRechargeLink(req *web.UserRechargeLinkReq) (*web.UserRechargeLinkResp, mir.Error) { diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 102a7554..65c49fcb 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -9,7 +9,9 @@ import ( "fmt" "math" "time" + "unicode/utf8" + "github.com/alimy/cfg" "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" @@ -17,15 +19,23 @@ import ( "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/rocboss/paopao-ce/pkg/app" + "github.com/rocboss/paopao-ce/pkg/convert" "github.com/rocboss/paopao-ce/pkg/xerror" "github.com/sirupsen/logrus" ) +const ( + // _MaxWhisperNumDaily 当日单用户私信总数限制(TODO 配置化、积分兑换等) + _MaxWhisperNumDaily = 20 + _MaxCaptchaTimes = 2 +) + var ( _ api.Core = (*coreSrv)(nil) _ api.CoreBinding = (*coreBinding)(nil) _ api.CoreRender = (*coreRender)(nil) + + _EnablePhoneVerify = cfg.If("Sms") ) type coreSrv struct { @@ -38,6 +48,7 @@ type coreSrv struct { type coreBinding struct { *api.UnimplementedCoreBinding + base.BaseBinding } type coreRender struct { @@ -47,7 +58,7 @@ type coreRender struct { func (b *coreBinding) BindSyncSearchIndex(c *gin.Context) (*web.SyncSearchIndexReq, mir.Error) { user, _ := base.UserFrom(c) return &web.SyncSearchIndexReq{ - BaseInfo: &web.BaseInfo{ + BaseInfo: web.BaseInfo{ User: user, }, Ctx: c.Request.Context(), @@ -55,8 +66,8 @@ func (b *coreBinding) BindSyncSearchIndex(c *gin.Context) (*web.SyncSearchIndexR } func (b *coreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) { - username, exists := base.UserNameFrom(c) - if !exists { + username, exist := base.UserNameFrom(c) + if !exist { return nil, xerror.UnauthorizedAuthNotExist } return &web.UserInfoReq{ @@ -65,15 +76,55 @@ func (b *coreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Err } func (b *coreBinding) BindGetMessages(c *gin.Context) (*web.GetMessagesReq, mir.Error) { - uid, ok := base.UserIdFrom(c) - if !ok { - return nil, xerror.UnauthorizedTokenError - } - page, pageSize := app.GetPageOffset(c) - return &web.GetMessagesReq{ - UserId: uid, - Page: page, - PageSize: pageSize, + v, err := web.BasePageReqFrom(c) + return (*web.GetMessagesReq)(v), err +} + +func (b *coreBinding) BindGetCollections(c *gin.Context) (*web.GetCollectionsReq, mir.Error) { + v, err := web.BasePageReqFrom(c) + return (*web.GetCollectionsReq)(v), err +} + +func (b *coreBinding) BindGetStars(c *gin.Context) (*web.GetStarsReq, mir.Error) { + v, err := web.BasePageReqFrom(c) + return (*web.GetStarsReq)(v), err +} + +func (b *coreBinding) BindSuggestTags(c *gin.Context) (*web.SuggestTagsReq, mir.Error) { + return &web.SuggestTagsReq{ + Keyword: c.Query("k"), + }, nil +} + +func (b *coreBinding) BindSuggestUsers(c *gin.Context) (*web.SuggestUsersReq, mir.Error) { + return &web.SuggestUsersReq{ + Keyword: c.Query("k"), + }, nil +} + +func (b *coreBinding) BindTweetCollectionStatus(c *gin.Context) (*web.TweetCollectionStatusReq, mir.Error) { + UserId, exist := base.UserIdFrom(c) + if !exist { + return nil, xerror.UnauthorizedAuthNotExist + } + return &web.TweetCollectionStatusReq{ + SimpleInfo: web.SimpleInfo{ + Uid: UserId, + }, + TweetId: convert.StrTo(c.Query("id")).MustInt64(), + }, nil +} + +func (b *coreBinding) BindTweetStarStatus(c *gin.Context) (*web.TweetStarStatusReq, mir.Error) { + UserId, exist := base.UserIdFrom(c) + if !exist { + return nil, xerror.UnauthorizedAuthNotExist + } + return &web.TweetStarStatusReq{ + SimpleInfo: web.SimpleInfo{ + Uid: UserId, + }, + TweetId: convert.StrTo(c.Query("id")).MustInt64(), }, nil } @@ -121,7 +172,7 @@ func (s *coreSrv) GetUnreadMsgCount(req *web.GetUnreadMsgCountReq) (*web.GetUnre }, nil } -func (s *coreSrv) GetMessages(req *web.GetMessagesReq) (*base.PageResp, mir.Error) { +func (s *coreSrv) GetMessages(req *web.GetMessagesReq) (*web.GetMessagesResp, mir.Error) { conditions := &core.ConditionsT{ "receiver_user_id": req.UserId, "ORDER": "id DESC", @@ -162,7 +213,8 @@ func (s *coreSrv) GetMessages(req *web.GetMessagesReq) (*base.PageResp, mir.Erro return nil, _errGetMessagesFailed } totalRows, _ := s.Ds.GetMessageCount(conditions) - return base.PageRespFrom(messages, req.Page, req.PageSize, totalRows), nil + resp := base.PageRespFrom(messages, req.Page, req.PageSize, totalRows) + return (*web.GetMessagesResp)(resp), nil } func (s *coreSrv) ReadMessage(req *web.ReadMessageReq) mir.Error { @@ -180,6 +232,219 @@ func (s *coreSrv) ReadMessage(req *web.ReadMessageReq) mir.Error { return nil } +func (s *coreSrv) SendUserWhisper(req *web.SendWhisperReq) mir.Error { + // 不允许发送私信给自己 + if req.Uid == req.UserID { + return _errNoWhisperToSelf + } + + // 今日频次限制 + ctx := context.Background() + whisperKey := fmt.Sprintf("WhisperTimes:%d", req.Uid) + if res, _ := s.Redis.Get(ctx, whisperKey).Result(); convert.StrTo(res).MustInt() >= _MaxWhisperNumDaily { + return _errTooManyWhisperNum + } + + // 创建私信 + _, err := s.Ds.CreateMessage(&core.Message{ + SenderUserID: req.Uid, + ReceiverUserID: req.UserID, + Type: core.MsgTypeWhisper, + Brief: "给你发送新私信了", + Content: req.Content, + }) + if err != nil { + logrus.Errorf("Ds.CreateWhisper err: %s", err) + return _errSendWhisperFailed + } + + // 写入当日(自然日)计数缓存 + s.Redis.Incr(ctx, whisperKey).Result() + currentTime := time.Now() + endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location()) + s.Redis.Expire(ctx, whisperKey, endTime.Sub(currentTime)) + + return nil +} + +func (s *coreSrv) GetCollections(req *web.GetCollectionsReq) (*web.GetCollectionsResp, mir.Error) { + collections, err := s.Ds.GetUserPostCollections(req.UserId, (req.Page-1)*req.PageSize, req.PageSize) + if err != nil { + logrus.Errorf("Ds.GetUserPostCollections err: %s", err) + return nil, _errGetCollectionsFailed + } + totalRows, err := s.Ds.GetUserPostCollectionCount(req.UserId) + if err != nil { + logrus.Errorf("Ds.GetUserPostCollectionCount err: %s", err) + return nil, _errGetCollectionsFailed + } + + var posts []*core.Post + for _, collection := range collections { + posts = append(posts, collection.Post) + } + postsFormated, err := s.Ds.MergePosts(posts) + if err != nil { + logrus.Errorf("Ds.MergePosts err: %s", err) + return nil, _errGetCollectionsFailed + } + resp := base.PageRespFrom(postsFormated, req.Page, req.PageSize, totalRows) + + return (*web.GetCollectionsResp)(resp), nil +} + +func (s *coreSrv) UserPhoneBind(req *web.UserPhoneBindReq) mir.Error { + // 手机重复性检查 + u, err := s.Ds.GetUserByPhone(req.Phone) + if err != nil { + logrus.Errorf("Ds.GetUserByPhone err: %v", err) + return _errExistedUserPhone + } + if u.Model == nil || u.ID == 0 { + return _errExistedUserPhone + } + if u.ID == req.User.ID { + return _errExistedUserPhone + } + + // 如果禁止phone verify 则允许通过任意验证码 + if !_EnablePhoneVerify { + c, err := s.Ds.GetLatestPhoneCaptcha(req.Phone) + if err != nil { + return _errErrorPhoneCaptcha + } + if c.Captcha != req.Captcha { + return _errErrorPhoneCaptcha + } + if c.ExpiredOn < time.Now().Unix() { + return _errErrorPhoneCaptcha + } + if c.UseTimes >= _MaxCaptchaTimes { + return _errMaxPhoneCaptchaUseTimes + } + // 更新检测次数 + s.Ds.UsePhoneCaptcha(c) + } + + // 执行绑定 + user := req.User + user.Phone = req.Phone + if err := s.Ds.UpdateUser(user); err != nil { + // TODO: 优化错误处理逻辑,失败后上面的逻辑也应该回退 + logrus.Errorf("Ds.UpdateUser err: %s", err) + return xerror.ServerError + } + return nil +} + +func (s *coreSrv) GetStars(req *web.GetStarsReq) (*web.GetStarsResp, mir.Error) { + stars, err := s.Ds.GetUserPostStars(req.UserId, (req.Page-1)*req.PageSize, req.PageSize) + if err != nil { + logrus.Errorf("Ds.GetUserPostStars err: %s", err) + return nil, _errGetStarsFailed + } + totalRows, err := s.Ds.GetUserPostStarCount(req.UserId) + if err != nil { + logrus.Errorf("Ds.GetUserPostStars err: %s", err) + return nil, _errGetStarsFailed + } + + var posts []*core.Post + for _, star := range stars { + posts = append(posts, star.Post) + } + postsFormated, err := s.Ds.MergePosts(posts) + if err != nil { + logrus.Errorf("Ds.MergePosts err: %s", err) + return nil, _errGetStarsFailed + } + resp := base.PageRespFrom(postsFormated, req.Page, req.PageSize, totalRows) + + return (*web.GetStarsResp)(resp), nil +} + +func (s *coreSrv) ChangePassword(req *web.ChangePasswordReq) mir.Error { + // 密码检查 + if err := checkPassword(req.Password); err != nil { + return err + } + // 旧密码校验 + user := req.User + if !validPassword(user.Password, req.OldPassword, req.User.Salt) { + return _errErrorOldPassword + } + // 更新入库 + user.Password, user.Salt = encryptPasswordAndSalt(req.Password) + if err := s.Ds.UpdateUser(user); err != nil { + logrus.Errorf("Ds.UpdateUser err: %s", err) + return xerror.ServerError + } + return nil +} + +func (s *coreSrv) SuggestTags(req *web.SuggestTagsReq) (*web.SuggestTagsResp, mir.Error) { + tags, err := s.Ds.GetTagsByKeyword(req.Keyword) + if err != nil { + logrus.Errorf("Ds.GetTagsByKeyword err: %s", err) + return nil, xerror.ServerError + } + resp := &web.SuggestTagsResp{} + for _, t := range tags { + resp.Suggests = append(resp.Suggests, t.Tag) + } + return resp, nil +} + +func (s *coreSrv) SuggestUsers(req *web.SuggestUsersReq) (*web.SuggestUsersResp, mir.Error) { + users, err := s.Ds.GetUsersByKeyword(req.Keyword) + if err != nil { + logrus.Errorf("Ds.GetUsersByKeyword err: %s", err) + return nil, xerror.ServerError + } + resp := &web.SuggestUsersResp{} + for _, user := range users { + resp.Suggests = append(resp.Suggests, user.Username) + } + return resp, nil +} + +func (s *coreSrv) ChangeNickname(req *web.ChangeNicknameReq) mir.Error { + if utf8.RuneCountInString(req.Nickname) < 2 || utf8.RuneCountInString(req.Nickname) > 12 { + return _errNicknameLengthLimit + } + user := req.User + user.Nickname = req.Nickname + if err := s.Ds.UpdateUser(user); err != nil { + logrus.Errorf("Ds.UpdateUser err: %s", err) + return xerror.ServerError + } + return nil +} + +func (s *coreSrv) ChangeAvatar(req *web.ChangeAvatarReq) (xerr mir.Error) { + defer func() { + if xerr != nil { + deleteOssObjects(s.oss, []string{req.Avatar}) + } + }() + + if err := s.Ds.CheckAttachment(req.Avatar); err != nil { + logrus.Errorf("Ds.CheckAttachment failed: %s", err) + return xerror.InvalidParams + } + if err := s.oss.PersistObject(s.oss.ObjectKey(req.Avatar)); err != nil { + logrus.Errorf("Ds.ChangeUserAvatar persist object failed: %s", err) + return xerror.ServerError + } + user := req.User + user.Avatar = req.Avatar + if err := s.Ds.UpdateUser(user); err != nil { + logrus.Errorf("Ds.UpdateUser failed: %s", err) + return xerror.ServerError + } + return nil +} + func (s *coreSrv) pushPostsToSearch(c context.Context) { if ok, _ := s.Redis.SetNX(c, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok { defer s.Redis.Del(c, "JOB_PUSH_TO_SEARCH") @@ -212,6 +477,28 @@ func (s *coreSrv) pushPostsToSearch(c context.Context) { } } +func (s *coreSrv) TweetCollectionStatus(req *web.TweetCollectionStatusReq) (*web.TweetCollectionStatusResp, mir.Error) { + resp := &web.TweetCollectionStatusResp{ + Status: true, + } + if _, err := s.Ds.GetUserPostCollection(req.TweetId, req.Uid); err != nil { + resp.Status = false + return resp, nil + } + return resp, nil +} + +func (s *coreSrv) TweetStarStatus(req *web.TweetStarStatusReq) (*web.TweetStarStatusResp, mir.Error) { + resp := &web.TweetStarStatusResp{ + Status: true, + } + if _, err := s.Ds.GetUserPostStar(req.TweetId, req.Uid); err != nil { + resp.Status = false + return resp, nil + } + return resp, nil +} + func (s *coreSrv) deleteSearchPost(post *core.Post) error { return s.ts.DeleteDocuments([]string{fmt.Sprintf("%d", post.ID)}) } diff --git a/internal/servants/web/utils.go b/internal/servants/web/utils.go new file mode 100644 index 00000000..1b5a05d7 --- /dev/null +++ b/internal/servants/web/utils.go @@ -0,0 +1,47 @@ +package web + +import ( + "strings" + "unicode/utf8" + + "github.com/alimy/mir/v3" + "github.com/gofrs/uuid" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/pkg/util" +) + +// checkPassword 密码检查 +func checkPassword(password string) mir.Error { + // 检测用户是否合规 + if utf8.RuneCountInString(password) < 6 || utf8.RuneCountInString(password) > 16 { + return _errPasswordLengthLimit + } + return nil +} + +// ValidPassword 检查密码是否一致 +func validPassword(dbPassword, password, salt string) bool { + return strings.Compare(dbPassword, util.EncodeMD5(util.EncodeMD5(password)+salt)) == 0 +} + +// encryptPasswordAndSalt 密码加密&生成salt +func encryptPasswordAndSalt(password string) (string, string) { + salt := uuid.Must(uuid.NewV4()).String()[:8] + password = util.EncodeMD5(util.EncodeMD5(password) + salt) + return password, salt +} + +// deleteOssObjects 删除推文的媒体内容, 宽松处理错误(就是不处理), 后续完善 +func deleteOssObjects(oss core.ObjectStorageService, mediaContents []string) { + mediaContentsSize := len(mediaContents) + if mediaContentsSize > 1 { + objectKeys := make([]string, 0, mediaContentsSize) + for _, cUrl := range mediaContents { + objectKeys = append(objectKeys, oss.ObjectKey(cUrl)) + } + // TODO: 优化处理尽量使用channel传递objectKeys使用可控数量的Goroutine集中处理object删除动作,后续完善 + go oss.DeleteObjects(objectKeys) + } else if mediaContentsSize == 1 { + oss.DeleteObject(oss.ObjectKey(mediaContents[0])) + } +} diff --git a/mirc/web/v1/core.go b/mirc/web/v1/core.go index 529f15de..af835074 100644 --- a/mirc/web/v1/core.go +++ b/mirc/web/v1/core.go @@ -31,35 +31,35 @@ type Core struct { ReadMessage func(Post, web.ReadMessageReq) `mir:"/user/message/read"` // SendUserWhisper 发送用户私信 - SendUserWhisper func(Post) `mir:"/user/whisper"` + SendUserWhisper func(Post, web.SendWhisperReq) `mir:"/user/whisper"` // GetCollections 获取用户收藏列表 - GetCollections func(Get) `mir:"/user/collections"` + GetCollections func(Get, web.GetCollectionsReq) web.GetCollectionsResp `mir:"/user/collections"` // GetStars 获取用户点赞列表 - GetStars func(Get) `mir:"/user/stars"` + GetStars func(Get, web.GetStarsReq) web.GetStarsResp `mir:"/user/stars"` // UserPhoneBind 绑定用户手机号 - UserPhoneBind func(Post) `mir:"/user/phone"` + UserPhoneBind func(Post, web.UserPhoneBindReq) `mir:"/user/phone"` // ChangePassword 修改密码 - ChangePassword func(Post) `mir:"/user/password"` + ChangePassword func(Post, web.ChangePasswordReq) `mir:"/user/password"` // ChangeNickname 修改昵称 - ChangeNickname func(Post) `mir:"/user/nickname"` + ChangeNickname func(Post, web.ChangeNicknameReq) `mir:"/user/nickname"` // ChangeAvatar 修改头像 ChangeAvatar func(Post, web.ChangeAvatarReq) `mir:"/user/avatar"` // SuggestUsers 检索用户 - SuggestUsers func(Get) `mir:"/suggest/users"` + SuggestUsers func(Get, web.SuggestUsersReq) web.SuggestUsersResp `mir:"/suggest/users"` // SuggestTags 检索标签 - SuggestTags func(Get) `mir:"/suggest/tags"` + SuggestTags func(Get, web.SuggestTagsReq) web.SuggestTagsResp `mir:"/suggest/tags"` // TweetStarStatus 获取动态点赞状态 - TweetStarStatus func(Get) `mir:"/post/star"` + TweetStarStatus func(Get, web.TweetStarStatusReq) web.TweetStarStatusResp `mir:"/post/star"` // TweetCollectionStatus 获取动态收藏状态 - TweetCollectionStatus func(Get) `mir:"/post/collection"` + TweetCollectionStatus func(Get, web.TweetCollectionStatusReq) web.TweetCollectionStatusResp `mir:"/post/collection"` } From 820d54108dc57633deac7df0fd0dd9ce939e8eff Mon Sep 17 00:00:00 2001 From: Michael Li Date: Thu, 29 Dec 2022 18:36:03 +0800 Subject: [PATCH 57/65] mir:add priv api implement for new web service --- auto/api/v1/priv.go | 234 +++++++++--- internal/model/web/core.go | 3 - internal/model/web/priv.go | 128 ++++++- internal/servants/base/base.go | 74 ++++ internal/servants/localoss/xerror.go | 15 - internal/servants/web/core.go | 63 +--- internal/servants/web/priv.go | 545 ++++++++++++++++++++++++++- internal/servants/web/utils.go | 98 +++++ internal/servants/web/web.go | 6 +- internal/servants/web/xerror.go | 4 + mirc/web/v1/priv.go | 18 +- 11 files changed, 1033 insertions(+), 155 deletions(-) delete mode 100644 internal/servants/localoss/xerror.go diff --git a/auto/api/v1/priv.go b/auto/api/v1/priv.go index e5c19fd2..29b39a92 100644 --- a/auto/api/v1/priv.go +++ b/auto/api/v1/priv.go @@ -18,22 +18,31 @@ type Priv interface { CreateCommentReply() mir.Error DeleteComment() mir.Error CreateComment() mir.Error - VisiblePost() mir.Error - StickTweet() mir.Error - LockTweet() mir.Error - CollectionTweet() mir.Error - StarTweet() mir.Error - DeleteTweet() mir.Error + VisiblePost(*web.VisiblePostReq) (*web.VisiblePostResp, mir.Error) + StickTweet(*web.StickTweetReq) (*web.StickTweetResp, mir.Error) + LockTweet(*web.LockTweetReq) (*web.LockTweetResp, mir.Error) + CollectionTweet(*web.CollectionTweetReq) (*web.CollectionTweetResp, mir.Error) + StarTweet(*web.StarTweetReq) (*web.StarTweetResp, mir.Error) + DeleteTweet(*web.DeleteTweetReq) mir.Error CreateTweet(*web.CreateTweetReq) (*web.CreateTweetResp, mir.Error) - DownloadAttachment() mir.Error - DownloadAttachmentPrecheck() mir.Error - UploadAttachment() mir.Error + DownloadAttachment(*web.DownloadAttachmentReq) (*web.DownloadAttachmentResp, mir.Error) + DownloadAttachmentPrecheck(*web.DownloadAttachmentPrecheckReq) (*web.DownloadAttachmentPrecheckResp, mir.Error) + UploadAttachment(*web.UploadAttachmentReq) (*web.UploadAttachmentResp, mir.Error) mustEmbedUnimplementedPrivServant() } type PrivBinding interface { + BindVisiblePost(*gin.Context) (*web.VisiblePostReq, mir.Error) + BindStickTweet(*gin.Context) (*web.StickTweetReq, mir.Error) + BindLockTweet(*gin.Context) (*web.LockTweetReq, mir.Error) + BindCollectionTweet(*gin.Context) (*web.CollectionTweetReq, mir.Error) + BindStarTweet(*gin.Context) (*web.StarTweetReq, mir.Error) + BindDeleteTweet(*gin.Context) (*web.DeleteTweetReq, mir.Error) BindCreateTweet(*gin.Context) (*web.CreateTweetReq, mir.Error) + BindDownloadAttachment(*gin.Context) (*web.DownloadAttachmentReq, mir.Error) + BindDownloadAttachmentPrecheck(*gin.Context) (*web.DownloadAttachmentPrecheckReq, mir.Error) + BindUploadAttachment(*gin.Context) (*web.UploadAttachmentReq, mir.Error) mustEmbedUnimplementedPrivBinding() } @@ -43,16 +52,16 @@ type PrivRender interface { RenderCreateCommentReply(*gin.Context, mir.Error) RenderDeleteComment(*gin.Context, mir.Error) RenderCreateComment(*gin.Context, mir.Error) - RenderVisiblePost(*gin.Context, mir.Error) - RenderStickTweet(*gin.Context, mir.Error) - RenderLockTweet(*gin.Context, mir.Error) - RenderCollectionTweet(*gin.Context, mir.Error) - RenderStarTweet(*gin.Context, mir.Error) + RenderVisiblePost(*gin.Context, *web.VisiblePostResp, mir.Error) + RenderStickTweet(*gin.Context, *web.StickTweetResp, mir.Error) + RenderLockTweet(*gin.Context, *web.LockTweetResp, mir.Error) + RenderCollectionTweet(*gin.Context, *web.CollectionTweetResp, mir.Error) + RenderStarTweet(*gin.Context, *web.StarTweetResp, mir.Error) RenderDeleteTweet(*gin.Context, mir.Error) RenderCreateTweet(*gin.Context, *web.CreateTweetResp, mir.Error) - RenderDownloadAttachment(*gin.Context, mir.Error) - RenderDownloadAttachmentPrecheck(*gin.Context, mir.Error) - RenderUploadAttachment(*gin.Context, mir.Error) + RenderDownloadAttachment(*gin.Context, *web.DownloadAttachmentResp, mir.Error) + RenderDownloadAttachmentPrecheck(*gin.Context, *web.DownloadAttachmentPrecheckResp, mir.Error) + RenderUploadAttachment(*gin.Context, *web.UploadAttachmentResp, mir.Error) mustEmbedUnimplementedPrivRender() } @@ -112,7 +121,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderVisiblePost(c, s.VisiblePost()) + req, err := b.BindVisiblePost(c) + if err != nil { + r.RenderVisiblePost(c, nil, err) + return + } + resp, err := s.VisiblePost(req) + r.RenderVisiblePost(c, resp, err) }) router.Handle("POST", "/post/stick", func(c *gin.Context) { @@ -122,7 +137,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderStickTweet(c, s.StickTweet()) + req, err := b.BindStickTweet(c) + if err != nil { + r.RenderStickTweet(c, nil, err) + return + } + resp, err := s.StickTweet(req) + r.RenderStickTweet(c, resp, err) }) router.Handle("POST", "/post/lock", func(c *gin.Context) { @@ -132,7 +153,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderLockTweet(c, s.LockTweet()) + req, err := b.BindLockTweet(c) + if err != nil { + r.RenderLockTweet(c, nil, err) + return + } + resp, err := s.LockTweet(req) + r.RenderLockTweet(c, resp, err) }) router.Handle("POST", "/post/collection", func(c *gin.Context) { @@ -142,7 +169,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderCollectionTweet(c, s.CollectionTweet()) + req, err := b.BindCollectionTweet(c) + if err != nil { + r.RenderCollectionTweet(c, nil, err) + return + } + resp, err := s.CollectionTweet(req) + r.RenderCollectionTweet(c, resp, err) }) router.Handle("POST", "/post/start", func(c *gin.Context) { @@ -152,7 +185,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderStarTweet(c, s.StarTweet()) + req, err := b.BindStarTweet(c) + if err != nil { + r.RenderStarTweet(c, nil, err) + return + } + resp, err := s.StarTweet(req) + r.RenderStarTweet(c, resp, err) }) router.Handle("DELETE", "/post", func(c *gin.Context) { @@ -162,7 +201,12 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderDeleteTweet(c, s.DeleteTweet()) + req, err := b.BindDeleteTweet(c) + if err != nil { + r.RenderDeleteTweet(c, err) + return + } + r.RenderDeleteTweet(c, s.DeleteTweet(req)) }) router.Handle("POST", "/post", func(c *gin.Context) { @@ -188,7 +232,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderDownloadAttachment(c, s.DownloadAttachment()) + req, err := b.BindDownloadAttachment(c) + if err != nil { + r.RenderDownloadAttachment(c, nil, err) + return + } + resp, err := s.DownloadAttachment(req) + r.RenderDownloadAttachment(c, resp, err) }) router.Handle("GET", "/attachment/precheck", func(c *gin.Context) { @@ -198,7 +248,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderDownloadAttachmentPrecheck(c, s.DownloadAttachmentPrecheck()) + req, err := b.BindDownloadAttachmentPrecheck(c) + if err != nil { + r.RenderDownloadAttachmentPrecheck(c, nil, err) + return + } + resp, err := s.DownloadAttachmentPrecheck(req) + r.RenderDownloadAttachmentPrecheck(c, resp, err) }) router.Handle("POST", "/attachment", func(c *gin.Context) { @@ -208,7 +264,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderUploadAttachment(c, s.UploadAttachment()) + req, err := b.BindUploadAttachment(c) + if err != nil { + r.RenderUploadAttachment(c, nil, err) + return + } + resp, err := s.UploadAttachment(req) + r.RenderUploadAttachment(c, resp, err) }) } @@ -237,27 +299,27 @@ func (UnimplementedPrivServant) CreateComment() mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) VisiblePost() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) StickTweet() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) StickTweet(req *web.StickTweetReq) (*web.StickTweetResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) LockTweet() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) LockTweet(req *web.LockTweetReq) (*web.LockTweetResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) CollectionTweet() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) CollectionTweet(req *web.CollectionTweetReq) (*web.CollectionTweetResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) StarTweet() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) StarTweet(req *web.StarTweetReq) (*web.StarTweetResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) DeleteTweet() mir.Error { +func (UnimplementedPrivServant) DeleteTweet(req *web.DeleteTweetReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -265,16 +327,16 @@ func (UnimplementedPrivServant) CreateTweet(req *web.CreateTweetReq) (*web.Creat return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) DownloadAttachment() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) DownloadAttachment(req *web.DownloadAttachmentReq) (*web.DownloadAttachmentResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) DownloadAttachmentPrecheck() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) DownloadAttachmentPrecheck(req *web.DownloadAttachmentPrecheckReq) (*web.DownloadAttachmentPrecheckResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) UploadAttachment() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) UploadAttachment(req *web.UploadAttachmentReq) (*web.UploadAttachmentResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedPrivServant) mustEmbedUnimplementedPrivServant() {} @@ -300,24 +362,24 @@ func (r *UnimplementedPrivRender) RenderCreateComment(c *gin.Context, err mir.Er r.RenderAny(c, nil, err) } -func (r *UnimplementedPrivRender) RenderVisiblePost(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderVisiblePost(c *gin.Context, data *web.VisiblePostResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPrivRender) RenderStickTweet(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderStickTweet(c *gin.Context, data *web.StickTweetResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPrivRender) RenderLockTweet(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderLockTweet(c *gin.Context, data *web.LockTweetResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPrivRender) RenderCollectionTweet(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderCollectionTweet(c *gin.Context, data *web.CollectionTweetResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPrivRender) RenderStarTweet(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderStarTweet(c *gin.Context, data *web.StarTweetResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedPrivRender) RenderDeleteTweet(c *gin.Context, err mir.Error) { @@ -328,16 +390,16 @@ func (r *UnimplementedPrivRender) RenderCreateTweet(c *gin.Context, data *web.Cr r.RenderAny(c, data, err) } -func (r *UnimplementedPrivRender) RenderDownloadAttachment(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderDownloadAttachment(c *gin.Context, data *web.DownloadAttachmentResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPrivRender) RenderDownloadAttachmentPrecheck(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderDownloadAttachmentPrecheck(c *gin.Context, data *web.DownloadAttachmentPrecheckResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPrivRender) RenderUploadAttachment(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderUploadAttachment(c *gin.Context, data *web.UploadAttachmentResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedPrivRender) mustEmbedUnimplementedPrivRender() {} @@ -347,10 +409,64 @@ type UnimplementedPrivBinding struct { BindAny func(*gin.Context, any) mir.Error } +func (b *UnimplementedPrivBinding) BindVisiblePost(c *gin.Context) (*web.VisiblePostReq, mir.Error) { + obj := new(web.VisiblePostReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindStickTweet(c *gin.Context) (*web.StickTweetReq, mir.Error) { + obj := new(web.StickTweetReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindLockTweet(c *gin.Context) (*web.LockTweetReq, mir.Error) { + obj := new(web.LockTweetReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindCollectionTweet(c *gin.Context) (*web.CollectionTweetReq, mir.Error) { + obj := new(web.CollectionTweetReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindStarTweet(c *gin.Context) (*web.StarTweetReq, mir.Error) { + obj := new(web.StarTweetReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindDeleteTweet(c *gin.Context) (*web.DeleteTweetReq, mir.Error) { + obj := new(web.DeleteTweetReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedPrivBinding) BindCreateTweet(c *gin.Context) (*web.CreateTweetReq, mir.Error) { obj := new(web.CreateTweetReq) err := b.BindAny(c, obj) return obj, err } +func (b *UnimplementedPrivBinding) BindDownloadAttachment(c *gin.Context) (*web.DownloadAttachmentReq, mir.Error) { + obj := new(web.DownloadAttachmentReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindDownloadAttachmentPrecheck(c *gin.Context) (*web.DownloadAttachmentPrecheckReq, mir.Error) { + obj := new(web.DownloadAttachmentPrecheckReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindUploadAttachment(c *gin.Context) (*web.UploadAttachmentReq, mir.Error) { + obj := new(web.UploadAttachmentReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedPrivBinding) mustEmbedUnimplementedPrivBinding() {} diff --git a/internal/model/web/core.go b/internal/model/web/core.go index c0e44e85..c43a0905 100644 --- a/internal/model/web/core.go +++ b/internal/model/web/core.go @@ -5,8 +5,6 @@ package web import ( - "context" - "github.com/rocboss/paopao-ce/internal/servants/base" ) @@ -17,7 +15,6 @@ type ChangeAvatarReq struct { type SyncSearchIndexReq struct { BaseInfo `json:"-" binding:"-"` - Ctx context.Context `json:"-" binding:"-"` } type UserInfoReq struct { diff --git a/internal/model/web/priv.go b/internal/model/web/priv.go index 9184a437..290f80bd 100644 --- a/internal/model/web/priv.go +++ b/internal/model/web/priv.go @@ -4,10 +4,132 @@ package web +import ( + "fmt" + "mime/multipart" + "strings" + + "github.com/rocboss/paopao-ce/internal/core" +) + +type PostContentItem struct { + Content string `json:"content" binding:"required"` + Type core.PostContentT `json:"type" binding:"required"` + Sort int64 `json:"sort" binding:"required"` +} + type CreateTweetReq struct { - *BaseInfo `json:"-"` + BaseInfo `json:"-" binding:"-"` + Contents []*PostContentItem `json:"contents" binding:"required"` + Tags []string `json:"tags" binding:"required"` + Users []string `json:"users" binding:"required"` + AttachmentPrice int64 `json:"attachment_price"` + Visibility core.PostVisibleT `json:"visibility"` + ClientIP string `json:"-" binding:"-"` +} + +type CreateTweetResp core.PostFormated + +type DeleteTweetReq struct { + BaseInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` +} + +type StarTweetReq struct { + SimpleInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` +} + +type StarTweetResp struct { + Status bool `json:"status"` +} + +type CollectionTweetReq struct { + SimpleInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` +} + +type CollectionTweetResp struct { + Status bool `json:"status"` +} + +type LockTweetReq struct { + BaseInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` +} + +type LockTweetResp struct { + LockStatus int `json:"lock_status"` +} + +type StickTweetReq struct { + BaseInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` +} + +type StickTweetResp struct { + StickStatus int `json:"top_status"` +} + +type VisiblePostReq struct { + BaseInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` + Visibility core.PostVisibleT `json:"visibility" binding:"required"` +} + +type VisiblePostResp struct { + Visibility core.PostVisibleT `json:"visibility"` +} + +type UploadAttachmentReq struct { + SimpleInfo `json:"-" binding:"-"` + UploadType string + ContentType string + File multipart.File + FileSize int64 + FileExt string +} + +type UploadAttachmentResp struct { + UserID int64 `json:"user_id"` + FileSize int64 `json:"file_size"` + ImgWidth int `json:"img_width"` + ImgHeight int `json:"img_height"` + Type core.AttachmentType `json:"type"` + Content string `json:"content"` +} + +type DownloadAttachmentPrecheckReq struct { + BaseInfo `json:"-" binding:"-"` + ContentID int64 `form:"id"` +} + +type DownloadAttachmentPrecheckResp struct { + Paid bool `json:"paid"` +} + +type DownloadAttachmentReq struct { + BaseInfo `json:"-" binding:"-"` + ContentID int64 `form:"id"` +} + +type DownloadAttachmentResp struct { + SignedURL string `json:"signed_url"` } -type CreateTweetResp struct { - // TODO +// Check 检查PostContentItem属性 +func (p *PostContentItem) Check(acs core.AttachmentCheckService) error { + // 检查附件是否是本站资源 + if p.Type == core.ContentTypeImage || p.Type == core.ContentTypeVideo || p.Type == core.ContentTypeAttachment { + if err := acs.CheckAttachment(p.Content); err != nil { + return err + } + } + // 检查链接是否合法 + if p.Type == core.ContentTypeLink { + if strings.Index(p.Content, "http://") != 0 && strings.Index(p.Content, "https://") != 0 { + return fmt.Errorf("链接不合法") + } + } + return nil } diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index dc1bbb9e..ad3ab6a7 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -5,7 +5,11 @@ package base import ( + "context" + "fmt" + "math" "net/http" + "time" "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" @@ -22,6 +26,7 @@ type BaseServant struct { type DaoServant struct { Redis *redis.Client Ds core.DataService + Ts core.TweetSearchService } type BaseBinding types.Empty @@ -125,3 +130,72 @@ func (s *DaoServant) GetTweetBy(id int64) (*core.PostFormated, error) { } return postFormated, nil } + +func (s *DaoServant) PushPostsToSearch(c context.Context) { + if ok, _ := s.Redis.SetNX(c, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok { + defer s.Redis.Del(c, "JOB_PUSH_TO_SEARCH") + + splitNum := 1000 + totalRows, _ := s.Ds.GetPostCount(&core.ConditionsT{ + "visibility IN ?": []core.PostVisibleT{core.PostVisitPublic, core.PostVisitFriend}, + }) + pages := math.Ceil(float64(totalRows) / float64(splitNum)) + nums := int(pages) + for i := 0; i < nums; i++ { + posts, postsFormated, err := s.getTweetList(&core.ConditionsT{}, i*splitNum, splitNum) + if err != nil || len(posts) != len(postsFormated) { + continue + } + for i, pf := range postsFormated { + contentFormated := "" + for _, content := range pf.Contents { + if content.Type == core.ContentTypeText || content.Type == core.ContentTypeTitle { + contentFormated = contentFormated + content.Content + "\n" + } + } + docs := []core.TsDocItem{{ + Post: posts[i], + Content: contentFormated, + }} + s.Ts.AddDocuments(docs, fmt.Sprintf("%d", posts[i].ID)) + } + } + } +} + +func (s *DaoServant) PushPostToSearch(post *core.Post) { + postFormated := post.Format() + postFormated.User = &core.UserFormated{ + ID: post.UserID, + } + contents, _ := s.Ds.GetPostContentsByIDs([]int64{post.ID}) + for _, content := range contents { + postFormated.Contents = append(postFormated.Contents, content.Format()) + } + + contentFormated := "" + for _, content := range postFormated.Contents { + if content.Type == core.ContentTypeText || content.Type == core.ContentTypeTitle { + contentFormated = contentFormated + content.Content + "\n" + } + } + + docs := []core.TsDocItem{{ + Post: post, + Content: contentFormated, + }} + s.Ts.AddDocuments(docs, fmt.Sprintf("%d", post.ID)) +} + +func (s *DaoServant) DeleteSearchPost(post *core.Post) error { + return s.Ts.DeleteDocuments([]string{fmt.Sprintf("%d", post.ID)}) +} + +func (s *DaoServant) getTweetList(conditions *core.ConditionsT, offset, limit int) ([]*core.Post, []*core.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 +} diff --git a/internal/servants/localoss/xerror.go b/internal/servants/localoss/xerror.go deleted file mode 100644 index 38132d24..00000000 --- a/internal/servants/localoss/xerror.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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 localoss - -import ( - "github.com/rocboss/paopao-ce/pkg/xerror" -) - -var ( - errFileUploadFailed = xerror.NewError(10200, "文件上传失败") - errFileInvalidExt = xerror.NewError(10201, "文件类型不合法") - errFileInvalidSize = xerror.NewError(10202, "文件大小超限") -) diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 65c49fcb..6173913a 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -7,7 +7,7 @@ package web import ( "context" "fmt" - "math" + "time" "unicode/utf8" @@ -42,7 +42,6 @@ type coreSrv struct { api.UnimplementedCoreServant *base.DaoServant - ts core.TweetSearchService oss core.ObjectStorageService } @@ -55,16 +54,6 @@ type coreRender struct { *api.UnimplementedCoreRender } -func (b *coreBinding) BindSyncSearchIndex(c *gin.Context) (*web.SyncSearchIndexReq, mir.Error) { - user, _ := base.UserFrom(c) - return &web.SyncSearchIndexReq{ - BaseInfo: web.BaseInfo{ - User: user, - }, - Ctx: c.Request.Context(), - }, nil -} - func (b *coreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) { username, exist := base.UserNameFrom(c) if !exist { @@ -134,7 +123,7 @@ func (s *coreSrv) Chain() gin.HandlersChain { func (s *coreSrv) SyncSearchIndex(req *web.SyncSearchIndexReq) mir.Error { if req.User != nil && req.User.IsAdmin { - go s.pushPostsToSearch(req.Ctx) + go s.PushPostsToSearch(context.Background()) } return nil } @@ -445,38 +434,6 @@ func (s *coreSrv) ChangeAvatar(req *web.ChangeAvatarReq) (xerr mir.Error) { return nil } -func (s *coreSrv) pushPostsToSearch(c context.Context) { - if ok, _ := s.Redis.SetNX(c, "JOB_PUSH_TO_SEARCH", 1, time.Hour).Result(); ok { - defer s.Redis.Del(c, "JOB_PUSH_TO_SEARCH") - - splitNum := 1000 - totalRows, _ := s.Ds.GetPostCount(&core.ConditionsT{ - "visibility IN ?": []core.PostVisibleT{core.PostVisitPublic, core.PostVisitFriend}, - }) - pages := math.Ceil(float64(totalRows) / float64(splitNum)) - nums := int(pages) - for i := 0; i < nums; i++ { - posts, postsFormated, err := s.getTweetList(&core.ConditionsT{}, i*splitNum, splitNum) - if err != nil || len(posts) != len(postsFormated) { - continue - } - for i, pf := range postsFormated { - contentFormated := "" - for _, content := range pf.Contents { - if content.Type == core.ContentTypeText || content.Type == core.ContentTypeTitle { - contentFormated = contentFormated + content.Content + "\n" - } - } - docs := []core.TsDocItem{{ - Post: posts[i], - Content: contentFormated, - }} - s.ts.AddDocuments(docs, fmt.Sprintf("%d", posts[i].ID)) - } - } - } -} - func (s *coreSrv) TweetCollectionStatus(req *web.TweetCollectionStatusReq) (*web.TweetCollectionStatusResp, mir.Error) { resp := &web.TweetCollectionStatusResp{ Status: true, @@ -499,23 +456,9 @@ func (s *coreSrv) TweetStarStatus(req *web.TweetStarStatusReq) (*web.TweetStarSt return resp, nil } -func (s *coreSrv) deleteSearchPost(post *core.Post) error { - return s.ts.DeleteDocuments([]string{fmt.Sprintf("%d", post.ID)}) -} - -func (s *coreSrv) getTweetList(conditions *core.ConditionsT, offset, limit int) ([]*core.Post, []*core.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 newCoreSrv(s *base.DaoServant, ts core.TweetSearchService, oss core.ObjectStorageService) api.Core { +func newCoreSrv(s *base.DaoServant, oss core.ObjectStorageService) api.Core { return &coreSrv{ DaoServant: s, - ts: ts, oss: oss, } } diff --git a/internal/servants/web/priv.go b/internal/servants/web/priv.go index 5e4890f0..87bc95dd 100644 --- a/internal/servants/web/priv.go +++ b/internal/servants/web/priv.go @@ -5,21 +5,42 @@ package web import ( + "image" + "strings" + + "github.com/alimy/mir/v3" + "github.com/disintegration/imaging" "github.com/gin-gonic/gin" + "github.com/gofrs/uuid" api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/core" + "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/rocboss/paopao-ce/pkg/convert" + "github.com/rocboss/paopao-ce/pkg/util" + "github.com/rocboss/paopao-ce/pkg/xerror" + "github.com/sirupsen/logrus" ) var ( _ api.Priv = (*privSrv)(nil) _ api.PrivBinding = (*privBinding)(nil) _ api.PrivRender = (*privRender)(nil) + + _uploadAttachmentTypeMap = map[string]core.AttachmentType{ + "public/image": core.AttachmentTypeImage, + "public/avatar": core.AttachmentTypeImage, + "public/video": core.AttachmentTypeVideo, + "attachment": core.AttachmentTypeOther, + } ) type privSrv struct { - base.BaseServant api.UnimplementedPrivServant + *base.DaoServant + + oss core.ObjectStorageService } type privBinding struct { @@ -32,12 +53,530 @@ type privRender struct { *api.UnimplementedPrivRender } +func (b *privBinding) BindUploadAttachment(c *gin.Context) (*web.UploadAttachmentReq, mir.Error) { + UserId, exist := base.UserIdFrom(c) + if !exist { + return nil, xerror.UnauthorizedAuthNotExist + } + uploadType := c.Request.FormValue("type") + file, fileHeader, err := c.Request.FormFile("file") + if err != nil { + return nil, _errFileUploadFailed + } + if err := fileCheck(uploadType, fileHeader.Size); err != nil { + return nil, err + } + contentType := fileHeader.Header.Get("Content-Type") + fileExt, xerr := getFileExt(contentType) + if xerr != nil { + return nil, xerr + } + return &web.UploadAttachmentReq{ + SimpleInfo: web.SimpleInfo{ + Uid: UserId, + }, + UploadType: uploadType, + ContentType: contentType, + File: file, + FileSize: fileHeader.Size, + FileExt: fileExt, + }, nil +} + +func (b *privBinding) BindDownloadAttachmentPrecheck(c *gin.Context) (*web.DownloadAttachmentPrecheckReq, mir.Error) { + user, exist := base.UserFrom(c) + if !exist { + return nil, xerror.UnauthorizedAuthNotExist + } + return &web.DownloadAttachmentPrecheckReq{ + BaseInfo: web.BaseInfo{ + User: user, + }, + ContentID: convert.StrTo(c.Query("id")).MustInt64(), + }, nil +} + +func (b *privBinding) BindDownloadAttachment(c *gin.Context) (*web.DownloadAttachmentReq, mir.Error) { + user, exist := base.UserFrom(c) + if !exist { + return nil, xerror.UnauthorizedAuthNotExist + } + return &web.DownloadAttachmentReq{ + BaseInfo: web.BaseInfo{ + User: user, + }, + ContentID: convert.StrTo(c.Query("id")).MustInt64(), + }, nil +} + +func (s *privBinding) BindCreateTweet(c *gin.Context) (*web.CreateTweetReq, mir.Error) { + v := &web.CreateTweetReq{} + err := s.BindAny(c, v) + v.ClientIP = c.ClientIP() + return v, err +} + func (s *privSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT(), chain.Priv()} } -func newPrivSrv() api.Priv { - return &privSrv{} +func (s *privSrv) UploadAttachment(req *web.UploadAttachmentReq) (*web.UploadAttachmentResp, mir.Error) { + defer req.File.Close() + + // 生成随机路径 + randomPath := uuid.Must(uuid.NewV4()).String() + ossSavePath := req.UploadType + "/" + generatePath(randomPath[:8]) + "/" + randomPath[9:] + req.FileExt + objectUrl, err := s.oss.PutObject(ossSavePath, req.File, req.FileSize, req.ContentType, false) + if err != nil { + logrus.Errorf("oss.putObject err: %s", err) + return nil, _errFileUploadFailed + } + + // 构造附件Model + attachment := &core.Attachment{ + UserID: req.Uid, + FileSize: req.FileSize, + Content: objectUrl, + Type: _uploadAttachmentTypeMap[req.UploadType], + } + if attachment.Type == core.AttachmentTypeImage { + var src image.Image + src, err = imaging.Decode(req.File) + if err == nil { + attachment.ImgWidth, attachment.ImgHeight = getImageSize(src.Bounds()) + } + } + attachment, err = s.Ds.CreateAttachment(attachment) + if err != nil { + logrus.Errorf("Ds.CreateAttachment err: %s", err) + return nil, _errFileUploadFailed + } + + return &web.UploadAttachmentResp{ + UserID: req.Uid, + FileSize: req.FileSize, + ImgWidth: attachment.ImgWidth, + ImgHeight: attachment.ImgHeight, + Type: attachment.Type, + Content: attachment.Content, + }, nil +} + +func (s *privSrv) DownloadAttachmentPrecheck(req *web.DownloadAttachmentPrecheckReq) (*web.DownloadAttachmentPrecheckResp, mir.Error) { + content, err := s.Ds.GetPostContentByID(req.ContentID) + if err != nil { + logrus.Errorf("Ds.GetPostContentByID err: %s", err) + return nil, _errInvalidDownloadReq + } + resp := &web.DownloadAttachmentPrecheckResp{true} + if content.Type == core.ContentTypeChargeAttachment { + tweet, err := s.GetTweetBy(content.PostID) + if err != nil { + logrus.Errorf("get tweet err: %v", err) + return nil, _errInvalidDownloadReq + } + // 发布者或管理员免费下载 + if tweet.UserID == req.User.ID || req.User.IsAdmin { + return resp, nil + } + // 检测是否有购买记录 + resp.Paid = s.checkPostAttachmentIsPaid(req.ContentID, req.User.ID) + } + return resp, nil +} + +func (s *privSrv) DownloadAttachment(req *web.DownloadAttachmentReq) (*web.DownloadAttachmentResp, mir.Error) { + content, err := s.Ds.GetPostContentByID(req.ContentID) + if err != nil { + logrus.Errorf("s.GetPostContentByID err: %v", err) + return nil, _errInvalidDownloadReq + } + // 收费附件 + if content.Type == core.ContentTypeChargeAttachment { + post, err := s.GetTweetBy(content.PostID) + if err != nil { + logrus.Errorf("s.GetTweetBy err: %v", err) + return nil, xerror.ServerError + } + paidFlag := false + // 发布者或管理员免费下载 或者 检测是否有购买记录 + if post.UserID == req.User.ID || req.User.IsAdmin || s.checkPostAttachmentIsPaid(post.ID, req.User.ID) { + paidFlag = true + } + // 未购买,则尝试购买 + if !paidFlag { + err := s.buyPostAttachment(&core.Post{ + Model: &core.Model{ + ID: post.ID, + }, + UserID: post.UserID, + AttachmentPrice: post.AttachmentPrice, + }, req.User) + if err != nil { + return nil, err + } + } + } + // 签发附件下载链接 + objectKey := s.oss.ObjectKey(content.Content) + signedURL, err := s.oss.SignURL(objectKey, 60) + if err != nil { + logrus.Errorf("client.SignURL err: %v", err) + return nil, _errDownloadReqError + } + return &web.DownloadAttachmentResp{ + SignedURL: signedURL, + }, nil +} + +func (s *privSrv) CreateTweet(req *web.CreateTweetReq) (_ *web.CreateTweetResp, xerr mir.Error) { + var mediaContents []string + defer func() { + if xerr != nil { + deleteOssObjects(s.oss, mediaContents) + } + }() + + contents, err := persistMediaContents(s.oss, req.Contents) + if err != nil { + return nil, _errCreatePostFailed + } + mediaContents = contents + tags := tagsFrom(req.Tags) + post := &core.Post{ + UserID: req.User.ID, + Tags: strings.Join(tags, ","), + IP: req.ClientIP, + IPLoc: util.GetIPLoc(req.ClientIP), + AttachmentPrice: req.AttachmentPrice, + Visibility: req.Visibility, + } + post, err = s.Ds.CreatePost(post) + if err != nil { + logrus.Errorf("Ds.CreatePost err: %s", err) + return nil, _errCreatePostFailed + } + + // 创建推文内容 + for _, item := range req.Contents { + if err := item.Check(s.Ds); err != nil { + // 属性非法 + logrus.Infof("contents check err: %s", err) + continue + } + if item.Type == core.ContentTypeAttachment && req.AttachmentPrice > 0 { + item.Type = core.ContentTypeChargeAttachment + } + postContent := &core.PostContent{ + PostID: post.ID, + UserID: req.User.ID, + Content: item.Content, + Type: item.Type, + Sort: item.Sort, + } + if _, err = s.Ds.CreatePostContent(postContent); err != nil { + logrus.Infof("Ds.CreatePostContent err: %s", err) + return nil, _errCreateCommentFailed + } + } + + // 私密推文不创建标签与用户提醒 + if post.Visibility != core.PostVisitPrivate { + // 创建标签 + for _, t := range tags { + tag := &core.Tag{ + UserID: req.User.ID, + Tag: t, + } + s.Ds.CreateTag(tag) + } + + // 创建用户消息提醒 + for _, u := range req.Users { + user, err := s.Ds.GetUserByUsername(u) + if err != nil || user.ID == req.User.ID { + continue + } + + // 创建消息提醒 + // TODO: 优化消息提醒处理机制 + go s.Ds.CreateMessage(&core.Message{ + SenderUserID: req.User.ID, + ReceiverUserID: user.ID, + Type: core.MsgTypePost, + Brief: "在新发布的泡泡动态中@了你", + PostID: post.ID, + }) + } + } + // 推送Search + go s.PushPostToSearch(post) + + formatedPosts, err := s.Ds.RevampPosts([]*core.PostFormated{post.Format()}) + if err != nil { + logrus.Infof("Ds.RevampPosts err: %s", err) + return nil, _errCreatePostFailed + } + return (*web.CreateTweetResp)(formatedPosts[0]), nil +} + +func (s *privSrv) DeleteTweet(req *web.DeleteTweetReq) mir.Error { + if req.User == nil { + return _errNoPermission + } + post, err := s.Ds.GetPostByID(req.ID) + if err != nil { + logrus.Errorf("Ds.GetPostByID err: %s", err) + return _errGetPostFailed + } + if post.UserID != req.User.ID && !req.User.IsAdmin { + return _errNoPermission + } + mediaContents, err := s.Ds.DeletePost(post) + if err != nil { + logrus.Errorf("Ds.DeletePost delete post failed: %s", err) + return _errDeletePostFailed + } + // 删除推文的媒体内容 + deleteOssObjects(s.oss, mediaContents) + // 删除索引 + s.DeleteSearchPost(post) + if err != nil { + logrus.Errorf("s.DeleteSearchPost failed: %s", err) + return _errDeletePostFailed + } + return nil +} + +func (s *privSrv) CollectionTweet(req *web.CollectionTweetReq) (*web.CollectionTweetResp, mir.Error) { + status := false + collection, err := s.Ds.GetUserPostCollection(req.ID, req.Uid) + if err != nil { + // 创建Star + if _, xerr := s.createPostCollection(req.ID, req.Uid); xerr != nil { + return nil, xerr + } + status = true + } else { + // 取消Star + if xerr := s.deletePostCollection(collection); xerr != nil { + return nil, xerr + } + } + return &web.CollectionTweetResp{ + Status: status, + }, nil +} + +func (s *privSrv) StarTweet(req *web.StarTweetReq) (*web.StarTweetResp, mir.Error) { + status := false + star, err := s.Ds.GetUserPostStar(req.ID, req.Uid) + if err != nil { + // 创建Star + if _, xerr := s.createPostStar(req.ID, req.Uid); xerr != nil { + return nil, xerr + } + status = true + } else { + // 取消Star + if xerr := s.deletePostStar(star); xerr != nil { + return nil, xerr + } + } + return &web.StarTweetResp{ + Status: status, + }, nil +} + +func (s *privSrv) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mir.Error) { + if req.Visibility >= core.PostVisitInvalid { + return nil, xerror.InvalidParams + } + post, err := s.Ds.GetPostByID(req.User.ID) + if err != nil { + return nil, _errVisblePostFailed + } + if xerr := checkPermision(req.User, post.UserID); xerr != nil { + return nil, xerr + } + if err = s.Ds.VisiblePost(post, req.Visibility); err != nil { + logrus.Warnf("update post failure: %v", err) + return nil, _errVisblePostFailed + } + + // 推送Search + post.Visibility = req.Visibility + go s.PushPostToSearch(post) + + return &web.VisiblePostResp{ + Visibility: req.Visibility, + }, nil +} + +func (s *privSrv) StickTweet(req *web.StickTweetReq) (*web.StickTweetResp, mir.Error) { + post, err := s.Ds.GetPostByID(req.ID) + if err != nil { + logrus.Errorf("Ds.GetPostByID err: %v\n", err) + return nil, _errStickPostFailed + } + + if !req.User.IsAdmin { + return nil, _errNoPermission + } + if err = s.Ds.StickPost(post); err != nil { + return nil, _errStickPostFailed + } + return &web.StickTweetResp{ + StickStatus: 1 - post.IsTop, + }, nil +} + +func (s *privSrv) LockTweet(req *web.LockTweetReq) (*web.LockTweetResp, mir.Error) { + post, err := s.Ds.GetPostByID(req.ID) + if err != nil { + return nil, _errLockPostFailed + } + + if post.UserID != req.User.ID && !req.User.IsAdmin { + return nil, _errNoPermission + } + + if err := s.Ds.LockPost(post); err != nil { + return nil, _errLockPostFailed + } + return &web.LockTweetResp{ + LockStatus: 1 - post.IsLock, + }, nil +} + +func (s *privSrv) createPostStar(postID, userID int64) (*core.PostStar, mir.Error) { + // 加载Post + post, err := s.Ds.GetPostByID(postID) + if err != nil { + return nil, xerror.ServerError + } + + // 私密post不可操作 + if post.Visibility == core.PostVisitPrivate { + return nil, _errNoPermission + } + + star, err := s.Ds.CreatePostStar(postID, userID) + if err != nil { + return nil, xerror.ServerError + } + + // 更新Post点赞数 + post.UpvoteCount++ + s.Ds.UpdatePost(post) + + // 更新索引 + s.PushPostToSearch(post) + + return star, nil +} + +func (s *privSrv) deletePostStar(star *core.PostStar) mir.Error { + err := s.Ds.DeletePostStar(star) + if err != nil { + return xerror.ServerError + } + // 加载Post + post, err := s.Ds.GetPostByID(star.PostID) + if err != nil { + return xerror.ServerError + } + + // 私密post不可操作 + if post.Visibility == core.PostVisitPrivate { + return _errNoPermission + } + + // 更新Post点赞数 + post.UpvoteCount-- + s.Ds.UpdatePost(post) + + // 更新索引 + s.PushPostToSearch(post) + + return nil +} + +func (s *privSrv) createPostCollection(postID, userID int64) (*core.PostCollection, mir.Error) { + // 加载Post + post, err := s.Ds.GetPostByID(postID) + if err != nil { + return nil, xerror.ServerError + } + + // 私密post不可操作 + if post.Visibility == core.PostVisitPrivate { + return nil, _errNoPermission + } + + collection, err := s.Ds.CreatePostCollection(postID, userID) + if err != nil { + return nil, xerror.ServerError + } + + // 更新Post点赞数 + post.CollectionCount++ + s.Ds.UpdatePost(post) + + // 更新索引 + s.PushPostToSearch(post) + + return collection, nil +} + +func (s *privSrv) deletePostCollection(collection *core.PostCollection) mir.Error { + err := s.Ds.DeletePostCollection(collection) + if err != nil { + return xerror.ServerError + } + // 加载Post + post, err := s.Ds.GetPostByID(collection.PostID) + if err != nil { + return xerror.ServerError + } + + // 私密post不可操作 + if post.Visibility == core.PostVisitPrivate { + return _errNoPermission + } + + // 更新Post点赞数 + post.CollectionCount-- + s.Ds.UpdatePost(post) + + // 更新索引 + s.PushPostToSearch(post) + + return nil +} + +func (s *privSrv) checkPostAttachmentIsPaid(postID, userID int64) bool { + bill, err := s.Ds.GetPostAttatchmentBill(postID, userID) + return err == nil && bill.Model != nil && bill.ID > 0 +} + +func (s *privSrv) buyPostAttachment(post *core.Post, user *core.User) mir.Error { + if user.Balance < post.AttachmentPrice { + return _errInsuffientDownloadMoney + } + // 执行购买 + if err := s.Ds.HandlePostAttachmentBought(post, user); err != nil { + logrus.Errorf("Ds.HandlePostAttachmentBought err: %s", err) + return xerror.ServerError + } + return nil +} + +func newPrivSrv(s *base.DaoServant, oss core.ObjectStorageService) api.Priv { + return &privSrv{ + DaoServant: s, + oss: oss, + } } func newPrivBinding() api.PrivBinding { diff --git a/internal/servants/web/utils.go b/internal/servants/web/utils.go index 1b5a05d7..2481b36d 100644 --- a/internal/servants/web/utils.go +++ b/internal/servants/web/utils.go @@ -1,13 +1,21 @@ +// 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 ( + "image" "strings" "unicode/utf8" "github.com/alimy/mir/v3" "github.com/gofrs/uuid" "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/model/web" "github.com/rocboss/paopao-ce/pkg/util" + "github.com/rocboss/paopao-ce/pkg/xerror" + "github.com/sirupsen/logrus" ) // checkPassword 密码检查 @@ -45,3 +53,93 @@ func deleteOssObjects(oss core.ObjectStorageService, mediaContents []string) { oss.DeleteObject(oss.ObjectKey(mediaContents[0])) } } + +// persistMediaContents 获取媒体内容并持久化 +func persistMediaContents(oss core.ObjectStorageService, contents []*web.PostContentItem) (items []string, err error) { + items = make([]string, 0, len(contents)) + for _, item := range contents { + switch item.Type { + case core.ContentTypeImage, + core.ContentTypeVideo, + core.ContentTypeAudio, + core.ContentTypeAttachment, + core.ContentTypeChargeAttachment: + items = append(items, item.Content) + if err != nil { + continue + } + if err = oss.PersistObject(oss.ObjectKey(item.Content)); err != nil { + logrus.Errorf("service.persistMediaContents failed: %s", err) + } + } + } + return +} + +func fileCheck(uploadType string, size int64) mir.Error { + if uploadType != "public/video" && + uploadType != "public/image" && + uploadType != "public/avatar" && + uploadType != "attachment" { + return xerror.InvalidParams + } + if size > 1024*1024*100 { + return _errFileInvalidSize.WithDetails("最大允许100MB") + } + return nil +} + +func getFileExt(s string) (string, mir.Error) { + switch s { + case "image/png": + return ".png", nil + case "image/jpg": + return ".jpg", nil + case "image/jpeg": + return ".jpeg", nil + case "image/gif": + return ".gif", nil + case "video/mp4": + return ".mp4", nil + case "video/quicktime": + return ".mov", nil + case "application/zip": + return ".zip", nil + default: + return "", _errFileInvalidExt.WithDetails("仅允许 png/jpg/gif/mp4/mov/zip 类型") + } +} + +func generatePath(s string) string { + n := len(s) + if n <= 2 { + return s + } + return generatePath(s[:n-2]) + "/" + s[n-2:] +} + +func getImageSize(img image.Rectangle) (int, int) { + b := img.Bounds() + width := b.Max.X + height := b.Max.Y + return width, height +} + +func tagsFrom(originTags []string) []string { + tags := make([]string, 0, len(originTags)) + for _, tag := range originTags { + // TODO: 优化tag有效性检测 + if tag = strings.TrimSpace(tag); len(tag) > 0 { + tags = append(tags, tag) + } + } + return tags +} + +// checkPermision 检查是否拥有者或管理员 +func checkPermision(user *core.User, targetUserId int64) mir.Error { + if user == nil || (user.ID != targetUserId && !user.IsAdmin) { + return _errNoPermission + } + return nil +} diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index f9f3127b..ee74eecf 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -17,17 +17,17 @@ import ( // RouteWeb register web route func RouteWeb(e *gin.Engine) { - ts := dao.TweetSearchService() oss := dao.ObjectStorageService() ds := &base.DaoServant{ Redis: conf.Redis, Ds: dao.DataService(), + Ts: dao.TweetSearchService(), } // aways register servants api.RegisterAdminServant(e, newAdminSrv(ds), newAdminBinding(), newAdminRender()) - api.RegisterCoreServant(e, newCoreSrv(ds, ts, oss), newCoreBinding(), newCoreRender()) + api.RegisterCoreServant(e, newCoreSrv(ds, oss), newCoreBinding(), newCoreRender()) api.RegisterLooseServant(e, newLooseSrv(), newLooseBinding(), newLooseRender()) - api.RegisterPrivServant(e, newPrivSrv(), newPrivBinding(), newPrivRender()) + api.RegisterPrivServant(e, newPrivSrv(ds, oss), newPrivBinding(), newPrivRender()) api.RegisterPubServant(e, newPubSrv(), newPubBinding(), newPubRender()) // regster servants if needed by configure cfg.In(cfg.Actions{ diff --git a/internal/servants/web/xerror.go b/internal/servants/web/xerror.go index 544053b2..4de0f4b7 100644 --- a/internal/servants/web/xerror.go +++ b/internal/servants/web/xerror.go @@ -76,4 +76,8 @@ var ( _errDeleteFriendFailed = xerror.NewError(80006, "删除好友失败") _errGetContactsFailed = xerror.NewError(80007, "获取联系人列表失败") _errNoActionToSelf = xerror.NewError(80008, "不允许对自己操作") + + _errFileUploadFailed = xerror.NewError(10200, "文件上传失败") + _errFileInvalidExt = xerror.NewError(10201, "文件类型不合法") + _errFileInvalidSize = xerror.NewError(10202, "文件大小超限") ) diff --git a/mirc/web/v1/priv.go b/mirc/web/v1/priv.go index 86321a4e..f06d6c8d 100644 --- a/mirc/web/v1/priv.go +++ b/mirc/web/v1/priv.go @@ -16,34 +16,34 @@ type Priv struct { Group Group `mir:"v1"` // UploadAttachment 上传资源 - UploadAttachment func(Post) `mir:"/attachment"` + UploadAttachment func(Post, web.UploadAttachmentReq) web.UploadAttachmentResp `mir:"/attachment"` // DownloadAttachmentPrecheck 下载资源预检 - DownloadAttachmentPrecheck func(Get) `mir:"/attachment/precheck"` + DownloadAttachmentPrecheck func(Get, web.DownloadAttachmentPrecheckReq) web.DownloadAttachmentPrecheckResp `mir:"/attachment/precheck"` // DownloadAttachment 下载资源 - DownloadAttachment func(Get) `mir:"/attachment"` + DownloadAttachment func(Get, web.DownloadAttachmentReq) web.DownloadAttachmentResp `mir:"/attachment"` // CreateTweet 发布动态 CreateTweet func(Post, web.CreateTweetReq) web.CreateTweetResp `mir:"/post"` // DeleteTweet 删除动态 - DeleteTweet func(Delete) `mir:"/post"` + DeleteTweet func(Delete, web.DeleteTweetReq) `mir:"/post"` // StarTweet 动态点赞操作 - StarTweet func(Post) `mir:"/post/start"` + StarTweet func(Post, web.StarTweetReq) web.StarTweetResp `mir:"/post/start"` // CollectionTweet 动态收藏操作 - CollectionTweet func(Post) `mir:"/post/collection"` + CollectionTweet func(Post, web.CollectionTweetReq) web.CollectionTweetResp `mir:"/post/collection"` // LockTweet 锁定动态 - LockTweet func(Post) `mir:"/post/lock"` + LockTweet func(Post, web.LockTweetReq) web.LockTweetResp `mir:"/post/lock"` // StickTweet 置顶动态 - StickTweet func(Post) `mir:"/post/stick"` + StickTweet func(Post, web.StickTweetReq) web.StickTweetResp `mir:"/post/stick"` // VisiblePost 修改动态可见度 - VisiblePost func(Post) `mir:"/post/visibility"` + VisiblePost func(Post, web.VisiblePostReq) web.VisiblePostResp `mir:"/post/visibility"` // CreateTweetComment 发布动态评论 CreateComment func(Post) `mir:"/post/comment"` From bc4596721ee2c2b9df31f4304fa1f979a45fe533 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 30 Dec 2022 18:21:06 +0800 Subject: [PATCH 58/65] mir: add priv api implement full implement for new web service --- auto/api/v1/priv.go | 90 +++++++--- internal/model/web/priv.go | 29 ++++ internal/servants/web/priv.go | 310 +++++++++++++++++++++++++++++++++- mirc/web/v1/priv.go | 8 +- 4 files changed, 408 insertions(+), 29 deletions(-) diff --git a/auto/api/v1/priv.go b/auto/api/v1/priv.go index 29b39a92..8e9b4856 100644 --- a/auto/api/v1/priv.go +++ b/auto/api/v1/priv.go @@ -14,10 +14,10 @@ type Priv interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - DeleteCommentReply() mir.Error - CreateCommentReply() mir.Error - DeleteComment() mir.Error - CreateComment() mir.Error + DeleteCommentReply(*web.DeleteCommentReplyReq) mir.Error + CreateCommentReply(*web.CreateCommentReplyReq) (*web.CreateCommentReplyResp, mir.Error) + DeleteComment(*web.DeleteCommentReq) mir.Error + CreateComment(*web.CreateCommentReq) (*web.CreateCommentResp, mir.Error) VisiblePost(*web.VisiblePostReq) (*web.VisiblePostResp, mir.Error) StickTweet(*web.StickTweetReq) (*web.StickTweetResp, mir.Error) LockTweet(*web.LockTweetReq) (*web.LockTweetResp, mir.Error) @@ -33,6 +33,10 @@ type Priv interface { } type PrivBinding interface { + BindDeleteCommentReply(*gin.Context) (*web.DeleteCommentReplyReq, mir.Error) + BindCreateCommentReply(*gin.Context) (*web.CreateCommentReplyReq, mir.Error) + BindDeleteComment(*gin.Context) (*web.DeleteCommentReq, mir.Error) + BindCreateComment(*gin.Context) (*web.CreateCommentReq, mir.Error) BindVisiblePost(*gin.Context) (*web.VisiblePostReq, mir.Error) BindStickTweet(*gin.Context) (*web.StickTweetReq, mir.Error) BindLockTweet(*gin.Context) (*web.LockTweetReq, mir.Error) @@ -49,9 +53,9 @@ type PrivBinding interface { type PrivRender interface { RenderDeleteCommentReply(*gin.Context, mir.Error) - RenderCreateCommentReply(*gin.Context, mir.Error) + RenderCreateCommentReply(*gin.Context, *web.CreateCommentReplyResp, mir.Error) RenderDeleteComment(*gin.Context, mir.Error) - RenderCreateComment(*gin.Context, mir.Error) + RenderCreateComment(*gin.Context, *web.CreateCommentResp, mir.Error) RenderVisiblePost(*gin.Context, *web.VisiblePostResp, mir.Error) RenderStickTweet(*gin.Context, *web.StickTweetResp, mir.Error) RenderLockTweet(*gin.Context, *web.LockTweetResp, mir.Error) @@ -81,7 +85,12 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderDeleteCommentReply(c, s.DeleteCommentReply()) + req, err := b.BindDeleteCommentReply(c) + if err != nil { + r.RenderDeleteCommentReply(c, err) + return + } + r.RenderDeleteCommentReply(c, s.DeleteCommentReply(req)) }) router.Handle("POST", "/post/comment/reply", func(c *gin.Context) { @@ -91,7 +100,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderCreateCommentReply(c, s.CreateCommentReply()) + req, err := b.BindCreateCommentReply(c) + if err != nil { + r.RenderCreateCommentReply(c, nil, err) + return + } + resp, err := s.CreateCommentReply(req) + r.RenderCreateCommentReply(c, resp, err) }) router.Handle("DELETE", "/post/comment", func(c *gin.Context) { @@ -101,7 +116,12 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderDeleteComment(c, s.DeleteComment()) + req, err := b.BindDeleteComment(c) + if err != nil { + r.RenderDeleteComment(c, err) + return + } + r.RenderDeleteComment(c, s.DeleteComment(req)) }) router.Handle("POST", "/post/comment", func(c *gin.Context) { @@ -111,7 +131,13 @@ func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) { default: } - r.RenderCreateComment(c, s.CreateComment()) + req, err := b.BindCreateComment(c) + if err != nil { + r.RenderCreateComment(c, nil, err) + return + } + resp, err := s.CreateComment(req) + r.RenderCreateComment(c, resp, err) }) router.Handle("POST", "/post/visibility", func(c *gin.Context) { @@ -283,20 +309,20 @@ func (UnimplementedPrivServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedPrivServant) DeleteCommentReply() mir.Error { +func (UnimplementedPrivServant) DeleteCommentReply(req *web.DeleteCommentReplyReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) CreateCommentReply() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) CreateCommentReply(req *web.CreateCommentReplyReq) (*web.CreateCommentReplyResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) DeleteComment() mir.Error { +func (UnimplementedPrivServant) DeleteComment(req *web.DeleteCommentReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPrivServant) CreateComment() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPrivServant) CreateComment(req *web.CreateCommentReq) (*web.CreateCommentResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedPrivServant) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mir.Error) { @@ -350,16 +376,16 @@ func (r *UnimplementedPrivRender) RenderDeleteCommentReply(c *gin.Context, err m r.RenderAny(c, nil, err) } -func (r *UnimplementedPrivRender) RenderCreateCommentReply(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderCreateCommentReply(c *gin.Context, data *web.CreateCommentReplyResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedPrivRender) RenderDeleteComment(c *gin.Context, err mir.Error) { r.RenderAny(c, nil, err) } -func (r *UnimplementedPrivRender) RenderCreateComment(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPrivRender) RenderCreateComment(c *gin.Context, data *web.CreateCommentResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedPrivRender) RenderVisiblePost(c *gin.Context, data *web.VisiblePostResp, err mir.Error) { @@ -409,6 +435,30 @@ type UnimplementedPrivBinding struct { BindAny func(*gin.Context, any) mir.Error } +func (b *UnimplementedPrivBinding) BindDeleteCommentReply(c *gin.Context) (*web.DeleteCommentReplyReq, mir.Error) { + obj := new(web.DeleteCommentReplyReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindCreateCommentReply(c *gin.Context) (*web.CreateCommentReplyReq, mir.Error) { + obj := new(web.CreateCommentReplyReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindDeleteComment(c *gin.Context) (*web.DeleteCommentReq, mir.Error) { + obj := new(web.DeleteCommentReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPrivBinding) BindCreateComment(c *gin.Context) (*web.CreateCommentReq, mir.Error) { + obj := new(web.CreateCommentReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedPrivBinding) BindVisiblePost(c *gin.Context) (*web.VisiblePostReq, mir.Error) { obj := new(web.VisiblePostReq) err := b.BindAny(c, obj) diff --git a/internal/model/web/priv.go b/internal/model/web/priv.go index 290f80bd..9a592141 100644 --- a/internal/model/web/priv.go +++ b/internal/model/web/priv.go @@ -81,6 +81,35 @@ type VisiblePostResp struct { Visibility core.PostVisibleT `json:"visibility"` } +type CreateCommentReq struct { + SimpleInfo `json:"-" binding:"-"` + PostID int64 `json:"post_id" binding:"required"` + Contents []*PostContentItem `json:"contents" binding:"required"` + Users []string `json:"users" binding:"required"` + ClientIP string `json:"-" binding:"-"` +} + +type CreateCommentResp core.Comment + +type CreateCommentReplyReq struct { + SimpleInfo `json:"-" binding:"-"` + CommentID int64 `json:"comment_id" binding:"required"` + Content string `json:"content" binding:"required"` + AtUserID int64 `json:"at_user_id"` + ClientIP string `json:"-" binding:"-"` +} + +type CreateCommentReplyResp core.CommentReply + +type DeleteCommentReq struct { + BaseInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` +} +type DeleteCommentReplyReq struct { + BaseInfo `json:"-" binding:"-"` + ID int64 `json:"id" binding:"required"` +} + type UploadAttachmentReq struct { SimpleInfo `json:"-" binding:"-"` UploadType string diff --git a/internal/servants/web/priv.go b/internal/servants/web/priv.go index 87bc95dd..f62cc1da 100644 --- a/internal/servants/web/priv.go +++ b/internal/servants/web/priv.go @@ -7,12 +7,14 @@ package web import ( "image" "strings" + "time" "github.com/alimy/mir/v3" "github.com/disintegration/imaging" "github.com/gin-gonic/gin" "github.com/gofrs/uuid" 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/web" "github.com/rocboss/paopao-ce/internal/servants/base" @@ -34,6 +36,8 @@ var ( "public/video": core.AttachmentTypeVideo, "attachment": core.AttachmentTypeOther, } + + _MaxCommentCount = conf.AppSetting.MaxCommentCount ) type privSrv struct { @@ -53,24 +57,33 @@ type privRender struct { *api.UnimplementedPrivRender } -func (b *privBinding) BindUploadAttachment(c *gin.Context) (*web.UploadAttachmentReq, mir.Error) { +func (b *privBinding) BindUploadAttachment(c *gin.Context) (_ *web.UploadAttachmentReq, xerr mir.Error) { UserId, exist := base.UserIdFrom(c) if !exist { return nil, xerror.UnauthorizedAuthNotExist } + uploadType := c.Request.FormValue("type") file, fileHeader, err := c.Request.FormFile("file") if err != nil { return nil, _errFileUploadFailed } + defer func() { + if xerr != nil { + file.Close() + } + }() + if err := fileCheck(uploadType, fileHeader.Size); err != nil { return nil, err } + contentType := fileHeader.Header.Get("Content-Type") fileExt, xerr := getFileExt(contentType) if xerr != nil { return nil, xerr } + return &web.UploadAttachmentReq{ SimpleInfo: web.SimpleInfo{ Uid: UserId, @@ -116,6 +129,20 @@ func (s *privBinding) BindCreateTweet(c *gin.Context) (*web.CreateTweetReq, mir. return v, err } +func (s *privBinding) BindCreateCommentReply(c *gin.Context) (*web.CreateCommentReplyReq, mir.Error) { + v := &web.CreateCommentReplyReq{} + err := s.BindAny(c, v) + v.ClientIP = c.ClientIP() + return v, err +} + +func (s *privBinding) BindCreateComment(c *gin.Context) (*web.CreateCommentReq, mir.Error) { + v := &web.CreateCommentReq{} + err := s.BindAny(c, v) + v.ClientIP = c.ClientIP() + return v, err +} + func (s *privSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT(), chain.Priv()} } @@ -168,7 +195,7 @@ func (s *privSrv) DownloadAttachmentPrecheck(req *web.DownloadAttachmentPrecheck logrus.Errorf("Ds.GetPostContentByID err: %s", err) return nil, _errInvalidDownloadReq } - resp := &web.DownloadAttachmentPrecheckResp{true} + resp := &web.DownloadAttachmentPrecheckResp{Paid: true} if content.Type == core.ContentTypeChargeAttachment { tweet, err := s.GetTweetBy(content.PostID) if err != nil { @@ -310,8 +337,7 @@ func (s *privSrv) CreateTweet(req *web.CreateTweetReq) (_ *web.CreateTweetResp, } } // 推送Search - go s.PushPostToSearch(post) - + s.PushPostToSearch(post) formatedPosts, err := s.Ds.RevampPosts([]*core.PostFormated{post.Format()}) if err != nil { logrus.Infof("Ds.RevampPosts err: %s", err) @@ -348,6 +374,223 @@ func (s *privSrv) DeleteTweet(req *web.DeleteTweetReq) mir.Error { return nil } +func (s *privSrv) DeleteCommentReply(req *web.DeleteCommentReplyReq) mir.Error { + reply, err := s.Ds.GetCommentReplyByID(req.ID) + if err != nil { + logrus.Errorf("Ds.GetCommentReplyByID err: %s", err) + return _errGetReplyFailed + } + if req.User.ID != reply.UserID && !req.User.IsAdmin { + return _errNoPermission + } + // 执行删除 + err = s.deletePostCommentReply(reply) + if err != nil { + logrus.Errorf("s.deletePostCommentReply err: %s", err) + return _errDeleteCommentFailed + } + return nil +} + +func (s *privSrv) CreateCommentReply(req *web.CreateCommentReplyReq) (*web.CreateCommentReplyResp, mir.Error) { + var ( + post *core.Post + comment *core.Comment + atUserID int64 + err error + ) + + if post, comment, atUserID, err = s.createPostPreHandler(req.CommentID, req.Uid, req.AtUserID); err != nil { + return nil, _errCreateReplyFailed + } + + // 创建评论 + reply := &core.CommentReply{ + CommentID: req.CommentID, + UserID: req.Uid, + Content: req.Content, + AtUserID: atUserID, + IP: req.ClientIP, + IPLoc: util.GetIPLoc(req.ClientIP), + } + + reply, err = s.Ds.CreateCommentReply(reply) + if err != nil { + return nil, _errCreateReplyFailed + } + + // 更新Post回复数 + post.CommentCount++ + post.LatestRepliedOn = time.Now().Unix() + s.Ds.UpdatePost(post) + + // 更新索引 + s.PushPostToSearch(post) + + // 创建用户消息提醒 + commentMaster, err := s.Ds.GetUserByID(comment.UserID) + if err == nil && commentMaster.ID != req.Uid { + go s.Ds.CreateMessage(&core.Message{ + SenderUserID: req.Uid, + ReceiverUserID: commentMaster.ID, + Type: core.MsgTypeReply, + Brief: "在泡泡评论下回复了你", + PostID: post.ID, + CommentID: comment.ID, + ReplyID: reply.ID, + }) + } + postMaster, err := s.Ds.GetUserByID(post.UserID) + if err == nil && postMaster.ID != req.Uid && commentMaster.ID != postMaster.ID { + go s.Ds.CreateMessage(&core.Message{ + SenderUserID: req.Uid, + ReceiverUserID: postMaster.ID, + Type: core.MsgTypeReply, + Brief: "在泡泡评论下发布了新回复", + PostID: post.ID, + CommentID: comment.ID, + ReplyID: reply.ID, + }) + } + if atUserID > 0 { + user, err := s.Ds.GetUserByID(atUserID) + if err == nil && user.ID != req.Uid && commentMaster.ID != user.ID && postMaster.ID != user.ID { + // 创建消息提醒 + go s.Ds.CreateMessage(&core.Message{ + SenderUserID: req.Uid, + ReceiverUserID: user.ID, + Type: core.MsgTypeReply, + Brief: "在泡泡评论的回复中@了你", + PostID: post.ID, + CommentID: comment.ID, + ReplyID: reply.ID, + }) + } + } + return (*web.CreateCommentReplyResp)(reply), nil +} + +func (s *privSrv) DeleteComment(req *web.DeleteCommentReq) mir.Error { + comment, err := s.Ds.GetCommentByID(req.ID) + if err != nil { + logrus.Errorf("Ds.GetCommentByID err: %v\n", err) + return _errGetCommentFailed + } + if req.User.ID != comment.UserID && !req.User.IsAdmin { + return _errNoPermission + } + // 加载post + post, err := s.Ds.GetPostByID(comment.PostID) + if err != nil { + return _errDeleteCommentFailed + } + // 更新post回复数 + post.CommentCount-- + if err := s.Ds.UpdatePost(post); err != nil { + logrus.Errorf("Ds.UpdatePost err: %s", err) + return _errDeleteCommentFailed + } + // TODO: 优化删除逻辑,事务化删除comment + if err := s.Ds.DeleteComment(comment); err != nil { + logrus.Errorf("Ds.DeleteComment err: %s", err) + return _errDeleteCommentFailed + } + return nil +} + +func (s *privSrv) CreateComment(req *web.CreateCommentReq) (_ *web.CreateCommentResp, xerr mir.Error) { + var ( + mediaContents []string + err error + ) + defer func() { + if xerr != nil { + deleteOssObjects(s.oss, mediaContents) + } + }() + + if mediaContents, err = persistMediaContents(s.oss, req.Contents); err != nil { + return nil, xerror.ServerError + } + + // 加载Post + post, err := s.Ds.GetPostByID(req.PostID) + if err != nil { + logrus.Errorf("Ds.GetPostByID err:%s", err) + return nil, xerror.ServerError + } + if post.CommentCount >= _MaxCommentCount { + return nil, _errMaxCommentCount + } + comment := &core.Comment{ + PostID: post.ID, + UserID: req.Uid, + IP: req.ClientIP, + IPLoc: util.GetIPLoc(req.ClientIP), + } + comment, err = s.Ds.CreateComment(comment) + if err != nil { + logrus.Errorf("Ds.CreateComment err:%s", err) + return nil, _errCreateCommentFailed + } + + for _, item := range req.Contents { + // 检查附件是否是本站资源 + if item.Type == core.ContentTypeImage || item.Type == core.ContentTypeVideo || item.Type == core.ContentTypeAttachment { + if err := s.Ds.CheckAttachment(item.Content); err != nil { + continue + } + } + postContent := &core.CommentContent{ + CommentID: comment.ID, + UserID: req.Uid, + Content: item.Content, + Type: item.Type, + Sort: item.Sort, + } + s.Ds.CreateCommentContent(postContent) + } + + // 更新Post回复数 + post.CommentCount++ + post.LatestRepliedOn = time.Now().Unix() + s.Ds.UpdatePost(post) + + // 更新索引 + s.PushPostToSearch(post) + + // 创建用户消息提醒 + postMaster, err := s.Ds.GetUserByID(post.UserID) + if err == nil && postMaster.ID != req.Uid { + go s.Ds.CreateMessage(&core.Message{ + SenderUserID: req.Uid, + ReceiverUserID: postMaster.ID, + Type: core.MsgtypeComment, + Brief: "在泡泡中评论了你", + PostID: post.ID, + CommentID: comment.ID, + }) + } + for _, u := range req.Users { + user, err := s.Ds.GetUserByUsername(u) + if err != nil || user.ID == req.Uid || user.ID == postMaster.ID { + continue + } + + // 创建消息提醒 + go s.Ds.CreateMessage(&core.Message{ + SenderUserID: req.Uid, + ReceiverUserID: user.ID, + Type: core.MsgtypeComment, + Brief: "在泡泡评论中@了你", + PostID: post.ID, + CommentID: comment.ID, + }) + } + + return (*web.CreateCommentResp)(comment), nil +} + func (s *privSrv) CollectionTweet(req *web.CollectionTweetReq) (*web.CollectionTweetResp, mir.Error) { status := false collection, err := s.Ds.GetUserPostCollection(req.ID, req.Uid) @@ -406,7 +649,7 @@ func (s *privSrv) VisiblePost(req *web.VisiblePostReq) (*web.VisiblePostResp, mi // 推送Search post.Visibility = req.Visibility - go s.PushPostToSearch(post) + s.PushPostToSearch(post) return &web.VisiblePostResp{ Visibility: req.Visibility, @@ -449,6 +692,63 @@ func (s *privSrv) LockTweet(req *web.LockTweetReq) (*web.LockTweetResp, mir.Erro }, nil } +func (s *privSrv) deletePostCommentReply(reply *core.CommentReply) error { + err := s.Ds.DeleteCommentReply(reply) + if err != nil { + return err + } + // 加载Comment + comment, err := s.Ds.GetCommentByID(reply.CommentID) + if err != nil { + return err + } + // 加载comment的post + post, err := s.Ds.GetPostByID(comment.PostID) + if err != nil { + return err + } + // 更新Post回复数 + post.CommentCount-- + post.LatestRepliedOn = time.Now().Unix() + s.Ds.UpdatePost(post) + // 更新索引 + s.PushPostToSearch(post) + return nil +} + +func (s *privSrv) createPostPreHandler(commentID int64, userID, atUserID int64) (*core.Post, *core.Comment, int64, + error) { + // 加载Comment + comment, err := s.Ds.GetCommentByID(commentID) + if err != nil { + return nil, nil, atUserID, err + } + + // 加载comment的post + post, err := s.Ds.GetPostByID(comment.PostID) + if err != nil { + return nil, nil, atUserID, err + } + + if post.CommentCount >= _MaxCommentCount { + return nil, nil, atUserID, _errMaxCommentCount + } + + if userID == atUserID { + atUserID = 0 + } + + if atUserID > 0 { + // 检测目前用户是否存在 + users, _ := s.Ds.GetUsersByIDs([]int64{atUserID}) + if len(users) == 0 { + atUserID = 0 + } + } + + return post, comment, atUserID, nil +} + func (s *privSrv) createPostStar(postID, userID int64) (*core.PostStar, mir.Error) { // 加载Post post, err := s.Ds.GetPostByID(postID) diff --git a/mirc/web/v1/priv.go b/mirc/web/v1/priv.go index f06d6c8d..e9737e02 100644 --- a/mirc/web/v1/priv.go +++ b/mirc/web/v1/priv.go @@ -46,14 +46,14 @@ type Priv struct { VisiblePost func(Post, web.VisiblePostReq) web.VisiblePostResp `mir:"/post/visibility"` // CreateTweetComment 发布动态评论 - CreateComment func(Post) `mir:"/post/comment"` + CreateComment func(Post, web.CreateCommentReq) web.CreateCommentResp `mir:"/post/comment"` // DeletePostComment 删除动态评论 - DeleteComment func(Delete) `mir:"/post/comment"` + DeleteComment func(Delete, web.DeleteCommentReq) `mir:"/post/comment"` // CreateCommentReply 发布评论回复 - CreateCommentReply func(Post) `mir:"/post/comment/reply"` + CreateCommentReply func(Post, web.CreateCommentReplyReq) web.CreateCommentReplyResp `mir:"/post/comment/reply"` // DeleteCommentReply 删除评论回复 - DeleteCommentReply func(Delete) `mir:"/post/comment/reply"` + DeleteCommentReply func(Delete, web.DeleteCommentReplyReq) `mir:"/post/comment/reply"` } From 058a30794dc540e0870e6b6baf0639b6d4f3283a Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 30 Dec 2022 20:07:59 +0800 Subject: [PATCH 59/65] mir: add pub api implement for new web service --- auto/api/v1/pub.go | 156 ++++++--- internal/model/web/pub.go | 70 +++- internal/servants/web/assets/assets.go | 12 + .../web/{routers/api => }/assets/comic.ttf | Bin internal/servants/web/pub.go | 330 +++++++++++++++++- internal/servants/web/routers/api/home.go | 7 +- internal/servants/web/utils.go | 60 ++++ internal/servants/web/web.go | 2 +- mirc/web/v1/pub.go | 16 +- pkg/debug/version.go | 6 +- 10 files changed, 588 insertions(+), 71 deletions(-) create mode 100644 internal/servants/web/assets/assets.go rename internal/servants/web/{routers/api => }/assets/comic.ttf (100%) diff --git a/auto/api/v1/pub.go b/auto/api/v1/pub.go index b783393a..7fe417e7 100644 --- a/auto/api/v1/pub.go +++ b/auto/api/v1/pub.go @@ -11,33 +11,38 @@ import ( ) type Pub interface { - TopicList() mir.Error - TweetComments() mir.Error + TopicList(*web.TopicListReq) (*web.TopicListResp, mir.Error) + TweetComments(*web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error) TweetDetail(*web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) - SendCaptcha() mir.Error - GetCaptcha() mir.Error - Register() mir.Error - Login() mir.Error - Version() mir.Error + SendCaptcha(*web.SendCaptchaReq) mir.Error + GetCaptcha() (*web.GetCaptchaResp, mir.Error) + Register(*web.RegisterReq) (*web.RegisterResp, mir.Error) + Login(*web.LoginReq) (*web.LoginResp, mir.Error) + Version() (*web.VersionResp, mir.Error) mustEmbedUnimplementedPubServant() } type PubBinding interface { + BindTopicList(*gin.Context) (*web.TopicListReq, mir.Error) + BindTweetComments(*gin.Context) (*web.TweetCommentsReq, mir.Error) BindTweetDetail(*gin.Context) (*web.TweetDetailReq, mir.Error) + BindSendCaptcha(*gin.Context) (*web.SendCaptchaReq, mir.Error) + BindRegister(*gin.Context) (*web.RegisterReq, mir.Error) + BindLogin(*gin.Context) (*web.LoginReq, mir.Error) mustEmbedUnimplementedPubBinding() } type PubRender interface { - RenderTopicList(*gin.Context, mir.Error) - RenderTweetComments(*gin.Context, mir.Error) + RenderTopicList(*gin.Context, *web.TopicListResp, mir.Error) + RenderTweetComments(*gin.Context, *web.TweetCommentsResp, mir.Error) RenderTweetDetail(*gin.Context, *web.TweetDetailResp, mir.Error) RenderSendCaptcha(*gin.Context, mir.Error) - RenderGetCaptcha(*gin.Context, mir.Error) - RenderRegister(*gin.Context, mir.Error) - RenderLogin(*gin.Context, mir.Error) - RenderVersion(*gin.Context, mir.Error) + RenderGetCaptcha(*gin.Context, *web.GetCaptchaResp, mir.Error) + RenderRegister(*gin.Context, *web.RegisterResp, mir.Error) + RenderLogin(*gin.Context, *web.LoginResp, mir.Error) + RenderVersion(*gin.Context, *web.VersionResp, mir.Error) mustEmbedUnimplementedPubRender() } @@ -54,7 +59,13 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { default: } - r.RenderTopicList(c, s.TopicList()) + req, err := b.BindTopicList(c) + if err != nil { + r.RenderTopicList(c, nil, err) + return + } + resp, err := s.TopicList(req) + r.RenderTopicList(c, resp, err) }) router.Handle("GET", "/post/comments", func(c *gin.Context) { @@ -64,7 +75,13 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { default: } - r.RenderTweetComments(c, s.TweetComments()) + req, err := b.BindTweetComments(c) + if err != nil { + r.RenderTweetComments(c, nil, err) + return + } + resp, err := s.TweetComments(req) + r.RenderTweetComments(c, resp, err) }) router.Handle("GET", "/post", func(c *gin.Context) { @@ -90,7 +107,12 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { default: } - r.RenderSendCaptcha(c, s.SendCaptcha()) + req, err := b.BindSendCaptcha(c) + if err != nil { + r.RenderSendCaptcha(c, err) + return + } + r.RenderSendCaptcha(c, s.SendCaptcha(req)) }) router.Handle("GET", "/captcha", func(c *gin.Context) { @@ -100,7 +122,8 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { default: } - r.RenderGetCaptcha(c, s.GetCaptcha()) + resp, err := s.GetCaptcha() + r.RenderGetCaptcha(c, resp, err) }) router.Handle("POST", "/auth/register", func(c *gin.Context) { @@ -110,7 +133,13 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { default: } - r.RenderRegister(c, s.Register()) + req, err := b.BindRegister(c) + if err != nil { + r.RenderRegister(c, nil, err) + return + } + resp, err := s.Register(req) + r.RenderRegister(c, resp, err) }) router.Handle("POST", "/auth/login", func(c *gin.Context) { @@ -120,7 +149,13 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { default: } - r.RenderLogin(c, s.Login()) + req, err := b.BindLogin(c) + if err != nil { + r.RenderLogin(c, nil, err) + return + } + resp, err := s.Login(req) + r.RenderLogin(c, resp, err) }) router.Handle("GET", "/", func(c *gin.Context) { @@ -130,7 +165,8 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { default: } - r.RenderVersion(c, s.Version()) + resp, err := s.Version() + r.RenderVersion(c, resp, err) }) } @@ -139,36 +175,36 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) { type UnimplementedPubServant struct { } -func (UnimplementedPubServant) TopicList() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPubServant) TopicList(req *web.TopicListReq) (*web.TopicListResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPubServant) TweetComments() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPubServant) TweetComments(req *web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedPubServant) TweetDetail(req *web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) { return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPubServant) SendCaptcha() mir.Error { +func (UnimplementedPubServant) SendCaptcha(req *web.SendCaptchaReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPubServant) GetCaptcha() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPubServant) GetCaptcha() (*web.GetCaptchaResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPubServant) Register() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPubServant) Register(req *web.RegisterReq) (*web.RegisterResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPubServant) Login() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPubServant) Login(req *web.LoginReq) (*web.LoginResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedPubServant) Version() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedPubServant) Version() (*web.VersionResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedPubServant) mustEmbedUnimplementedPubServant() {} @@ -178,12 +214,12 @@ type UnimplementedPubRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedPubRender) RenderTopicList(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPubRender) RenderTopicList(c *gin.Context, data *web.TopicListResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPubRender) RenderTweetComments(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPubRender) RenderTweetComments(c *gin.Context, data *web.TweetCommentsResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedPubRender) RenderTweetDetail(c *gin.Context, data *web.TweetDetailResp, err mir.Error) { @@ -194,20 +230,20 @@ func (r *UnimplementedPubRender) RenderSendCaptcha(c *gin.Context, err mir.Error r.RenderAny(c, nil, err) } -func (r *UnimplementedPubRender) RenderGetCaptcha(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPubRender) RenderGetCaptcha(c *gin.Context, data *web.GetCaptchaResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPubRender) RenderRegister(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPubRender) RenderRegister(c *gin.Context, data *web.RegisterResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPubRender) RenderLogin(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPubRender) RenderLogin(c *gin.Context, data *web.LoginResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedPubRender) RenderVersion(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedPubRender) RenderVersion(c *gin.Context, data *web.VersionResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedPubRender) mustEmbedUnimplementedPubRender() {} @@ -217,10 +253,40 @@ type UnimplementedPubBinding struct { BindAny func(*gin.Context, any) mir.Error } +func (b *UnimplementedPubBinding) BindTopicList(c *gin.Context) (*web.TopicListReq, mir.Error) { + obj := new(web.TopicListReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPubBinding) BindTweetComments(c *gin.Context) (*web.TweetCommentsReq, mir.Error) { + obj := new(web.TweetCommentsReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedPubBinding) BindTweetDetail(c *gin.Context) (*web.TweetDetailReq, mir.Error) { obj := new(web.TweetDetailReq) err := b.BindAny(c, obj) return obj, err } +func (b *UnimplementedPubBinding) BindSendCaptcha(c *gin.Context) (*web.SendCaptchaReq, mir.Error) { + obj := new(web.SendCaptchaReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPubBinding) BindRegister(c *gin.Context) (*web.RegisterReq, mir.Error) { + obj := new(web.RegisterReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedPubBinding) BindLogin(c *gin.Context) (*web.LoginReq, mir.Error) { + obj := new(web.LoginReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedPubBinding) mustEmbedUnimplementedPubBinding() {} diff --git a/internal/model/web/pub.go b/internal/model/web/pub.go index f0df15e2..7afaa0af 100644 --- a/internal/model/web/pub.go +++ b/internal/model/web/pub.go @@ -4,10 +4,74 @@ package web +import ( + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/base" + "github.com/rocboss/paopao-ce/pkg/debug" +) + +const ( + TagTypeHot TagType = "hot" + TagTypeNew TagType = "new" +) + +type TagType string + type TweetDetailReq struct { - // TODO + TweetId int64 `form:"id"` +} + +type TweetDetailResp core.PostFormated + +type TweetCommentsReq struct { + TweetId int64 `form:"id"` + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type TweetCommentsResp base.PageResp + +type TopicListReq struct { + Type TagType `json:"type" form:"type" binding:"required"` + Num int `json:"num" form:"num" binding:"required"` +} + +// TopicListResp 主题返回值 +// TODO: 优化内容定义 +type TopicListResp struct { + Topics []*core.TagFormated `json:"topics"` +} + +type GetCaptchaResp struct { + Id string `json:"id"` + Content string `json:"b64s"` +} + +type SendCaptchaReq struct { + Phone string `json:"phone" form:"phone" binding:"required"` + ImgCaptcha string `json:"img_captcha" form:"img_captcha" binding:"required"` + ImgCaptchaID string `json:"img_captcha_id" form:"img_captcha_id" binding:"required"` +} + +type VersionResp struct { + BuildInfo *debug.BuildInfo `json:"build_info"` +} + +type LoginReq struct { + Username string `json:"username" form:"username" binding:"required"` + Password string `json:"password" form:"password" binding:"required"` +} + +type LoginResp struct { + Token string `json:"token"` +} + +type RegisterReq struct { + Username string `json:"username" form:"username" binding:"required"` + Password string `json:"password" form:"password" binding:"required"` } -type TweetDetailResp struct { - // TODO +type RegisterResp struct { + UserId int64 `json:"id"` + Username string `json:"username"` } diff --git a/internal/servants/web/assets/assets.go b/internal/servants/web/assets/assets.go new file mode 100644 index 00000000..e69dbd67 --- /dev/null +++ b/internal/servants/web/assets/assets.go @@ -0,0 +1,12 @@ +// 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 assets + +import ( + _ "embed" +) + +//go:embed comic.ttf +var ComicBytes []byte diff --git a/internal/servants/web/routers/api/assets/comic.ttf b/internal/servants/web/assets/comic.ttf similarity index 100% rename from internal/servants/web/routers/api/assets/comic.ttf rename to internal/servants/web/assets/comic.ttf diff --git a/internal/servants/web/pub.go b/internal/servants/web/pub.go index f072a6b2..93c4f6c0 100644 --- a/internal/servants/web/pub.go +++ b/internal/servants/web/pub.go @@ -5,21 +5,51 @@ package web import ( + "bytes" + "context" + "encoding/base64" + "fmt" + "image/color" + "image/png" + "regexp" + "time" + "unicode/utf8" + + "github.com/afocus/captcha" + "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" + "github.com/gofrs/uuid" 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/web" "github.com/rocboss/paopao-ce/internal/servants/base" - "github.com/rocboss/paopao-ce/internal/servants/chain" + "github.com/rocboss/paopao-ce/internal/servants/web/assets" + "github.com/rocboss/paopao-ce/pkg/app" + "github.com/rocboss/paopao-ce/pkg/convert" + "github.com/rocboss/paopao-ce/pkg/debug" + "github.com/rocboss/paopao-ce/pkg/util" + "github.com/rocboss/paopao-ce/pkg/xerror" + "github.com/sirupsen/logrus" ) var ( _ api.Pub = (*pubSrv)(nil) _ api.PubBinding = (*pubBinding)(nil) _ api.PubRender = (*pubRender)(nil) + + _MaxPageSize = conf.AppSetting.MaxPageSize +) + +const ( + _LoginErrKey = "PaoPaoUserLoginErr" + _MaxLoginErrTimes = 10 + _MaxPhoneCaptcha = 10 ) type pubSrv struct { - base.BaseServant api.UnimplementedPubServant + *base.DaoServant } type pubBinding struct { @@ -32,12 +62,300 @@ type pubRender struct { *api.UnimplementedPubRender } -func (s *pubSrv) Chain() gin.HandlersChain { - return gin.HandlersChain{chain.JwtLoose()} +func (b *pubBinding) BindTweetComments(c *gin.Context) (*web.TweetCommentsReq, mir.Error) { + tweetId := convert.StrTo(c.Query("id")).MustInt64() + page, pageSize := app.GetPageOffset(c) + return &web.TweetCommentsReq{ + TweetId: tweetId, + Page: page, + PageSize: pageSize, + }, nil + +} + +func (s *pubSrv) TopicList(req *web.TopicListReq) (*web.TopicListResp, mir.Error) { + // tags, err := broker.GetPostTags(¶m) + num := req.Num + if num > _MaxPageSize { + num = _MaxPageSize + } + + conditions := &core.ConditionsT{} + if req.Type == web.TagTypeHot { + // 热门标签 + conditions = &core.ConditionsT{ + "ORDER": "quote_num DESC", + } + } else if req.Type == web.TagTypeNew { + // 热门标签 + conditions = &core.ConditionsT{ + "ORDER": "id DESC", + } + } + tags, err := s.Ds.GetTags(conditions, 0, num) + if err != nil { + return nil, _errGetPostTagsFailed + } + // 获取创建者User IDs + userIds := []int64{} + for _, tag := range tags { + userIds = append(userIds, tag.UserID) + } + users, _ := s.Ds.GetUsersByIDs(userIds) + tagsFormated := []*core.TagFormated{} + for _, tag := range tags { + tagFormated := tag.Format() + for _, user := range users { + if user.ID == tagFormated.UserID { + tagFormated.User = user.Format() + } + } + tagsFormated = append(tagsFormated, tagFormated) + } + return &web.TopicListResp{ + Topics: tagsFormated, + }, nil +} + +func (s *pubSrv) TweetComments(req *web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error) { + conditions := &core.ConditionsT{ + "post_id": req.TweetId, + "ORDER": "id ASC", + } + + comments, err := s.Ds.GetComments(conditions, (req.Page-1)*req.PageSize, req.PageSize) + if err != nil { + return nil, _errGetCommentsFailed + } + + userIDs := []int64{} + commentIDs := []int64{} + for _, comment := range comments { + userIDs = append(userIDs, comment.UserID) + commentIDs = append(commentIDs, comment.ID) + } + + users, err := s.Ds.GetUsersByIDs(userIDs) + if err != nil { + return nil, _errGetCommentsFailed + } + + contents, err := s.Ds.GetCommentContentsByIDs(commentIDs) + if err != nil { + return nil, _errGetCommentsFailed + } + + replies, err := s.Ds.GetCommentRepliesByID(commentIDs) + if err != nil { + return nil, _errGetCommentsFailed + } + + commentsFormated := []*core.CommentFormated{} + for _, comment := range comments { + commentFormated := comment.Format() + for _, content := range contents { + if content.CommentID == comment.ID { + commentFormated.Contents = append(commentFormated.Contents, content) + } + } + for _, reply := range replies { + if reply.CommentID == commentFormated.ID { + commentFormated.Replies = append(commentFormated.Replies, reply) + } + } + for _, user := range users { + if user.ID == comment.UserID { + commentFormated.User = user.Format() + } + } + commentsFormated = append(commentsFormated, commentFormated) + } + + // 获取总量 + totalRows, _ := s.Ds.GetCommentCount(conditions) + resp := base.PageRespFrom(contents, req.Page, req.PageSize, totalRows) + return (*web.TweetCommentsResp)(resp), nil +} + +func (s *pubSrv) TweetDetail(req *web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) { + post, err := s.Ds.GetPostByID(req.TweetId) + if err != nil { + return nil, _errGetPostFailed + } + postContents, err := s.Ds.GetPostContentsByIDs([]int64{post.ID}) + if err != nil { + return nil, _errGetPostFailed + } + users, err := s.Ds.GetUsersByIDs([]int64{post.UserID}) + if err != nil { + return nil, _errGetPostFailed + } + // 数据整合 + postFormated := post.Format() + for _, user := range users { + postFormated.User = user.Format() + } + for _, content := range postContents { + if content.PostID == post.ID { + postFormated.Contents = append(postFormated.Contents, content.Format()) + } + } + return (*web.TweetDetailResp)(postFormated), nil +} + +func (s *pubSrv) SendCaptcha(req *web.SendCaptchaReq) mir.Error { + ctx := context.Background() + + // 验证图片验证码 + if res, err := s.Redis.Get(ctx, "PaoPaoCaptcha:"+req.ImgCaptchaID).Result(); err != nil || res != req.ImgCaptcha { + return _errErrorCaptchaPassword + } + s.Redis.Del(ctx, "PaoPaoCaptcha:"+req.ImgCaptchaID).Result() + + // 今日频次限制 + if res, _ := s.Redis.Get(ctx, "PaoPaoSmsCaptcha:"+req.Phone).Result(); convert.StrTo(res).MustInt() >= _MaxPhoneCaptcha { + return _errTooManyPhoneCaptchaSend + } + + if err := s.Ds.SendPhoneCaptcha(req.Phone); err != nil { + return xerror.ServerError + } + // 写入计数缓存 + s.Redis.Incr(ctx, "PaoPaoSmsCaptcha:"+req.Phone).Result() + currentTime := time.Now() + endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, currentTime.Location()) + s.Redis.Expire(ctx, "PaoPaoSmsCaptcha:"+req.Phone, endTime.Sub(currentTime)) + + return nil +} + +func (s *pubSrv) GetCaptcha() (*web.GetCaptchaResp, mir.Error) { + cap := captcha.New() + if err := cap.AddFontFromBytes(assets.ComicBytes); err != nil { + logrus.Errorf("cap.AddFontFromBytes err:%s", err) + return nil, xerror.ServerError + } + cap.SetSize(160, 64) + cap.SetDisturbance(captcha.MEDIUM) + cap.SetFrontColor(color.RGBA{0, 0, 0, 255}) + cap.SetBkgColor(color.RGBA{218, 240, 228, 255}) + img, password := cap.Create(6, captcha.NUM) + emptyBuff := bytes.NewBuffer(nil) + if err := png.Encode(emptyBuff, img); err != nil { + logrus.Errorf("png.Encode err:%s", err) + return nil, xerror.ServerError + } + key := util.EncodeMD5(uuid.Must(uuid.NewV4()).String()) + // 五分钟有效期 + s.Redis.SetEX(context.Background(), "PaoPaoCaptcha:"+key, password, time.Minute*5) + return &web.GetCaptchaResp{ + Id: key, + Content: "data:image/png;base64," + base64.StdEncoding.EncodeToString(emptyBuff.Bytes()), + }, nil +} + +func (s *pubSrv) Register(req *web.RegisterReq) (*web.RegisterResp, mir.Error) { + // 用户名检查 + if err := s.validUsername(req.Username); err != nil { + return nil, err + } + // 密码检查 + if err := checkPassword(req.Password); err != nil { + logrus.Errorf("scheckPassword err: %v", err) + return nil, _errUserRegisterFailed + } + password, salt := encryptPasswordAndSalt(req.Password) + user := &core.User{ + Nickname: req.Username, + Username: req.Username, + Password: password, + Avatar: getRandomAvatar(), + Salt: salt, + Status: core.UserStatusNormal, + } + user, err := s.Ds.CreateUser(user) + if err != nil { + logrus.Errorf("Ds.CreateUser err: %s", err) + return nil, _errUserRegisterFailed + } + return &web.RegisterResp{ + UserId: user.ID, + Username: user.Username, + }, nil +} + +func (s *pubSrv) Login(req *web.LoginReq) (*web.LoginResp, mir.Error) { + ctx := context.Background() + user, err := s.Ds.GetUserByUsername(req.Username) + if err != nil { + logrus.Errorf("Ds.GetUserByUsername err:%s", err) + return nil, xerror.UnauthorizedAuthNotExist + } + + if user.Model != nil && user.ID > 0 { + if errTimes, err := s.Redis.Get(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result(); err == nil { + if convert.StrTo(errTimes).MustInt() >= _MaxLoginErrTimes { + return nil, _errTooManyLoginError + } + } + // 对比密码是否正确 + if validPassword(user.Password, req.Password, user.Salt) { + if user.Status == core.UserStatusClosed { + return nil, _errUserHasBeenBanned + } + // 清空登录计数 + s.Redis.Del(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)) + } else { + // 登录错误计数 + _, err = s.Redis.Incr(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID)).Result() + if err == nil { + s.Redis.Expire(ctx, fmt.Sprintf("%s:%d", _LoginErrKey, user.ID), time.Hour).Result() + } + return nil, xerror.UnauthorizedAuthFailed + } + } else { + return nil, xerror.UnauthorizedAuthNotExist + } + + token, err := app.GenerateToken(user) + if err != nil { + logrus.Errorf("app.GenerateToken err: %v", err) + return nil, xerror.UnauthorizedTokenGenerate + } + return &web.LoginResp{ + Token: token, + }, nil +} + +func (s *pubSrv) Version() (*web.VersionResp, mir.Error) { + return &web.VersionResp{ + BuildInfo: debug.ReadBuildInfo(), + }, nil } -func newPubSrv() api.Pub { - return &pubSrv{} +// validUsername 验证用户 +func (s *pubSrv) validUsername(username string) mir.Error { + // 检测用户是否合规 + if utf8.RuneCountInString(username) < 3 || utf8.RuneCountInString(username) > 12 { + return _errUsernameLengthLimit + } + + if !regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString(username) { + return _errUsernameCharLimit + } + + // 重复检查 + user, _ := s.Ds.GetUserByUsername(username) + if user.Model != nil && user.ID > 0 { + return _errUsernameHasExisted + } + return nil +} + +func newPubSrv(s *base.DaoServant) api.Pub { + return &pubSrv{ + DaoServant: s, + } } func newPubBinding() api.PubBinding { diff --git a/internal/servants/web/routers/api/home.go b/internal/servants/web/routers/api/home.go index b863b712..30f115a9 100644 --- a/internal/servants/web/routers/api/home.go +++ b/internal/servants/web/routers/api/home.go @@ -6,7 +6,6 @@ package api import ( "bytes" - _ "embed" "encoding/base64" "image/color" "image/png" @@ -17,6 +16,7 @@ import ( "github.com/gofrs/uuid" "github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/web/assets" "github.com/rocboss/paopao-ce/internal/servants/web/broker" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/convert" @@ -26,9 +26,6 @@ import ( "github.com/sirupsen/logrus" ) -//go:embed assets/comic.ttf -var comic []byte - const MAX_PHONE_CAPTCHA = 10 func Version(c *gin.Context) { @@ -53,7 +50,7 @@ func SyncSearchIndex(c *gin.Context) { func GetCaptcha(c *gin.Context) { cap := captcha.New() - if err := cap.AddFontFromBytes(comic); err != nil { + if err := cap.AddFontFromBytes(assets.ComicBytes); err != nil { panic(err.Error()) } diff --git a/internal/servants/web/utils.go b/internal/servants/web/utils.go index 2481b36d..e42e03b5 100644 --- a/internal/servants/web/utils.go +++ b/internal/servants/web/utils.go @@ -6,7 +6,9 @@ package web import ( "image" + "math/rand" "strings" + "time" "unicode/utf8" "github.com/alimy/mir/v3" @@ -18,6 +20,64 @@ import ( "github.com/sirupsen/logrus" ) +var defaultAvatars = []string{ + "https://assets.paopao.info/public/avatar/default/zoe.png", + "https://assets.paopao.info/public/avatar/default/william.png", + "https://assets.paopao.info/public/avatar/default/walter.png", + "https://assets.paopao.info/public/avatar/default/thomas.png", + "https://assets.paopao.info/public/avatar/default/taylor.png", + "https://assets.paopao.info/public/avatar/default/sophia.png", + "https://assets.paopao.info/public/avatar/default/sam.png", + "https://assets.paopao.info/public/avatar/default/ryan.png", + "https://assets.paopao.info/public/avatar/default/ruby.png", + "https://assets.paopao.info/public/avatar/default/quinn.png", + "https://assets.paopao.info/public/avatar/default/paul.png", + "https://assets.paopao.info/public/avatar/default/owen.png", + "https://assets.paopao.info/public/avatar/default/olivia.png", + "https://assets.paopao.info/public/avatar/default/norman.png", + "https://assets.paopao.info/public/avatar/default/nora.png", + "https://assets.paopao.info/public/avatar/default/natalie.png", + "https://assets.paopao.info/public/avatar/default/naomi.png", + "https://assets.paopao.info/public/avatar/default/miley.png", + "https://assets.paopao.info/public/avatar/default/mike.png", + "https://assets.paopao.info/public/avatar/default/lucas.png", + "https://assets.paopao.info/public/avatar/default/kylie.png", + "https://assets.paopao.info/public/avatar/default/julia.png", + "https://assets.paopao.info/public/avatar/default/joshua.png", + "https://assets.paopao.info/public/avatar/default/john.png", + "https://assets.paopao.info/public/avatar/default/jane.png", + "https://assets.paopao.info/public/avatar/default/jackson.png", + "https://assets.paopao.info/public/avatar/default/ivy.png", + "https://assets.paopao.info/public/avatar/default/isaac.png", + "https://assets.paopao.info/public/avatar/default/henry.png", + "https://assets.paopao.info/public/avatar/default/harry.png", + "https://assets.paopao.info/public/avatar/default/harold.png", + "https://assets.paopao.info/public/avatar/default/hanna.png", + "https://assets.paopao.info/public/avatar/default/grace.png", + "https://assets.paopao.info/public/avatar/default/george.png", + "https://assets.paopao.info/public/avatar/default/freddy.png", + "https://assets.paopao.info/public/avatar/default/frank.png", + "https://assets.paopao.info/public/avatar/default/finn.png", + "https://assets.paopao.info/public/avatar/default/emma.png", + "https://assets.paopao.info/public/avatar/default/emily.png", + "https://assets.paopao.info/public/avatar/default/edward.png", + "https://assets.paopao.info/public/avatar/default/clara.png", + "https://assets.paopao.info/public/avatar/default/claire.png", + "https://assets.paopao.info/public/avatar/default/chloe.png", + "https://assets.paopao.info/public/avatar/default/audrey.png", + "https://assets.paopao.info/public/avatar/default/arthur.png", + "https://assets.paopao.info/public/avatar/default/anna.png", + "https://assets.paopao.info/public/avatar/default/andy.png", + "https://assets.paopao.info/public/avatar/default/alfred.png", + "https://assets.paopao.info/public/avatar/default/alexa.png", + "https://assets.paopao.info/public/avatar/default/abigail.png", +} + +func getRandomAvatar() string { + rand.Seed(time.Now().UnixMicro()) + return defaultAvatars[rand.Intn(len(defaultAvatars))] +} + // checkPassword 密码检查 func checkPassword(password string) mir.Error { // 检测用户是否合规 diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index ee74eecf..fb112719 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -28,7 +28,7 @@ func RouteWeb(e *gin.Engine) { api.RegisterCoreServant(e, newCoreSrv(ds, oss), newCoreBinding(), newCoreRender()) api.RegisterLooseServant(e, newLooseSrv(), newLooseBinding(), newLooseRender()) api.RegisterPrivServant(e, newPrivSrv(ds, oss), newPrivBinding(), newPrivRender()) - api.RegisterPubServant(e, newPubSrv(), newPubBinding(), newPubRender()) + api.RegisterPubServant(e, newPubSrv(ds), newPubBinding(), newPubRender()) // regster servants if needed by configure cfg.In(cfg.Actions{ "Alipay": func() { diff --git a/mirc/web/v1/pub.go b/mirc/web/v1/pub.go index b69bc47b..2364f223 100644 --- a/mirc/web/v1/pub.go +++ b/mirc/web/v1/pub.go @@ -15,26 +15,26 @@ type Pub struct { Group Group `mir:"v1"` // Version 获取后台版本信息 - Version func(Get) `mir:"/"` + Version func(Get) web.VersionResp `mir:"/"` // Login 用户登录 - Login func(Post) `mir:"/auth/login"` + Login func(Post, web.LoginReq) web.LoginResp `mir:"/auth/login"` // Register 用户注册 - Register func(Post) `mir:"/auth/register"` + Register func(Post, web.RegisterReq) web.RegisterResp `mir:"/auth/register"` // GetCaptcha 获取验证码 - GetCaptcha func(Get) `mir:"/captcha"` + GetCaptcha func(Get) web.GetCaptchaResp `mir:"/captcha"` - // PostCaptcha 发送验证码 - SendCaptcha func(Post) `mir:"/captcha"` + // SendCaptcha 发送验证码 + SendCaptcha func(Post, web.SendCaptchaReq) `mir:"/captcha"` // TweetDetail 获取动态详情 TweetDetail func(Get, web.TweetDetailReq) web.TweetDetailResp `mir:"/post"` // TweetComments 获取动态评论 - TweetComments func(Get) `mir:"/post/comments"` + TweetComments func(Get, web.TweetCommentsReq) web.TweetCommentsResp `mir:"/post/comments"` // TopicList 获取话题列表 - TopicList func(Get) `mir:"/tags"` + TopicList func(Get, web.TopicListReq) web.TopicListResp `mir:"/tags"` } diff --git a/pkg/debug/version.go b/pkg/debug/version.go index 68236f05..12623f96 100644 --- a/pkg/debug/version.go +++ b/pkg/debug/version.go @@ -11,9 +11,9 @@ import ( var version, commitID, buildDate string type BuildInfo struct { - Version string - Sum string - BuildDate string + Version string `json:"version"` + Sum string `json:"sum"` + BuildDate string `json:"build_date"` } func VersionInfo() string { From 6b2f320cd8bff315bc0f56e26916d41a044b27a1 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 31 Dec 2022 14:33:12 +0800 Subject: [PATCH 60/65] mir: add loose api implement for new web service --- auto/api/v1/loose.go | 54 ++++++++++---- internal/model/web/loose.go | 42 ++++++++++- internal/model/web/pub.go | 4 +- internal/model/web/web.go | 2 +- internal/servants/base/base.go | 14 +++- internal/servants/web/alipay.go | 2 +- internal/servants/web/core.go | 1 - internal/servants/web/loose.go | 125 ++++++++++++++++++++++++++++++-- internal/servants/web/priv.go | 2 - internal/servants/web/pub.go | 4 +- internal/servants/web/web.go | 2 +- mirc/web/v1/loose.go | 4 +- pkg/app/pagination.go | 14 ++++ 13 files changed, 233 insertions(+), 37 deletions(-) diff --git a/auto/api/v1/loose.go b/auto/api/v1/loose.go index 02d12831..7d4d1046 100644 --- a/auto/api/v1/loose.go +++ b/auto/api/v1/loose.go @@ -14,22 +14,24 @@ type Loose interface { // Chain provide handlers chain for gin Chain() gin.HandlersChain - GetUserProfile() mir.Error - GetUserTweets() mir.Error + GetUserProfile(*web.GetUserProfileReq) (*web.GetUserProfileResp, mir.Error) + GetUserTweets(*web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error) Timeline(*web.TimelineReq) (*web.TimelineResp, mir.Error) mustEmbedUnimplementedLooseServant() } type LooseBinding interface { + BindGetUserProfile(*gin.Context) (*web.GetUserProfileReq, mir.Error) + BindGetUserTweets(*gin.Context) (*web.GetUserTweetsReq, mir.Error) BindTimeline(*gin.Context) (*web.TimelineReq, mir.Error) mustEmbedUnimplementedLooseBinding() } type LooseRender interface { - RenderGetUserProfile(*gin.Context, mir.Error) - RenderGetUserTweets(*gin.Context, mir.Error) + RenderGetUserProfile(*gin.Context, *web.GetUserProfileResp, mir.Error) + RenderGetUserTweets(*gin.Context, *web.GetUserTweetsResp, mir.Error) RenderTimeline(*gin.Context, *web.TimelineResp, mir.Error) mustEmbedUnimplementedLooseRender() @@ -50,7 +52,13 @@ func RegisterLooseServant(e *gin.Engine, s Loose, b LooseBinding, r LooseRender) default: } - r.RenderGetUserProfile(c, s.GetUserProfile()) + req, err := b.BindGetUserProfile(c) + if err != nil { + r.RenderGetUserProfile(c, nil, err) + return + } + resp, err := s.GetUserProfile(req) + r.RenderGetUserProfile(c, resp, err) }) router.Handle("GET", "/user/posts", func(c *gin.Context) { @@ -60,7 +68,13 @@ func RegisterLooseServant(e *gin.Engine, s Loose, b LooseBinding, r LooseRender) default: } - r.RenderGetUserTweets(c, s.GetUserTweets()) + req, err := b.BindGetUserTweets(c) + if err != nil { + r.RenderGetUserTweets(c, nil, err) + return + } + resp, err := s.GetUserTweets(req) + r.RenderGetUserTweets(c, resp, err) }) router.Handle("GET", "/posts", func(c *gin.Context) { @@ -89,12 +103,12 @@ func (UnimplementedLooseServant) Chain() gin.HandlersChain { return nil } -func (UnimplementedLooseServant) GetUserProfile() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedLooseServant) GetUserProfile(req *web.GetUserProfileReq) (*web.GetUserProfileResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedLooseServant) GetUserTweets() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedLooseServant) GetUserTweets(req *web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } func (UnimplementedLooseServant) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error) { @@ -108,12 +122,12 @@ type UnimplementedLooseRender struct { RenderAny func(*gin.Context, any, mir.Error) } -func (r *UnimplementedLooseRender) RenderGetUserProfile(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedLooseRender) RenderGetUserProfile(c *gin.Context, data *web.GetUserProfileResp, err mir.Error) { + r.RenderAny(c, data, err) } -func (r *UnimplementedLooseRender) RenderGetUserTweets(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedLooseRender) RenderGetUserTweets(c *gin.Context, data *web.GetUserTweetsResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedLooseRender) RenderTimeline(c *gin.Context, data *web.TimelineResp, err mir.Error) { @@ -127,6 +141,18 @@ type UnimplementedLooseBinding struct { BindAny func(*gin.Context, any) mir.Error } +func (b *UnimplementedLooseBinding) BindGetUserProfile(c *gin.Context) (*web.GetUserProfileReq, mir.Error) { + obj := new(web.GetUserProfileReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedLooseBinding) BindGetUserTweets(c *gin.Context) (*web.GetUserTweetsReq, mir.Error) { + obj := new(web.GetUserTweetsReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedLooseBinding) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) { obj := new(web.TimelineReq) err := b.BindAny(c, obj) diff --git a/internal/model/web/loose.go b/internal/model/web/loose.go index 6115e2cc..e505e35b 100644 --- a/internal/model/web/loose.go +++ b/internal/model/web/loose.go @@ -4,10 +4,46 @@ package web +import ( + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/servants/base" +) + type TimelineReq struct { - *BaseInfo `json:"-"` + BaseInfo `form:"-" binding:"-"` + Query string `form:"query"` + Visibility []core.PostVisibleT `form:"query"` + Type string `form:"type"` + Page int `form:"-" binding:"-"` + PageSize int `form:"-" binding:"-"` +} + +type TimelineResp base.PageResp + +type GetUserTweetsReq struct { + BaseInfo `form:"-" binding:"-"` + Username string `form:"username" binding:"required"` + Page int `form:"-" binding:"-"` + PageSize int `form:"-" binding:"-"` +} + +type GetUserTweetsResp base.PageResp + +type GetUserProfileReq struct { + BaseInfo `form:"-" binding:"-"` + Username string `form:"username" binding:"required"` +} + +type GetUserProfileResp struct { + ID int64 `json:"id"` + Nickname string `json:"nickname"` + Username string `json:"username"` + Status int `json:"status"` + Avatar string `json:"avatar"` + IsAdmin bool `json:"is_admin"` + IsFriend bool `json:"is_friend"` } -type TimelineResp struct { - // TODO +func (r *GetUserTweetsReq) SetPageInfo(page int, pageSize int) { + r.Page, r.PageSize = page, pageSize } diff --git a/internal/model/web/pub.go b/internal/model/web/pub.go index 7afaa0af..a951b33a 100644 --- a/internal/model/web/pub.go +++ b/internal/model/web/pub.go @@ -25,8 +25,8 @@ type TweetDetailResp core.PostFormated type TweetCommentsReq struct { TweetId int64 `form:"id"` - Page int `form:"page"` - PageSize int `form:"page_size"` + Page int `form:"-"` + PageSize int `form:"-"` } type TweetCommentsResp base.PageResp diff --git a/internal/model/web/web.go b/internal/model/web/web.go index a4a8941f..bec917fa 100644 --- a/internal/model/web/web.go +++ b/internal/model/web/web.go @@ -40,7 +40,7 @@ func BasePageReqFrom(c *gin.Context) (*BasePageReq, mir.Error) { if !ok { return nil, xerror.UnauthorizedTokenError } - page, pageSize := app.GetPageOffset(c) + page, pageSize := app.GetPageInfo(c) return &BasePageReq{ UserId: uid, Page: page, diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index ad3ab6a7..acc33bd6 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -15,6 +15,7 @@ import ( "github.com/gin-gonic/gin" "github.com/go-redis/redis/v8" "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/types" "github.com/rocboss/paopao-ce/pkg/xerror" ) @@ -47,6 +48,10 @@ type UserIdSetter interface { SetUserId(int64) } +type PageInfoSetter interface { + SetPageInfo(page, pageSize int) +} + func UserFrom(c *gin.Context) (*core.User, bool) { if u, exists := c.Get("USER"); exists { user, ok := u.(*core.User) @@ -87,6 +92,11 @@ func BindAny(c *gin.Context, obj any) mir.Error { uid, _ := UserIdFrom(c) setter.SetUserId(uid) } + // setup PageInfo if needed + if setter, ok := obj.(PageInfoSetter); ok { + page, pageSize := app.GetPageInfo(c) + setter.SetPageInfo(page, pageSize) + } return nil } @@ -142,7 +152,7 @@ func (s *DaoServant) PushPostsToSearch(c context.Context) { pages := math.Ceil(float64(totalRows) / float64(splitNum)) nums := int(pages) for i := 0; i < nums; i++ { - posts, postsFormated, err := s.getTweetList(&core.ConditionsT{}, i*splitNum, splitNum) + posts, postsFormated, err := s.GetTweetList(&core.ConditionsT{}, i*splitNum, splitNum) if err != nil || len(posts) != len(postsFormated) { continue } @@ -191,7 +201,7 @@ func (s *DaoServant) DeleteSearchPost(post *core.Post) error { return s.Ts.DeleteDocuments([]string{fmt.Sprintf("%d", post.ID)}) } -func (s *DaoServant) getTweetList(conditions *core.ConditionsT, offset, limit int) ([]*core.Post, []*core.PostFormated, error) { +func (s *DaoServant) GetTweetList(conditions *core.ConditionsT, offset, limit int) ([]*core.Post, []*core.PostFormated, error) { posts, err := s.Ds.GetPosts(conditions, offset, limit) if err != nil { return nil, nil, err diff --git a/internal/servants/web/alipay.go b/internal/servants/web/alipay.go index ab8401f7..c5ce3264 100644 --- a/internal/servants/web/alipay.go +++ b/internal/servants/web/alipay.go @@ -105,7 +105,7 @@ func (b *alipayPrivBinding) BindUserWalletBills(c *gin.Context) (*web.UserWallet if !ok { return nil, xerror.UnauthorizedTokenError } - page, pageSize := app.GetPageOffset(c) + page, pageSize := app.GetPageInfo(c) return &web.UserWalletBillsReq{ UserId: uid, Page: page, diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index 6173913a..92dcfbaa 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -47,7 +47,6 @@ type coreSrv struct { type coreBinding struct { *api.UnimplementedCoreBinding - base.BaseBinding } type coreRender struct { diff --git a/internal/servants/web/loose.go b/internal/servants/web/loose.go index 3b6e37a7..4b04ad36 100644 --- a/internal/servants/web/loose.go +++ b/internal/servants/web/loose.go @@ -5,10 +5,15 @@ package web import ( + "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/core" + "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/rocboss/paopao-ce/pkg/app" + "github.com/sirupsen/logrus" ) var ( @@ -18,26 +23,136 @@ var ( ) type looseSrv struct { - base.BaseServant api.UnimplementedLooseServant + *base.DaoServant } type looseBinding struct { - base.BaseBinding *api.UnimplementedLooseBinding } type looseRender struct { - base.BaseRender *api.UnimplementedLooseRender } +func (s *looseSrv) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) { + user, _ := base.UserFrom(c) + page, pageSize := app.GetPageInfo(c) + v := &web.TimelineReq{ + BaseInfo: web.BaseInfo{ + User: user, + }, + Query: c.Query("query"), + Type: "search", + Page: page, + PageSize: pageSize, + } + if c.Query("type") == "tag" { + v.Type = "tag" + } + return v, nil +} + func (s *looseSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JwtLoose()} } -func newLooseSrv() api.Loose { - return &looseSrv{} +func (s *looseSrv) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error) { + var resp *base.PageResp + offset, limit := (req.Page-1)*req.PageSize, req.PageSize + if req.Query == "" && req.Type == "search" { + res, err := s.Ds.IndexPosts(req.User, offset, limit) + if err != nil { + logrus.Errorf("Ds.IndexPosts err: %s", err) + return nil, _errGetPostsFailed + } + resp = base.PageRespFrom(res.Tweets, req.Page, req.PageSize, res.Total) + } else { + q := &core.QueryReq{ + Query: req.Query, + Type: core.SearchType(req.Type), + } + res, err := s.Ts.Search(req.User, q, offset, limit) + if err != nil { + logrus.Errorf("Ts.Search err: %s", err) + return nil, _errGetPostsFailed + } + posts, err := s.Ds.RevampPosts(res.Items) + if err != nil { + logrus.Errorf("Ds.RevampPosts err: %s", err) + return nil, _errGetPostsFailed + } + resp = base.PageRespFrom(posts, req.Page, req.PageSize, res.Total) + } + return (*web.TimelineResp)(resp), nil +} + +func (s *looseSrv) GetUserTweets(req *web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error) { + other, xerr := s.GetUserProfile(&web.GetUserProfileReq{ + BaseInfo: req.BaseInfo, + Username: req.Username, + }) + if xerr != nil { + return nil, xerr + } + + visibilities := []core.PostVisibleT{core.PostVisitPublic} + if req.User != nil { + if req.User.ID == other.ID || req.User.IsAdmin { + visibilities = append(visibilities, core.PostVisitPrivate, core.PostVisitFriend) + } else if other.IsFriend { + visibilities = append(visibilities, core.PostVisitFriend) + } + } + conditions := &core.ConditionsT{ + "user_id": other.ID, + "visibility IN ?": visibilities, + "ORDER": "latest_replied_on DESC", + } + _, posts, err := s.GetTweetList(conditions, (req.Page-1)*req.PageSize, req.PageSize) + if err != nil { + logrus.Errorf("s.GetTweetList err: %s", err) + return nil, _errGetPostsFailed + } + totalRows, err := s.Ds.GetPostCount(conditions) + if err != nil { + logrus.Errorf("s.GetPostCount err: %s", err) + return nil, _errGetPostsFailed + } + + resp := base.PageRespFrom(posts, req.Page, req.PageSize, totalRows) + return (*web.GetUserTweetsResp)(resp), nil +} + +func (s *looseSrv) GetUserProfile(req *web.GetUserProfileReq) (*web.GetUserProfileResp, mir.Error) { + he, err := s.Ds.GetUserByUsername(req.Username) + if err != nil { + logrus.Errorf("Ds.GetUserByUsername err: %s", err) + return nil, _errNoExistUsername + } + if he.Model == nil && he.ID <= 0 { + return nil, _errNoExistUsername + } + // 设定自己不是自己的朋友 + isFriend := !(req.User == nil || req.User.ID == he.ID) + if req.User != nil && req.User.ID != he.ID { + isFriend = s.Ds.IsFriend(req.User.ID, he.ID) + } + return &web.GetUserProfileResp{ + ID: he.ID, + Nickname: he.Nickname, + Username: he.Username, + Status: he.Status, + Avatar: he.Avatar, + IsAdmin: he.IsAdmin, + IsFriend: isFriend, + }, nil +} + +func newLooseSrv(s *base.DaoServant) api.Loose { + return &looseSrv{ + DaoServant: s, + } } func newLooseBinding() api.LooseBinding { diff --git a/internal/servants/web/priv.go b/internal/servants/web/priv.go index f62cc1da..5236cf4e 100644 --- a/internal/servants/web/priv.go +++ b/internal/servants/web/priv.go @@ -48,12 +48,10 @@ type privSrv struct { } type privBinding struct { - base.BaseBinding *api.UnimplementedPrivBinding } type privRender struct { - base.BaseRender *api.UnimplementedPrivRender } diff --git a/internal/servants/web/pub.go b/internal/servants/web/pub.go index 93c4f6c0..afc14779 100644 --- a/internal/servants/web/pub.go +++ b/internal/servants/web/pub.go @@ -53,18 +53,16 @@ type pubSrv struct { } type pubBinding struct { - base.BaseBinding *api.UnimplementedPubBinding } type pubRender struct { - base.BaseRender *api.UnimplementedPubRender } func (b *pubBinding) BindTweetComments(c *gin.Context) (*web.TweetCommentsReq, mir.Error) { tweetId := convert.StrTo(c.Query("id")).MustInt64() - page, pageSize := app.GetPageOffset(c) + page, pageSize := app.GetPageInfo(c) return &web.TweetCommentsReq{ TweetId: tweetId, Page: page, diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index fb112719..50f6a88b 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -26,7 +26,7 @@ func RouteWeb(e *gin.Engine) { // aways register servants api.RegisterAdminServant(e, newAdminSrv(ds), newAdminBinding(), newAdminRender()) api.RegisterCoreServant(e, newCoreSrv(ds, oss), newCoreBinding(), newCoreRender()) - api.RegisterLooseServant(e, newLooseSrv(), newLooseBinding(), newLooseRender()) + api.RegisterLooseServant(e, newLooseSrv(ds), newLooseBinding(), newLooseRender()) api.RegisterPrivServant(e, newPrivSrv(ds, oss), newPrivBinding(), newPrivRender()) api.RegisterPubServant(e, newPubSrv(ds), newPubBinding(), newPubRender()) // regster servants if needed by configure diff --git a/mirc/web/v1/loose.go b/mirc/web/v1/loose.go index 665a9837..887e3c9b 100644 --- a/mirc/web/v1/loose.go +++ b/mirc/web/v1/loose.go @@ -19,8 +19,8 @@ type Loose struct { Timeline func(Get, web.TimelineReq) web.TimelineResp `mir:"/posts"` // GetUserTweets 获取用户动态列表 - GetUserTweets func(Get) `mir:"/user/posts"` + GetUserTweets func(Get, web.GetUserTweetsReq) web.GetUserTweetsResp `mir:"/user/posts"` // GetUserProfile 获取用户基本信息 - GetUserProfile func(Get) `mir:"/user/profile"` + GetUserProfile func(Get, web.GetUserProfileReq) web.GetUserProfileResp `mir:"/user/profile"` } diff --git a/pkg/app/pagination.go b/pkg/app/pagination.go index 699d1dd2..09d7532b 100644 --- a/pkg/app/pagination.go +++ b/pkg/app/pagination.go @@ -46,3 +46,17 @@ func GetPageOffset(c *gin.Context) (offset, limit int) { offset = (page - 1) * limit return } + +func GetPageInfo(c *gin.Context) (page, pageSize int) { + page = convert.StrTo(c.Query("page")).MustInt() + if page <= 0 { + page = 1 + } + pageSize = convert.StrTo(c.Query("page_size")).MustInt() + if pageSize <= 0 { + pageSize = conf.AppSetting.DefaultPageSize + } else if pageSize > conf.AppSetting.MaxPageSize { + pageSize = conf.AppSetting.MaxPageSize + } + return +} From 53383b9916f998aae30691d9da371c23bb7d8d01 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 31 Dec 2022 15:05:30 +0800 Subject: [PATCH 61/65] mir: add friendship api implement for new web service --- auto/api/v1/followship.go | 63 +++++++++++++++---- auto/api/v1/friendship.go | 72 ++++++++++++++++++---- internal/model/web/followship.go | 22 +++++-- internal/model/web/friendship.go | 33 +++++++++- internal/model/web/priv.go | 4 +- internal/servants/web/followship.go | 6 +- internal/servants/web/friendship.go | 95 +++++++++++++++++++++++++++-- internal/servants/web/web.go | 4 +- mirc/web/v1/followship.go | 6 +- mirc/web/v1/friendship.go | 8 +-- 10 files changed, 261 insertions(+), 52 deletions(-) diff --git a/auto/api/v1/followship.go b/auto/api/v1/followship.go index 13f94946..7e83efc9 100644 --- a/auto/api/v1/followship.go +++ b/auto/api/v1/followship.go @@ -15,22 +15,25 @@ type Followship interface { Chain() gin.HandlersChain ListFollowers(*web.ListFollowersReq) (*web.ListFollowersResp, mir.Error) - ListFollowings() mir.Error - DeleteFollowing() mir.Error - AddFollowing() mir.Error + ListFollowings(*web.ListFollowingsReq) (*web.ListFollowingsResp, mir.Error) + DeleteFollowing(*web.DeleteFollowingReq) mir.Error + AddFollowing(*web.AddFollowingReq) mir.Error mustEmbedUnimplementedFollowshipServant() } type FollowshipBinding interface { BindListFollowers(*gin.Context) (*web.ListFollowersReq, mir.Error) + BindListFollowings(*gin.Context) (*web.ListFollowingsReq, mir.Error) + BindDeleteFollowing(*gin.Context) (*web.DeleteFollowingReq, mir.Error) + BindAddFollowing(*gin.Context) (*web.AddFollowingReq, mir.Error) mustEmbedUnimplementedFollowshipBinding() } type FollowshipRender interface { RenderListFollowers(*gin.Context, *web.ListFollowersResp, mir.Error) - RenderListFollowings(*gin.Context, mir.Error) + RenderListFollowings(*gin.Context, *web.ListFollowingsResp, mir.Error) RenderDeleteFollowing(*gin.Context, mir.Error) RenderAddFollowing(*gin.Context, mir.Error) @@ -68,7 +71,13 @@ func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding, default: } - r.RenderListFollowings(c, s.ListFollowings()) + req, err := b.BindListFollowings(c) + if err != nil { + r.RenderListFollowings(c, nil, err) + return + } + resp, err := s.ListFollowings(req) + r.RenderListFollowings(c, resp, err) }) router.Handle("POST", "/following/delete", func(c *gin.Context) { @@ -78,7 +87,12 @@ func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding, default: } - r.RenderDeleteFollowing(c, s.DeleteFollowing()) + req, err := b.BindDeleteFollowing(c) + if err != nil { + r.RenderDeleteFollowing(c, err) + return + } + r.RenderDeleteFollowing(c, s.DeleteFollowing(req)) }) router.Handle("POST", "/following/add", func(c *gin.Context) { @@ -88,7 +102,12 @@ func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding, default: } - r.RenderAddFollowing(c, s.AddFollowing()) + req, err := b.BindAddFollowing(c) + if err != nil { + r.RenderAddFollowing(c, err) + return + } + r.RenderAddFollowing(c, s.AddFollowing(req)) }) } @@ -105,15 +124,15 @@ func (UnimplementedFollowshipServant) ListFollowers(req *web.ListFollowersReq) ( return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedFollowshipServant) ListFollowings() mir.Error { - return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) +func (UnimplementedFollowshipServant) ListFollowings(req *web.ListFollowingsReq) (*web.ListFollowingsResp, mir.Error) { + return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedFollowshipServant) DeleteFollowing() mir.Error { +func (UnimplementedFollowshipServant) DeleteFollowing(req *web.DeleteFollowingReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedFollowshipServant) AddFollowing() mir.Error { +func (UnimplementedFollowshipServant) AddFollowing(req *web.AddFollowingReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -128,8 +147,8 @@ func (r *UnimplementedFollowshipRender) RenderListFollowers(c *gin.Context, data r.RenderAny(c, data, err) } -func (r *UnimplementedFollowshipRender) RenderListFollowings(c *gin.Context, err mir.Error) { - r.RenderAny(c, nil, err) +func (r *UnimplementedFollowshipRender) RenderListFollowings(c *gin.Context, data *web.ListFollowingsResp, err mir.Error) { + r.RenderAny(c, data, err) } func (r *UnimplementedFollowshipRender) RenderDeleteFollowing(c *gin.Context, err mir.Error) { @@ -153,4 +172,22 @@ func (b *UnimplementedFollowshipBinding) BindListFollowers(c *gin.Context) (*web return obj, err } +func (b *UnimplementedFollowshipBinding) BindListFollowings(c *gin.Context) (*web.ListFollowingsReq, mir.Error) { + obj := new(web.ListFollowingsReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedFollowshipBinding) BindDeleteFollowing(c *gin.Context) (*web.DeleteFollowingReq, mir.Error) { + obj := new(web.DeleteFollowingReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedFollowshipBinding) BindAddFollowing(c *gin.Context) (*web.AddFollowingReq, mir.Error) { + obj := new(web.AddFollowingReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedFollowshipBinding) mustEmbedUnimplementedFollowshipBinding() {} diff --git a/auto/api/v1/friendship.go b/auto/api/v1/friendship.go index f0bc6208..fbec2417 100644 --- a/auto/api/v1/friendship.go +++ b/auto/api/v1/friendship.go @@ -15,16 +15,20 @@ type Friendship interface { Chain() gin.HandlersChain GetContacts(*web.GetContactsReq) (*web.GetContactsResp, mir.Error) - DeleteFriend() mir.Error - RejectFriend() mir.Error - AddFriend() mir.Error - RequestingFriend() mir.Error + DeleteFriend(*web.DeleteFriendReq) mir.Error + RejectFriend(*web.RejectFriendReq) mir.Error + AddFriend(*web.AddFriendReq) mir.Error + RequestingFriend(*web.RequestingFriendReq) mir.Error mustEmbedUnimplementedFriendshipServant() } type FriendshipBinding interface { BindGetContacts(*gin.Context) (*web.GetContactsReq, mir.Error) + BindDeleteFriend(*gin.Context) (*web.DeleteFriendReq, mir.Error) + BindRejectFriend(*gin.Context) (*web.RejectFriendReq, mir.Error) + BindAddFriend(*gin.Context) (*web.AddFriendReq, mir.Error) + BindRequestingFriend(*gin.Context) (*web.RequestingFriendReq, mir.Error) mustEmbedUnimplementedFriendshipBinding() } @@ -70,7 +74,12 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding, default: } - r.RenderDeleteFriend(c, s.DeleteFriend()) + req, err := b.BindDeleteFriend(c) + if err != nil { + r.RenderDeleteFriend(c, err) + return + } + r.RenderDeleteFriend(c, s.DeleteFriend(req)) }) router.Handle("POST", "/friend/reject", func(c *gin.Context) { @@ -80,7 +89,12 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding, default: } - r.RenderRejectFriend(c, s.RejectFriend()) + req, err := b.BindRejectFriend(c) + if err != nil { + r.RenderRejectFriend(c, err) + return + } + r.RenderRejectFriend(c, s.RejectFriend(req)) }) router.Handle("POST", "/friend/add", func(c *gin.Context) { @@ -90,7 +104,12 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding, default: } - r.RenderAddFriend(c, s.AddFriend()) + req, err := b.BindAddFriend(c) + if err != nil { + r.RenderAddFriend(c, err) + return + } + r.RenderAddFriend(c, s.AddFriend(req)) }) router.Handle("POST", "/friend/requesting", func(c *gin.Context) { @@ -100,7 +119,12 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding, default: } - r.RenderRequestingFriend(c, s.RequestingFriend()) + req, err := b.BindRequestingFriend(c) + if err != nil { + r.RenderRequestingFriend(c, err) + return + } + r.RenderRequestingFriend(c, s.RequestingFriend(req)) }) } @@ -117,19 +141,19 @@ func (UnimplementedFriendshipServant) GetContacts(req *web.GetContactsReq) (*web return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedFriendshipServant) DeleteFriend() mir.Error { +func (UnimplementedFriendshipServant) DeleteFriend(req *web.DeleteFriendReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedFriendshipServant) RejectFriend() mir.Error { +func (UnimplementedFriendshipServant) RejectFriend(req *web.RejectFriendReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedFriendshipServant) AddFriend() mir.Error { +func (UnimplementedFriendshipServant) AddFriend(req *web.AddFriendReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } -func (UnimplementedFriendshipServant) RequestingFriend() mir.Error { +func (UnimplementedFriendshipServant) RequestingFriend(req *web.RequestingFriendReq) mir.Error { return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) } @@ -173,4 +197,28 @@ func (b *UnimplementedFriendshipBinding) BindGetContacts(c *gin.Context) (*web.G return obj, err } +func (b *UnimplementedFriendshipBinding) BindDeleteFriend(c *gin.Context) (*web.DeleteFriendReq, mir.Error) { + obj := new(web.DeleteFriendReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedFriendshipBinding) BindRejectFriend(c *gin.Context) (*web.RejectFriendReq, mir.Error) { + obj := new(web.RejectFriendReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedFriendshipBinding) BindAddFriend(c *gin.Context) (*web.AddFriendReq, mir.Error) { + obj := new(web.AddFriendReq) + err := b.BindAny(c, obj) + return obj, err +} + +func (b *UnimplementedFriendshipBinding) BindRequestingFriend(c *gin.Context) (*web.RequestingFriendReq, mir.Error) { + obj := new(web.RequestingFriendReq) + err := b.BindAny(c, obj) + return obj, err +} + func (b *UnimplementedFriendshipBinding) mustEmbedUnimplementedFriendshipBinding() {} diff --git a/internal/model/web/followship.go b/internal/model/web/followship.go index 1b1f0428..aba69f72 100644 --- a/internal/model/web/followship.go +++ b/internal/model/web/followship.go @@ -4,10 +4,24 @@ package web -type ListFollowersReq struct { - *BaseInfo `json:"-"` +import "github.com/rocboss/paopao-ce/internal/servants/base" + +type AddFollowingReq struct { + BaseInfo `json:"-" binding:"-"` } -type ListFollowersResp struct { - // TODO +type DeleteFollowingReq struct { + BaseInfo `json:"-" binding:"-"` } + +type ListFollowingsReq struct { + BaseInfo `json:"-" binding:"-"` +} + +type ListFollowingsResp base.PageResp + +type ListFollowersReq struct { + BaseInfo `form:"-" binding:"-"` +} + +type ListFollowersResp base.PageResp diff --git a/internal/model/web/friendship.go b/internal/model/web/friendship.go index 1cece059..08f5fd27 100644 --- a/internal/model/web/friendship.go +++ b/internal/model/web/friendship.go @@ -4,10 +4,37 @@ package web +import "github.com/rocboss/paopao-ce/internal/servants/base" + +type RequestingFriendReq struct { + BaseInfo `json:"-" binding:"-"` + UserId int64 `json:"user_id" binding:"required"` + Greetings string `json:"greetings" binding:"required"` +} + +type AddFriendReq struct { + BaseInfo `json:"-" binding:"-"` + UserId int64 `json:"user_id" binding:"required"` +} + +type RejectFriendReq struct { + BaseInfo `json:"-" binding:"-"` + UserId int64 `json:"user_id" binding:"required"` +} + +type DeleteFriendReq struct { + BaseInfo `json:"-" binding:"-"` + UserId int64 `json:"user_id"` +} + type GetContactsReq struct { - *BaseInfo `json:"-"` + BaseInfo `form:"-" binding:"-"` + Page int `form:"-" binding:"-"` + PageSize int `form:"-" binding:"-"` } -type GetContactsResp struct { - // TODO +type GetContactsResp base.PageResp + +func (r *GetContactsReq) SetPageInfo(page int, pageSize int) { + r.Page, r.PageSize = page, pageSize } diff --git a/internal/model/web/priv.go b/internal/model/web/priv.go index 9a592141..0657a485 100644 --- a/internal/model/web/priv.go +++ b/internal/model/web/priv.go @@ -129,7 +129,7 @@ type UploadAttachmentResp struct { } type DownloadAttachmentPrecheckReq struct { - BaseInfo `json:"-" binding:"-"` + BaseInfo `form:"-" binding:"-"` ContentID int64 `form:"id"` } @@ -138,7 +138,7 @@ type DownloadAttachmentPrecheckResp struct { } type DownloadAttachmentReq struct { - BaseInfo `json:"-" binding:"-"` + BaseInfo `form:"-" binding:"-"` ContentID int64 `form:"id"` } diff --git a/internal/servants/web/followship.go b/internal/servants/web/followship.go index fc9d6788..95d19ec3 100644 --- a/internal/servants/web/followship.go +++ b/internal/servants/web/followship.go @@ -18,17 +18,15 @@ var ( ) type followshipSrv struct { - base.BaseServant api.UnimplementedFollowshipServant + *base.DaoServant } type followshipBinding struct { - base.BaseBinding *api.UnimplementedFollowshipBinding } type followshipRender struct { - base.BaseRender *api.UnimplementedFollowshipRender } @@ -36,7 +34,7 @@ func (s *followshipSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func newFollowshipSrv() api.Followship { +func newFollowshipSrv(s *base.DaoServant) api.Followship { return &followshipSrv{} } diff --git a/internal/servants/web/friendship.go b/internal/servants/web/friendship.go index 3813763b..54c239ba 100644 --- a/internal/servants/web/friendship.go +++ b/internal/servants/web/friendship.go @@ -5,10 +5,14 @@ package web import ( + "github.com/alimy/mir/v3" "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" + "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/rocboss/paopao-ce/pkg/xerror" + "github.com/sirupsen/logrus" ) var ( @@ -18,17 +22,15 @@ var ( ) type friendshipSrv struct { - base.BaseServant api.UnimplementedFriendshipServant + *base.DaoServant } type friendshipBinding struct { - base.BaseBinding *api.UnimplementedFriendshipBinding } type friendshipRender struct { - base.BaseRender *api.UnimplementedFriendshipRender } @@ -36,8 +38,91 @@ func (s *friendshipSrv) Chain() gin.HandlersChain { return gin.HandlersChain{chain.JWT()} } -func newFriendshipSrv() api.Friendship { - return &friendshipSrv{} +func (s *friendshipSrv) GetContacts(req *web.GetContactsReq) (*web.GetContactsResp, mir.Error) { + if req.User == nil { + return nil, xerror.ServerError + } + res, err := s.Ds.GetContacts(req.User.ID, (req.Page-1)*req.PageSize, req.PageSize) + if err != nil { + logrus.Errorf("service.GetContacts err: %s", err) + return nil, _errGetContactsFailed + } + resp := base.PageRespFrom(res.Contacts, req.Page, req.PageSize, res.Total) + return (*web.GetContactsResp)(resp), nil +} + +func (s *friendshipSrv) DeleteFriend(req *web.DeleteFriendReq) mir.Error { + if req.User == nil { + return xerror.ServerError + } + if req.User != nil && req.User.ID == req.UserId { + return _errNoActionToSelf + } + if _, err := s.Ds.GetUserByID(req.UserId); err != nil { + return _errNotExistFriendId + } + if err := s.Ds.DeleteFriend(req.User.ID, req.UserId); err != nil { + logrus.Errorf("Ds.DeleteFriend err: %s", err) + return _errDeleteFriendFailed + } + return nil +} + +func (s *friendshipSrv) RejectFriend(req *web.RejectFriendReq) mir.Error { + if req.User == nil { + return xerror.ServerError + } + if req.User.ID == req.UserId { + return _errNoActionToSelf + } + if _, err := s.Ds.GetUserByID(req.UserId); err != nil { + return _errNotExistFriendId + } + if err := s.Ds.RejectFriend(req.User.ID, req.UserId); err != nil { + logrus.Errorf("Ds.RejectFriend err: %s", err) + return _errRejectFriendFailed + } + return nil +} + +func (s *friendshipSrv) AddFriend(req *web.AddFriendReq) mir.Error { + if req.User == nil { + return xerror.ServerError + } + if req.User.ID == req.UserId { + return _errNoActionToSelf + } + if _, err := s.Ds.GetUserByID(req.UserId); err != nil { + return _errNotExistFriendId + } + if err := s.Ds.AddFriend(req.User.ID, req.UserId); err != nil { + logrus.Errorf("Ds.AddFriend err: %s", err) + return _errAddFriendFailed + } + return nil +} + +func (s *friendshipSrv) RequestingFriend(req *web.RequestingFriendReq) mir.Error { + if req.User == nil { + return xerror.ServerError + } + if req.User.ID == req.UserId { + return _errNoRequestingFriendToSelf + } + if _, err := s.Ds.GetUserByID(req.UserId); err != nil { + return _errNotExistFriendId + } + if err := s.Ds.RequestingFriend(req.User.ID, req.UserId, req.Greetings); err != nil { + logrus.Errorf("Ds.RequestingFriend err: %s", err) + return _errSendRequestingFriendFailed + } + return nil +} + +func newFriendshipSrv(s *base.DaoServant) api.Friendship { + return &friendshipSrv{ + DaoServant: s, + } } func newFriendshipBinding() api.FriendshipBinding { diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index 50f6a88b..286109d3 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -37,10 +37,10 @@ func RouteWeb(e *gin.Engine) { api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(ds, client), newAlipayPrivBinding(), newAlipayPrivRender()) }, "Followship": func() { - api.RegisterFollowshipServant(e, newFollowshipSrv(), newFollowshipBinding(), newFollowshipRender()) + api.RegisterFollowshipServant(e, newFollowshipSrv(ds), newFollowshipBinding(), newFollowshipRender()) }, "Friendship": func() { - api.RegisterFriendshipServant(e, newFriendshipSrv(), newFriendshipBinding(), newFriendshipRender()) + api.RegisterFriendshipServant(e, newFriendshipSrv(ds), newFriendshipBinding(), newFriendshipRender()) }, }) } diff --git a/mirc/web/v1/followship.go b/mirc/web/v1/followship.go index 8c4e81fe..99c0dba6 100644 --- a/mirc/web/v1/followship.go +++ b/mirc/web/v1/followship.go @@ -16,13 +16,13 @@ type Followship struct { Group Group `mir:"v1"` // AddFollowing 添加关注 - AddFollowing func(Post) `mir:"/following/add"` + AddFollowing func(Post, web.AddFollowingReq) `mir:"/following/add"` // DeleteFollowing 取消关注 - DeleteFollowing func(Post) `mir:"/following/delete"` + DeleteFollowing func(Post, web.DeleteFollowingReq) `mir:"/following/delete"` // ListFollowings 获取用户的关注列表 - ListFollowings func(Get) `mir:"/following/list"` + ListFollowings func(Get, web.ListFollowingsReq) web.ListFollowingsResp `mir:"/following/list"` // ListFollowers 获取用户的追随者列表 ListFollowers func(Get, web.ListFollowersReq) web.ListFollowersResp `mir:"/follower/list"` diff --git a/mirc/web/v1/friendship.go b/mirc/web/v1/friendship.go index ae29910a..1013a894 100644 --- a/mirc/web/v1/friendship.go +++ b/mirc/web/v1/friendship.go @@ -16,16 +16,16 @@ type Friendship struct { Group Group `mir:"v1"` // RequestingFriend 请求添加朋友 - RequestingFriend func(Post) `mir:"/friend/requesting"` + RequestingFriend func(Post, web.RequestingFriendReq) `mir:"/friend/requesting"` // AddFriend 同意添加好友 - AddFriend func(Post) `mir:"/friend/add"` + AddFriend func(Post, web.AddFriendReq) `mir:"/friend/add"` // RejectFriend 拒绝添加好友 - RejectFriend func(Post) `mir:"/friend/reject"` + RejectFriend func(Post, web.RejectFriendReq) `mir:"/friend/reject"` // DeleteFriend 删除好友 - DeleteFriend func(Post) `mir:"/friend/delete"` + DeleteFriend func(Post, web.DeleteFriendReq) `mir:"/friend/delete"` // GetContacts 获取好友列表 GetContacts func(Get, web.GetContactsReq) web.GetContactsResp `mir:"/user/contacts"` From 10e5bc470a23bbe254251d4e8d3d41c063980e74 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 31 Dec 2022 15:11:07 +0800 Subject: [PATCH 62/65] mir:fixed new service initial error --- internal/servants/web/priv.go | 6 ++---- internal/servants/web/pub.go | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/internal/servants/web/priv.go b/internal/servants/web/priv.go index 5236cf4e..514bbdd7 100644 --- a/internal/servants/web/priv.go +++ b/internal/servants/web/priv.go @@ -36,8 +36,6 @@ var ( "public/video": core.AttachmentTypeVideo, "attachment": core.AttachmentTypeOther, } - - _MaxCommentCount = conf.AppSetting.MaxCommentCount ) type privSrv struct { @@ -517,7 +515,7 @@ func (s *privSrv) CreateComment(req *web.CreateCommentReq) (_ *web.CreateComment logrus.Errorf("Ds.GetPostByID err:%s", err) return nil, xerror.ServerError } - if post.CommentCount >= _MaxCommentCount { + if post.CommentCount >= conf.AppSetting.MaxCommentCount { return nil, _errMaxCommentCount } comment := &core.Comment{ @@ -728,7 +726,7 @@ func (s *privSrv) createPostPreHandler(commentID int64, userID, atUserID int64) return nil, nil, atUserID, err } - if post.CommentCount >= _MaxCommentCount { + if post.CommentCount >= conf.AppSetting.MaxCommentCount { return nil, nil, atUserID, _errMaxCommentCount } diff --git a/internal/servants/web/pub.go b/internal/servants/web/pub.go index afc14779..f24913d1 100644 --- a/internal/servants/web/pub.go +++ b/internal/servants/web/pub.go @@ -37,8 +37,6 @@ var ( _ api.Pub = (*pubSrv)(nil) _ api.PubBinding = (*pubBinding)(nil) _ api.PubRender = (*pubRender)(nil) - - _MaxPageSize = conf.AppSetting.MaxPageSize ) const ( @@ -74,8 +72,8 @@ func (b *pubBinding) BindTweetComments(c *gin.Context) (*web.TweetCommentsReq, m func (s *pubSrv) TopicList(req *web.TopicListReq) (*web.TopicListResp, mir.Error) { // tags, err := broker.GetPostTags(¶m) num := req.Num - if num > _MaxPageSize { - num = _MaxPageSize + if num > conf.AppSetting.MaxPageSize { + num = conf.AppSetting.MaxPageSize } conditions := &core.ConditionsT{} From 275e132927e0f83a1d8bfe1103752370ddaa762f Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 31 Dec 2022 17:35:33 +0800 Subject: [PATCH 63/65] mir: fixed http service initial error by wrong ReadTimeout/WriteTimeout setting --- README.md | 3 +-- config.yaml.sample | 4 ++-- internal/conf/conf.go | 2 -- internal/conf/settting.go | 8 ++++++++ internal/servants/base/base.go | 2 +- internal/servants/web/loose.go | 2 +- internal/service/admin.go | 4 ++-- internal/service/bot.go | 4 ++-- internal/service/localoss.go | 4 ++-- internal/service/service.go | 7 +++---- internal/service/space.go | 4 ++-- internal/service/web.go | 5 +++-- internal/service/web_old.go | 4 ++-- main.go | 2 +- 14 files changed, 30 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index acc0d1d1..16304c57 100644 --- a/README.md +++ b/README.md @@ -316,13 +316,12 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r 目前支持的功能集合: | 功能项 | 类别 | 状态 | 备注 | | ----- | ----- | ----- | ----- | -|`OldWeb` | 子服务 | 稳定(默认) | 开启旧的Web服务 | |`Web` | 子服务 | WIP | 开启Web服务| |`Admin` | 子服务 | WIP | 开启Admin后台运维服务| |`SpaceX` | 子服务 | WIP | 开启SpaceX服务| |`Bot` | 子服务 | WIP | 开启Bot服务| |`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务| -|`Deprecated:Web` | 子服务 | 稳定 | Deprecated(关闭) OldWeb服务| +|`Deprecated:Web` | 子服务 | 稳定 | 开启旧的Web服务| |`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM,默认使用 `Gorm` + `MySQL`组合| |`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM| |`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库| diff --git a/config.yaml.sample b/config.yaml.sample index 30535257..73cf89db 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -12,14 +12,14 @@ Server: # 服务设置 ReadTimeout: 60 WriteTimeout: 60 Features: - Default: ["Base", "MySQL", "Option", "Zinc", "LocalOSS", "LoggerFile", "Friendship"] + Default: ["Base", "MySQL", "Option", "Zinc", "LocalOSS", "LoggerFile", "Friendship", "Deprecated"] Develop: ["Base", "MySQL", "BigCacheIndex", "Meili", "Sms", "AliOSS", "LoggerMeili", "OSS:Retention"] Demo: ["Base", "MySQL", "Option", "Zinc", "Sms", "MinIO", "LoggerZinc", "Migration"] Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile", "OSS:TempDir"] Base: ["Redis", "PhoneBind"] Docs: ["Docs:OpenAPI"] Deprecated: ["Deprecated:OldWeb"] - Service: ["Admin", "SpaceX", "Bot", "LocalOSS", "Mobile"] + Service: ["Web", "Admin", "SpaceX", "Bot", "LocalOSS", "Mobile"] Option: ["SimpleCacheIndex"] Sms: "SmsJuhe" WebServer: # Web服务 diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 35755f04..6a994e01 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -105,8 +105,6 @@ func setupSetting(suite []string, noDefault bool) error { } JWTSetting.Expire *= time.Second - ServerSetting.ReadTimeout *= time.Second - ServerSetting.WriteTimeout *= time.Second SimpleCacheIndexSetting.CheckTickDuration *= time.Second SimpleCacheIndexSetting.ExpireTickDuration *= time.Second BigCacheIndexSetting.ExpireInSecond *= time.Second diff --git a/internal/conf/settting.go b/internal/conf/settting.go index 0c543706..93443f64 100644 --- a/internal/conf/settting.go +++ b/internal/conf/settting.go @@ -270,6 +270,14 @@ func (s *Setting) featuresInfoFrom(k string) (map[string][]string, map[string]st return suites, kv } +func (s *HttpServerSettingS) GetReadTimeout() time.Duration { + return s.ReadTimeout * time.Second +} + +func (s *HttpServerSettingS) GetWriteTimeout() time.Duration { + return s.WriteTimeout * time.Second +} + func (s *MySQLSettingS) Dsn() string { return fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=%s&parseTime=%t&loc=Local", s.UserName, diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index acc33bd6..7cf2ffeb 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -37,7 +37,7 @@ type BaseRender types.Empty type JsonResp struct { Code int `json:"code"` Msg string `json:"msg,omitempty"` - Data any `json:",omitempty"` + Data any `json:"data,omitempty"` } type UserSetter interface { diff --git a/internal/servants/web/loose.go b/internal/servants/web/loose.go index 4b04ad36..9e9b1bff 100644 --- a/internal/servants/web/loose.go +++ b/internal/servants/web/loose.go @@ -35,7 +35,7 @@ type looseRender struct { *api.UnimplementedLooseRender } -func (s *looseSrv) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) { +func (s *looseBinding) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) { user, _ := base.UserFrom(c) page, pageSize := app.GetPageInfo(c) v := &web.TimelineReq{ diff --git a/internal/service/admin.go b/internal/service/admin.go index 52bd120b..04ae090e 100644 --- a/internal/service/admin.go +++ b/internal/service/admin.go @@ -82,8 +82,8 @@ func newAdminService() Service { server: &http.Server{ Addr: addr, Handler: engine, - ReadTimeout: conf.AdminServerSetting.ReadTimeout, - WriteTimeout: conf.AdminServerSetting.WriteTimeout, + ReadTimeout: conf.AdminServerSetting.GetReadTimeout(), + WriteTimeout: conf.AdminServerSetting.GetWriteTimeout(), MaxHeaderBytes: 1 << 20, }, } diff --git a/internal/service/bot.go b/internal/service/bot.go index d1cb4ea7..3c9b2f4d 100644 --- a/internal/service/bot.go +++ b/internal/service/bot.go @@ -82,8 +82,8 @@ func newBotService() Service { server: &http.Server{ Addr: addr, Handler: engine, - ReadTimeout: conf.BotServerSetting.ReadTimeout, - WriteTimeout: conf.BotServerSetting.WriteTimeout, + ReadTimeout: conf.BotServerSetting.GetReadTimeout(), + WriteTimeout: conf.BotServerSetting.GetWriteTimeout(), MaxHeaderBytes: 1 << 20, }, } diff --git a/internal/service/localoss.go b/internal/service/localoss.go index 7d70291d..5bead183 100644 --- a/internal/service/localoss.go +++ b/internal/service/localoss.go @@ -57,8 +57,8 @@ func newLocalossService() Service { server: &http.Server{ Addr: addr, Handler: engine, - ReadTimeout: conf.LocalossServerSetting.ReadTimeout, - WriteTimeout: conf.LocalossServerSetting.WriteTimeout, + ReadTimeout: conf.LocalossServerSetting.GetReadTimeout(), + WriteTimeout: conf.LocalossServerSetting.GetWriteTimeout(), MaxHeaderBytes: 1 << 20, }, } diff --git a/internal/service/service.go b/internal/service/service.go index 957979c3..21375631 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -58,12 +58,11 @@ func MaxSidSize(ss []Service) int { } func newService() (ss []Service) { - // add oldWebService if not depredcated OldWebService - cfg.Not("Deprecated:OldWeb", func() { - ss = append(ss, newOldWebService()) - }) // add all service if declared in features on config.yaml cfg.In(cfg.Actions{ + "Deprecated:OldWeb": func() { + ss = append(ss, newOldWebService()) + }, "Web": func() { ss = append(ss, newWebService()) }, diff --git a/internal/service/space.go b/internal/service/space.go index 2d5ff1ff..5cce8914 100644 --- a/internal/service/space.go +++ b/internal/service/space.go @@ -82,8 +82,8 @@ func newSpaceXService() Service { server: &http.Server{ Addr: addr, Handler: engine, - ReadTimeout: conf.SpaceXServerSetting.ReadTimeout, - WriteTimeout: conf.SpaceXServerSetting.WriteTimeout, + ReadTimeout: conf.SpaceXServerSetting.GetReadTimeout(), + WriteTimeout: conf.SpaceXServerSetting.GetWriteTimeout(), MaxHeaderBytes: 1 << 20, }, } diff --git a/internal/service/web.go b/internal/service/web.go index 0d1b9f12..a0c821a0 100644 --- a/internal/service/web.go +++ b/internal/service/web.go @@ -82,12 +82,13 @@ func newWebService() Service { server: &http.Server{ Addr: addr, Handler: engine, - ReadTimeout: conf.WebServerSetting.ReadTimeout, - WriteTimeout: conf.WebServerSetting.WriteTimeout, + ReadTimeout: conf.WebServerSetting.GetReadTimeout(), + WriteTimeout: conf.WebServerSetting.GetWriteTimeout(), MaxHeaderBytes: 1 << 20, }, } }) + return &webService{ baseHttpService: &baseHttpService{ server: server, diff --git a/internal/service/web_old.go b/internal/service/web_old.go index bcef11cd..beb3902c 100644 --- a/internal/service/web_old.go +++ b/internal/service/web_old.go @@ -49,8 +49,8 @@ func newOldWebService() Service { server: &http.Server{ Addr: addr, Handler: engine, - ReadTimeout: conf.ServerSetting.ReadTimeout, - WriteTimeout: conf.ServerSetting.WriteTimeout, + ReadTimeout: conf.ServerSetting.GetReadTimeout(), + WriteTimeout: conf.ServerSetting.GetWriteTimeout(), MaxHeaderBytes: 1 << 20, }, } diff --git a/main.go b/main.go index 5e0fcc01..d1886084 100644 --- a/main.go +++ b/main.go @@ -99,6 +99,6 @@ func main() { wg.Wait() } else { - fmt.Fprintf(color.Output, "no service need start so just exit") + fmt.Fprintln(color.Output, "no service need start so just exit") } } From 6576d74f4df030ec652e92c4112e52ee649f11a1 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 31 Dec 2022 18:21:54 +0800 Subject: [PATCH 64/65] add frontend:web / frontend:embedweb / docs service --- README.md | 5 +- config.yaml.sample | 7 ++- features-status.md | 15 ++++- internal/conf/conf.go | 70 +++++++++++----------- internal/conf/config.yaml | 5 ++ internal/servants/servants.go | 17 ++++-- internal/servants/statick/statick.go | 4 +- internal/servants/statick/statick_embed.go | 8 +-- internal/servants/web/routers/router.go | 14 ++--- internal/service/docs.go | 63 +++++++++++++++++++ internal/service/frontend_web.go | 63 +++++++++++++++++++ internal/service/service.go | 12 +++- 12 files changed, 224 insertions(+), 59 deletions(-) create mode 100644 internal/service/docs.go create mode 100644 internal/service/frontend_web.go diff --git a/README.md b/README.md index 16304c57..d3fb0b33 100644 --- a/README.md +++ b/README.md @@ -316,11 +316,14 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r 目前支持的功能集合: | 功能项 | 类别 | 状态 | 备注 | | ----- | ----- | ----- | ----- | -|`Web` | 子服务 | WIP | 开启Web服务| +|`Web` | 子服务 | 内测 | 开启Web服务| |`Admin` | 子服务 | WIP | 开启Admin后台运维服务| |`SpaceX` | 子服务 | WIP | 开启SpaceX服务| |`Bot` | 子服务 | WIP | 开启Bot服务| |`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务| +|`Docs` | 子服务 | WIP | 开启开发者文档服务| +|`Frontend:Web` | 子服务 | 内测 | 开启独立前端服务| +|`Frontend:EmbedWeb` | 子服务 | 内测 | 开启内嵌于后端Web API服务中的前端服务| |`Deprecated:Web` | 子服务 | 稳定 | 开启旧的Web服务| |`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM,默认使用 `Gorm` + `MySQL`组合| |`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM| diff --git a/config.yaml.sample b/config.yaml.sample index 73cf89db..ec33d9eb 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -19,7 +19,7 @@ Features: Base: ["Redis", "PhoneBind"] Docs: ["Docs:OpenAPI"] Deprecated: ["Deprecated:OldWeb"] - Service: ["Web", "Admin", "SpaceX", "Bot", "LocalOSS", "Mobile"] + Service: ["Web", "Admin", "SpaceX", "Bot", "LocalOSS", "Mobile", "Frontend:Web", "Fronetend:EmbedWeb", "Docs"] Option: ["SimpleCacheIndex"] Sms: "SmsJuhe" WebServer: # Web服务 @@ -47,6 +47,11 @@ LocalossServer: # Localoss服务 HttpPort: 8018 ReadTimeout: 60 WriteTimeout: 60 +FrontendWebServer: # Web前端服务 + HttpIp: 0.0.0.0 + HttpPort: 8006 + ReadTimeout: 60 + WriteTimeout: 60 DocsServer: # 开发文档服务 HttpIp: 0.0.0.0 HttpPort: 8011 diff --git a/features-status.md b/features-status.md index 38f8eb6e..8937a2bc 100644 --- a/features-status.md +++ b/features-status.md @@ -11,8 +11,8 @@ * `Web` 开启Web服务(目前状态: WIP) * [ ] 提按文档 * [x] 服务初始化逻辑 - * [ ] 接口定义 - * [ ] 业务逻辑实现 + * [x] 接口定义 + * [x] 业务逻辑实现 * `Admin` 开启Admin后台运维服务(目前状态: WIP) * [ ] 提按文档 * [x] 服务初始化逻辑 @@ -33,7 +33,16 @@ * [ ] 服务初始化逻辑 * [ ] 接口定义 * [ ] 业务逻辑实现 -* `Deprecated:OldWeb` Deprecated(关闭)旧的Web服务(目前状态: WIP) +* `Docs` 开启NativeOBS服务(目前状态: WIP) + * [ ] 提按文档 + * [x] 服务初始化逻辑 +* `Frontend:Web` 开启独立前端服务(目前状态: 内测) + * [ ] 提按文档 + * [x] 服务初始化逻辑 +* `Frontend:EmbedWeb` 开启内嵌于后端Web API服务中的前端服务(目前状态: 内测) + * [ ] 提按文档 + * [x] 服务初始化逻辑 +* `Deprecated:OldWeb` 开启旧的Web服务(目前状态: 内测) * [ ] 提按文档 * [x] 服务初始化逻辑 diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 6a994e01..950d2d8a 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -29,6 +29,7 @@ var ( SpaceXServerSetting *HttpServerSettingS BotServerSetting *HttpServerSettingS LocalossServerSetting *HttpServerSettingS + FrontendWebSetting *HttpServerSettingS DocsServerSetting *HttpServerSettingS MobileServerSetting *GRPCServerSettingS AppSetting *AppSettingS @@ -65,40 +66,41 @@ func setupSetting(suite []string, noDefault bool) error { } objects := map[string]any{ - "App": &AppSetting, - "Server": &ServerSetting, - "WebServer": &WebServerSetting, - "AdminServer": &AdminServerSetting, - "SpaceXServer": &SpaceXServerSetting, - "BotServer": &BotServerSetting, - "LocalossServer": &LocalossServerSetting, - "DocsServer": &DocsServerSetting, - "MobileServer": &MobileServerSetting, - "CacheIndex": &CacheIndexSetting, - "SimpleCacheIndex": &SimpleCacheIndexSetting, - "BigCacheIndex": &BigCacheIndexSetting, - "Alipay": &AlipaySetting, - "SmsJuhe": &SmsJuheSetting, - "Logger": &loggerSetting, - "LoggerFile": &loggerFileSetting, - "LoggerZinc": &loggerZincSetting, - "LoggerMeili": &loggerMeiliSetting, - "Database": &DatabaseSetting, - "MySQL": &MysqlSetting, - "Postgres": &PostgresSetting, - "Sqlite3": &Sqlite3Setting, - "TweetSearch": &TweetSearchSetting, - "Zinc": &ZincSetting, - "Meili": &MeiliSetting, - "Redis": &redisSetting, - "JWT": &JWTSetting, - "ObjectStorage": &ObjectStorage, - "AliOSS": &AliOSSSetting, - "COS": &COSSetting, - "HuaweiOBS": &HuaweiOBSSetting, - "MinIO": &MinIOSetting, - "LocalOSS": &LocalOSSSetting, - "S3": &S3Setting, + "App": &AppSetting, + "Server": &ServerSetting, + "WebServer": &WebServerSetting, + "AdminServer": &AdminServerSetting, + "SpaceXServer": &SpaceXServerSetting, + "BotServer": &BotServerSetting, + "LocalossServer": &LocalossServerSetting, + "FrontendWebServer": &FrontendWebSetting, + "DocsServer": &DocsServerSetting, + "MobileServer": &MobileServerSetting, + "CacheIndex": &CacheIndexSetting, + "SimpleCacheIndex": &SimpleCacheIndexSetting, + "BigCacheIndex": &BigCacheIndexSetting, + "Alipay": &AlipaySetting, + "SmsJuhe": &SmsJuheSetting, + "Logger": &loggerSetting, + "LoggerFile": &loggerFileSetting, + "LoggerZinc": &loggerZincSetting, + "LoggerMeili": &loggerMeiliSetting, + "Database": &DatabaseSetting, + "MySQL": &MysqlSetting, + "Postgres": &PostgresSetting, + "Sqlite3": &Sqlite3Setting, + "TweetSearch": &TweetSearchSetting, + "Zinc": &ZincSetting, + "Meili": &MeiliSetting, + "Redis": &redisSetting, + "JWT": &JWTSetting, + "ObjectStorage": &ObjectStorage, + "AliOSS": &AliOSSSetting, + "COS": &COSSetting, + "HuaweiOBS": &HuaweiOBSSetting, + "MinIO": &MinIOSetting, + "LocalOSS": &LocalOSSSetting, + "S3": &S3Setting, } if err = setting.Unmarshal(objects); err != nil { return err diff --git a/internal/conf/config.yaml b/internal/conf/config.yaml index 6c642ed8..c86d168a 100644 --- a/internal/conf/config.yaml +++ b/internal/conf/config.yaml @@ -38,6 +38,11 @@ LocalossServer: # Localoss服务 HttpPort: 8018 ReadTimeout: 60 WriteTimeout: 60 +FrontendWebServer: # Web前端静态资源服务 + HttpIp: 0.0.0.0 + HttpPort: 8006 + ReadTimeout: 60 + WriteTimeout: 60 DocsServer: # 开发文档服务 HttpIp: 0.0.0.0 HttpPort: 8011 diff --git a/internal/servants/servants.go b/internal/servants/servants.go index 74d7e8ce..e206ad08 100644 --- a/internal/servants/servants.go +++ b/internal/servants/servants.go @@ -20,13 +20,12 @@ import ( // RegisterWebServants register all the servants to gin.Engine func RegisterWebServants(e *gin.Engine) { - docs.RegisterDocs(e) - statick.RegisterStatick(e) - + cfg.Be("Frontend:EmbedWeb", func() { + statick.RegisterWebStatick(e) + }) cfg.Be("LocalOSS", func() { localoss.RouteLocalOSS(e) }) - web.RouteWeb(e) } @@ -50,6 +49,16 @@ func RegisterLocalossServants(e *gin.Engine) { localoss.RouteLocaloss(e) } +// RegisterDocsServants register all the servants to gin.Engine +func RegisterDocsServants(e *gin.Engine) { + docs.RegisterDocs(e) +} + +// RegisterFrontendWebServants register all the servants to gin.Engine +func RegisterFrontendWebServants(e *gin.Engine) { + statick.RegisterWebStatick(e) +} + // RegisterMobileServants register all the servants to grpc.Server func RegisterMobileServants(s *grpc.Server) { mobile.RegisterServants(s) diff --git a/internal/servants/statick/statick.go b/internal/servants/statick/statick.go index d4c2bfdc..ef323b0b 100644 --- a/internal/servants/statick/statick.go +++ b/internal/servants/statick/statick.go @@ -11,7 +11,7 @@ import ( "github.com/gin-gonic/gin" ) -// RegisterStatick stub function for register static asset route -func RegisterStatick(e *gin.Engine) { +// RegisterWebStatick stub function for register static asset route +func RegisterWebStatick(e *gin.Engine) { // empty } diff --git a/internal/servants/statick/statick_embed.go b/internal/servants/statick/statick_embed.go index 32da717f..33392531 100644 --- a/internal/servants/statick/statick_embed.go +++ b/internal/servants/statick/statick_embed.go @@ -14,12 +14,12 @@ import ( "github.com/rocboss/paopao-ce/web" ) -// RegisterStatick register static assets route -func RegisterStatick(e *gin.Engine) { - routeStatic(e, "/", "/index.html", "/favicon.ico", "/assets/*filepath") +// RegisterWebStatick register web static assets route +func RegisterWebStatick(e *gin.Engine) { + routeWebStatic(e, "/", "/index.html", "/favicon.ico", "/assets/*filepath") } -func routeStatic(e *gin.Engine, paths ...string) { +func routeWebStatic(e *gin.Engine, paths ...string) { staticHandler := http.FileServer(web.NewFileSystem()) handler := func(c *gin.Context) { staticHandler.ServeHTTP(c.Writer, c.Request) diff --git a/internal/servants/web/routers/router.go b/internal/servants/web/routers/router.go index 80b29be3..70247c6a 100644 --- a/internal/servants/web/routers/router.go +++ b/internal/servants/web/routers/router.go @@ -119,15 +119,15 @@ func NewRouter() *gin.Engine { } func RegisterRoute(e *gin.Engine) { - // 按需注册 docs、静态资源、LocalOSS 路由 - { - registerDocs(e) + // 按需注册 Web前端静态资源 + cfg.Be("Frontend:EmbedWeb", func() { registerStatick(e) + }) - cfg.Be("LocalOSS", func() { - routeLocalOSS(e) - }) - } + // 按需注册 LocalOSS 路由 + cfg.Be("LocalOSS", func() { + routeLocalOSS(e) + }) // v1 group api r := e.Group("/v1") diff --git a/internal/service/docs.go b/internal/service/docs.go new file mode 100644 index 00000000..4f8a48d3 --- /dev/null +++ b/internal/service/docs.go @@ -0,0 +1,63 @@ +// 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 service + +import ( + "fmt" + "net/http" + + "github.com/Masterminds/semver/v3" + "github.com/fatih/color" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" +) + +var ( + _ Service = (*docsService)(nil) +) + +type docsService struct { + *baseHttpService +} + +func (s *docsService) Name() string { + return "DocsService" +} + +func (s *docsService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + +func (s *docsService) OnInit() error { + s.registerRoute(servants.RegisterDocsServants) + return nil +} + +func (s *docsService) String() string { + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.DocsServerSetting.HttpIp, conf.DocsServerSetting.HttpPort)) +} + +func newDocsService() Service { + addr := conf.DocsServerSetting.HttpIp + ":" + conf.DocsServerSetting.HttpPort + server := httpServers.from(addr, func() *httpServer { + engine := newWebEngine() + return &httpServer{ + baseServer: newBaseServe(), + e: engine, + server: &http.Server{ + Addr: addr, + Handler: engine, + ReadTimeout: conf.DocsServerSetting.GetReadTimeout(), + WriteTimeout: conf.DocsServerSetting.GetWriteTimeout(), + MaxHeaderBytes: 1 << 20, + }, + } + }) + return &docsService{ + baseHttpService: &baseHttpService{ + server: server, + }, + } +} diff --git a/internal/service/frontend_web.go b/internal/service/frontend_web.go new file mode 100644 index 00000000..f3903c21 --- /dev/null +++ b/internal/service/frontend_web.go @@ -0,0 +1,63 @@ +// 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 service + +import ( + "fmt" + "net/http" + + "github.com/Masterminds/semver/v3" + "github.com/fatih/color" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/servants" +) + +var ( + _ Service = (*frontendWebService)(nil) +) + +type frontendWebService struct { + *baseHttpService +} + +func (s *frontendWebService) Name() string { + return "FrontendWebService" +} + +func (s *frontendWebService) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + +func (s *frontendWebService) OnInit() error { + s.registerRoute(servants.RegisterFrontendWebServants) + return nil +} + +func (s *frontendWebService) String() string { + return fmt.Sprintf("listen on %s\n", color.GreenString("http://%s:%s", conf.FrontendWebSetting.HttpIp, conf.FrontendWebSetting.HttpPort)) +} + +func newFrontendWebServiceService() Service { + addr := conf.FrontendWebSetting.HttpIp + ":" + conf.FrontendWebSetting.HttpPort + server := httpServers.from(addr, func() *httpServer { + engine := newWebEngine() + return &httpServer{ + baseServer: newBaseServe(), + e: engine, + server: &http.Server{ + Addr: addr, + Handler: engine, + ReadTimeout: conf.FrontendWebSetting.GetReadTimeout(), + WriteTimeout: conf.FrontendWebSetting.GetWriteTimeout(), + MaxHeaderBytes: 1 << 20, + }, + } + }) + return &frontendWebService{ + baseHttpService: &baseHttpService{ + server: server, + }, + } +} diff --git a/internal/service/service.go b/internal/service/service.go index 21375631..db648406 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -60,9 +60,6 @@ func MaxSidSize(ss []Service) int { func newService() (ss []Service) { // add all service if declared in features on config.yaml cfg.In(cfg.Actions{ - "Deprecated:OldWeb": func() { - ss = append(ss, newOldWebService()) - }, "Web": func() { ss = append(ss, newWebService()) }, @@ -81,6 +78,15 @@ func newService() (ss []Service) { "Mobile": func() { ss = append(ss, newMobileService()) }, + "Frontend:Web": func() { + ss = append(ss, newFrontendWebServiceService()) + }, + "Docs": func() { + ss = append(ss, newDocsService()) + }, + "Deprecated:OldWeb": func() { + ss = append(ss, newOldWebService()) + }, }) return } From b99c239ff98257b54bed55cd6d95e1004dc0420f Mon Sep 17 00:00:00 2001 From: Michael Li Date: Sat, 31 Dec 2022 19:14:39 +0800 Subject: [PATCH 65/65] mir:ajust frontend adapter new web service api --- .../servants/web/routers/api/attachment.go | 4 +- internal/servants/web/routers/api/post.go | 4 +- internal/servants/web/routers/api/user.go | 8 +- web/.env | 4 +- web/dist/assets/404.15b4dcd0.js | 32 - web/dist/assets/Alert.a854329b.js | 34 - web/dist/assets/Anouncement.98ee5b6f.js | 1 - web/dist/assets/Collection.02f600ee.js | 1 - web/dist/assets/Contacts.a6b6de0d.js | 1 - web/dist/assets/Home.d188c936.js | 177 -- web/dist/assets/IEnum.bfd96c78.js | 30 - web/dist/assets/InputGroup.f69c4956.js | 56 - web/dist/assets/List.49bcdf81.js | 53 - web/dist/assets/Messages.c822d4d1.js | 1 - web/dist/assets/MoreHorizFilled.80db5156.js | 1 - web/dist/assets/Pagination.1263479e.js | 252 --- web/dist/assets/Post.db4b62c9.js | 57 - web/dist/assets/Profile.75de1930.js | 1 - web/dist/assets/Setting.837d491b.js | 1 - web/dist/assets/Skeleton.57e98fe3.js | 135 -- web/dist/assets/Thing.eef6b133.js | 34 - web/dist/assets/Topic.9a2ef7f9.css | 1 - web/dist/assets/Topic.c6bdf01d.js | 1 - web/dist/assets/Upload.efe3adfd.js | 382 ---- web/dist/assets/User.695fa64f.js | 22 - web/dist/assets/Wallet.b8e2b626.js | 30 - web/dist/assets/content.ef1e095a.js | 810 -------- web/dist/assets/content.ef781517.css | 1 - web/dist/assets/formatTime.02109bf5.js | 11 - web/dist/assets/index.2a3b289f.css | 1 - web/dist/assets/index.f480f018.js | 1771 ----------------- web/dist/assets/main-nav.9110259b.js | 100 - web/dist/assets/post-item.03452002.js | 1 - web/dist/assets/post-skeleton.39a35f5b.js | 1 - web/dist/index.html | 4 +- web/src/components/compose.vue | 4 +- web/src/components/post-attachment.vue | 2 +- web/src/components/rightbar.vue | 2 +- web/src/types/NetReq.d.ts | 17 +- web/src/views/Topic.vue | 2 +- 40 files changed, 34 insertions(+), 4016 deletions(-) delete mode 100644 web/dist/assets/404.15b4dcd0.js delete mode 100644 web/dist/assets/Alert.a854329b.js delete mode 100644 web/dist/assets/Anouncement.98ee5b6f.js delete mode 100644 web/dist/assets/Collection.02f600ee.js delete mode 100644 web/dist/assets/Contacts.a6b6de0d.js delete mode 100644 web/dist/assets/Home.d188c936.js delete mode 100644 web/dist/assets/IEnum.bfd96c78.js delete mode 100644 web/dist/assets/InputGroup.f69c4956.js delete mode 100644 web/dist/assets/List.49bcdf81.js delete mode 100644 web/dist/assets/Messages.c822d4d1.js delete mode 100644 web/dist/assets/MoreHorizFilled.80db5156.js delete mode 100644 web/dist/assets/Pagination.1263479e.js delete mode 100644 web/dist/assets/Post.db4b62c9.js delete mode 100644 web/dist/assets/Profile.75de1930.js delete mode 100644 web/dist/assets/Setting.837d491b.js delete mode 100644 web/dist/assets/Skeleton.57e98fe3.js delete mode 100644 web/dist/assets/Thing.eef6b133.js delete mode 100644 web/dist/assets/Topic.9a2ef7f9.css delete mode 100644 web/dist/assets/Topic.c6bdf01d.js delete mode 100644 web/dist/assets/Upload.efe3adfd.js delete mode 100644 web/dist/assets/User.695fa64f.js delete mode 100644 web/dist/assets/Wallet.b8e2b626.js delete mode 100644 web/dist/assets/content.ef1e095a.js delete mode 100644 web/dist/assets/content.ef781517.css delete mode 100644 web/dist/assets/formatTime.02109bf5.js delete mode 100644 web/dist/assets/index.2a3b289f.css delete mode 100644 web/dist/assets/index.f480f018.js delete mode 100644 web/dist/assets/main-nav.9110259b.js delete mode 100644 web/dist/assets/post-item.03452002.js delete mode 100644 web/dist/assets/post-skeleton.39a35f5b.js diff --git a/internal/servants/web/routers/api/attachment.go b/internal/servants/web/routers/api/attachment.go index 143c0c12..fb6a173c 100644 --- a/internal/servants/web/routers/api/attachment.go +++ b/internal/servants/web/routers/api/attachment.go @@ -250,5 +250,7 @@ func DownloadAttachment(c *gin.Context) { response.ToErrorResponse(errcode.DownloadReqError) return } - response.ToResponse(signedURL) + response.ToResponse(gin.H{ + "signed_url": signedURL, + }) } diff --git a/internal/servants/web/routers/api/post.go b/internal/servants/web/routers/api/post.go index 9ca19f3f..0dc923b0 100644 --- a/internal/servants/web/routers/api/post.go +++ b/internal/servants/web/routers/api/post.go @@ -329,5 +329,7 @@ func GetPostTags(c *gin.Context) { } - response.ToResponse(tags) + response.ToResponse(gin.H{ + "topics": tags, + }) } diff --git a/internal/servants/web/routers/api/user.go b/internal/servants/web/routers/api/user.go index f45ff8ce..89aa6615 100644 --- a/internal/servants/web/routers/api/user.go +++ b/internal/servants/web/routers/api/user.go @@ -505,7 +505,9 @@ func GetSuggestUsers(c *gin.Context) { return } - response.ToResponse(usernames) + response.ToResponse(gin.H{ + "suggest": usernames, + }) } func GetSuggestTags(c *gin.Context) { @@ -519,7 +521,9 @@ func GetSuggestTags(c *gin.Context) { return } - response.ToResponse(tags) + response.ToResponse(gin.H{ + "suggest": tags, + }) } func GetUserRechargeLink(c *gin.Context) { diff --git a/web/.env b/web/.env index 2082466b..6d3d734c 100644 --- a/web/.env +++ b/web/.env @@ -5,9 +5,9 @@ VITE_ENABLE_ANOUNCEMENT=false VITE_ENABLE_WALLET=false # 功能开启 -VITE_ALLOW_TWEET_ATTACHMENT=false +VITE_ALLOW_TWEET_ATTACHMENT=true VITE_ALLOW_TWEET_ATTACHMENT_PRICE=false -VITE_ALLOW_TWEET_VIDEO=false +VITE_ALLOW_TWEET_VIDEO=true VITE_ALLOW_TWEET_VISIBILITY=true VITE_ALLOW_ACTIVATION=false VITE_ALLOW_PHONE_BIND=true diff --git a/web/dist/assets/404.15b4dcd0.js b/web/dist/assets/404.15b4dcd0.js deleted file mode 100644 index 757fd2b8..00000000 --- a/web/dist/assets/404.15b4dcd0.js +++ /dev/null @@ -1,32 +0,0 @@ -import{_ as E}from"./main-nav.9110259b.js";import{h as e,l as u,m as p,d as h,u as F,q as m,cH as V,s as _,v as d,y as S,N as D,bv as M,bs as R,bu as $,bt as I,ah as L,aj as T,V as H,W as P,a3 as f,a4 as v,a8 as j,J as N}from"./index.f480f018.js";import{_ as k}from"./List.49bcdf81.js";var O=e("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 36 36"},e("circle",{fill:"#FFCB4C",cx:"18",cy:"17.018",r:"17"}),e("path",{fill:"#65471B",d:"M14.524 21.036c-.145-.116-.258-.274-.312-.464-.134-.46.13-.918.59-1.021 4.528-1.021 7.577 1.363 7.706 1.465.384.306.459.845.173 1.205-.286.358-.828.401-1.211.097-.11-.084-2.523-1.923-6.182-1.098-.274.061-.554-.016-.764-.184z"}),e("ellipse",{fill:"#65471B",cx:"13.119",cy:"11.174",rx:"2.125",ry:"2.656"}),e("ellipse",{fill:"#65471B",cx:"24.375",cy:"12.236",rx:"2.125",ry:"2.656"}),e("path",{fill:"#F19020",d:"M17.276 35.149s1.265-.411 1.429-1.352c.173-.972-.624-1.167-.624-1.167s1.041-.208 1.172-1.376c.123-1.101-.861-1.363-.861-1.363s.97-.4 1.016-1.539c.038-.959-.995-1.428-.995-1.428s5.038-1.221 5.556-1.341c.516-.12 1.32-.615 1.069-1.694-.249-1.08-1.204-1.118-1.697-1.003-.494.115-6.744 1.566-8.9 2.068l-1.439.334c-.54.127-.785-.11-.404-.512.508-.536.833-1.129.946-2.113.119-1.035-.232-2.313-.433-2.809-.374-.921-1.005-1.649-1.734-1.899-1.137-.39-1.945.321-1.542 1.561.604 1.854.208 3.375-.833 4.293-2.449 2.157-3.588 3.695-2.83 6.973.828 3.575 4.377 5.876 7.952 5.048l3.152-.681z"}),e("path",{fill:"#65471B",d:"M9.296 6.351c-.164-.088-.303-.224-.391-.399-.216-.428-.04-.927.393-1.112 4.266-1.831 7.699-.043 7.843.034.433.231.608.747.391 1.154-.216.405-.74.546-1.173.318-.123-.063-2.832-1.432-6.278.047-.257.109-.547.085-.785-.042zm12.135 3.75c-.156-.098-.286-.243-.362-.424-.187-.442.023-.927.468-1.084 4.381-1.536 7.685.48 7.823.567.415.26.555.787.312 1.178-.242.39-.776.495-1.191.238-.12-.072-2.727-1.621-6.267-.379-.266.091-.553.046-.783-.096z"})),W=e("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 36 36"},e("path",{fill:"#FFCC4D",d:"M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"}),e("ellipse",{fill:"#664500",cx:"18",cy:"27",rx:"5",ry:"6"}),e("path",{fill:"#664500",d:"M5.999 11c-.208 0-.419-.065-.599-.2-.442-.331-.531-.958-.2-1.4C8.462 5.05 12.816 5 13 5c.552 0 1 .448 1 1 0 .551-.445.998-.996 1-.155.002-3.568.086-6.204 3.6-.196.262-.497.4-.801.4zm24.002 0c-.305 0-.604-.138-.801-.4-2.64-3.521-6.061-3.598-6.206-3.6-.55-.006-.994-.456-.991-1.005C22.006 5.444 22.45 5 23 5c.184 0 4.537.05 7.8 4.4.332.442.242 1.069-.2 1.4-.18.135-.39.2-.599.2zm-16.087 4.5l1.793-1.793c.391-.391.391-1.023 0-1.414s-1.023-.391-1.414 0L12.5 14.086l-1.793-1.793c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414l1.793 1.793-1.793 1.793c-.391.391-.391 1.023 0 1.414.195.195.451.293.707.293s.512-.098.707-.293l1.793-1.793 1.793 1.793c.195.195.451.293.707.293s.512-.098.707-.293c.391-.391.391-1.023 0-1.414L13.914 15.5zm11 0l1.793-1.793c.391-.391.391-1.023 0-1.414s-1.023-.391-1.414 0L23.5 14.086l-1.793-1.793c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414l1.793 1.793-1.793 1.793c-.391.391-.391 1.023 0 1.414.195.195.451.293.707.293s.512-.098.707-.293l1.793-1.793 1.793 1.793c.195.195.451.293.707.293s.512-.098.707-.293c.391-.391.391-1.023 0-1.414L24.914 15.5z"})),q=e("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 36 36"},e("ellipse",{fill:"#292F33",cx:"18",cy:"26",rx:"18",ry:"10"}),e("ellipse",{fill:"#66757F",cx:"18",cy:"24",rx:"18",ry:"10"}),e("path",{fill:"#E1E8ED",d:"M18 31C3.042 31 1 16 1 12h34c0 2-1.958 19-17 19z"}),e("path",{fill:"#77B255",d:"M35 12.056c0 5.216-7.611 9.444-17 9.444S1 17.271 1 12.056C1 6.84 8.611 3.611 18 3.611s17 3.229 17 8.445z"}),e("ellipse",{fill:"#A6D388",cx:"18",cy:"13",rx:"15",ry:"7"}),e("path",{d:"M21 17c-.256 0-.512-.098-.707-.293-2.337-2.337-2.376-4.885-.125-8.262.739-1.109.9-2.246.478-3.377-.461-1.236-1.438-1.996-1.731-2.077-.553 0-.958-.443-.958-.996 0-.552.491-.995 1.043-.995.997 0 2.395 1.153 3.183 2.625 1.034 1.933.91 4.039-.351 5.929-1.961 2.942-1.531 4.332-.125 5.738.391.391.391 1.023 0 1.414-.195.196-.451.294-.707.294zm-6-2c-.256 0-.512-.098-.707-.293-2.337-2.337-2.376-4.885-.125-8.262.727-1.091.893-2.083.494-2.947-.444-.961-1.431-1.469-1.684-1.499-.552 0-.989-.447-.989-1 0-.552.458-1 1.011-1 .997 0 2.585.974 3.36 2.423.481.899 1.052 2.761-.528 5.131-1.961 2.942-1.531 4.332-.125 5.738.391.391.391 1.023 0 1.414-.195.197-.451.295-.707.295z",fill:"#5C913B"})),A=e("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 36 36"},e("path",{fill:"#EF9645",d:"M15.5 2.965c1.381 0 2.5 1.119 2.5 2.5v.005L20.5.465c1.381 0 2.5 1.119 2.5 2.5V4.25l2.5-1.535c1.381 0 2.5 1.119 2.5 2.5V8.75L29 18H15.458L15.5 2.965z"}),e("path",{fill:"#FFDC5D",d:"M4.625 16.219c1.381-.611 3.354.208 4.75 2.188.917 1.3 1.187 3.151 2.391 3.344.46.073 1.234-.313 1.234-1.397V4.5s0-2 2-2 2 2 2 2v11.633c0-.029 1-.064 1-.082V2s0-2 2-2 2 2 2 2v14.053c0 .017 1 .041 1 .069V4.25s0-2 2-2 2 2 2 2v12.638c0 .118 1 .251 1 .398V8.75s0-2 2-2 2 2 2 2V24c0 6.627-5.373 12-12 12-4.775 0-8.06-2.598-9.896-5.292C8.547 28.423 8.096 26.051 8 25.334c0 0-.123-1.479-1.156-2.865-1.469-1.969-2.5-3.156-3.125-3.866-.317-.359-.625-1.707.906-2.384z"})),J=u("result",` - color: var(--n-text-color); - line-height: var(--n-line-height); - font-size: var(--n-font-size); - transition: - color .3s var(--n-bezier); -`,[u("result-icon",` - display: flex; - justify-content: center; - transition: color .3s var(--n-bezier); - `,[p("status-image",` - font-size: var(--n-icon-size); - width: 1em; - height: 1em; - `),u("base-icon",` - color: var(--n-icon-color); - font-size: var(--n-icon-size); - `)]),u("result-content",{marginTop:"24px"}),u("result-footer",` - margin-top: 24px; - text-align: center; - `),u("result-header",[p("title",` - margin-top: 16px; - font-weight: var(--n-title-font-weight); - transition: color .3s var(--n-bezier); - text-align: center; - color: var(--n-title-text-color); - font-size: var(--n-title-font-size); - `),p("description",` - margin-top: 4px; - text-align: center; - font-size: var(--n-font-size); - `)])]);const K={403:A,404:O,418:q,500:W,info:e(M,null),success:e(R,null),warning:e($,null),error:e(I,null)},G=Object.assign(Object.assign({},m.props),{size:{type:String,default:"medium"},status:{type:String,default:"info"},title:String,description:String});var Q=h({name:"Result",props:G,setup(n){const{mergedClsPrefixRef:r,inlineThemeDisabled:t}=F(n),s=m("Result","-result",J,V,n,r),o=_(()=>{const{size:l,status:a}=n,{common:{cubicBezierEaseInOut:c},self:{textColor:g,lineHeight:x,titleTextColor:z,titleFontWeight:w,[d("iconColor",a)]:C,[d("fontSize",l)]:y,[d("titleFontSize",l)]:B,[d("iconSize",l)]:b}}=s.value;return{"--n-bezier":c,"--n-font-size":y,"--n-icon-size":b,"--n-line-height":x,"--n-text-color":g,"--n-title-font-size":B,"--n-title-font-weight":w,"--n-title-text-color":z,"--n-icon-color":C||""}}),i=t?S("result",_(()=>{const{size:l,status:a}=n;let c="";return l&&(c+=l[0]),a&&(c+=a[0]),c}),o,n):void 0;return{mergedClsPrefix:r,cssVars:t?void 0:o,themeClass:i==null?void 0:i.themeClass,onRender:i==null?void 0:i.onRender}},render(){var n;const{status:r,$slots:t,mergedClsPrefix:s,onRender:o}=this;return o==null||o(),e("div",{class:[`${s}-result`,this.themeClass],style:this.cssVars},e("div",{class:`${s}-result-icon`},((n=t.icon)===null||n===void 0?void 0:n.call(t))||e(D,{clsPrefix:s},{default:()=>K[r]})),e("div",{class:`${s}-result-header`},this.title?e("div",{class:`${s}-result-header__title`},this.title):null,this.description?e("div",{class:`${s}-result-header__description`},this.description):null),t.default&&e("div",{class:`${s}-result-content`},t),t.footer&&e("div",{class:`${s}-result-footer`},t.footer()))}});const U=j("\u56DE\u4E3B\u9875"),X=h({setup(n){const r=T(),t=()=>{r.push({path:"/"})};return(s,o)=>{const i=E,l=N,a=Q,c=k;return H(),P("div",null,[f(i,{title:"404"}),f(c,{class:"main-content-wrap wrap404",bordered:""},{default:v(()=>[f(a,{status:"404",title:"404 \u8D44\u6E90\u4E0D\u5B58\u5728",description:"\u518D\u770B\u770B\u5176\u4ED6\u7684\u5427"},{footer:v(()=>[f(l,{onClick:t},{default:v(()=>[U]),_:1})]),_:1})]),_:1})])}}});var t1=L(X,[["__scopeId","data-v-4c5da4ba"]]);export{t1 as default}; diff --git a/web/dist/assets/Alert.a854329b.js b/web/dist/assets/Alert.a854329b.js deleted file mode 100644 index 85228da5..00000000 --- a/web/dist/assets/Alert.a854329b.js +++ /dev/null @@ -1,34 +0,0 @@ -import{c as j,ce as k,cf as u,b as f,l as y,m as c,bz as B,o as F,n as M,d as O,u as N,q as E,x as V,s as S,ba as K,v as g,y as q,r as D,h as s,b2 as G,cg as J,K as Q,N as U,bt as X,bu as Y,bv as Z,bs as ee,z as oe,bx as re}from"./index.f480f018.js";const ne=r=>{const{lineHeight:o,borderRadius:i,fontWeightStrong:m,baseColor:n,dividerColor:v,actionColor:z,textColor1:t,textColor2:a,closeColor:h,closeColorHover:C,closeColorPressed:b,infoColor:l,successColor:e,warningColor:p,errorColor:x,fontSize:T}=r;return Object.assign(Object.assign({},k),{fontSize:T,lineHeight:o,titleFontWeight:m,borderRadius:i,border:`1px solid ${v}`,color:z,titleTextColor:t,iconColor:a,contentTextColor:a,closeColor:h,closeColorHover:C,closeColorPressed:b,borderInfo:`1px solid ${u(n,f(l,{alpha:.25}))}`,colorInfo:u(n,f(l,{alpha:.08})),titleTextColorInfo:t,iconColorInfo:l,contentTextColorInfo:a,closeColorInfo:h,closeColorHoverInfo:C,closeColorPressedInfo:b,borderSuccess:`1px solid ${u(n,f(e,{alpha:.25}))}`,colorSuccess:u(n,f(e,{alpha:.08})),titleTextColorSuccess:t,iconColorSuccess:e,contentTextColorSuccess:a,closeColorSuccess:h,closeColorHoverSuccess:C,closeColorPressedSuccess:b,borderWarning:`1px solid ${u(n,f(p,{alpha:.33}))}`,colorWarning:u(n,f(p,{alpha:.08})),titleTextColorWarning:t,iconColorWarning:p,contentTextColorWarning:a,closeColorWarning:h,closeColorHoverWarning:C,closeColorPressedWarning:b,borderError:`1px solid ${u(n,f(x,{alpha:.25}))}`,colorError:u(n,f(x,{alpha:.08})),titleTextColorError:t,iconColorError:x,contentTextColorError:a,closeColorError:h,closeColorHoverError:C,closeColorPressedError:b})},te={name:"Alert",common:j,self:ne};var le=te,se=y("alert",` - line-height: var(--n-line-height); - border-radius: var(--n-border-radius); - position: relative; - transition: background-color .3s var(--n-bezier); - background-color: var(--n-color); - text-align: start; -`,[c("icon",{color:"var(--n-icon-color)"}),y("alert-body",{border:"var(--n-border)",padding:"var(--n-padding)"},[c("title",{color:"var(--n-title-text-color)"}),c("content",{color:"var(--n-content-text-color)"})]),B({originalTransition:"transform .3s var(--n-bezier)",enterToProps:{transform:"scale(1)"},leaveToProps:{transform:"scale(0.9)"}}),c("icon",` - position: absolute; - left: 0; - top: 0; - align-items: center; - justify-content: center; - display: flex; - width: var(--n-icon-size); - height: var(--n-icon-size); - font-size: var(--n-icon-size); - margin: var(--n-icon-margin); - `),c("close",` - transition: color .3s var(--n-bezier); - position: absolute; - right: 0; - top: 0; - margin: var(--n-close-margin); - font-size: var(--n-close-size); - `),F("show-icon",[y("alert-body",{paddingLeft:"calc(var(--n-icon-margin-left) + var(--n-icon-size) + var(--n-icon-margin-right))"})]),y("alert-body",` - border-radius: var(--n-border-radius); - transition: border-color .3s var(--n-bezier); - `,[c("title",` - transition: color .3s var(--n-bezier); - font-size: 16px; - line-height: 19px; - font-weight: var(--n-title-font-weight); - `,[M("& +",[c("content",{marginTop:"9px"})])]),c("content",{transition:"color .3s var(--n-bezier)",fontSize:"var(--n-font-size)"})]),c("icon",{transition:"color .3s var(--n-bezier)"})]);const ie=Object.assign(Object.assign({},E.props),{title:{type:String,default:void 0},showIcon:{type:Boolean,default:!0},type:{type:String,default:"default"},closable:{type:Boolean,default:!1},onClose:Function,onAfterLeave:{type:Function,default:void 0},onAfterHide:{type:Function,validator:()=>!0,default:void 0}});var ce=O({name:"Alert",inheritAttrs:!1,props:ie,setup(r){const{mergedClsPrefixRef:o,inlineThemeDisabled:i,mergedRtlRef:m}=N(r),n=E("Alert","-alert",se,le,r,o),v=V("Alert",m,o),z=S(()=>{const{common:{cubicBezierEaseInOut:l},self:e}=n.value,{fontSize:p,borderRadius:x,titleFontWeight:T,lineHeight:P,iconSize:$,iconMargin:I,iconMarginRtl:R,closeSize:_,closeMargin:A,closeMarginRtl:W,padding:w}=e,{type:d}=r,{left:H,right:L}=K(I);return{"--n-bezier":l,"--n-color":e[g("color",d)],"--n-close-color":e[g("closeColor",d)],"--n-close-color-hover":e[g("closeColorHover",d)],"--n-close-color-pressed":e[g("closeColorPressed",d)],"--n-icon-color":e[g("iconColor",d)],"--n-border":e[g("border",d)],"--n-title-text-color":e[g("titleTextColor",d)],"--n-content-text-color":e[g("contentTextColor",d)],"--n-line-height":P,"--n-border-radius":x,"--n-font-size":p,"--n-title-font-weight":T,"--n-icon-size":$,"--n-icon-margin":I,"--n-icon-margin-rtl":R,"--n-close-size":_,"--n-close-margin":A,"--n-close-margin-rtl":W,"--n-padding":w,"--n-icon-margin-left":H,"--n-icon-margin-right":L}}),t=i?q("alert",S(()=>r.type[0]),z,r):void 0,a=D(!0),h=()=>{const{onAfterLeave:l,onAfterHide:e}=r;l&&l(),e&&e()};return{rtlEnabled:v,mergedClsPrefix:o,visible:a,handleCloseClick:()=>{var l;Promise.resolve((l=r.onClose)===null||l===void 0?void 0:l.call(r)).then(e=>{e!==!1&&(a.value=!1)})},handleAfterLeave:()=>{h()},mergedTheme:n,cssVars:i?void 0:z,themeClass:t==null?void 0:t.themeClass,onRender:t==null?void 0:t.onRender}},render(){var r;return(r=this.onRender)===null||r===void 0||r.call(this),s(re,{onAfterLeave:this.handleAfterLeave},{default:()=>{const{mergedClsPrefix:o,$slots:i}=this,m={class:[`${o}-alert`,this.themeClass,this.showIcon&&`${o}-alert--show-icon`,this.rtlEnabled&&`${o}-alert--rtl`],style:this.cssVars,role:"alert"};return this.visible?s("div",Object.assign({},G(this.$attrs,m)),this.closable&&s(J,{clsPrefix:o,class:`${o}-alert__close`,onClick:this.handleCloseClick}),this.showIcon&&s("div",{class:`${o}-alert__icon`,"aria-hidden":"true"},Q(i.icon,()=>[s(U,{clsPrefix:o},{default:()=>{switch(this.type){case"success":return s(ee,null);case"info":return s(Z,null);case"warning":return s(Y,null);case"error":return s(X,null);default:return null}}})])),s("div",{class:`${o}-alert-body`},oe(i.header,n=>{const v=n||this.title;return v?s("div",{class:`${o}-alert-body__title`},v):null}),i.default&&s("div",{class:`${o}-alert-body__content`},i))):null}})}});export{ce as _}; diff --git a/web/dist/assets/Anouncement.98ee5b6f.js b/web/dist/assets/Anouncement.98ee5b6f.js deleted file mode 100644 index 1b7d2050..00000000 --- a/web/dist/assets/Anouncement.98ee5b6f.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as N}from"./post-skeleton.39a35f5b.js";import{_ as V}from"./main-nav.9110259b.js";import{ah as z,d as A,Z as E,ai as R,r as a,a1 as S,V as n,W as t,a3 as o,a4 as c,a2 as l,a6 as m,aa as F,ab as P,a5 as q,Y as s,a9 as _,c3 as D}from"./index.f480f018.js";import{f as I}from"./formatTime.02109bf5.js";import{_ as L}from"./List.49bcdf81.js";import{_ as M}from"./Pagination.1263479e.js";import{a as O,_ as T}from"./Skeleton.57e98fe3.js";const U={key:0,class:"pagination-wrap"},W={key:0,class:"skeleton-wrap"},Y={key:1},Z={key:0,class:"empty-wrap"},$={class:"bill-line"},j=A({setup(G){const d=E(),g=R(),v=a(!1),u=a([]),r=a(+g.query.p||1),f=a(20),p=a(0),h=i=>{r.value=i};return S(()=>{}),(i,H)=>{const y=V,k=M,x=N,w=O,C=T,B=L;return n(),t("div",null,[o(y,{title:"\u516C\u544A"}),o(B,{class:"main-content-wrap",bordered:""},{footer:c(()=>[p.value>1?(n(),t("div",U,[o(k,{page:r.value,"onUpdate:page":h,"page-slot":l(d).state.collapsedRight?5:8,"page-count":p.value},null,8,["page","page-slot","page-count"])])):m("",!0)]),default:c(()=>[v.value?(n(),t("div",W,[o(x,{num:f.value},null,8,["num"])])):(n(),t("div",Y,[u.value.length===0?(n(),t("div",Z,[o(w,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):m("",!0),(n(!0),t(F,null,P(u.value,e=>(n(),q(C,{key:e.id},{default:c(()=>[s("div",$,[s("div",null,"NO."+_(e.id),1),s("div",null,_(e.reason),1),s("div",{class:D({income:e.change_amount>=0,out:e.change_amount<0})},_((e.change_amount>0?"+":"")+(e.change_amount/100).toFixed(2)),3),s("div",null,_(l(I)(e.created_on)),1)])]),_:2},1024))),128))]))]),_:1})])}}});var te=z(j,[["__scopeId","data-v-543914f4"]]);export{te as default}; diff --git a/web/dist/assets/Collection.02f600ee.js b/web/dist/assets/Collection.02f600ee.js deleted file mode 100644 index 45ce9370..00000000 --- a/web/dist/assets/Collection.02f600ee.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as z}from"./post-item.03452002.js";import{_ as B}from"./post-skeleton.39a35f5b.js";import{_ as E}from"./main-nav.9110259b.js";import{ah as P,d as R,Z as V,ai as b,aj as F,r as n,a1 as M,V as e,W as o,a3 as a,a4 as p,cm as N,a2 as S,a6 as m,aa as $,ab as j,a5 as q}from"./index.f480f018.js";import{_ as I}from"./List.49bcdf81.js";import{_ as L}from"./Pagination.1263479e.js";import{a as T,_ as U}from"./Skeleton.57e98fe3.js";import"./content.ef1e095a.js";import"./formatTime.02109bf5.js";import"./Thing.eef6b133.js";const W={key:0,class:"pagination-wrap"},Z={key:0,class:"skeleton-wrap"},A={key:1},D={key:0,class:"empty-wrap"},G=R({setup(H){const d=V(),g=b();F();const s=n(!1),_=n([]),l=n(+g.query.p||1),c=n(20),u=n(0),r=()=>{s.value=!0,N({page:l.value,page_size:c.value}).then(t=>{s.value=!1,_.value=t.list,u.value=Math.ceil(t.pager.total_rows/c.value),window.scrollTo(0,0)}).catch(t=>{s.value=!1})},v=t=>{l.value=t,r()};return M(()=>{r()}),(t,J)=>{const f=E,h=L,k=B,y=T,w=z,C=U,x=I;return e(),o("div",null,[a(f,{title:"\u6536\u85CF"}),a(x,{class:"main-content-wrap",bordered:""},{footer:p(()=>[u.value>1?(e(),o("div",W,[a(h,{page:l.value,"onUpdate:page":v,"page-slot":S(d).state.collapsedRight?5:8,"page-count":u.value},null,8,["page","page-slot","page-count"])])):m("",!0)]),default:p(()=>[s.value?(e(),o("div",Z,[a(k,{num:c.value},null,8,["num"])])):(e(),o("div",A,[_.value.length===0?(e(),o("div",D,[a(y,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):m("",!0),(e(!0),o($,null,j(_.value,i=>(e(),q(C,{key:i.id},{default:p(()=>[a(w,{post:i},null,8,["post"])]),_:2},1024))),128))]))]),_:1})])}}});var se=P(G,[["__scopeId","data-v-2f4c0166"]]);export{se as default}; diff --git a/web/dist/assets/Contacts.a6b6de0d.js b/web/dist/assets/Contacts.a6b6de0d.js deleted file mode 100644 index 609e0044..00000000 --- a/web/dist/assets/Contacts.a6b6de0d.js +++ /dev/null @@ -1 +0,0 @@ -import{ah as k,d as C,aj as D,V as e,W as n,Y as c,a3 as o,a9 as v,ad as E,Z as N,ai as P,r as l,a1 as R,cn as S,a4 as g,a2 as U,a6 as y,aa as q,ab as M,a5 as T}from"./index.f480f018.js";import{_ as j}from"./post-skeleton.39a35f5b.js";import{_ as F}from"./main-nav.9110259b.js";import{_ as L}from"./List.49bcdf81.js";import{_ as W}from"./Pagination.1263479e.js";import{a as Y,_ as Z}from"./Skeleton.57e98fe3.js";const A={class:"avatar"},G={class:"base-info"},H={class:"username"},J={class:"uid"},K=C({props:{contact:null},setup(s){const p=D(),m=t=>{p.push({name:"user",query:{username:t}})};return(t,a)=>{const _=E;return e(),n("div",{class:"contact-item",onClick:a[0]||(a[0]=u=>m(s.contact.username))},[c("div",A,[o(_,{size:"large",src:s.contact.avatar},null,8,["src"])]),c("div",G,[c("div",H,[c("strong",null,v(s.contact.nickname),1),c("span",null," @"+v(s.contact.username),1)]),c("div",J,"UID. "+v(s.contact.user_id),1)])])}}});var O=k(K,[["__scopeId","data-v-23bc18c8"]]);const Q={key:0,class:"pagination-wrap"},X={key:0,class:"skeleton-wrap"},ee={key:1},te={key:0,class:"empty-wrap"},ae=C({setup(s){const p=N(),m=P(),t=l(!1),a=l([]),_=l(+m.query.p||1),u=l(20),d=l(0),w=r=>{_.value=r,f()};R(()=>{f()});const f=(r=!1)=>{a.value.length===0&&(t.value=!0),S({page:_.value,page_size:u.value}).then(i=>{t.value=!1,a.value=i.list,d.value=Math.ceil(i.pager.total_rows/u.value),r&&setTimeout(()=>{window.scrollTo(0,99999)},50)}).catch(i=>{t.value=!1})};return(r,i)=>{const x=F,$=W,B=j,b=Y,z=O,I=Z,V=L;return e(),n("div",null,[o(x,{title:"\u597D\u53CB"}),o(V,{class:"main-content-wrap",bordered:""},{footer:g(()=>[d.value>1?(e(),n("div",Q,[o($,{page:_.value,"onUpdate:page":w,"page-slot":U(p).state.collapsedRight?5:8,"page-count":d.value},null,8,["page","page-slot","page-count"])])):y("",!0)]),default:g(()=>[t.value?(e(),n("div",X,[o(B,{num:u.value},null,8,["num"])])):(e(),n("div",ee,[a.value.length===0?(e(),n("div",te,[o(b,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):y("",!0),(e(!0),n(q,null,M(a.value,h=>(e(),T(I,{key:h.user_id},{default:g(()=>[o(z,{contact:h},null,8,["contact"])]),_:2},1024))),128))]))]),_:1})])}}});var ue=k(ae,[["__scopeId","data-v-e9de9e50"]]);export{ue as default}; diff --git a/web/dist/assets/Home.d188c936.js b/web/dist/assets/Home.d188c936.js deleted file mode 100644 index 5a5d3412..00000000 --- a/web/dist/assets/Home.d188c936.js +++ /dev/null @@ -1,177 +0,0 @@ -var Ct=Object.defineProperty,xt=Object.defineProperties;var kt=Object.getOwnPropertyDescriptors;var Xe=Object.getOwnPropertySymbols;var Rt=Object.prototype.hasOwnProperty,St=Object.prototype.propertyIsEnumerable;var Qe=(e,n,t)=>n in e?Ct(e,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[n]=t,Ye=(e,n)=>{for(var t in n||(n={}))Rt.call(n,t)&&Qe(e,t,n[t]);if(Xe)for(var t of Xe(n))St.call(n,t)&&Qe(e,t,n[t]);return e},Ze=(e,n)=>xt(e,kt(n));import{_ as Vt}from"./post-item.03452002.js";import{_ as Ft}from"./post-skeleton.39a35f5b.js";import{d as W,h as i,c as He,a as Bt,b as et,u as Ce,e as st,f as Ke,r as R,i as Ve,t as se,g as Fe,j as te,w as It,k as J,l as K,m as G,n as Q,o as Y,p as Le,q as ue,s as Z,v as Re,x as Ge,y as We,z as $t,A as ut,B as Dt,C as zt,D as dt,E as ct,F as pt,G as At,_ as Se,H as Et,I as ft,J as he,K as tt,N as me,L as je,M as Pt,O as Tt,P as Ne,Q as Oe,R as Nt,S as mt,T as Ot,X as nt,U as ot,V as M,W as j,Y as q,Z as vt,$ as Ut,a0 as Mt,a1 as ht,a2 as ne,a3 as y,a4 as P,a5 as we,a6 as oe,a7 as at,a8 as xe,a9 as Lt,aa as gt,ab as bt,ac as jt,ad as qt,ae as Ht,af as Kt,ag as Gt,ah as Wt,ai as Jt,aj as Xt,ak as Qt}from"./index.f480f018.js";import{V as ie,l as rt,I as Yt,P as ye,_ as Zt}from"./IEnum.bfd96c78.js";import{p as en}from"./content.ef1e095a.js";import{_ as tn,a as nn,b as on,c as an}from"./Upload.efe3adfd.js";import{_ as rn}from"./main-nav.9110259b.js";import{_ as ln}from"./List.49bcdf81.js";import{_ as sn}from"./Pagination.1263479e.js";import{_ as un,a as dn}from"./Skeleton.57e98fe3.js";import"./formatTime.02109bf5.js";import"./Thing.eef6b133.js";var cn=W({name:"ArrowDown",render(){return i("svg",{viewBox:"0 0 28 28",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},i("g",{stroke:"none","stroke-width":"1","fill-rule":"evenodd"},i("g",{"fill-rule":"nonzero"},i("path",{d:"M23.7916,15.2664 C24.0788,14.9679 24.0696,14.4931 23.7711,14.206 C23.4726,13.9188 22.9978,13.928 22.7106,14.2265 L14.7511,22.5007 L14.7511,3.74792 C14.7511,3.33371 14.4153,2.99792 14.0011,2.99792 C13.5869,2.99792 13.2511,3.33371 13.2511,3.74793 L13.2511,22.4998 L5.29259,14.2265 C5.00543,13.928 4.53064,13.9188 4.23213,14.206 C3.93361,14.4931 3.9244,14.9679 4.21157,15.2664 L13.2809,24.6944 C13.6743,25.1034 14.3289,25.1034 14.7223,24.6944 L23.7916,15.2664 Z"}))))}}),pn=W({name:"ArrowUp",render(){return i("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20"},i("g",{fill:"none"},i("path",{d:"M3.13 9.163a.5.5 0 1 0 .74.674L9.5 3.67V17.5a.5.5 0 0 0 1 0V3.672l5.63 6.165a.5.5 0 0 0 .738-.674l-6.315-6.916a.746.746 0 0 0-.632-.24a.746.746 0 0 0-.476.24L3.131 9.163z",fill:"currentColor"})))}}),_t=W({name:"Remove",render(){return i("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},i("line",{x1:"400",y1:"256",x2:"112",y2:"256",style:` - fill: none; - stroke: currentColor; - stroke-linecap: round; - stroke-linejoin: round; - stroke-width: 32px; - `}))}});const fn=e=>{const{borderColor:n,primaryColor:t,baseColor:c,textColorDisabled:l,inputColorDisabled:v,textColor2:r,opacityDisabled:k,borderRadius:p,fontSizeSmall:D,fontSizeMedium:f,fontSizeLarge:T,heightSmall:b,heightMedium:s,heightLarge:S,lineHeight:_}=e;return Object.assign(Object.assign({},Bt),{labelLineHeight:_,buttonHeightSmall:b,buttonHeightMedium:s,buttonHeightLarge:S,fontSizeSmall:D,fontSizeMedium:f,fontSizeLarge:T,boxShadow:`inset 0 0 0 1px ${n}`,boxShadowActive:`inset 0 0 0 1px ${t}`,boxShadowFocus:`inset 0 0 0 1px ${t}, 0 0 0 2px ${et(t,{alpha:.2})}`,boxShadowHover:`inset 0 0 0 1px ${t}`,boxShadowDisabled:`inset 0 0 0 1px ${n}`,color:c,colorDisabled:v,textColor:r,textColorDisabled:l,dotColorActive:t,dotColorDisabled:n,buttonBorderColor:n,buttonBorderColorActive:t,buttonBorderColorHover:n,buttonColor:c,buttonColorActive:c,buttonTextColor:r,buttonTextColorActive:t,buttonTextColorHover:t,opacityDisabled:k,buttonBoxShadowFocus:`inset 0 0 0 1px ${t}, 0 0 0 2px ${et(t,{alpha:.3})}`,buttonBoxShadowHover:"inset 0 0 0 1px #0000",buttonBoxShadow:"inset 0 0 0 1px #0000",buttonBorderRadius:p})},mn={name:"Radio",common:He,self:fn};var yt=mn;const vn={name:String,value:{type:[String,Number],default:"on"},checked:{type:Boolean,default:void 0},defaultChecked:Boolean,disabled:{type:Boolean,default:void 0},label:String,size:String,onUpdateChecked:[Function,Array],"onUpdate:checked":[Function,Array],checkedValue:{type:Boolean,validator:()=>(It("radio","`checked-value` is deprecated, please use `checked` instead."),!0),default:void 0}},wt=st("n-radio-group");function qe(e){const n=Ke(e,{mergedSize(u){const{size:I}=e;if(I!==void 0)return I;if(r){const{mergedSizeRef:{value:U}}=r;if(U!==void 0)return U}return u?u.mergedSize.value:"medium"},mergedDisabled(u){return!!(e.disabled||r!=null&&r.disabledRef.value||u!=null&&u.disabled.value)}}),{mergedSizeRef:t,mergedDisabledRef:c}=n,l=R(null),v=R(null),r=Ve(wt,null),k=R(e.defaultChecked),p=se(e,"checked"),D=Fe(p,k),f=te(()=>r?r.valueRef.value===e.value:D.value),T=te(()=>{const{name:u}=e;if(u!==void 0)return u;if(r)return r.nameRef.value}),b=R(!1);function s(){if(r){const{doUpdateValue:u}=r,{value:I}=e;J(u,I)}else{const{onUpdateChecked:u,"onUpdate:checked":I}=e,{nTriggerFormInput:U,nTriggerFormChange:N}=n;u&&J(u,!0),I&&J(I,!0),U(),N(),k.value=!0}}function S(){c.value||f.value||s()}function _(){S()}function w(){b.value=!1}function A(){b.value=!0}return{mergedClsPrefix:r?r.mergedClsPrefixRef:Ce(e).mergedClsPrefixRef,inputRef:l,labelRef:v,mergedName:T,mergedDisabled:c,uncontrolledChecked:k,renderSafeChecked:f,focus:b,mergedSize:t,handleRadioInputChange:_,handleRadioInputBlur:w,handleRadioInputFocus:A}}qe.props=vn;var hn=K("radio",` - line-height: var(--n-label-line-height); - outline: none; - position: relative; - user-select: none; - display: inline-flex; - align-items: flex-start; - flex-wrap: nowrap; - font-size: var(--n-font-size); - word-break: break-word; -`,[G("dot-wrapper",` - position: relative; - flex-shrink: 0; - flex-grow: 0; - width: var(--n-radio-size); - `),K("radio-input",` - position: absolute; - border: 0; - border-radius: inherit; - left: 0; - right: 0; - top: 0; - bottom: 0; - opacity: 0; - z-index: 1; - cursor: pointer; - `),G("dot",` - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - height: var(--n-radio-size); - width: var(--n-radio-size); - background: var(--n-color); - box-shadow: var(--n-box-shadow); - border-radius: 50%; - transition: - background-color .3s var(--n-bezier), - box-shadow .3s var(--n-bezier); - `,[Q("&::before",` - content: ""; - opacity: 0; - position: absolute; - left: 4px; - top: 4px; - height: calc(100% - 8px); - width: calc(100% - 8px); - border-radius: 50%; - transform: scale(.8); - background: var(--n-dot-color-active); - transition: - opacity .3s var(--n-bezier), - background-color .3s var(--n-bezier), - transform .3s var(--n-bezier); - `),Y("checked",{boxShadow:"var(--n-box-shadow-active)"},[Q("&::before",` - opacity: 1; - transform: scale(1); - `)])]),G("label",` - color: var(--n-text-color); - padding: var(--n-label-padding); - display: inline-block; - transition: color .3s var(--n-bezier); - `),Le("disabled",` - cursor: pointer; - `,[Q("&:hover",[G("dot",{boxShadow:"var(--n-box-shadow-hover)"})]),Y("focus",[Q("&:not(:active)",[G("dot",{boxShadow:"var(--n-box-shadow-focus)"})])])]),Y("disabled",` - cursor: not-allowed; - `,[G("dot",{boxShadow:"var(--n-box-shadow-disabled)",backgroundColor:"var(--n-color-disabled)"},[Q("&::before",{backgroundColor:"var(--n-dot-color-disabled)"}),Y("checked",` - opacity: 1; - `)]),G("label",{color:"var(--n-text-color-disabled)"}),K("radio-input",` - cursor: not-allowed; - `)])]),gn=W({name:"Radio",props:Object.assign(Object.assign({},ue.props),qe.props),setup(e){const n=qe(e),t=ue("Radio","-radio",hn,yt,e,n.mergedClsPrefix),c=Z(()=>{const{mergedSize:{value:D}}=n,{common:{cubicBezierEaseInOut:f},self:{boxShadow:T,boxShadowActive:b,boxShadowDisabled:s,boxShadowFocus:S,boxShadowHover:_,color:w,colorDisabled:A,textColor:u,textColorDisabled:I,dotColorActive:U,dotColorDisabled:N,labelPadding:z,labelLineHeight:a,[Re("fontSize",D)]:d,[Re("radioSize",D)]:V}}=t.value;return{"--n-bezier":f,"--n-label-line-height":a,"--n-box-shadow":T,"--n-box-shadow-active":b,"--n-box-shadow-disabled":s,"--n-box-shadow-focus":S,"--n-box-shadow-hover":_,"--n-color":w,"--n-color-disabled":A,"--n-dot-color-active":U,"--n-dot-color-disabled":N,"--n-font-size":d,"--n-radio-size":V,"--n-text-color":u,"--n-text-color-disabled":I,"--n-label-padding":z}}),{inlineThemeDisabled:l,mergedClsPrefixRef:v,mergedRtlRef:r}=Ce(e),k=Ge("Radio",r,v),p=l?We("radio",Z(()=>n.mergedSize.value[0]),c,e):void 0;return Object.assign(n,{rtlEnabled:k,cssVars:l?void 0:c,themeClass:p==null?void 0:p.themeClass,onRender:p==null?void 0:p.onRender})},render(){const{$slots:e,mergedClsPrefix:n,onRender:t,label:c}=this;return t==null||t(),i("label",{class:[`${n}-radio`,this.themeClass,{[`${n}-radio--rtl`]:this.rtlEnabled,[`${n}-radio--disabled`]:this.mergedDisabled,[`${n}-radio--checked`]:this.renderSafeChecked,[`${n}-radio--focus`]:this.focus}],style:this.cssVars},i("input",{ref:"inputRef",type:"radio",class:`${n}-radio-input`,value:this.value,name:this.mergedName,checked:this.renderSafeChecked,disabled:this.mergedDisabled,onChange:this.handleRadioInputChange,onFocus:this.handleRadioInputFocus,onBlur:this.handleRadioInputBlur}),i("div",{class:`${n}-radio__dot-wrapper`},"\xA0",i("div",{class:[`${n}-radio__dot`,this.renderSafeChecked&&`${n}-radio__dot--checked`]})),$t(e.default,l=>!l&&!c?null:i("div",{ref:"labelRef",class:`${n}-radio__label`},l||c)))}}),bn=K("radio-group",` - display: inline-block; - font-size: var(--n-font-size); -`,[G("splitor",` - display: inline-block; - vertical-align: bottom; - width: 1px; - transition: - background-color .3s var(--n-bezier), - opacity .3s var(--n-bezier); - background: var(--n-button-border-color); - `,[Y("checked",{backgroundColor:"var(--n-button-border-color-active)"}),Y("disabled",{opacity:"var(--n-opacity-disabled)"})]),Y("button-group",` - white-space: nowrap; - height: var(--n-height); - line-height: var(--n-height); - `,[K("radio-button",{height:"var(--n-height)",lineHeight:"var(--n-height)"}),G("splitor",{height:"var(--n-height)"})]),K("radio-button",` - vertical-align: bottom; - outline: none; - position: relative; - user-select: none; - display: inline-block; - box-sizing: border-box; - padding-left: 14px; - padding-right: 14px; - white-space: nowrap; - transition: - background-color .3s var(--n-bezier), - opacity .3s var(--n-bezier), - border-color .3s var(--n-bezier), - color .3s var(--n-bezier); - color: var(--n-button-text-color); - border-top: 1px solid var(--n-button-border-color); - border-bottom: 1px solid var(--n-button-border-color); - `,[K("radio-input",` - position: absolute; - border: 0; - border-radius: inherit; - left: 0; - right: 0; - top: 0; - bottom: 0; - opacity: 0; - z-index: 1; - `),G("state-border",` - z-index: 1; - pointer-events: none; - position: absolute; - box-shadow: var(--n-button-box-shadow); - transition: box-shadow .3s var(--n-bezier); - left: -1px; - bottom: -1px; - right: -1px; - top: -1px; - `),Q("&:first-child",` - border-top-left-radius: var(--n-button-border-radius); - border-bottom-left-radius: var(--n-button-border-radius); - border-left: 1px solid var(--n-button-border-color); - `,[G("state-border",` - border-top-left-radius: var(--n-button-border-radius); - border-bottom-left-radius: var(--n-button-border-radius); - `)]),Q("&:last-child",` - border-top-right-radius: var(--n-button-border-radius); - border-bottom-right-radius: var(--n-button-border-radius); - border-right: 1px solid var(--n-button-border-color); - `,[G("state-border",` - border-top-right-radius: var(--n-button-border-radius); - border-bottom-right-radius: var(--n-button-border-radius); - `)]),Le("disabled",` - cursor: pointer; - `,[Q("&:hover",[G("state-border",` - transition: box-shadow .3s var(--n-bezier); - box-shadow: var(--n-button-box-shadow-hover); - `),Le("checked",{color:"var(--n-button-text-color-hover)"})]),Y("focus",[Q("&:not(:active)",[G("state-border",{boxShadow:"var(--n-button-box-shadow-focus)"})])])]),Y("checked",` - background: var(--n-button-color-active); - color: var(--n-button-text-color-active); - border-color: var(--n-button-border-color-active); - `),Y("disabled",` - cursor: not-allowed; - opacity: var(--n-opacity-disabled); - `)])]);function _n(e,n,t){var c;const l=[];let v=!1;for(let r=0;r{const{value:N}=t,{common:{cubicBezierEaseInOut:z},self:{buttonBorderColor:a,buttonBorderColorActive:d,buttonBorderRadius:V,buttonBoxShadow:C,buttonBoxShadowFocus:H,buttonBoxShadowHover:de,buttonColorActive:ce,buttonTextColor:ae,buttonTextColorActive:pe,buttonTextColorHover:ee,opacityDisabled:ge,[Re("buttonHeight",N)]:be,[Re("fontSize",N)]:ve}}=T.value;return{"--n-font-size":ve,"--n-bezier":z,"--n-button-border-color":a,"--n-button-border-color-active":d,"--n-button-border-radius":V,"--n-button-box-shadow":C,"--n-button-box-shadow-focus":H,"--n-button-box-shadow-hover":de,"--n-button-color-active":ce,"--n-button-text-color":ae,"--n-button-text-color-hover":ee,"--n-button-text-color-active":pe,"--n-height":be,"--n-opacity-disabled":ge}}),U=D?We("radio-group",Z(()=>t.value[0]),I,e):void 0;return{selfElRef:n,rtlEnabled:u,mergedClsPrefix:p,mergedValue:S,handleFocusout:A,handleFocusin:w,cssVars:D?void 0:I,themeClass:U==null?void 0:U.themeClass,onRender:U==null?void 0:U.onRender}},render(){var e;const{mergedValue:n,mergedClsPrefix:t,handleFocusin:c,handleFocusout:l}=this,{children:v,isButtonGroup:r}=_n(Dt(zt(this)),n,t);return(e=this.onRender)===null||e===void 0||e.call(this),i("div",{onFocusin:c,onFocusout:l,ref:"selfElRef",class:[`${t}-radio-group`,this.rtlEnabled&&`${t}-radio-group--rtl`,this.themeClass,r&&`${t}-radio-group--button-group`],style:this.cssVars},v)}});const Cn=()=>At,xn=dt({name:"DynamicInput",common:He,peers:{Input:ct,Button:pt},self:Cn});var kn=xn;const Je=st("n-dynamic-input");var Rn=W({name:"DynamicInputInputPreset",props:{clsPrefix:{type:String,required:!0},value:{type:String,default:""},parentPath:String,path:String,onUpdateValue:{type:Function,required:!0}},setup(){const{mergedThemeRef:e,placeholderRef:n}=Ve(Je);return{mergedTheme:e,placeholder:n}},render(){const{mergedTheme:e,placeholder:n,value:t,clsPrefix:c,onUpdateValue:l}=this;return i("div",{class:`${c}-dynamic-input-preset-input`},i(Se,{theme:e.peers.Input,"theme-overrides":e.peerOverrides.Input,value:t,placeholder:n,onUpdateValue:l}))}}),Sn=W({name:"DynamicInputPairPreset",props:{clsPrefix:{type:String,required:!0},value:{type:Object,default:()=>({key:"",value:""})},parentPath:String,path:String,onUpdateValue:{type:Function,required:!0}},setup(e){const{mergedThemeRef:n,keyPlaceholderRef:t,valuePlaceholderRef:c}=Ve(Je);return{mergedTheme:n,keyPlaceholder:t,valuePlaceholder:c,handleKeyInput(l){e.onUpdateValue({key:l,value:e.value.value})},handleValueInput(l){e.onUpdateValue({key:e.value.key,value:l})}}},render(){const{mergedTheme:e,keyPlaceholder:n,valuePlaceholder:t,value:c,clsPrefix:l}=this;return i("div",{class:`${l}-dynamic-input-preset-pair`},i(Se,{theme:e.peers.Input,"theme-overrides":e.peerOverrides.Input,value:c.key,class:`${l}-dynamic-input-pair-input`,placeholder:n,onUpdateValue:this.handleKeyInput}),i(Se,{theme:e.peers.Input,"theme-overrides":e.peerOverrides.Input,value:c.value,class:`${l}-dynamic-input-pair-input`,placeholder:t,onUpdateValue:this.handleValueInput}))}}),Vn=K("dynamic-input",{width:"100%"},[K("dynamic-input-item",` - margin-bottom: 10px; - display: flex; - flex-wrap: nowrap; - `,[K("dynamic-input-preset-input",{flex:1,alignItems:"center"}),K("dynamic-input-preset-pair",` - flex: 1; - display: flex; - align-items: center; - `,[K("dynamic-input-pair-input",[Q("&:first-child",{"margin-right":"12px"})])]),G("action",` - align-self: flex-start; - display: flex; - justify-content: flex-end; - flex-shrink: 0; - flex-grow: 0; - margin: var(--action-margin); - `,[Y("icon",{cursor:"pointer"})]),Q("&:last-child",{marginBottom:0})]),K("form-item",` - padding-top: 0 !important; - margin-right: 0 !important; - `,[K("form-item-blank",{paddingTop:"0 !important"})])]);const ke=new WeakMap,Fn=Object.assign(Object.assign({},ue.props),{max:Number,min:{type:Number,default:0},value:Array,defaultValue:{type:Array,default:()=>[]},preset:{type:String,default:"input"},keyField:String,itemStyle:[String,Object],keyPlaceholder:{type:String,default:""},valuePlaceholder:{type:String,default:""},placeholder:{type:String,default:""},showSortButton:Boolean,createButtonProps:Object,onCreate:Function,onRemove:Function,"onUpdate:value":[Function,Array],onUpdateValue:[Function,Array],onClear:Function,onInput:[Function,Array]});var Bn=W({name:"DynamicInput",props:Fn,setup(e,{slots:n}){const{mergedComponentPropsRef:t,mergedClsPrefixRef:c,inlineThemeDisabled:l}=Ce(),v=Ve(Et,null),r=R(e.defaultValue),k=se(e,"value"),p=Fe(k,r),D=ue("DynamicInput","-dynamic-input",Vn,kn,e,c),f=Z(()=>{const{value:a}=p;if(Array.isArray(a)){const{max:d}=e;return d!==void 0&&a.length>=d}return!1}),T=Z(()=>{const{value:a}=p;return Array.isArray(a)?a.length<=e.min:!0}),b=Z(()=>{var a,d;return(d=(a=t==null?void 0:t.value)===null||a===void 0?void 0:a.DynamicInput)===null||d===void 0?void 0:d.buttonSize});function s(a){const{onInput:d,"onUpdate:value":V,onUpdateValue:C}=e;d&&J(d,a),V&&J(V,a),C&&J(C,a),r.value=a}function S(a,d){if(a==null||typeof a!="object")return d;const V=Ne(a)?Oe(a):a;let C=ke.get(V);return C===void 0&&ke.set(V,C=Nt()),C}function _(a,d){const{value:V}=p,C=Array.from(V!=null?V:[]),H=C[a];if(C[a]=d,H&&d&&typeof H=="object"&&typeof d=="object"){const de=Ne(H)?Oe(H):H,ce=Ne(d)?Oe(d):d,ae=ke.get(de);ae!==void 0&&ke.set(ce,ae)}s(C)}function w(){A(0)}function A(a){const{value:d}=p,{onCreate:V}=e,C=Array.from(d!=null?d:[]);if(V)C.splice(a+1,0,V(a+1)),s(C);else if(n.default)C.splice(a+1,0,null),s(C);else switch(e.preset){case"input":C.splice(a+1,0,""),s(C);break;case"pair":C.splice(a+1,0,{key:"",value:""}),s(C);break}}function u(a){const{value:d}=p;if(!Array.isArray(d))return;const{min:V}=e;if(d.length<=V)return;const C=Array.from(d);C.splice(a,1),s(C);const{onRemove:H}=e;H&&H(a)}function I(a,d,V){if(d<0||V<0||d>=a.length||V>=a.length||d===V)return;const C=a[d];a[d]=a[V],a[V]=C}function U(a,d){const{value:V}=p;if(!Array.isArray(V))return;const C=Array.from(V);a==="up"&&I(C,d,d-1),a==="down"&&I(C,d,d+1),s(C)}ut(Je,{mergedThemeRef:D,keyPlaceholderRef:se(e,"keyPlaceholder"),valuePlaceholderRef:se(e,"valuePlaceholder"),placeholderRef:se(e,"placeholder")});const N=Z(()=>{const{self:{actionMargin:a}}=D.value;return{"--action-margin":a}}),z=l?We("dynamic-input",void 0,N,e):void 0;return{locale:ft("DynamicInput").localeRef,buttonSize:b,mergedClsPrefix:c,NFormItem:v,uncontrolledValue:r,mergedValue:p,insertionDisabled:f,removeDisabled:T,handleCreateClick:w,ensureKey:S,handleValueChange:_,remove:u,move:U,createItem:A,mergedTheme:D,cssVars:l?void 0:N,themeClass:z==null?void 0:z.themeClass,onRender:z==null?void 0:z.onRender}},render(){const{$slots:e,buttonSize:n,mergedClsPrefix:t,mergedValue:c,locale:l,mergedTheme:v,keyField:r,itemStyle:k,preset:p,showSortButton:D,NFormItem:f,ensureKey:T,handleValueChange:b,remove:s,createItem:S,move:_,onRender:w}=this;return w==null||w(),i("div",{class:[`${t}-dynamic-input`,this.themeClass],style:this.cssVars},!Array.isArray(c)||c.length===0?i(he,Object.assign({block:!0,ghost:!0,dashed:!0,size:n},this.createButtonProps,{disabled:this.insertionDisabled,theme:v.peers.Button,themeOverrides:v.peerOverrides.Button,onClick:this.handleCreateClick}),{default:()=>tt(e["create-button-default"],()=>[l.create]),icon:()=>tt(e["create-button-icon"],()=>[i(me,{clsPrefix:t},{default:()=>i(je,null)})])}):c.map((A,u)=>i("div",{key:r?A[r]:T(A,u),"data-key":r?A[r]:T(A,u),class:`${t}-dynamic-input-item`,style:k},Pt(e.default,{value:c[u],index:u},()=>[p==="input"?i(Rn,{clsPrefix:t,value:c[u],parentPath:f?f.path.value:void 0,path:f!=null&&f.path.value?`${f.path.value}[${u}]`:void 0,onUpdateValue:I=>b(u,I)}):p==="pair"?i(Sn,{clsPrefix:t,value:c[u],parentPath:f?f.path.value:void 0,path:f!=null&&f.path.value?`${f.path.value}[${u}]`:void 0,onUpdateValue:I=>b(u,I)}):null]),i("div",{class:`${t}-dynamic-input-item__action`},i(Tt,{size:n},{default:()=>[i(he,{disabled:this.removeDisabled,theme:v.peers.Button,themeOverrides:v.peerOverrides.Button,circle:!0,onClick:()=>s(u)},{icon:()=>i(me,{clsPrefix:t},{default:()=>i(_t,null)})}),i(he,{disabled:this.insertionDisabled,circle:!0,theme:v.peers.Button,themeOverrides:v.peerOverrides.Button,onClick:()=>S(u)},{icon:()=>i(me,{clsPrefix:t},{default:()=>i(je,null)})}),D?i(he,{disabled:u===0,circle:!0,theme:v.peers.Button,themeOverrides:v.peerOverrides.Button,onClick:()=>_("up",u)},{icon:()=>i(me,{clsPrefix:t},{default:()=>i(pn,null)})}):null,D?i(he,{disabled:u===c.length-1,circle:!0,theme:v.peers.Button,themeOverrides:v.peerOverrides.Button,onClick:()=>_("down",u)},{icon:()=>i(me,{clsPrefix:t},{default:()=>i(cn,null)})}):null]})))))}});const In=e=>{const{textColorDisabled:n}=e;return{iconColorDisabled:n}},$n=dt({name:"InputNumber",common:He,peers:{Button:pt,Input:ct},self:In});var Dn=$n;function zn(e){return e==null||typeof e=="string"&&e.trim()===""?null:Number(e)}function An(e){return e.includes(".")&&(/^(-)?\d+.*(\.|0)$/.test(e)||/^\.\d+$/.test(e))}function Ue(e){return e==null?!0:!Number.isNaN(e)}function En(e){return e==null?"":String(e)}function Me(e){if(e===null)return null;if(typeof e=="number")return e;{const n=Number(e);return Number.isNaN(n)?null:n}}var Pn=Q([K("input-number-suffix",` - display: inline-block; - margin-right: 10px; - `)]);const lt=800,it=100,Tn=Object.assign(Object.assign({},ue.props),{autofocus:Boolean,loading:{type:Boolean,default:void 0},placeholder:String,defaultValue:{type:Number,default:null},value:Number,step:{type:[Number,String],default:1},min:[Number,String],max:[Number,String],size:String,disabled:{type:Boolean,default:void 0},validator:Function,bordered:{type:Boolean,default:void 0},showButton:{type:Boolean,default:!0},readonly:Boolean,clearable:Boolean,keyboard:{type:Object,default:{}},updateValueOnInput:{type:Boolean,default:!0},status:String,"onUpdate:value":[Function,Array],onUpdateValue:[Function,Array],onFocus:[Function,Array],onBlur:[Function,Array],onClear:[Function,Array],onChange:[Function,Array]});var Nn=W({name:"InputNumber",props:Tn,setup(e){const{mergedBorderedRef:n,mergedClsPrefixRef:t,mergedRtlRef:c}=Ce(e),l=ue("InputNumber","-input-number",Pn,Dn,e,t),{localeRef:v}=ft("InputNumber"),r=Ke(e),{mergedSizeRef:k,mergedDisabledRef:p,mergedStatusRef:D}=r,f=R(null),T=R(null),b=R(null),s=R(e.defaultValue),S=se(e,"value"),_=Fe(S,s),w=R(""),A=o=>{const m=[e.min,e.max,e.step,o].map(B=>{const O=String(B).split(".")[1];return O?O.length:0});return Math.max(...m)},u=te(()=>{const{placeholder:o}=e;return o!==void 0?o:v.value.placeholder}),I=te(()=>{const o=Me(e.step);return o!==null?o===0?1:Math.abs(o):1}),U=te(()=>{const o=Me(e.min);return o!==null?o:null}),N=te(()=>{const o=Me(e.max);return o!==null?o:null}),z=o=>{const{value:m}=_;if(o===m){d();return}const{"onUpdate:value":B,onUpdateValue:O,onChange:$}=e,{nTriggerFormInput:_e,nTriggerFormChange:X}=r;$&&J($,o),O&&J(O,o),B&&J(B,o),s.value=o,_e(),X()},a=(o=0,m=!0,B=!1)=>{const{value:O}=w;if(B&&An(O))return!1;const $=zn(O);if($===null)return m&&z(null),null;if(Ue($)){const _e=A($);let X=parseFloat(($+o).toFixed(_e));if(Ue(X)){const{value:Pe}=N,{value:Te}=U;if(Pe!==null&&X>Pe){if(!m||B)return!1;X=Pe}if(Te!==null&&X{const{value:o}=_;Ue(o)?w.value=En(o):w.value=String(o)};d();const V=te(()=>a(0,!1)===!1),C=te(()=>{const{value:o}=_;if(e.validator&&o===null)return!1;const{value:m}=I;return a(-m,!1)!==!1}),H=te(()=>{const{value:o}=_;if(e.validator&&o===null)return!1;const{value:m}=I;return a(+m,!1)!==!1});function de(o){const{onFocus:m}=e,{nTriggerFormFocus:B}=r;m&&J(m,o),B()}function ce(o){var m,B;if(o.target===((m=f.value)===null||m===void 0?void 0:m.wrapperElRef))return;const O=a();if(O!==!1){const X=(B=f.value)===null||B===void 0?void 0:B.inputElRef;X&&(X.value=String(O||"")),_.value===O&&d()}else d();const{onBlur:$}=e,{nTriggerFormBlur:_e}=r;$&&J($,o),_e()}function ae(o){const{onClear:m}=e;m&&J(m,o)}function pe(){const{value:o}=H;if(!o){F();return}const{value:m}=_;if(m===null)e.validator||z(ve());else{const{value:B}=I;a(B)}}function ee(){const{value:o}=C;if(!o){g();return}const{value:m}=_;if(m===null)e.validator||z(ve());else{const{value:B}=I;a(-B)}}const ge=de,be=ce;function ve(){if(e.validator)return null;const{value:o}=U,{value:m}=N;return o!==null?Math.max(0,o):m!==null?Math.min(0,m):0}function Be(o){ae(o),z(null)}function Ie(o){var m,B,O;!((m=b.value)===null||m===void 0)&&m.$el.contains(o.target)&&o.preventDefault(),!((B=T.value)===null||B===void 0)&&B.$el.contains(o.target)&&o.preventDefault(),(O=f.value)===null||O===void 0||O.activate()}let fe=null,re=null,h=null;function g(){h&&(window.clearTimeout(h),h=null),fe&&(window.clearInterval(fe),fe=null)}function F(){E&&(window.clearTimeout(E),E=null),re&&(window.clearInterval(re),re=null)}function x(){h=window.setTimeout(()=>{fe=window.setInterval(()=>{ee()},it)},lt),ot("mouseup",document,()=>{window.setTimeout(g,0)})}let E=null;function L(){E=window.setTimeout(()=>{re=window.setInterval(()=>{pe()},it)},lt),ot("mouseup",document,()=>{window.setTimeout(F,0)})}const le=()=>{re||pe()},$e=()=>{fe||ee()};function De(o){var m,B;if(o.code==="Enter"||o.code==="NumpadEnter"){if(o.target===((m=f.value)===null||m===void 0?void 0:m.wrapperElRef))return;a()!==!1&&((B=f.value)===null||B===void 0||B.deactivate())}else if(o.code==="ArrowUp"){if(e.keyboard.ArrowUp===!1)return;o.preventDefault(),a()!==!1&&pe()}else if(o.code==="ArrowDown"){if(e.keyboard.ArrowDown===!1)return;o.preventDefault(),a()!==!1&&ee()}}function ze(o){w.value=o,e.updateValueOnInput&&a(0,!0,!0)}mt(_,()=>{d()});const Ae={focus:()=>{var o;return(o=f.value)===null||o===void 0?void 0:o.focus()},blur:()=>{var o;return(o=f.value)===null||o===void 0?void 0:o.blur()}},Ee=Ge("InputNumber",c,t);return Object.assign(Object.assign({},Ae),{rtlEnabled:Ee,inputInstRef:f,minusButtonInstRef:T,addButtonInstRef:b,mergedClsPrefix:t,mergedBordered:n,uncontrolledValue:s,mergedValue:_,mergedPlaceholder:u,displayedValueInvalid:V,mergedSize:k,mergedDisabled:p,displayedValue:w,addable:H,minusable:C,mergedStatus:D,handleFocus:ge,handleBlur:be,handleClear:Be,handleMouseDown:Ie,handleAddClick:le,handleMinusClick:$e,handleAddMousedown:L,handleMinusMousedown:x,handleKeyDown:De,handleUpdateDisplayedValue:ze,mergedTheme:l,inputThemeOverrides:{paddingSmall:"0 8px 0 10px",paddingMedium:"0 8px 0 12px",paddingLarge:"0 8px 0 14px"},buttonThemeOverrides:Z(()=>{const{self:{iconColorDisabled:o}}=l.value,[m,B,O,$]=Ot(o);return{textColorTextDisabled:`rgb(${m}, ${B}, ${O})`,opacityDisabled:`${$}`}})})},render(){const{mergedClsPrefix:e}=this;return i("div",{class:[`${e}-input-number`,this.rtlEnabled&&`${e}-input-number--rtl`]},i(Se,{ref:"inputInstRef",autofocus:this.autofocus,status:this.mergedStatus,bordered:this.mergedBordered,loading:this.loading,value:this.displayedValue,onUpdateValue:this.handleUpdateDisplayedValue,theme:this.mergedTheme.peers.Input,themeOverrides:this.mergedTheme.peerOverrides.Input,builtinThemeOverrides:this.inputThemeOverrides,size:this.mergedSize,placeholder:this.mergedPlaceholder,disabled:this.mergedDisabled,readonly:this.readonly,textDecoration:this.displayedValueInvalid?"line-through":void 0,onFocus:this.handleFocus,onBlur:this.handleBlur,onKeydown:this.handleKeyDown,onMousedown:this.handleMouseDown,onClear:this.handleClear,clearable:this.clearable,internalLoadingBeforeSuffix:!0},{prefix:()=>{var n,t;return(t=(n=this.$slots).prefix)===null||t===void 0?void 0:t.call(n)},suffix:()=>{var n,t;return this.showButton?[this.$slots.suffix&&i("span",{class:`${e}-input-number-suffix`},{default:this.$slots.suffix}),i(nt,{text:!0,disabled:!this.minusable||this.mergedDisabled||this.readonly,focusable:!1,builtinThemeOverrides:this.buttonThemeOverrides,onClick:this.handleMinusClick,onMousedown:this.handleMinusMousedown,ref:"minusButtonInstRef"},{default:()=>i(me,{clsPrefix:e,"aria-disabled":!0},{default:()=>i(_t,null)})}),i(nt,{text:!0,disabled:!this.addable||this.mergedDisabled||this.readonly,focusable:!1,builtinThemeOverrides:this.buttonThemeOverrides,onClick:this.handleAddClick,onMousedown:this.handleAddMousedown,ref:"addButtonInstRef"},{default:()=>i(me,{clsPrefix:e},{default:()=>i(je,null)})})]:(t=(n=this.$slots).suffix)===null||t===void 0?void 0:t.call(n)}}))}});const On={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Un=q("path",{d:"M216.08 192v143.85a40.08 40.08 0 0 0 80.15 0l.13-188.55a67.94 67.94 0 1 0-135.87 0v189.82a95.51 95.51 0 1 0 191 0V159.74",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-miterlimit":"10","stroke-width":"32"},null,-1),Mn=[Un];var Ln=W({name:"AttachOutline",render:function(n,t){return M(),j("svg",On,Mn)}});const jn={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},qn=q("path",{d:"M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192s192-86 192-192z",fill:"none",stroke:"currentColor","stroke-miterlimit":"10","stroke-width":"32"},null,-1),Hn=q("path",{d:"M350.67 150.93l-117.2 46.88a64 64 0 0 0-35.66 35.66l-46.88 117.2a8 8 0 0 0 10.4 10.4l117.2-46.88a64 64 0 0 0 35.66-35.66l46.88-117.2a8 8 0 0 0-10.4-10.4zM256 280a24 24 0 1 1 24-24a24 24 0 0 1-24 24z",fill:"currentColor"},null,-1),Kn=[qn,Hn];var Gn=W({name:"CompassOutline",render:function(n,t){return M(),j("svg",jn,Kn)}});const Wn={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Jn=q("path",{d:"M255.66 112c-77.94 0-157.89 45.11-220.83 135.33a16 16 0 0 0-.27 17.77C82.92 340.8 161.8 400 255.66 400c92.84 0 173.34-59.38 221.79-135.25a16.14 16.14 0 0 0 0-17.47C428.89 172.28 347.8 112 255.66 112z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),Xn=q("circle",{cx:"256",cy:"256",r:"80",fill:"none",stroke:"currentColor","stroke-miterlimit":"10","stroke-width":"32"},null,-1),Qn=[Jn,Xn];var Yn=W({name:"EyeOutline",render:function(n,t){return M(),j("svg",Wn,Qn)}});const Zn={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},eo=q("path",{d:"M374.79 308.78L457.5 367a16 16 0 0 0 22.5-14.62V159.62A16 16 0 0 0 457.5 145l-82.71 58.22A16 16 0 0 0 368 216.3v79.4a16 16 0 0 0 6.79 13.08z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),to=q("path",{d:"M268 384H84a52.15 52.15 0 0 1-52-52V180a52.15 52.15 0 0 1 52-52h184.48A51.68 51.68 0 0 1 320 179.52V332a52.15 52.15 0 0 1-52 52z",fill:"none",stroke:"currentColor","stroke-miterlimit":"10","stroke-width":"32"},null,-1),no=[eo,to];var oo=W({name:"VideocamOutline",render:function(n,t){return M(),j("svg",Zn,no)}});const ao={key:0,class:"compose-wrap"},ro={class:"compose-line"},lo={class:"compose-user"},io={class:"compose-line compose-options"},so={class:"attachment"},uo={class:"submit-wrap"},co=xe(" \u53D1\u5E03 "),po={class:"attachment-list-wrap"},fo={key:0,class:"attachment-price-wrap"},mo=q("span",null," \u9644\u4EF6\u4EF7\u683C\uFFE5",-1),vo={key:0,class:"eye-wrap"},ho={key:1,class:"link-wrap"},go=xe(" \u521B\u5EFA\u94FE\u63A5 "),bo={key:1,class:"compose-wrap"},_o=q("div",{class:"login-wrap"},[q("span",{class:"login-banner"}," \u767B\u5F55\u540E\uFF0C\u7CBE\u5F69\u66F4\u591A")],-1),yo={class:"login-wrap"},wo=xe(" \u767B\u5F55 "),Co=xe(" \u6CE8\u518C "),xo=W({emits:["post-success"],setup(e,{emit:n}){const t=vt(),c=R([]),l=R(!1),v=R(!1),r=R(!1),k=R(!1),p=R(""),D=R([]),f=R(),T=R(0),b=R("public/image"),s=R([]),S=R([]),_=R([]),w=R([]),A=R(ie.FRIEND),u=R(ie.FRIEND),I=[{value:ie.PUBLIC,label:"\u516C\u5F00"},{value:ie.PRIVATE,label:"\u79C1\u5BC6"},{value:ie.FRIEND,label:"\u597D\u53CB\u53EF\u89C1"}],U="false".toLocaleLowerCase()==="true",N="false".toLocaleLowerCase()==="true",z="true".toLocaleLowerCase()==="true",a="true".toLocaleLowerCase()==="true",d="/v1/attachment",V=R(),C=()=>{r.value=!r.value,r.value&&k.value&&(k.value=!1)},H=()=>{k.value=!k.value,k.value&&r.value&&(r.value=!1)},de=rt.exports.debounce(h=>{Ut({k:h}).then(g=>{let F=[];g.map(x=>{F.push({label:x,value:x})}),c.value=F,l.value=!1}).catch(g=>{l.value=!1})},200),ce=rt.exports.debounce(h=>{Mt({k:h}).then(g=>{let F=[];g.map(x=>{F.push({label:x,value:x})}),c.value=F,l.value=!1}).catch(g=>{l.value=!1})},200),ae=(h,g)=>{l.value||(l.value=!0,g==="@"?de(h):ce(h))},pe=h=>{h.length>200||(p.value=h)},ee=h=>{b.value=h},ge=h=>{s.value=h},be=async h=>{var g,F,x,E,L,le;return b.value==="public/image"&&!["image/png","image/jpg","image/jpeg","image/gif"].includes((g=h.file.file)==null?void 0:g.type)?(window.$message.warning("\u56FE\u7247\u4EC5\u5141\u8BB8 png/jpg/gif \u683C\u5F0F"),!1):b.value==="image"&&((F=h.file.file)==null?void 0:F.size)>10485760?(window.$message.warning("\u56FE\u7247\u5927\u5C0F\u4E0D\u80FD\u8D85\u8FC710MB"),!1):b.value==="public/video"&&!["video/mp4","video/quicktime"].includes((x=h.file.file)==null?void 0:x.type)?(window.$message.warning("\u89C6\u9891\u4EC5\u5141\u8BB8 mp4/mov \u683C\u5F0F"),!1):b.value==="public/video"&&((E=h.file.file)==null?void 0:E.size)>104857600?(window.$message.warning("\u89C6\u9891\u5927\u5C0F\u4E0D\u80FD\u8D85\u8FC7100MB"),!1):b.value==="attachment"&&!["application/zip"].includes((L=h.file.file)==null?void 0:L.type)?(window.$message.warning("\u9644\u4EF6\u4EC5\u5141\u8BB8 zip \u683C\u5F0F"),!1):b.value==="attachment"&&((le=h.file.file)==null?void 0:le.size)>104857600?(window.$message.warning("\u9644\u4EF6\u5927\u5C0F\u4E0D\u80FD\u8D85\u8FC7100MB"),!1):!0},ve=({file:h,event:g})=>{var F;try{let x=JSON.parse((F=g.target)==null?void 0:F.response);x.code===0&&(b.value==="public/image"&&S.value.push({id:h.id,content:x.data.content}),b.value==="public/video"&&_.value.push({id:h.id,content:x.data.content}),b.value==="attachment"&&w.value.push({id:h.id,content:x.data.content}))}catch{window.$message.error("\u4E0A\u4F20\u5931\u8D25")}},Be=({file:h,event:g})=>{var F;try{let x=JSON.parse((F=g.target)==null?void 0:F.response);if(x.code!==0){let E=x.msg||"\u4E0A\u4F20\u5931\u8D25";x.details&&x.details.length>0&&x.details.map(L=>{E+=":"+L}),window.$message.error(E)}}catch{window.$message.error("\u4E0A\u4F20\u5931\u8D25")}},Ie=({file:h})=>{let g=S.value.findIndex(F=>F.id===h.id);g>-1&&S.value.splice(g,1),g=_.value.findIndex(F=>F.id===h.id),g>-1&&_.value.splice(g,1),g=w.value.findIndex(F=>F.id===h.id),g>-1&&w.value.splice(g,1)},fe=()=>{if(p.value.trim().length===0){window.$message.warning("\u8BF7\u8F93\u5165\u5185\u5BB9\u54E6");return}let{tags:h,users:g}=en(p.value);const F=[];let x=100;F.push({content:p.value,type:ye.TEXT,sort:x}),S.value.map(E=>{x++,F.push({content:E.content,type:ye.IMAGEURL,sort:x})}),_.value.map(E=>{x++,F.push({content:E.content,type:ye.VIDEOURL,sort:x})}),w.value.map(E=>{x++,F.push({content:E.content,type:ye.ATTACHMENT,sort:x})}),D.value.length>0&&D.value.map(E=>{x++,F.push({content:E,type:ye.LINKURL,sort:x})}),v.value=!0,jt({contents:F,tags:Array.from(new Set(h)),users:Array.from(new Set(g)),attachment_price:+T.value*100,visibility:A.value}).then(E=>{var L;window.$message.success("\u53D1\u5E03\u6210\u529F"),v.value=!1,n("post-success",E),r.value=!1,k.value=!1,(L=f.value)==null||L.clear(),s.value=[],p.value="",D.value=[],S.value=[],_.value=[],w.value=[],A.value=u.value}).catch(E=>{v.value=!1})},re=h=>{t.commit("triggerAuth",!0),t.commit("triggerAuthKey",h)};return ht(()=>{"friend".toLowerCase()==="friend"?u.value=ie.FRIEND:"friend".toLowerCase()==="public"?u.value=ie.PUBLIC:u.value=ie.PRIVATE,A.value=u.value,V.value="Bearer "+localStorage.getItem("PAOPAO_TOKEN")}),(h,g)=>{const F=qt,x=Zt,E=Ht,L=he,le=tn,$e=nn,De=Kt,ze=on,Ae=Nn,Ee=an,o=gn,m=Gt,B=wn,O=Bn;return M(),j("div",null,[ne(t).state.userInfo.id>0?(M(),j("div",ao,[q("div",ro,[q("div",lo,[y(F,{round:"",size:30,src:ne(t).state.userInfo.avatar},null,8,["src"])]),y(x,{type:"textarea",size:"large",autosize:"",bordered:!1,loading:l.value,value:p.value,prefix:["@","#"],options:c.value,onSearch:ae,"onUpdate:value":pe,placeholder:"\u8BF4\u8BF4\u60A8\u7684\u65B0\u9C9C\u4E8B..."},null,8,["loading","value","options"])]),y(Ee,{ref_key:"uploadRef",ref:f,abstract:"","list-type":"image",multiple:!0,max:9,action:d,headers:{Authorization:V.value},data:{type:b.value},onBeforeUpload:be,onFinish:ve,onError:Be,onRemove:Ie,"onUpdate:fileList":ge},{default:P(()=>[q("div",io,[q("div",so,[y(le,{abstract:""},{default:P(({handleClick:$})=>[y(L,{disabled:s.value.length>0&&b.value==="public/video"||s.value.length===9,onClick:()=>{ee("public/image"),$()},quaternary:"",circle:"",type:"primary"},{icon:P(()=>[y(E,{size:"20",color:"var(--primary-color)"},{default:P(()=>[y(ne(Yt))]),_:1})]),_:2},1032,["disabled","onClick"])]),_:1}),U?(M(),we(le,{key:0,abstract:""},{default:P(({handleClick:$})=>[y(L,{disabled:s.value.length>0&&b.value!=="public/video"||s.value.length===9,onClick:()=>{ee("public/video"),$()},quaternary:"",circle:"",type:"primary"},{icon:P(()=>[y(E,{size:"20",color:"var(--primary-color)"},{default:P(()=>[y(ne(oo))]),_:1})]),_:2},1032,["disabled","onClick"])]),_:1})):oe("",!0),N?(M(),we(le,{key:1,abstract:""},{default:P(({handleClick:$})=>[y(L,{disabled:s.value.length>0&&b.value==="public/video"||s.value.length===9,onClick:()=>{ee("attachment"),$()},quaternary:"",circle:"",type:"primary"},{icon:P(()=>[y(E,{size:"20",color:"var(--primary-color)"},{default:P(()=>[y(ne(Ln))]),_:1})]),_:2},1032,["disabled","onClick"])]),_:1})):oe("",!0),y(L,{quaternary:"",circle:"",type:"primary",onClick:at(C,["stop"])},{icon:P(()=>[y(E,{size:"20",color:"var(--primary-color)"},{default:P(()=>[y(ne(Gn))]),_:1})]),_:1},8,["onClick"]),a?(M(),we(L,{key:2,quaternary:"",circle:"",type:"primary",onClick:at(H,["stop"])},{icon:P(()=>[y(E,{size:"20",color:"var(--primary-color)"},{default:P(()=>[y(ne(Yn))]),_:1})]),_:1},8,["onClick"])):oe("",!0)]),q("div",uo,[y(De,{trigger:"hover",placement:"bottom"},{trigger:P(()=>[y($e,{class:"text-statistic",type:"circle","show-indicator":!1,status:"success","stroke-width":10,percentage:p.value.length/200*100},null,8,["percentage"])]),default:P(()=>[xe(" "+Lt(p.value.length)+" / 200 ",1)]),_:1}),y(L,{loading:v.value,onClick:fe,type:"primary",secondary:"",round:""},{default:P(()=>[co]),_:1},8,["loading"])])]),q("div",po,[y(ze),w.value.length>0?(M(),j("div",fo,[z?(M(),we(Ae,{key:0,value:T.value,"onUpdate:value":g[0]||(g[0]=$=>T.value=$),min:0,max:1e5,placeholder:"\u8BF7\u8F93\u5165\u9644\u4EF6\u4EF7\u683C\uFF0C0\u4E3A\u514D\u8D39\u9644\u4EF6"},{prefix:P(()=>[mo]),_:1},8,["value"])):oe("",!0)])):oe("",!0)])]),_:1},8,["headers","data"]),k.value?(M(),j("div",vo,[y(B,{value:A.value,"onUpdate:value":g[1]||(g[1]=$=>A.value=$),name:"radiogroup"},{default:P(()=>[y(m,null,{default:P(()=>[(M(),j(gt,null,bt(I,$=>y(o,{key:$.value,value:$.value,label:$.label},null,8,["value","label"])),64))]),_:1})]),_:1},8,["value"])])):oe("",!0),r.value?(M(),j("div",ho,[y(O,{value:D.value,"onUpdate:value":g[2]||(g[2]=$=>D.value=$),placeholder:"\u8BF7\u8F93\u5165\u4EE5http(s)://\u5F00\u5934\u7684\u94FE\u63A5",min:0,max:3},{"create-button-default":P(()=>[go]),_:1},8,["value"])])):oe("",!0)])):(M(),j("div",bo,[_o,q("div",yo,[y(L,{strong:"",secondary:"",round:"",type:"primary",onClick:g[3]||(g[3]=$=>re("signin"))},{default:P(()=>[wo]),_:1}),y(L,{strong:"",secondary:"",round:"",type:"info",onClick:g[4]||(g[4]=$=>re("signup"))},{default:P(()=>[Co]),_:1})])]))])}}});const ko={key:0,class:"pagination-wrap"},Ro={key:0,class:"skeleton-wrap"},So={key:1},Vo={key:0,class:"empty-wrap"},Fo=W({setup(e){const n=vt(),t=Jt(),c=Xt(),l=R(!1),v=R([]),r=R(+t.query.p||1),k=R(20),p=R(0),D=Z(()=>{let s="\u6CE1\u6CE1\u5E7F\u573A";return t.query&&t.query.q&&(t.query.t&&t.query.t==="tag"?s="#"+decodeURIComponent(t.query.q):s="\u641C\u7D22: "+decodeURIComponent(t.query.q)),s}),f=()=>{l.value=!0,Qt({query:t.query.q?decodeURIComponent(t.query.q):null,type:t.query.t,page:r.value,page_size:k.value}).then(s=>{l.value=!1,v.value=s.list,p.value=Math.ceil(s.pager.total_rows/k.value),window.scrollTo(0,0)}).catch(s=>{l.value=!1})},T=s=>{if(r.value!=1){c.push({name:"post",query:{id:s.id}});return}let S=[],_=v.value.length;_==k.value&&_--;for(var w=0;w<_;w++){let A=v.value[w];if(!A.is_top)break;S.push(A)}for(S.push(s);w<_;w++)S.push(v.value[w]);v.value=S},b=s=>{c.push({name:"home",query:Ze(Ye({},t.query),{p:s})})};return ht(()=>{f()}),mt(()=>({path:t.path,query:t.query,refresh:n.state.refresh}),(s,S)=>{if(s.refresh!==S.refresh){r.value=+t.query.p||1,setTimeout(()=>{f()},0);return}S.path!=="/post"&&s.path==="/"&&(r.value=+t.query.p||1,setTimeout(()=>{f()},0))}),(s,S)=>{const _=rn,w=sn,A=xo,u=un,I=Ft,U=dn,N=Vt,z=ln;return M(),j("div",null,[y(_,{title:ne(D)},null,8,["title"]),y(z,{class:"main-content-wrap",bordered:""},{footer:P(()=>[p.value>1?(M(),j("div",ko,[y(w,{page:r.value,"onUpdate:page":b,"page-slot":ne(n).state.collapsedRight?5:8,"page-count":p.value},null,8,["page","page-slot","page-count"])])):oe("",!0)]),default:P(()=>[y(u,null,{default:P(()=>[y(A,{onPostSuccess:T})]),_:1}),l.value?(M(),j("div",Ro,[y(I,{num:k.value},null,8,["num"])])):(M(),j("div",So,[v.value.length===0?(M(),j("div",Vo,[y(U,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):oe("",!0),(M(!0),j(gt,null,bt(v.value,a=>(M(),we(u,{key:a.id},{default:P(()=>[y(N,{post:a},null,8,["post"])]),_:2},1024))),128))]))]),_:1})])}}});var Lo=Wt(Fo,[["__scopeId","data-v-7e0dfc66"]]);export{Lo as default}; diff --git a/web/dist/assets/IEnum.bfd96c78.js b/web/dist/assets/IEnum.bfd96c78.js deleted file mode 100644 index 6b750cee..00000000 --- a/web/dist/assets/IEnum.bfd96c78.js +++ /dev/null @@ -1,30 +0,0 @@ -import{D as gp,c as dp,b8 as pp,E as _p,n as vp,l as Io,aO as wp,d as Lo,u as xp,q as Eo,f as Ap,r as He,s as zi,aQ as Sp,t as mp,g as Rp,y as Ip,aT as Ki,aS as Tp,h as Le,aU as yp,aV as Cp,aW as Lp,aX as Ep,_ as Op,w as bp,aF as To,k as yo,V as Mp,W as Bp,Y as pr}from"./index.f480f018.js";import{N as Wp}from"./Skeleton.57e98fe3.js";const Fp=w=>{const{boxShadow2:nn}=w;return{menuBoxShadow:nn}},Up=gp({name:"Mention",common:dp,peers:{InternalSelectMenu:pp,Input:_p},self:Fp});var Pp=Up;function Dp(w,nn={debug:!1,useSelectionEnd:!1,checkWidthOverflow:!0}){const l=w.selectionStart!==null?w.selectionStart:0,te=w.selectionEnd!==null?w.selectionEnd:0,An=nn.useSelectionEnd?te:l,Ge=["direction","boxSizing","width","height","overflowX","overflowY","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","borderStyle","paddingTop","paddingRight","paddingBottom","paddingLeft","fontStyle","fontVariant","fontWeight","fontStretch","fontSize","fontSizeAdjust","lineHeight","fontFamily","textAlign","textTransform","textIndent","textDecoration","letterSpacing","wordSpacing","tabSize","MozTabSize"],Z=navigator.userAgent.toLowerCase().includes("firefox");if(!(typeof window!="undefined"))throw new Error("textarea-caret-position#getCaretPosition should only be called in a browser");const Jn=nn==null?void 0:nn.debug;if(Jn){const fn=document.querySelector("#input-textarea-caret-position-mirror-div");fn!=null&&fn.parentNode&&fn.parentNode.removeChild(fn)}const gn=document.createElement("div");gn.id="input-textarea-caret-position-mirror-div",document.body.appendChild(gn);const V=gn.style,P=window.getComputedStyle?window.getComputedStyle(w):w.currentStyle,Sn=w.nodeName==="INPUT";V.whiteSpace=Sn?"nowrap":"pre-wrap",Sn||(V.wordWrap="break-word"),V.position="absolute",Jn||(V.visibility="hidden"),Ge.forEach(fn=>{if(Sn&&fn==="lineHeight")if(P.boxSizing==="border-box"){const Q=parseInt(P.height),sn=parseInt(P.paddingTop)+parseInt(P.paddingBottom)+parseInt(P.borderTopWidth)+parseInt(P.borderBottomWidth),de=sn+parseInt(P.lineHeight);Q>de?V.lineHeight=`${Q-sn}px`:Q===de?V.lineHeight=P.lineHeight:V.lineHeight="0"}else V.lineHeight=P.height;else V[fn]=P[fn]}),Z?w.scrollHeight>parseInt(P.height)&&(V.overflowY="scroll"):V.overflow="hidden",gn.textContent=w.value.substring(0,An),Sn&&gn.textContent&&(gn.textContent=gn.textContent.replace(/\s/g,"\xA0"));const X=document.createElement("span");X.textContent=w.value.substring(An)||".",X.style.position="relative",X.style.left=`${-w.scrollLeft}px`,X.style.top=`${-w.scrollTop}px`,gn.appendChild(X);const On={top:X.offsetTop+parseInt(P.borderTopWidth),left:X.offsetLeft+parseInt(P.borderLeftWidth),absolute:!1,height:parseInt(P.fontSize)*1.5};return Jn?X.style.backgroundColor="#aaa":document.body.removeChild(gn),On.left>=w.clientWidth&&nn.checkWidthOverflow&&(On.left=w.clientWidth),On}var Np=vp([Io("mention","width: 100%; z-index: auto; position: relative;"),Io("mention-menu",` - box-shadow: var(--n-menu-box-shadow); - `,[wp()])]);const Hp=Object.assign(Object.assign({},Eo.props),{to:Ki.propTo,autosize:[Boolean,Object],options:{type:Array,default:[]},type:{type:String,default:"text"},separator:{type:String,validator:w=>w.length!==1?(bp("mention","`separator`'s length must be 1."),!1):!0,default:" "},bordered:{type:Boolean,default:void 0},disabled:Boolean,value:String,defaultValue:{type:String,default:""},loading:Boolean,prefix:{type:[String,Array],default:"@"},placeholder:{type:String,default:""},placement:{type:String,default:"bottom-start"},size:String,renderLabel:Function,status:String,"onUpdate:value":[Array,Function],onUpdateValue:[Array,Function],onSearch:Function,onSelect:Function,onFocus:Function,onBlur:Function,internalDebug:Boolean});var Qp=Lo({name:"Mention",props:Hp,setup(w){const{namespaceRef:nn,mergedClsPrefixRef:l,mergedBorderedRef:te,inlineThemeDisabled:An}=xp(w),Ge=Eo("Mention","-mention",Np,Pp,w,l),Z=Ap(w),Xn=He(null),Jn=He(null),gn=He(null),V=He("");let P=null,Sn=null,X=null;const On=zi(()=>{const{value:S}=V;return w.options.filter(B=>S?typeof B.label=="string"?B.label.startsWith(S):B.value.startsWith(S):!0)}),fn=zi(()=>Sp(On.value,{getKey:S=>S.value})),Q=He(null),sn=He(!1),de=He(w.defaultValue),bn=mp(w,"value"),pe=Rp(bn,de),mn=zi(()=>{const{self:{menuBoxShadow:S}}=Ge.value;return{"--n-menu-box-shadow":S}}),Rn=An?Ip("mention",void 0,mn,w):void 0;function tn(S){w.disabled||(S||(P=null,Sn=null,X=null),sn.value=S)}function _e(S){const{onUpdateValue:B,"onUpdate:value":G}=w,{nTriggerFormChange:J,nTriggerFormInput:dn}=Z;G&&yo(G,S),B&&yo(B,S),dn(),J(),de.value=S}function Ee(){return w.type==="text"?Xn.value.inputElRef:Xn.value.textareaElRef}function It(){var S;const B=Ee();if(document.activeElement!==B){tn(!1);return}const{selectionEnd:G}=B;if(G===null){tn(!1);return}const J=B.value,{separator:dn}=w,{prefix:we}=w,Qn=typeof we=="string"?[we]:we;for(let pn=G-1;pn>=0;--pn){const Gn=J[pn];if(Gn===dn||Gn===` -`||Gn==="\r"){tn(!1);return}if(Qn.includes(Gn)){const kn=J.slice(pn+1,G);tn(!0),(S=w.onSearch)===null||S===void 0||S.call(w,kn,Gn),V.value=kn,P=Gn,Sn=pn+1,X=G;return}}tn(!1)}function _r(){const{value:S}=Jn;if(!S)return;const B=Ee(),G=Dp(B);G.left+=B.parentElement.offsetLeft,S.style.left=`${G.left}px`,S.style.top=`${G.top+G.height}px`}function vr(){var S;!sn.value||(S=gn.value)===null||S===void 0||S.syncPosition()}function wr(S){_e(S),ve()}function ve(){setTimeout(()=>{_r(),It(),To().then(vr)},0)}function xr(S){var B,G;if(S.code==="ArrowLeft"||S.code==="ArrowRight"){if(!((B=Xn.value)===null||B===void 0)&&B.isCompositing)return;ve()}else if(S.code==="ArrowUp"||S.code==="ArrowDown"||S.code==="Enter"||S.code==="NumpadEnter"){if(!((G=Xn.value)===null||G===void 0)&&G.isCompositing)return;const{value:J}=Q;if(sn.value){if(J)if(S.preventDefault(),S.code==="ArrowUp")J.prev();else if(S.code==="ArrowDown")J.next();else{const dn=J.getPendingTmNode();dn?Oe(dn):tn(!1)}}else ve()}}function Ar(S){const{onFocus:B}=w;B==null||B(S);const{nTriggerFormFocus:G}=Z;G(),ve()}function re(){var S;(S=Xn.value)===null||S===void 0||S.focus()}function Vn(){var S;(S=Xn.value)===null||S===void 0||S.blur()}function Sr(S){const{onBlur:B}=w;B==null||B(S);const{nTriggerFormBlur:G}=Z;G(),tn(!1)}function Oe(S){var B;if(P===null||Sn===null||X===null)return;const{rawNode:{value:G}}=S,J=Ee(),dn=J.value,{separator:we}=w,Qn=dn.slice(X),pn=Qn.startsWith(we),Gn=`${G}${pn?"":we}`;_e(dn.slice(0,Sn)+Gn+Qn),(B=w.onSelect)===null||B===void 0||B.call(w,S.rawNode,P);const kn=Sn+Gn.length+(pn?1:0);To().then(()=>{J.selectionStart=kn,J.selectionEnd=kn,It()})}function Mn(){w.disabled||ve()}return{namespace:nn,mergedClsPrefix:l,mergedBordered:te,mergedSize:Z.mergedSizeRef,mergedStatus:Z.mergedStatusRef,mergedTheme:Ge,treeMate:fn,selectMenuInstRef:Q,inputInstRef:Xn,cursorRef:Jn,followerRef:gn,showMenu:sn,adjustedTo:Ki(w),isMounted:Tp(),mergedValue:pe,handleInputFocus:Ar,handleInputBlur:Sr,handleInputUpdateValue:wr,handleInputKeyDown:xr,handleSelect:Oe,handleInputMouseDown:Mn,focus:re,blur:Vn,cssVars:An?void 0:mn,themeClass:Rn==null?void 0:Rn.themeClass,onRender:Rn==null?void 0:Rn.onRender}},render(){const{mergedTheme:w,mergedClsPrefix:nn,$slots:l}=this;return Le("div",{class:`${nn}-mention`},Le(Op,{status:this.mergedStatus,themeOverrides:w.peerOverrides.Input,theme:w.peers.Input,size:this.mergedSize,autosize:this.autosize,type:this.type,ref:"inputInstRef",placeholder:this.placeholder,onMousedown:this.handleInputMouseDown,onUpdateValue:this.handleInputUpdateValue,onKeydown:this.handleInputKeyDown,onFocus:this.handleInputFocus,onBlur:this.handleInputBlur,bordered:this.mergedBordered,disabled:this.disabled,value:this.mergedValue}),Le(yp,null,{default:()=>[Le(Cp,null,{default:()=>Le("div",{style:{position:"absolute",width:0,height:0},ref:"cursorRef"})}),Le(Lp,{ref:"followerRef",placement:this.placement,show:this.showMenu,containerClass:this.namespace,to:this.adjustedTo,teleportDisabled:this.adjustedTo===Ki.tdkey},{default:()=>Le(Ep,{name:"fade-in-scale-up-transition",appear:this.isMounted},{default:()=>{const{mergedTheme:te,onRender:An}=this;return An==null||An(),this.showMenu?Le(Wp,{clsPrefix:nn,theme:te.peers.InternalSelectMenu,themeOverrides:te.peerOverrides.InternalSelectMenu,autoPending:!0,ref:"selectMenuInstRef",class:[`${nn}-mention-menu`,this.themeClass],loading:this.loading,treeMate:this.treeMate,virtualScroll:!1,style:this.cssVars,onToggle:this.handleSelect,renderLabel:this.renderLabel},l):null}})})]}))}}),Rt=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{};const Gp={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},$p=pr("rect",{x:"48",y:"80",width:"416",height:"352",rx:"48",ry:"48",fill:"none",stroke:"currentColor","stroke-linejoin":"round","stroke-width":"32"},null,-1),zp=pr("circle",{cx:"336",cy:"176",r:"32",fill:"none",stroke:"currentColor","stroke-miterlimit":"10","stroke-width":"32"},null,-1),Kp=pr("path",{d:"M304 335.79l-90.66-90.49a32 32 0 0 0-43.87-1.3L48 352",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),qp=pr("path",{d:"M224 432l123.34-123.34a32 32 0 0 1 43.11-2L464 368",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),Yp=[$p,zp,Kp,qp];var kp=Lo({name:"ImageOutline",render:function(nn,l){return Mp(),Bp("svg",Gp,Yp)}}),Co={exports:{}};/** - * @license - * Lodash - * Copyright OpenJS Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */(function(w,nn){(function(){var l,te="4.17.21",An=200,Ge="Unsupported core-js use. Try https://npms.io/search?q=ponyfill.",Z="Expected a function",Xn="Invalid `variable` option passed into `_.template`",Jn="__lodash_hash_undefined__",gn=500,V="__lodash_placeholder__",P=1,Sn=2,X=4,On=1,fn=2,Q=1,sn=2,de=4,bn=8,pe=16,mn=32,Rn=64,tn=128,_e=256,Ee=512,It=30,_r="...",vr=800,wr=16,ve=1,xr=2,Ar=3,re=1/0,Vn=9007199254740991,Sr=17976931348623157e292,Oe=0/0,Mn=4294967295,S=Mn-1,B=Mn>>>1,G=[["ary",tn],["bind",Q],["bindKey",sn],["curry",bn],["curryRight",pe],["flip",Ee],["partial",mn],["partialRight",Rn],["rearg",_e]],J="[object Arguments]",dn="[object Array]",we="[object AsyncFunction]",Qn="[object Boolean]",pn="[object Date]",Gn="[object DOMException]",kn="[object Error]",Tt="[object Function]",qi="[object GeneratorFunction]",$n="[object Map]",rt="[object Number]",Oo="[object Null]",ie="[object Object]",Yi="[object Promise]",bo="[object Proxy]",it="[object RegExp]",zn="[object Set]",ut="[object String]",yt="[object Symbol]",Mo="[object Undefined]",ft="[object WeakMap]",Bo="[object WeakSet]",ot="[object ArrayBuffer]",$e="[object DataView]",mr="[object Float32Array]",Rr="[object Float64Array]",Ir="[object Int8Array]",Tr="[object Int16Array]",yr="[object Int32Array]",Cr="[object Uint8Array]",Lr="[object Uint8ClampedArray]",Er="[object Uint16Array]",Or="[object Uint32Array]",Wo=/\b__p \+= '';/g,Fo=/\b(__p \+=) '' \+/g,Uo=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Zi=/&(?:amp|lt|gt|quot|#39);/g,Xi=/[&<>"']/g,Po=RegExp(Zi.source),Do=RegExp(Xi.source),No=/<%-([\s\S]+?)%>/g,Ho=/<%([\s\S]+?)%>/g,Ji=/<%=([\s\S]+?)%>/g,Go=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,$o=/^\w*$/,zo=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,br=/[\\^$.*+?()[\]{}|]/g,Ko=RegExp(br.source),Mr=/^\s+/,qo=/\s/,Yo=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Zo=/\{\n\/\* \[wrapped with (.+)\] \*/,Xo=/,? & /,Jo=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Vo=/[()=,{}\[\]\/\s]/,Qo=/\\(\\)?/g,ko=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Vi=/\w*$/,jo=/^[-+]0x[0-9a-f]+$/i,nl=/^0b[01]+$/i,el=/^\[object .+?Constructor\]$/,tl=/^0o[0-7]+$/i,rl=/^(?:0|[1-9]\d*)$/,il=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Ct=/($^)/,ul=/['\n\r\u2028\u2029\\]/g,Lt="\\ud800-\\udfff",fl="\\u0300-\\u036f",ol="\\ufe20-\\ufe2f",ll="\\u20d0-\\u20ff",Qi=fl+ol+ll,ki="\\u2700-\\u27bf",ji="a-z\\xdf-\\xf6\\xf8-\\xff",sl="\\xac\\xb1\\xd7\\xf7",al="\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf",cl="\\u2000-\\u206f",hl=" \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",nu="A-Z\\xc0-\\xd6\\xd8-\\xde",eu="\\ufe0e\\ufe0f",tu=sl+al+cl+hl,Br="['\u2019]",gl="["+Lt+"]",ru="["+tu+"]",Et="["+Qi+"]",iu="\\d+",dl="["+ki+"]",uu="["+ji+"]",fu="[^"+Lt+tu+iu+ki+ji+nu+"]",Wr="\\ud83c[\\udffb-\\udfff]",pl="(?:"+Et+"|"+Wr+")",ou="[^"+Lt+"]",Fr="(?:\\ud83c[\\udde6-\\uddff]){2}",Ur="[\\ud800-\\udbff][\\udc00-\\udfff]",ze="["+nu+"]",lu="\\u200d",su="(?:"+uu+"|"+fu+")",_l="(?:"+ze+"|"+fu+")",au="(?:"+Br+"(?:d|ll|m|re|s|t|ve))?",cu="(?:"+Br+"(?:D|LL|M|RE|S|T|VE))?",hu=pl+"?",gu="["+eu+"]?",vl="(?:"+lu+"(?:"+[ou,Fr,Ur].join("|")+")"+gu+hu+")*",wl="\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",xl="\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])",du=gu+hu+vl,Al="(?:"+[dl,Fr,Ur].join("|")+")"+du,Sl="(?:"+[ou+Et+"?",Et,Fr,Ur,gl].join("|")+")",ml=RegExp(Br,"g"),Rl=RegExp(Et,"g"),Pr=RegExp(Wr+"(?="+Wr+")|"+Sl+du,"g"),Il=RegExp([ze+"?"+uu+"+"+au+"(?="+[ru,ze,"$"].join("|")+")",_l+"+"+cu+"(?="+[ru,ze+su,"$"].join("|")+")",ze+"?"+su+"+"+au,ze+"+"+cu,xl,wl,iu,Al].join("|"),"g"),Tl=RegExp("["+lu+Lt+Qi+eu+"]"),yl=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Cl=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Ll=-1,H={};H[mr]=H[Rr]=H[Ir]=H[Tr]=H[yr]=H[Cr]=H[Lr]=H[Er]=H[Or]=!0,H[J]=H[dn]=H[ot]=H[Qn]=H[$e]=H[pn]=H[kn]=H[Tt]=H[$n]=H[rt]=H[ie]=H[it]=H[zn]=H[ut]=H[ft]=!1;var N={};N[J]=N[dn]=N[ot]=N[$e]=N[Qn]=N[pn]=N[mr]=N[Rr]=N[Ir]=N[Tr]=N[yr]=N[$n]=N[rt]=N[ie]=N[it]=N[zn]=N[ut]=N[yt]=N[Cr]=N[Lr]=N[Er]=N[Or]=!0,N[kn]=N[Tt]=N[ft]=!1;var El={\u00C0:"A",\u00C1:"A",\u00C2:"A",\u00C3:"A",\u00C4:"A",\u00C5:"A",\u00E0:"a",\u00E1:"a",\u00E2:"a",\u00E3:"a",\u00E4:"a",\u00E5:"a",\u00C7:"C",\u00E7:"c",\u00D0:"D",\u00F0:"d",\u00C8:"E",\u00C9:"E",\u00CA:"E",\u00CB:"E",\u00E8:"e",\u00E9:"e",\u00EA:"e",\u00EB:"e",\u00CC:"I",\u00CD:"I",\u00CE:"I",\u00CF:"I",\u00EC:"i",\u00ED:"i",\u00EE:"i",\u00EF:"i",\u00D1:"N",\u00F1:"n",\u00D2:"O",\u00D3:"O",\u00D4:"O",\u00D5:"O",\u00D6:"O",\u00D8:"O",\u00F2:"o",\u00F3:"o",\u00F4:"o",\u00F5:"o",\u00F6:"o",\u00F8:"o",\u00D9:"U",\u00DA:"U",\u00DB:"U",\u00DC:"U",\u00F9:"u",\u00FA:"u",\u00FB:"u",\u00FC:"u",\u00DD:"Y",\u00FD:"y",\u00FF:"y",\u00C6:"Ae",\u00E6:"ae",\u00DE:"Th",\u00FE:"th",\u00DF:"ss",\u0100:"A",\u0102:"A",\u0104:"A",\u0101:"a",\u0103:"a",\u0105:"a",\u0106:"C",\u0108:"C",\u010A:"C",\u010C:"C",\u0107:"c",\u0109:"c",\u010B:"c",\u010D:"c",\u010E:"D",\u0110:"D",\u010F:"d",\u0111:"d",\u0112:"E",\u0114:"E",\u0116:"E",\u0118:"E",\u011A:"E",\u0113:"e",\u0115:"e",\u0117:"e",\u0119:"e",\u011B:"e",\u011C:"G",\u011E:"G",\u0120:"G",\u0122:"G",\u011D:"g",\u011F:"g",\u0121:"g",\u0123:"g",\u0124:"H",\u0126:"H",\u0125:"h",\u0127:"h",\u0128:"I",\u012A:"I",\u012C:"I",\u012E:"I",\u0130:"I",\u0129:"i",\u012B:"i",\u012D:"i",\u012F:"i",\u0131:"i",\u0134:"J",\u0135:"j",\u0136:"K",\u0137:"k",\u0138:"k",\u0139:"L",\u013B:"L",\u013D:"L",\u013F:"L",\u0141:"L",\u013A:"l",\u013C:"l",\u013E:"l",\u0140:"l",\u0142:"l",\u0143:"N",\u0145:"N",\u0147:"N",\u014A:"N",\u0144:"n",\u0146:"n",\u0148:"n",\u014B:"n",\u014C:"O",\u014E:"O",\u0150:"O",\u014D:"o",\u014F:"o",\u0151:"o",\u0154:"R",\u0156:"R",\u0158:"R",\u0155:"r",\u0157:"r",\u0159:"r",\u015A:"S",\u015C:"S",\u015E:"S",\u0160:"S",\u015B:"s",\u015D:"s",\u015F:"s",\u0161:"s",\u0162:"T",\u0164:"T",\u0166:"T",\u0163:"t",\u0165:"t",\u0167:"t",\u0168:"U",\u016A:"U",\u016C:"U",\u016E:"U",\u0170:"U",\u0172:"U",\u0169:"u",\u016B:"u",\u016D:"u",\u016F:"u",\u0171:"u",\u0173:"u",\u0174:"W",\u0175:"w",\u0176:"Y",\u0177:"y",\u0178:"Y",\u0179:"Z",\u017B:"Z",\u017D:"Z",\u017A:"z",\u017C:"z",\u017E:"z",\u0132:"IJ",\u0133:"ij",\u0152:"Oe",\u0153:"oe",\u0149:"'n",\u017F:"s"},Ol={"&":"&","<":"<",">":">",'"':""","'":"'"},bl={"&":"&","<":"<",">":">",""":'"',"'":"'"},Ml={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Bl=parseFloat,Wl=parseInt,pu=typeof Rt=="object"&&Rt&&Rt.Object===Object&&Rt,Fl=typeof self=="object"&&self&&self.Object===Object&&self,rn=pu||Fl||Function("return this")(),Dr=nn&&!nn.nodeType&&nn,be=Dr&&!0&&w&&!w.nodeType&&w,_u=be&&be.exports===Dr,Nr=_u&&pu.process,Bn=function(){try{var a=be&&be.require&&be.require("util").types;return a||Nr&&Nr.binding&&Nr.binding("util")}catch{}}(),vu=Bn&&Bn.isArrayBuffer,wu=Bn&&Bn.isDate,xu=Bn&&Bn.isMap,Au=Bn&&Bn.isRegExp,Su=Bn&&Bn.isSet,mu=Bn&&Bn.isTypedArray;function In(a,g,h){switch(h.length){case 0:return a.call(g);case 1:return a.call(g,h[0]);case 2:return a.call(g,h[0],h[1]);case 3:return a.call(g,h[0],h[1],h[2])}return a.apply(g,h)}function Ul(a,g,h,x){for(var T=-1,W=a==null?0:a.length;++T-1}function Hr(a,g,h){for(var x=-1,T=a==null?0:a.length;++x-1;);return h}function Ou(a,g){for(var h=a.length;h--&&Ke(g,a[h],0)>-1;);return h}function ql(a,g){for(var h=a.length,x=0;h--;)a[h]===g&&++x;return x}var Yl=Kr(El),Zl=Kr(Ol);function Xl(a){return"\\"+Ml[a]}function Jl(a,g){return a==null?l:a[g]}function qe(a){return Tl.test(a)}function Vl(a){return yl.test(a)}function Ql(a){for(var g,h=[];!(g=a.next()).done;)h.push(g.value);return h}function Xr(a){var g=-1,h=Array(a.size);return a.forEach(function(x,T){h[++g]=[T,x]}),h}function bu(a,g){return function(h){return a(g(h))}}function Se(a,g){for(var h=-1,x=a.length,T=0,W=[];++h-1}function Ds(n,e){var t=this.__data__,r=Zt(t,n);return r<0?(++this.size,t.push([n,e])):t[r][1]=e,this}ue.prototype.clear=Ws,ue.prototype.delete=Fs,ue.prototype.get=Us,ue.prototype.has=Ps,ue.prototype.set=Ds;function fe(n){var e=-1,t=n==null?0:n.length;for(this.clear();++e=e?n:e)),n}function Pn(n,e,t,r,i,f){var o,s=e&P,c=e&Sn,d=e&X;if(t&&(o=i?t(n,r,i,f):t(n)),o!==l)return o;if(!z(n))return n;var p=y(n);if(p){if(o=$a(n),!s)return _n(n,o)}else{var _=ln(n),v=_==Tt||_==qi;if(Ce(n))return df(n,s);if(_==ie||_==J||v&&!i){if(o=c||v?{}:Bf(n),!s)return c?ba(n,na(o,n)):Oa(n,zu(o,n))}else{if(!N[_])return i?n:{};o=za(n,_,s)}}f||(f=new qn);var A=f.get(n);if(A)return A;f.set(n,o),lo(n)?n.forEach(function(I){o.add(Pn(I,e,t,I,n,f))}):fo(n)&&n.forEach(function(I,O){o.set(O,Pn(I,e,t,O,n,f))});var R=d?c?Ai:xi:c?wn:en,L=p?l:R(n);return Wn(L||n,function(I,O){L&&(O=I,I=n[O]),dt(o,O,Pn(I,e,t,O,n,f))}),o}function ea(n){var e=en(n);return function(t){return Ku(t,n,e)}}function Ku(n,e,t){var r=t.length;if(n==null)return!r;for(n=D(n);r--;){var i=t[r],f=e[i],o=n[i];if(o===l&&!(i in n)||!f(o))return!1}return!0}function qu(n,e,t){if(typeof n!="function")throw new Fn(Z);return St(function(){n.apply(l,t)},e)}function pt(n,e,t,r){var i=-1,f=Ot,o=!0,s=n.length,c=[],d=e.length;if(!s)return c;t&&(e=$(e,Tn(t))),r?(f=Hr,o=!1):e.length>=An&&(f=lt,o=!1,e=new We(e));n:for(;++ii?0:i+t),r=r===l||r>i?i:C(r),r<0&&(r+=i),r=t>r?0:ao(r);t0&&t(s)?e>1?un(s,e-1,t,r,i):Ae(i,s):r||(i[i.length]=s)}return i}var ei=Af(),Xu=Af(!0);function jn(n,e){return n&&ei(n,e,en)}function ti(n,e){return n&&Xu(n,e,en)}function Jt(n,e){return xe(e,function(t){return ce(n[t])})}function Ue(n,e){e=Te(e,n);for(var t=0,r=e.length;n!=null&&te}function ia(n,e){return n!=null&&U.call(n,e)}function ua(n,e){return n!=null&&e in D(n)}function fa(n,e,t){return n>=on(e,t)&&n=120&&p.length>=120)?new We(o&&p):l}p=n[0];var _=-1,v=s[0];n:for(;++_-1;)s!==n&&Ht.call(s,c,1),Ht.call(n,c,1);return n}function ff(n,e){for(var t=n?e.length:0,r=t-1;t--;){var i=e[t];if(t==r||i!==f){var f=i;ae(i)?Ht.call(n,i,1):hi(n,i)}}return n}function si(n,e){return n+zt(Nu()*(e-n+1))}function xa(n,e,t,r){for(var i=-1,f=j($t((e-n)/(t||1)),0),o=h(f);f--;)o[r?f:++i]=n,n+=t;return o}function ai(n,e){var t="";if(!n||e<1||e>Vn)return t;do e%2&&(t+=n),e=zt(e/2),e&&(n+=n);while(e);return t}function E(n,e){return Ci(Uf(n,e,xn),n+"")}function Aa(n){return $u(tt(n))}function Sa(n,e){var t=tt(n);return fr(t,Fe(e,0,t.length))}function wt(n,e,t,r){if(!z(n))return n;e=Te(e,n);for(var i=-1,f=e.length,o=f-1,s=n;s!=null&&++ii?0:i+e),t=t>i?i:t,t<0&&(t+=i),i=e>t?0:t-e>>>0,e>>>=0;for(var f=h(i);++r>>1,o=n[f];o!==null&&!Cn(o)&&(t?o<=e:o=An){var d=e?null:Fa(n);if(d)return Mt(d);o=!1,i=lt,c=new We}else c=e?[]:s;n:for(;++r=r?n:Dn(n,e,t)}var gf=hs||function(n){return rn.clearTimeout(n)};function df(n,e){if(e)return n.slice();var t=n.length,r=Wu?Wu(t):new n.constructor(t);return n.copy(r),r}function _i(n){var e=new n.constructor(n.byteLength);return new Dt(e).set(new Dt(n)),e}function ya(n,e){var t=e?_i(n.buffer):n.buffer;return new n.constructor(t,n.byteOffset,n.byteLength)}function Ca(n){var e=new n.constructor(n.source,Vi.exec(n));return e.lastIndex=n.lastIndex,e}function La(n){return gt?D(gt.call(n)):{}}function pf(n,e){var t=e?_i(n.buffer):n.buffer;return new n.constructor(t,n.byteOffset,n.length)}function _f(n,e){if(n!==e){var t=n!==l,r=n===null,i=n===n,f=Cn(n),o=e!==l,s=e===null,c=e===e,d=Cn(e);if(!s&&!d&&!f&&n>e||f&&o&&c&&!s&&!d||r&&o&&c||!t&&c||!i)return 1;if(!r&&!f&&!d&&n=s)return c;var d=t[r];return c*(d=="desc"?-1:1)}}return n.index-e.index}function vf(n,e,t,r){for(var i=-1,f=n.length,o=t.length,s=-1,c=e.length,d=j(f-o,0),p=h(c+d),_=!r;++s1?t[i-1]:l,o=i>2?t[2]:l;for(f=n.length>3&&typeof f=="function"?(i--,f):l,o&&cn(t[0],t[1],o)&&(f=i<3?l:f,i=1),e=D(e);++r-1?i[f?e[o]:o]:l}}function Rf(n){return se(function(e){var t=e.length,r=t,i=Un.prototype.thru;for(n&&e.reverse();r--;){var f=e[r];if(typeof f!="function")throw new Fn(Z);if(i&&!o&&ir(f)=="wrapper")var o=new Un([],!0)}for(r=o?r:t;++r1&&M.reverse(),p&&cs))return!1;var d=f.get(n),p=f.get(e);if(d&&p)return d==e&&p==n;var _=-1,v=!0,A=t&fn?new We:l;for(f.set(n,e),f.set(e,n);++_1?"& ":"")+e[r],e=e.join(t>2?", ":" "),n.replace(Yo,`{ -/* [wrapped with `+e+`] */ -`)}function qa(n){return y(n)||Ne(n)||!!(Pu&&n&&n[Pu])}function ae(n,e){var t=typeof n;return e=e==null?Vn:e,!!e&&(t=="number"||t!="symbol"&&rl.test(n))&&n>-1&&n%1==0&&n0){if(++e>=vr)return arguments[0]}else e=0;return n.apply(l,arguments)}}function fr(n,e){var t=-1,r=n.length,i=r-1;for(e=e===l?r:e;++t1?n[e-1]:l;return t=typeof t=="function"?(n.pop(),t):l,Xf(n,t)});function Jf(n){var e=u(n);return e.__chain__=!0,e}function th(n,e){return e(n),n}function or(n,e){return e(n)}var rh=se(function(n){var e=n.length,t=e?n[0]:0,r=this.__wrapped__,i=function(f){return ni(f,n)};return e>1||this.__actions__.length||!(r instanceof b)||!ae(t)?this.thru(i):(r=r.slice(t,+t+(e?1:0)),r.__actions__.push({func:or,args:[i],thisArg:l}),new Un(r,this.__chain__).thru(function(f){return e&&!f.length&&f.push(l),f}))});function ih(){return Jf(this)}function uh(){return new Un(this.value(),this.__chain__)}function fh(){this.__values__===l&&(this.__values__=so(this.value()));var n=this.__index__>=this.__values__.length,e=n?l:this.__values__[this.__index__++];return{done:n,value:e}}function oh(){return this}function lh(n){for(var e,t=this;t instanceof Yt;){var r=$f(t);r.__index__=0,r.__values__=l,e?i.__wrapped__=r:e=r;var i=r;t=t.__wrapped__}return i.__wrapped__=n,e}function sh(){var n=this.__wrapped__;if(n instanceof b){var e=n;return this.__actions__.length&&(e=new b(this)),e=e.reverse(),e.__actions__.push({func:or,args:[Li],thisArg:l}),new Un(e,this.__chain__)}return this.thru(Li)}function ah(){return cf(this.__wrapped__,this.__actions__)}var ch=jt(function(n,e,t){U.call(n,t)?++n[t]:oe(n,t,1)});function hh(n,e,t){var r=y(n)?Ru:ta;return t&&cn(n,e,t)&&(e=l),r(n,m(e,3))}function gh(n,e){var t=y(n)?xe:Zu;return t(n,m(e,3))}var dh=mf(zf),ph=mf(Kf);function _h(n,e){return un(lr(n,e),1)}function vh(n,e){return un(lr(n,e),re)}function wh(n,e,t){return t=t===l?1:C(t),un(lr(n,e),t)}function Vf(n,e){var t=y(n)?Wn:Re;return t(n,m(e,3))}function Qf(n,e){var t=y(n)?Pl:Yu;return t(n,m(e,3))}var xh=jt(function(n,e,t){U.call(n,t)?n[t].push(e):oe(n,t,[e])});function Ah(n,e,t,r){n=vn(n)?n:tt(n),t=t&&!r?C(t):0;var i=n.length;return t<0&&(t=j(i+t,0)),gr(n)?t<=i&&n.indexOf(e,t)>-1:!!i&&Ke(n,e,t)>-1}var Sh=E(function(n,e,t){var r=-1,i=typeof e=="function",f=vn(n)?h(n.length):[];return Re(n,function(o){f[++r]=i?In(e,o,t):_t(o,e,t)}),f}),mh=jt(function(n,e,t){oe(n,t,e)});function lr(n,e){var t=y(n)?$:ju;return t(n,m(e,3))}function Rh(n,e,t,r){return n==null?[]:(y(e)||(e=e==null?[]:[e]),t=r?l:t,y(t)||(t=t==null?[]:[t]),rf(n,e,t))}var Ih=jt(function(n,e,t){n[t?0:1].push(e)},function(){return[[],[]]});function Th(n,e,t){var r=y(n)?Gr:Cu,i=arguments.length<3;return r(n,m(e,4),t,i,Re)}function yh(n,e,t){var r=y(n)?Dl:Cu,i=arguments.length<3;return r(n,m(e,4),t,i,Yu)}function Ch(n,e){var t=y(n)?xe:Zu;return t(n,cr(m(e,3)))}function Lh(n){var e=y(n)?$u:Aa;return e(n)}function Eh(n,e,t){(t?cn(n,e,t):e===l)?e=1:e=C(e);var r=y(n)?Qs:Sa;return r(n,e)}function Oh(n){var e=y(n)?ks:Ra;return e(n)}function bh(n){if(n==null)return 0;if(vn(n))return gr(n)?Ye(n):n.length;var e=ln(n);return e==$n||e==zn?n.size:fi(n).length}function Mh(n,e,t){var r=y(n)?$r:Ia;return t&&cn(n,e,t)&&(e=l),r(n,m(e,3))}var Bh=E(function(n,e){if(n==null)return[];var t=e.length;return t>1&&cn(n,e[0],e[1])?e=[]:t>2&&cn(e[0],e[1],e[2])&&(e=[e[0]]),rf(n,un(e,1),[])}),sr=gs||function(){return rn.Date.now()};function Wh(n,e){if(typeof e!="function")throw new Fn(Z);return n=C(n),function(){if(--n<1)return e.apply(this,arguments)}}function kf(n,e,t){return e=t?l:e,e=n&&e==null?n.length:e,le(n,tn,l,l,l,l,e)}function jf(n,e){var t;if(typeof e!="function")throw new Fn(Z);return n=C(n),function(){return--n>0&&(t=e.apply(this,arguments)),n<=1&&(e=l),t}}var Oi=E(function(n,e,t){var r=Q;if(t.length){var i=Se(t,nt(Oi));r|=mn}return le(n,r,e,t,i)}),no=E(function(n,e,t){var r=Q|sn;if(t.length){var i=Se(t,nt(no));r|=mn}return le(e,r,n,t,i)});function eo(n,e,t){e=t?l:e;var r=le(n,bn,l,l,l,l,l,e);return r.placeholder=eo.placeholder,r}function to(n,e,t){e=t?l:e;var r=le(n,pe,l,l,l,l,l,e);return r.placeholder=to.placeholder,r}function ro(n,e,t){var r,i,f,o,s,c,d=0,p=!1,_=!1,v=!0;if(typeof n!="function")throw new Fn(Z);e=Hn(e)||0,z(t)&&(p=!!t.leading,_="maxWait"in t,f=_?j(Hn(t.maxWait)||0,e):f,v="trailing"in t?!!t.trailing:v);function A(Y){var Zn=r,ge=i;return r=i=l,d=Y,o=n.apply(ge,Zn),o}function R(Y){return d=Y,s=St(O,e),p?A(Y):o}function L(Y){var Zn=Y-c,ge=Y-d,Ro=e-Zn;return _?on(Ro,f-ge):Ro}function I(Y){var Zn=Y-c,ge=Y-d;return c===l||Zn>=e||Zn<0||_&&ge>=f}function O(){var Y=sr();if(I(Y))return M(Y);s=St(O,L(Y))}function M(Y){return s=l,v&&r?A(Y):(r=i=l,o)}function Ln(){s!==l&&gf(s),d=0,r=c=i=s=l}function hn(){return s===l?o:M(sr())}function En(){var Y=sr(),Zn=I(Y);if(r=arguments,i=this,c=Y,Zn){if(s===l)return R(c);if(_)return gf(s),s=St(O,e),A(c)}return s===l&&(s=St(O,e)),o}return En.cancel=Ln,En.flush=hn,En}var Fh=E(function(n,e){return qu(n,1,e)}),Uh=E(function(n,e,t){return qu(n,Hn(e)||0,t)});function Ph(n){return le(n,Ee)}function ar(n,e){if(typeof n!="function"||e!=null&&typeof e!="function")throw new Fn(Z);var t=function(){var r=arguments,i=e?e.apply(this,r):r[0],f=t.cache;if(f.has(i))return f.get(i);var o=n.apply(this,r);return t.cache=f.set(i,o)||f,o};return t.cache=new(ar.Cache||fe),t}ar.Cache=fe;function cr(n){if(typeof n!="function")throw new Fn(Z);return function(){var e=arguments;switch(e.length){case 0:return!n.call(this);case 1:return!n.call(this,e[0]);case 2:return!n.call(this,e[0],e[1]);case 3:return!n.call(this,e[0],e[1],e[2])}return!n.apply(this,e)}}function Dh(n){return jf(2,n)}var Nh=Ta(function(n,e){e=e.length==1&&y(e[0])?$(e[0],Tn(m())):$(un(e,1),Tn(m()));var t=e.length;return E(function(r){for(var i=-1,f=on(r.length,t);++i=e}),Ne=Vu(function(){return arguments}())?Vu:function(n){return K(n)&&U.call(n,"callee")&&!Uu.call(n,"callee")},y=h.isArray,ng=vu?Tn(vu):la;function vn(n){return n!=null&&hr(n.length)&&!ce(n)}function q(n){return K(n)&&vn(n)}function eg(n){return n===!0||n===!1||K(n)&&an(n)==Qn}var Ce=ps||$i,tg=wu?Tn(wu):sa;function rg(n){return K(n)&&n.nodeType===1&&!mt(n)}function ig(n){if(n==null)return!0;if(vn(n)&&(y(n)||typeof n=="string"||typeof n.splice=="function"||Ce(n)||et(n)||Ne(n)))return!n.length;var e=ln(n);if(e==$n||e==zn)return!n.size;if(At(n))return!fi(n).length;for(var t in n)if(U.call(n,t))return!1;return!0}function ug(n,e){return vt(n,e)}function fg(n,e,t){t=typeof t=="function"?t:l;var r=t?t(n,e):l;return r===l?vt(n,e,l,t):!!r}function Mi(n){if(!K(n))return!1;var e=an(n);return e==kn||e==Gn||typeof n.message=="string"&&typeof n.name=="string"&&!mt(n)}function og(n){return typeof n=="number"&&Du(n)}function ce(n){if(!z(n))return!1;var e=an(n);return e==Tt||e==qi||e==we||e==bo}function uo(n){return typeof n=="number"&&n==C(n)}function hr(n){return typeof n=="number"&&n>-1&&n%1==0&&n<=Vn}function z(n){var e=typeof n;return n!=null&&(e=="object"||e=="function")}function K(n){return n!=null&&typeof n=="object"}var fo=xu?Tn(xu):ca;function lg(n,e){return n===e||ui(n,e,mi(e))}function sg(n,e,t){return t=typeof t=="function"?t:l,ui(n,e,mi(e),t)}function ag(n){return oo(n)&&n!=+n}function cg(n){if(Xa(n))throw new T(Ge);return Qu(n)}function hg(n){return n===null}function gg(n){return n==null}function oo(n){return typeof n=="number"||K(n)&&an(n)==rt}function mt(n){if(!K(n)||an(n)!=ie)return!1;var e=Nt(n);if(e===null)return!0;var t=U.call(e,"constructor")&&e.constructor;return typeof t=="function"&&t instanceof t&&Ft.call(t)==ss}var Bi=Au?Tn(Au):ha;function dg(n){return uo(n)&&n>=-Vn&&n<=Vn}var lo=Su?Tn(Su):ga;function gr(n){return typeof n=="string"||!y(n)&&K(n)&&an(n)==ut}function Cn(n){return typeof n=="symbol"||K(n)&&an(n)==yt}var et=mu?Tn(mu):da;function pg(n){return n===l}function _g(n){return K(n)&&ln(n)==ft}function vg(n){return K(n)&&an(n)==Bo}var wg=rr(oi),xg=rr(function(n,e){return n<=e});function so(n){if(!n)return[];if(vn(n))return gr(n)?Kn(n):_n(n);if(st&&n[st])return Ql(n[st]());var e=ln(n),t=e==$n?Xr:e==zn?Mt:tt;return t(n)}function he(n){if(!n)return n===0?n:0;if(n=Hn(n),n===re||n===-re){var e=n<0?-1:1;return e*Sr}return n===n?n:0}function C(n){var e=he(n),t=e%1;return e===e?t?e-t:e:0}function ao(n){return n?Fe(C(n),0,Mn):0}function Hn(n){if(typeof n=="number")return n;if(Cn(n))return Oe;if(z(n)){var e=typeof n.valueOf=="function"?n.valueOf():n;n=z(e)?e+"":e}if(typeof n!="string")return n===0?n:+n;n=Lu(n);var t=nl.test(n);return t||tl.test(n)?Wl(n.slice(2),t?2:8):jo.test(n)?Oe:+n}function co(n){return ne(n,wn(n))}function Ag(n){return n?Fe(C(n),-Vn,Vn):n===0?n:0}function F(n){return n==null?"":yn(n)}var Sg=ke(function(n,e){if(At(e)||vn(e)){ne(e,en(e),n);return}for(var t in e)U.call(e,t)&&dt(n,t,e[t])}),ho=ke(function(n,e){ne(e,wn(e),n)}),dr=ke(function(n,e,t,r){ne(e,wn(e),n,r)}),mg=ke(function(n,e,t,r){ne(e,en(e),n,r)}),Rg=se(ni);function Ig(n,e){var t=Qe(n);return e==null?t:zu(t,e)}var Tg=E(function(n,e){n=D(n);var t=-1,r=e.length,i=r>2?e[2]:l;for(i&&cn(e[0],e[1],i)&&(r=1);++t1),f}),ne(n,Ai(n),t),r&&(t=Pn(t,P|Sn|X,Ua));for(var i=e.length;i--;)hi(t,e[i]);return t});function zg(n,e){return po(n,cr(m(e)))}var Kg=se(function(n,e){return n==null?{}:va(n,e)});function po(n,e){if(n==null)return{};var t=$(Ai(n),function(r){return[r]});return e=m(e),uf(n,t,function(r,i){return e(r,i[0])})}function qg(n,e,t){e=Te(e,n);var r=-1,i=e.length;for(i||(i=1,n=l);++re){var r=n;n=e,e=r}if(t||n%1||e%1){var i=Nu();return on(n+i*(e-n+Bl("1e-"+((i+"").length-1))),e)}return si(n,e)}var td=je(function(n,e,t){return e=e.toLowerCase(),n+(t?wo(e):e)});function wo(n){return Ui(F(n).toLowerCase())}function xo(n){return n=F(n),n&&n.replace(il,Yl).replace(Rl,"")}function rd(n,e,t){n=F(n),e=yn(e);var r=n.length;t=t===l?r:Fe(C(t),0,r);var i=t;return t-=e.length,t>=0&&n.slice(t,i)==e}function id(n){return n=F(n),n&&Do.test(n)?n.replace(Xi,Zl):n}function ud(n){return n=F(n),n&&Ko.test(n)?n.replace(br,"\\$&"):n}var fd=je(function(n,e,t){return n+(t?"-":"")+e.toLowerCase()}),od=je(function(n,e,t){return n+(t?" ":"")+e.toLowerCase()}),ld=Sf("toLowerCase");function sd(n,e,t){n=F(n),e=C(e);var r=e?Ye(n):0;if(!e||r>=e)return n;var i=(e-r)/2;return tr(zt(i),t)+n+tr($t(i),t)}function ad(n,e,t){n=F(n),e=C(e);var r=e?Ye(n):0;return e&&r>>0,t?(n=F(n),n&&(typeof e=="string"||e!=null&&!Bi(e))&&(e=yn(e),!e&&qe(n))?ye(Kn(n),0,t):n.split(e,t)):[]}var vd=je(function(n,e,t){return n+(t?" ":"")+Ui(e)});function wd(n,e,t){return n=F(n),t=t==null?0:Fe(C(t),0,n.length),e=yn(e),n.slice(t,t+e.length)==e}function xd(n,e,t){var r=u.templateSettings;t&&cn(n,e,t)&&(e=l),n=F(n),e=dr({},e,r,Lf);var i=dr({},e.imports,r.imports,Lf),f=en(i),o=Zr(i,f),s,c,d=0,p=e.interpolate||Ct,_="__p += '",v=Jr((e.escape||Ct).source+"|"+p.source+"|"+(p===Ji?ko:Ct).source+"|"+(e.evaluate||Ct).source+"|$","g"),A="//# sourceURL="+(U.call(e,"sourceURL")?(e.sourceURL+"").replace(/\s/g," "):"lodash.templateSources["+ ++Ll+"]")+` -`;n.replace(v,function(I,O,M,Ln,hn,En){return M||(M=Ln),_+=n.slice(d,En).replace(ul,Xl),O&&(s=!0,_+=`' + -__e(`+O+`) + -'`),hn&&(c=!0,_+=`'; -`+hn+`; -__p += '`),M&&(_+=`' + -((__t = (`+M+`)) == null ? '' : __t) + -'`),d=En+I.length,I}),_+=`'; -`;var R=U.call(e,"variable")&&e.variable;if(!R)_=`with (obj) { -`+_+` -} -`;else if(Vo.test(R))throw new T(Xn);_=(c?_.replace(Wo,""):_).replace(Fo,"$1").replace(Uo,"$1;"),_="function("+(R||"obj")+`) { -`+(R?"":`obj || (obj = {}); -`)+"var __t, __p = ''"+(s?", __e = _.escape":"")+(c?`, __j = Array.prototype.join; -function print() { __p += __j.call(arguments, '') } -`:`; -`)+_+`return __p -}`;var L=So(function(){return W(f,A+"return "+_).apply(l,o)});if(L.source=_,Mi(L))throw L;return L}function Ad(n){return F(n).toLowerCase()}function Sd(n){return F(n).toUpperCase()}function md(n,e,t){if(n=F(n),n&&(t||e===l))return Lu(n);if(!n||!(e=yn(e)))return n;var r=Kn(n),i=Kn(e),f=Eu(r,i),o=Ou(r,i)+1;return ye(r,f,o).join("")}function Rd(n,e,t){if(n=F(n),n&&(t||e===l))return n.slice(0,Mu(n)+1);if(!n||!(e=yn(e)))return n;var r=Kn(n),i=Ou(r,Kn(e))+1;return ye(r,0,i).join("")}function Id(n,e,t){if(n=F(n),n&&(t||e===l))return n.replace(Mr,"");if(!n||!(e=yn(e)))return n;var r=Kn(n),i=Eu(r,Kn(e));return ye(r,i).join("")}function Td(n,e){var t=It,r=_r;if(z(e)){var i="separator"in e?e.separator:i;t="length"in e?C(e.length):t,r="omission"in e?yn(e.omission):r}n=F(n);var f=n.length;if(qe(n)){var o=Kn(n);f=o.length}if(t>=f)return n;var s=t-Ye(r);if(s<1)return r;var c=o?ye(o,0,s).join(""):n.slice(0,s);if(i===l)return c+r;if(o&&(s+=c.length-s),Bi(i)){if(n.slice(s).search(i)){var d,p=c;for(i.global||(i=Jr(i.source,F(Vi.exec(i))+"g")),i.lastIndex=0;d=i.exec(p);)var _=d.index;c=c.slice(0,_===l?s:_)}}else if(n.indexOf(yn(i),s)!=s){var v=c.lastIndexOf(i);v>-1&&(c=c.slice(0,v))}return c+r}function yd(n){return n=F(n),n&&Po.test(n)?n.replace(Zi,es):n}var Cd=je(function(n,e,t){return n+(t?" ":"")+e.toUpperCase()}),Ui=Sf("toUpperCase");function Ao(n,e,t){return n=F(n),e=t?l:e,e===l?Vl(n)?is(n):Gl(n):n.match(e)||[]}var So=E(function(n,e){try{return In(n,l,e)}catch(t){return Mi(t)?t:new T(t)}}),Ld=se(function(n,e){return Wn(e,function(t){t=ee(t),oe(n,t,Oi(n[t],n))}),n});function Ed(n){var e=n==null?0:n.length,t=m();return n=e?$(n,function(r){if(typeof r[1]!="function")throw new Fn(Z);return[t(r[0]),r[1]]}):[],E(function(r){for(var i=-1;++iVn)return[];var t=Mn,r=on(n,Mn);e=m(e),n-=Mn;for(var i=Yr(r,e);++t0||e<0)?new b(t):(n<0?t=t.takeRight(-n):n&&(t=t.drop(n)),e!==l&&(e=C(e),t=e<0?t.dropRight(-e):t.take(e-n)),t)},b.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},b.prototype.toArray=function(){return this.take(Mn)},jn(b.prototype,function(n,e){var t=/^(?:filter|find|map|reject)|While$/.test(e),r=/^(?:head|last)$/.test(e),i=u[r?"take"+(e=="last"?"Right":""):e],f=r||/^find/.test(e);!i||(u.prototype[e]=function(){var o=this.__wrapped__,s=r?[1]:arguments,c=o instanceof b,d=s[0],p=c||y(o),_=function(O){var M=i.apply(u,Ae([O],s));return r&&v?M[0]:M};p&&t&&typeof d=="function"&&d.length!=1&&(c=p=!1);var v=this.__chain__,A=!!this.__actions__.length,R=f&&!v,L=c&&!A;if(!f&&p){o=L?o:new b(this);var I=n.apply(o,s);return I.__actions__.push({func:or,args:[_],thisArg:l}),new Un(I,v)}return R&&L?n.apply(this,s):(I=this.thru(_),R?r?I.value()[0]:I.value():I)})}),Wn(["pop","push","shift","sort","splice","unshift"],function(n){var e=Bt[n],t=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",r=/^(?:pop|shift)$/.test(n);u.prototype[n]=function(){var i=arguments;if(r&&!this.__chain__){var f=this.value();return e.apply(y(f)?f:[],i)}return this[t](function(o){return e.apply(y(o)?o:[],i)})}}),jn(b.prototype,function(n,e){var t=u[e];if(t){var r=t.name+"";U.call(Ve,r)||(Ve[r]=[]),Ve[r].push({name:e,func:t})}}),Ve[nr(l,sn).name]=[{name:"wrapper",func:l}],b.prototype.clone=ys,b.prototype.reverse=Cs,b.prototype.value=Ls,u.prototype.at=rh,u.prototype.chain=ih,u.prototype.commit=uh,u.prototype.next=fh,u.prototype.plant=lh,u.prototype.reverse=sh,u.prototype.toJSON=u.prototype.valueOf=u.prototype.value=ah,u.prototype.first=u.prototype.head,st&&(u.prototype[st]=oh),u},Ze=us();be?((be.exports=Ze)._=Ze,Dr._=Ze):rn._=Ze}).call(Rt)})(Co,Co.exports);var Zp=(w=>(w[w.TITLE=1]="TITLE",w[w.TEXT=2]="TEXT",w[w.IMAGEURL=3]="IMAGEURL",w[w.VIDEOURL=4]="VIDEOURL",w[w.AUDIOURL=5]="AUDIOURL",w[w.LINKURL=6]="LINKURL",w[w.ATTACHMENT=7]="ATTACHMENT",w[w.CHARGEATTACHMENT=8]="CHARGEATTACHMENT",w))(Zp||{}),Xp=(w=>(w[w.PUBLIC=0]="PUBLIC",w[w.PRIVATE=1]="PRIVATE",w[w.FRIEND=2]="FRIEND",w))(Xp||{});export{kp as I,Zp as P,Xp as V,Qp as _,Co as l}; diff --git a/web/dist/assets/InputGroup.f69c4956.js b/web/dist/assets/InputGroup.f69c4956.js deleted file mode 100644 index 6289b2bf..00000000 --- a/web/dist/assets/InputGroup.f69c4956.js +++ /dev/null @@ -1,56 +0,0 @@ -import{l as t,n as r,m as o,d as a,u as d,b$ as s,h as n}from"./index.f480f018.js";var p=t("input-group",` - display: inline-flex; - width: 100%; - flex-wrap: nowrap; - vertical-align: bottom; -`,[r(">",[t("input",[r("&:not(:last-child)",` - border-top-right-radius: 0!important; - border-bottom-right-radius: 0!important; - `),r("&:not(:first-child)",` - border-top-left-radius: 0!important; - border-bottom-left-radius: 0!important; - margin-left: -1px!important; - `)]),t("button",[r("&:not(:last-child)",` - border-top-right-radius: 0!important; - border-bottom-right-radius: 0!important; - `,[o("state-border, border",` - border-top-right-radius: 0!important; - border-bottom-right-radius: 0!important; - `)]),r("&:not(:first-child)",` - border-top-left-radius: 0!important; - border-bottom-left-radius: 0!important; - `,[o("state-border, border",` - border-top-left-radius: 0!important; - border-bottom-left-radius: 0!important; - `)])]),r("*",[r("&:not(:last-child)",` - border-top-right-radius: 0!important; - border-bottom-right-radius: 0!important; - `,[r(">",[t("input",` - border-top-right-radius: 0!important; - border-bottom-right-radius: 0!important; - `),t("base-selection",[t("base-selection-label",` - border-top-right-radius: 0!important; - border-bottom-right-radius: 0!important; - `),t("base-selection-tags",` - border-top-right-radius: 0!important; - border-bottom-right-radius: 0!important; - `),o("box-shadow, border, state-border",` - border-top-right-radius: 0!important; - border-bottom-right-radius: 0!important; - `)])])]),r("&:not(:first-child)",` - margin-left: -1px!important; - border-top-left-radius: 0!important; - border-bottom-left-radius: 0!important; - `,[r(">",[t("input",` - border-top-left-radius: 0!important; - border-bottom-left-radius: 0!important; - `),t("base-selection",[t("base-selection-label",` - border-top-left-radius: 0!important; - border-bottom-left-radius: 0!important; - `),t("base-selection-tags",` - border-top-left-radius: 0!important; - border-bottom-left-radius: 0!important; - `),o("box-shadow, border, state-border",` - border-top-left-radius: 0!important; - border-bottom-left-radius: 0!important; - `)])])])])])]);const b={};var u=a({name:"InputGroup",props:b,setup(i){const{mergedClsPrefixRef:e}=d(i);return s("-input-group",p,e),{mergedClsPrefix:e}},render(){const{mergedClsPrefix:i}=this;return n("div",{class:`${i}-input-group`},this.$slots)}});export{u as _}; diff --git a/web/dist/assets/List.49bcdf81.js b/web/dist/assets/List.49bcdf81.js deleted file mode 100644 index d17b8a09..00000000 --- a/web/dist/assets/List.49bcdf81.js +++ /dev/null @@ -1,53 +0,0 @@ -import{n as d,l as n,o as z,m as i,aA as y,aB as _,d as P,u as R,q as c,A as $,s as j,y as B,h as a,e as M,aC as I}from"./index.f480f018.js";var L=d([n("list",` - --n-merged-border-color: var(--n-border-color); - --n-merged-color: var(--n-color) - font-size: var(--n-font-size); - transition: - background-color .3s var(--n-bezier), - color .3s var(--n-bezier), - border-color .3s var(--n-bezier); - padding: 0; - list-style-type: none; - color: var(--n-text-color); - background-color: var(--n-merged-color); - `,[z("bordered",` - border-radius: var(--n-border-radius); - border: 1px solid var(--n-merged-border-color); - `,[n("list-item",` - padding: 12px 20px; - `,[d("&:not(:last-child)",` - border-bottom: 1px solid var(--n-merged-border-color); - `)]),i("header, footer",` - padding: 12px 20px; - `,[d("&:not(:last-child)",` - border-bottom: 1px solid var(--n-merged-border-color); - `)])]),i("header, footer",` - padding: 12px 0; - box-sizing: border-box; - transition: border-color .3s var(--n-bezier); - `,[d("&:not(:last-child)",` - border-bottom: 1px solid var(--n-merged-border-color); - `)]),n("list-item",` - padding: 12px 0; - box-sizing: border-box; - display: flex; - flex-wrap: nowrap; - align-items: center; - transition: border-color .3s var(--n-bezier); - `,[i("prefix",` - margin-right: 20px; - flex: 0; - `),i("suffix",` - margin-left: 20px; - flex: 0; - `),i("main",` - flex: 1; - `),d("&:not(:last-child)",` - border-bottom: 1px solid var(--n-merged-border-color); - `)])]),y(n("list",` - --merged-color: var(--n-color-modal); - --merged-border-color: var(--n-border-color-modal); - `)),_(n("list",` - --merged-color: var(--n-color-popover); - --merged-border-color: var(--n-border-color-popover); - `))]);const O=Object.assign(Object.assign({},c.props),{size:{type:String,default:"medium"},bordered:{type:Boolean,default:!1}}),T=M("n-list");var k=P({name:"List",props:O,setup(r){const{mergedClsPrefixRef:o,inlineThemeDisabled:e}=R(r),s=c("List","-list",L,I,r,o);$(T,{mergedClsPrefixRef:o});const t=j(()=>{const{common:{cubicBezierEaseInOut:b},self:{fontSize:m,textColor:p,color:v,colorModal:f,colorPopover:u,borderColor:g,borderColorModal:x,borderColorPopover:h,borderRadius:C}}=s.value;return{"--n-font-size":m,"--n-bezier":b,"--n-text-color":p,"--n-color":v,"--n-border-radius":C,"--n-border-color":g,"--n-border-color-modal":x,"--n-border-color-popover":h,"--n-color-modal":f,"--n-color-popover":u}}),l=e?B("list",void 0,t,r):void 0;return{mergedClsPrefix:o,cssVars:e?void 0:t,themeClass:l==null?void 0:l.themeClass,onRender:l==null?void 0:l.onRender}},render(){var r;const{$slots:o,mergedClsPrefix:e,onRender:s}=this;return s==null||s(),a("ul",{class:[`${e}-list`,this.bordered&&`${e}-list--bordered`,this.themeClass],style:this.cssVars},o.header?a("div",{class:`${e}-list__header`},o.header()):null,(r=o.default)===null||r===void 0?void 0:r.call(o),o.footer?a("div",{class:`${e}-list__footer`},o.footer()):null)}});export{k as _,T as l}; diff --git a/web/dist/assets/Messages.c822d4d1.js b/web/dist/assets/Messages.c822d4d1.js deleted file mode 100644 index e372032b..00000000 --- a/web/dist/assets/Messages.c822d4d1.js +++ /dev/null @@ -1 +0,0 @@ -import{d as v,V as n,W as s,Y as i,ah as M,aj as z,al as I,a3 as a,a4 as r,a7 as $,a8 as p,a9 as w,a5 as b,a6 as l,a2 as k,c3 as N,ch as R,ci as q,cj as P,ad as T,ck as H,ae as U,ab as O,aa as A,ai as W,Z as Y,r as x,a1 as Z,cl as G}from"./index.f480f018.js";import{f as J}from"./formatTime.02109bf5.js";import{_ as K}from"./Alert.a854329b.js";import{_ as Q}from"./Thing.eef6b133.js";import{b as X,a as ee,_ as ne}from"./Skeleton.57e98fe3.js";import{_ as te}from"./main-nav.9110259b.js";import{_ as se}from"./List.49bcdf81.js";import{_ as oe}from"./Pagination.1263479e.js";const ae={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},re=i("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M464 128L240 384l-96-96"},null,-1),ie=i("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M144 384l-96-96"},null,-1),le=i("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M368 128L232 284"},null,-1),ue=[re,ie,le];var ce=v({name:"CheckmarkDoneOutline",render:function(c,_){return n(),s("svg",ae,ue)}});const _e={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},de=i("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M416 128L192 384l-96-96"},null,-1),me=[de];var pe=v({name:"CheckmarkOutline",render:function(c,_){return n(),s("svg",_e,me)}});const he={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},ge=i("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M368 368L144 144"},null,-1),ke=i("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M368 144L144 368"},null,-1),ve=[ge,ke];var E=v({name:"CloseOutline",render:function(c,_){return n(),s("svg",he,ve)}});const we={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},fe=i("path",{d:"M336 192h40a40 40 0 0 1 40 40v192a40 40 0 0 1-40 40H136a40 40 0 0 1-40-40V232a40 40 0 0 1 40-40h40",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),ye=i("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M336 128l-80-80l-80 80"},null,-1),xe=i("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M256 321V48"},null,-1),$e=[fe,ye,xe];var Ce=v({name:"ShareOutline",render:function(c,_){return n(),s("svg",we,$e)}});const De={class:"sender-wrap"},Fe={key:0,class:"nickname"},Me={class:"username"},Be={key:1,class:"nickname"},je={class:"timestamp"},Ee={class:"timestamp-txt"},be={key:0,class:"brief-content"},Oe=p(" \u67E5\u770B\u8BE6\u60C5 "),Ae={key:1,class:"whisper-content-wrap"},Ve={key:2,class:"requesting-friend-wrap"},Le=p(" \u540C\u610F "),Se=p(" \u62D2\u7EDD "),ze={key:2,class:"status-info"},Ie=p(" \u5DF2\u540C\u610F "),Ne={key:3,class:"status-info"},Re=p(" \u5DF2\u62D2\u7EDD "),qe=v({props:{message:null},setup(e){const c="https://assets.paopao.info/public/avatar/default/admin.png",_=z(),u=t=>{d(t),(t.type===1||t.type===2||t.type===3)&&(t.post&&t.post.id>0?_.push({name:"post",query:{id:t.post_id}}):window.$message.error("\u8BE5\u52A8\u6001\u5DF2\u88AB\u5220\u9664"))},h=t=>{d(t),R({user_id:t.sender_user_id}).then(o=>{t.reply_id=2,window.$message.success("\u5DF2\u540C\u610F\u6DFB\u52A0\u597D\u53CB")}).catch(o=>{console.log(o)})},f=t=>{d(t),q({user_id:t.sender_user_id}).then(o=>{t.reply_id=3,window.$message.success("\u5DF2\u62D2\u7EDD\u6DFB\u52A0\u597D\u53CB")}).catch(o=>{console.log(o)})},d=t=>{t.is_read===0&&P({id:t.id}).then(o=>{t.is_read=1}).catch(o=>{console.log(o)})};return(t,o)=>{const C=T,m=I("router-link"),B=H,g=U,D=K,F=Q;return n(),s("div",{class:N(["message-item",{unread:e.message.is_read===0}]),onClick:o[4]||(o[4]=y=>d(e.message))},[a(F,{"content-indented":""},{avatar:r(()=>[a(C,{round:"",size:30,src:e.message.sender_user.id>0?e.message.sender_user.avatar:c},null,8,["src"])]),header:r(()=>[i("div",De,[e.message.sender_user.id>0?(n(),s("span",Fe,[a(m,{onClick:o[0]||(o[0]=$(()=>{},["stop"])),class:"username-link",to:{name:"user",query:{username:e.message.sender_user.username}}},{default:r(()=>[p(w(e.message.sender_user.nickname),1)]),_:1},8,["to"]),i("span",Me," @"+w(e.message.sender_user.username),1)])):(n(),s("span",Be," \u7CFB\u7EDF "))])]),"header-extra":r(()=>[i("span",je,[e.message.is_read===0?(n(),b(B,{key:0,dot:"",processing:""})):l("",!0),i("span",Ee,w(k(J)(e.message.created_on)),1)])]),description:r(()=>[a(D,{"show-icon":!1,class:"brief-wrap",type:e.message.is_read>0?"default":"success"},{default:r(()=>[e.message.type!=4?(n(),s("div",be,[p(w(e.message.brief)+" ",1),e.message.type===1||e.message.type===2||e.message.type===3?(n(),s("span",{key:0,onClick:o[1]||(o[1]=$(y=>u(e.message),["stop"])),class:"hash-link view-link"},[a(g,null,{default:r(()=>[a(k(Ce))]),_:1}),Oe])):l("",!0)])):l("",!0),e.message.type===4?(n(),s("div",Ae,w(e.message.content),1)):l("",!0),e.message.type===5?(n(),s("div",Ve,[p(w(e.message.content)+" ",1),e.message.reply_id===1?(n(),s("span",{key:0,onClick:o[2]||(o[2]=$(y=>h(e.message),["stop"])),class:"hash-link view-link"},[a(g,null,{default:r(()=>[a(k(pe))]),_:1}),Le])):l("",!0),e.message.reply_id===1?(n(),s("span",{key:1,onClick:o[3]||(o[3]=$(y=>f(e.message),["stop"])),class:"hash-link view-link"},[a(g,null,{default:r(()=>[a(k(E))]),_:1}),Se])):l("",!0),e.message.reply_id===2?(n(),s("span",ze,[a(g,null,{default:r(()=>[a(k(ce))]),_:1}),Ie])):l("",!0),e.message.reply_id===3?(n(),s("span",Ne,[a(g,null,{default:r(()=>[a(k(E))]),_:1}),Re])):l("",!0)])):l("",!0)]),_:1},8,["type"])]),_:1})],2)}}});var Pe=M(qe,[["__scopeId","data-v-44920a13"]]);const Te={class:"content"},He=v({props:{num:{default:1}},setup(e){return(c,_)=>{const u=X;return n(!0),s(A,null,O(new Array(e.num),h=>(n(),s("div",{class:"skeleton-item",key:h},[i("div",Te,[a(u,{text:"",repeat:2}),a(u,{text:"",style:{width:"60%"}})])]))),128)}}});var Ue=M(He,[["__scopeId","data-v-d0b0628c"]]);const We={key:0,class:"skeleton-wrap"},Ye={key:1},Ze={key:0,class:"empty-wrap"},Ge={key:0,class:"pagination-wrap"},Je=v({setup(e){const c=W(),_=Y(),u=x(!1),h=x(+c.query.p||1),f=x(10),d=x(0),t=x([]),o=()=>{u.value=!0,G({page:h.value,page_size:f.value}).then(m=>{u.value=!1,t.value=m.list,d.value=Math.ceil(m.pager.total_rows/f.value)}).catch(m=>{u.value=!1})},C=m=>{h.value=m,o()};return Z(()=>{o()}),(m,B)=>{const g=te,D=Ue,F=ee,y=Pe,V=ne,L=oe,S=se;return n(),s("div",null,[a(g,{title:"\u6D88\u606F"}),a(S,{class:"main-content-wrap messages-wrap",bordered:""},{footer:r(()=>[d.value>1?(n(),s("div",Ge,[a(L,{page:h.value,"onUpdate:page":C,"page-slot":k(_).state.collapsedRight?5:8,"page-count":d.value},null,8,["page","page-slot","page-count"])])):l("",!0)]),default:r(()=>[u.value?(n(),s("div",We,[a(D,{num:f.value},null,8,["num"])])):(n(),s("div",Ye,[t.value.length===0?(n(),s("div",Ze,[a(F,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):l("",!0),(n(!0),s(A,null,O(t.value,j=>(n(),b(V,{key:j.id},{default:r(()=>[a(y,{message:j},null,8,["message"])]),_:2},1024))),128))]))]),_:1})])}}});var an=M(Je,[["__scopeId","data-v-532e9e3c"]]);export{an as default}; diff --git a/web/dist/assets/MoreHorizFilled.80db5156.js b/web/dist/assets/MoreHorizFilled.80db5156.js deleted file mode 100644 index 319b349b..00000000 --- a/web/dist/assets/MoreHorizFilled.80db5156.js +++ /dev/null @@ -1 +0,0 @@ -import{d as e,V as o,W as s,Y as r}from"./index.f480f018.js";const t={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},n=r("path",{d:"M6 10c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2z",fill:"currentColor"},null,-1),l=[n];var m=e({name:"MoreHorizFilled",render:function(i,a){return o(),s("svg",t,l)}});export{m as M}; diff --git a/web/dist/assets/Pagination.1263479e.js b/web/dist/assets/Pagination.1263479e.js deleted file mode 100644 index 5af23bdf..00000000 --- a/web/dist/assets/Pagination.1263479e.js +++ /dev/null @@ -1,252 +0,0 @@ -import{d as se,h as n,r as m,aD as Bt,aE as _t,a1 as lt,aF as je,aG as $t,aH as At,n as re,l as x,m as D,p as Ze,o as Y,q as Me,t as ve,aI as Et,s as B,aJ as Ve,S as De,aK as st,v as Qe,y as qe,aL as Lt,an as He,aM as Ye,aa as Ge,aN as Dt,aO as jt,u as dt,aP as Vt,g as Ne,aQ as Nt,I as ut,aR as Wt,f as Ut,aS as Kt,aT as Je,aU as Ht,aV as Zt,aW as Jt,aX as qt,aY as Qt,aZ as Yt,a_ as Xe,a$ as Gt,k as U,b0 as Xt,x as en,K as tn,_ as nn,N as Oe}from"./index.f480f018.js";import{N as on}from"./Skeleton.57e98fe3.js";var et=se({name:"Backward",render(){return n("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},n("path",{d:"M12.2674 15.793C11.9675 16.0787 11.4927 16.0672 11.2071 15.7673L6.20572 10.5168C5.9298 10.2271 5.9298 9.7719 6.20572 9.48223L11.2071 4.23177C11.4927 3.93184 11.9675 3.92031 12.2674 4.206C12.5673 4.49169 12.5789 4.96642 12.2932 5.26634L7.78458 9.99952L12.2932 14.7327C12.5789 15.0326 12.5673 15.5074 12.2674 15.793Z",fill:"currentColor"}))}}),tt=se({name:"FastBackward",render(){return n("svg",{viewBox:"0 0 20 20",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},n("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},n("g",{fill:"currentColor","fill-rule":"nonzero"},n("path",{d:"M8.73171,16.7949 C9.03264,17.0795 9.50733,17.0663 9.79196,16.7654 C10.0766,16.4644 10.0634,15.9897 9.76243,15.7051 L4.52339,10.75 L17.2471,10.75 C17.6613,10.75 17.9971,10.4142 17.9971,10 C17.9971,9.58579 17.6613,9.25 17.2471,9.25 L4.52112,9.25 L9.76243,4.29275 C10.0634,4.00812 10.0766,3.53343 9.79196,3.2325 C9.50733,2.93156 9.03264,2.91834 8.73171,3.20297 L2.31449,9.27241 C2.14819,9.4297 2.04819,9.62981 2.01448,9.8386 C2.00308,9.89058 1.99707,9.94459 1.99707,10 C1.99707,10.0576 2.00356,10.1137 2.01585,10.1675 C2.05084,10.3733 2.15039,10.5702 2.31449,10.7254 L8.73171,16.7949 Z"}))))}}),nt=se({name:"FastForward",render(){return n("svg",{viewBox:"0 0 20 20",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},n("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},n("g",{fill:"currentColor","fill-rule":"nonzero"},n("path",{d:"M11.2654,3.20511 C10.9644,2.92049 10.4897,2.93371 10.2051,3.23464 C9.92049,3.53558 9.93371,4.01027 10.2346,4.29489 L15.4737,9.25 L2.75,9.25 C2.33579,9.25 2,9.58579 2,10.0000012 C2,10.4142 2.33579,10.75 2.75,10.75 L15.476,10.75 L10.2346,15.7073 C9.93371,15.9919 9.92049,16.4666 10.2051,16.7675 C10.4897,17.0684 10.9644,17.0817 11.2654,16.797 L17.6826,10.7276 C17.8489,10.5703 17.9489,10.3702 17.9826,10.1614 C17.994,10.1094 18,10.0554 18,10.0000012 C18,9.94241 17.9935,9.88633 17.9812,9.83246 C17.9462,9.62667 17.8467,9.42976 17.6826,9.27455 L11.2654,3.20511 Z"}))))}}),ot=se({name:"Forward",render(){return n("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},n("path",{d:"M7.73271 4.20694C8.03263 3.92125 8.50737 3.93279 8.79306 4.23271L13.7944 9.48318C14.0703 9.77285 14.0703 10.2281 13.7944 10.5178L8.79306 15.7682C8.50737 16.0681 8.03263 16.0797 7.73271 15.794C7.43279 15.5083 7.42125 15.0336 7.70694 14.7336L12.2155 10.0005L7.70694 5.26729C7.42125 4.96737 7.43279 4.49264 7.73271 4.20694Z",fill:"currentColor"}))}}),rt=se({name:"More",render(){return n("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},n("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},n("g",{fill:"currentColor","fill-rule":"nonzero"},n("path",{d:"M4,7 C4.55228,7 5,7.44772 5,8 C5,8.55229 4.55228,9 4,9 C3.44772,9 3,8.55229 3,8 C3,7.44772 3.44772,7 4,7 Z M8,7 C8.55229,7 9,7.44772 9,8 C9,8.55229 8.55229,9 8,9 C7.44772,9 7,8.55229 7,8 C7,7.44772 7.44772,7 8,7 Z M12,7 C12.5523,7 13,7.44772 13,8 C13,8.55229 12.5523,9 12,9 C11.4477,9 11,8.55229 11,8 C11,7.44772 11.4477,7 12,7 Z"}))))}});const pe="v-hidden",rn=At("[v-hidden]",{display:"none!important"});var at=se({name:"Overflow",props:{getCounter:Function,getTail:Function,updateCounter:Function,onUpdateOverflow:Function},setup(e,{slots:r}){const d=m(null),f=m(null);function u(){const{value:g}=d,{getCounter:s,getTail:R}=e;let p;if(s!==void 0?p=s():p=f.value,!g||!p)return;p.hasAttribute(pe)&&p.removeAttribute(pe);const{children:b}=g,M=g.offsetWidth,S=[],P=r.tail?R==null?void 0:R():null;let C=P?P.offsetWidth:0,y=!1;const $=g.children.length-(r.tail?1:0);for(let A=0;A<$-1;++A){if(A<0)continue;const j=b[A];if(y){j.hasAttribute(pe)||j.setAttribute(pe,"");continue}else j.hasAttribute(pe)&&j.removeAttribute(pe);const K=j.offsetWidth;if(C+=K,S[A]=K,C>M){const{updateCounter:E}=e;for(let k=A;k>=0;--k){const W=$-1-k;E!==void 0?E(W):p.textContent=`${W}`;const H=p.offsetWidth;if(C-=S[k],C+H<=M||k===0){y=!0,A=k-1,P&&(A===-1?(P.style.maxWidth=`${M-H}px`,P.style.boxSizing="border-box"):P.style.maxWidth="");break}}}}const{onUpdateOverflow:O}=e;y?O!==void 0&&O(!0):(O!==void 0&&O(!1),p.setAttribute(pe,""))}const w=Bt();return rn.mount({id:"vueuc/overflow",head:!0,anchorMetaName:_t,ssr:w}),lt(u),{selfRef:d,counterRef:f,sync:u}},render(){const{$slots:e}=this;return je(this.sync),n("div",{class:"v-overflow",ref:"selfRef"},[$t(e,"default"),e.counter?e.counter():n("span",{style:{display:"inline-block"},ref:"counterRef"}),e.tail?e.tail():null])}}),an=re([x("base-selection",` - position: relative; - z-index: auto; - box-shadow: none; - width: 100%; - max-width: 100%; - display: inline-block; - vertical-align: bottom; - border-radius: var(--n-border-radius); - min-height: var(--n-height); - line-height: 1.5; - font-size: var(--n-font-size); - `,[x("base-loading",` - color: var(--n-loading-color); - `),x("base-selection-tags","min-height: var(--n-height);"),D("border, state-border",` - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - pointer-events: none; - border: var(--n-border); - border-radius: inherit; - transition: - box-shadow .3s var(--n-bezier), - border-color .3s var(--n-bezier); - `),D("state-border",` - z-index: 1; - border-color: #0000; - `),x("base-suffix",` - cursor: pointer; - position: absolute; - top: 50%; - transform: translateY(-50%); - right: 10px; - `,[D("arrow",` - font-size: var(--n-arrow-size); - color: var(--n-arrow-color); - transition: color .3s var(--n-bezier); - `)]),x("base-selection-overlay",` - display: flex; - align-items: center; - white-space: nowrap; - pointer-events: none; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - padding: var(--n-padding-single); - transition: color .3s var(--n-bezier); - `,[D("wrapper",` - flex-basis: 0; - flex-grow: 1; - overflow: hidden; - text-overflow: ellipsis; - `)]),x("base-selection-placeholder",` - color: var(--n-placeholder-color); - `),x("base-selection-tags",` - cursor: pointer; - outline: none; - box-sizing: border-box; - position: relative; - z-index: auto; - display: flex; - padding: var(--n-padding-multiple); - flex-wrap: wrap; - align-items: center; - width: 100%; - vertical-align: bottom; - background-color: var(--n-color); - border-radius: inherit; - transition: - color .3s var(--n-bezier), - box-shadow .3s var(--n-bezier), - background-color .3s var(--n-bezier); - `),x("base-selection-label",` - height: var(--n-height); - display: inline-flex; - width: 100%; - vertical-align: bottom; - cursor: pointer; - outline: none; - z-index: auto; - box-sizing: border-box; - position: relative; - transition: - color .3s var(--n-bezier), - box-shadow .3s var(--n-bezier), - background-color .3s var(--n-bezier); - border-radius: inherit; - background-color: var(--n-color); - align-items: center; - `,[x("base-selection-input",` - line-height: inherit; - outline: none; - cursor: pointer; - box-sizing: border-box; - border:none; - width: 100%; - padding: var(--n-padding-single); - background-color: #0000; - color: var(--n-text-color); - transition: color .3s var(--n-bezier); - caret-color: var(--n-caret-color); - `,[D("content",` - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - `)]),D("render-label",` - color: var(--n-text-color); - `)]),Ze("disabled",[re("&:hover",[D("state-border",` - box-shadow: var(--n-box-shadow-hover); - border: var(--n-border-hover); - `)]),Y("focus",[D("state-border",` - box-shadow: var(--n-box-shadow-focus); - border: var(--n-border-focus); - `)]),Y("active",[D("state-border",` - box-shadow: var(--n-box-shadow-active); - border: var(--n-border-active); - `),x("base-selection-label","background-color: var(--n-color-active);"),x("base-selection-tags","background-color: var(--n-color-active);")])]),Y("disabled","cursor: not-allowed;",[D("arrow",` - color: var(--n-arrow-color-disabled); - `),x("base-selection-label",` - cursor: not-allowed; - background-color: var(--n-color-disabled); - `,[x("base-selection-input",` - cursor: not-allowed; - color: var(--n-text-color-disabled); - `),D("render-label",` - color: var(--n-text-color-disabled); - `)]),x("base-selection-tags",` - cursor: not-allowed; - background-color: var(--n-color-disabled); - `),x("base-selection-placeholder",` - cursor: not-allowed; - color: var(--n-placeholder-color-disabled); - `)]),x("base-selection-input-tag",` - height: calc(var(--n-height) - 6px); - line-height: calc(var(--n-height) - 6px); - outline: none; - display: none; - position: relative; - margin-bottom: 3px; - max-width: 100%; - vertical-align: bottom; - `,[D("input",` - min-width: 1px; - padding: 0; - background-color: #0000; - outline: none; - border: none; - max-width: 100%; - overflow: hidden; - width: 1em; - line-height: inherit; - cursor: pointer; - color: var(--n-text-color); - caret-color: var(--n-caret-color); - `),D("mirror",` - position: absolute; - left: 0; - top: 0; - white-space: pre; - visibility: hidden; - user-select: none; - opacity: 0; - `)]),["warning","error"].map(e=>Y(`${e}-status`,[D("state-border",`border: var(--n-border-${e});`),Ze("disabled",[re("&:hover",[D("state-border",` - box-shadow: var(--n-box-shadow-hover-${e}); - border: var(--n-border-hover-${e}); - `)]),Y("active",[D("state-border",` - box-shadow: var(--n-box-shadow-active-${e}); - border: var(--n-border-active-${e}); - `),x("base-selection-label",`background-color: var(--n-color-active-${e});`),x("base-selection-tags",`background-color: var(--n-color-active-${e});`)]),Y("focus",[D("state-border",` - box-shadow: var(--n-box-shadow-focus-${e}); - border: var(--n-border-focus-${e}); - `)])])]))]),x("base-selection-popover",` - margin-bottom: -3px; - display: flex; - flex-wrap: wrap; - `),x("base-selection-tag-wrapper",` - max-width: 100%; - display: inline-flex; - padding: 0 7px 3px 0; - `,[re("&:last-child","padding-right: 0;"),x("tag",` - font-size: 14px; - max-width: 100%; - `,[D("content",` - line-height: 1.25; - text-overflow: ellipsis; - overflow: hidden; - `)])])]),ln=se({name:"InternalSelection",props:Object.assign(Object.assign({},Me.props),{clsPrefix:{type:String,required:!0},bordered:{type:Boolean,default:void 0},active:Boolean,pattern:{type:String,default:""},placeholder:String,selectedOption:{type:Object,default:null},selectedOptions:{type:Array,default:null},multiple:Boolean,filterable:Boolean,clearable:Boolean,disabled:Boolean,size:{type:String,default:"medium"},loading:Boolean,autofocus:Boolean,showArrow:{type:Boolean,default:!0},inputProps:Object,focused:Boolean,renderTag:Function,onKeyup:Function,onKeydown:Function,onClick:Function,onBlur:Function,onFocus:Function,onDeleteOption:Function,maxTagCount:[String,Number],onClear:Function,onPatternInput:Function,onPatternFocus:Function,onPatternBlur:Function,renderLabel:Function,status:String,inlineThemeDisabled:Boolean}),setup(e){const r=m(null),d=m(null),f=m(null),u=m(null),w=m(null),g=m(null),s=m(null),R=m(null),p=m(null),b=m(null),M=m(!1),S=m(!1),P=m(!1),C=Me("InternalSelection","-internal-selection",an,Et,e,ve(e,"clsPrefix")),y=B(()=>e.clearable&&!e.disabled&&(P.value||e.active)),$=B(()=>e.selectedOption?e.renderTag?e.renderTag({option:e.selectedOption,handleClose:()=>{}}):e.renderLabel?e.renderLabel(e.selectedOption,!0):Ve(e.selectedOption.label,e.selectedOption,!0):e.placeholder),O=B(()=>{const o=e.selectedOption;if(!!o)return o.label}),A=B(()=>e.multiple?!!(Array.isArray(e.selectedOptions)&&e.selectedOptions.length):e.selectedOption!==null);function j(){var o;const{value:l}=r;if(l){const{value:_}=d;_&&(_.style.width=`${l.offsetWidth}px`,e.maxTagCount!=="responsive"&&((o=p.value)===null||o===void 0||o.sync()))}}function K(){const{value:o}=b;o&&(o.style.display="none")}function E(){const{value:o}=b;o&&(o.style.display="inline-block")}De(ve(e,"active"),o=>{o||K()}),De(ve(e,"pattern"),()=>{e.multiple&&je(j)});function k(o){const{onFocus:l}=e;l&&l(o)}function W(o){const{onBlur:l}=e;l&&l(o)}function H(o){const{onDeleteOption:l}=e;l&&l(o)}function V(o){const{onClear:l}=e;l&&l(o)}function I(o){const{onPatternInput:l}=e;l&&l(o)}function ae(o){var l;(!o.relatedTarget||!(!((l=f.value)===null||l===void 0)&&l.contains(o.relatedTarget)))&&k(o)}function de(o){var l;!((l=f.value)===null||l===void 0)&&l.contains(o.relatedTarget)||W(o)}function ue(o){V(o)}function ne(){P.value=!0}function ie(){P.value=!1}function ee(o){!e.active||!e.filterable||o.target!==d.value&&o.preventDefault()}function le(o){H(o)}function G(o){if(o.code==="Backspace"&&!Z.value&&!e.pattern.length){const{selectedOptions:l}=e;l!=null&&l.length&&le(l[l.length-1])}}const Z=m(!1);let J=null;function q(o){const{value:l}=r;if(l){const _=o.target.value;l.textContent=_,j()}Z.value?J=o:I(o)}function X(){Z.value=!0}function a(){Z.value=!1,I(J),J=null}function c(o){var l;S.value=!0,(l=e.onPatternFocus)===null||l===void 0||l.call(e,o)}function L(o){var l;S.value=!1,(l=e.onPatternBlur)===null||l===void 0||l.call(e,o)}function N(){var o,l;if(e.filterable)S.value=!1,(o=g.value)===null||o===void 0||o.blur(),(l=d.value)===null||l===void 0||l.blur();else if(e.multiple){const{value:_}=u;_==null||_.blur()}else{const{value:_}=w;_==null||_.blur()}}function Q(){var o,l,_;e.filterable?(S.value=!1,(o=g.value)===null||o===void 0||o.focus()):e.multiple?(l=u.value)===null||l===void 0||l.focus():(_=w.value)===null||_===void 0||_.focus()}function me(){const{value:o}=d;o&&(E(),o.focus())}function ce(){const{value:o}=d;o&&o.blur()}function Ie(o){const{value:l}=s;l&&l.setTextContent(`+${o}`)}function Re(){const{value:o}=R;return o}function Fe(){return d.value}let he=null;function be(){he!==null&&window.clearTimeout(he)}function ke(){e.disabled||e.active||(be(),he=window.setTimeout(()=>{M.value=!0},100))}function Te(){be()}function ze(o){o||(be(),M.value=!1)}lt(()=>{st(()=>{const o=g.value;!o||(o.tabIndex=e.disabled||S.value?-1:0)})});const{inlineThemeDisabled:we}=e,Ce=B(()=>{const{size:o}=e,{common:{cubicBezierEaseInOut:l},self:{borderRadius:_,color:Be,placeholderColor:_e,textColor:$e,paddingSingle:xe,paddingMultiple:ye,caretColor:Ae,colorDisabled:ge,textColorDisabled:Ee,placeholderColorDisabled:Se,colorActive:oe,boxShadowFocus:t,boxShadowActive:i,boxShadowHover:v,border:F,borderFocus:h,borderHover:T,borderActive:z,arrowColor:fe,arrowColorDisabled:Pe,loadingColor:Le,colorActiveWarning:Ue,boxShadowFocusWarning:Ke,boxShadowActiveWarning:ft,boxShadowHoverWarning:vt,borderWarning:ht,borderFocusWarning:bt,borderHoverWarning:gt,borderActiveWarning:pt,colorActiveError:mt,boxShadowFocusError:wt,boxShadowActiveError:Ct,boxShadowHoverError:xt,borderError:yt,borderFocusError:St,borderHoverError:Pt,borderActiveError:Ot,clearColor:Mt,clearColorHover:It,clearColorPressed:Rt,clearSize:Ft,arrowSize:kt,[Qe("height",o)]:Tt,[Qe("fontSize",o)]:zt}}=C.value;return{"--n-bezier":l,"--n-border":F,"--n-border-active":z,"--n-border-focus":h,"--n-border-hover":T,"--n-border-radius":_,"--n-box-shadow-active":i,"--n-box-shadow-focus":t,"--n-box-shadow-hover":v,"--n-caret-color":Ae,"--n-color":Be,"--n-color-active":oe,"--n-color-disabled":ge,"--n-font-size":zt,"--n-height":Tt,"--n-padding-single":xe,"--n-padding-multiple":ye,"--n-placeholder-color":_e,"--n-placeholder-color-disabled":Se,"--n-text-color":$e,"--n-text-color-disabled":Ee,"--n-arrow-color":fe,"--n-arrow-color-disabled":Pe,"--n-loading-color":Le,"--n-color-active-warning":Ue,"--n-box-shadow-focus-warning":Ke,"--n-box-shadow-active-warning":ft,"--n-box-shadow-hover-warning":vt,"--n-border-warning":ht,"--n-border-focus-warning":bt,"--n-border-hover-warning":gt,"--n-border-active-warning":pt,"--n-color-active-error":mt,"--n-box-shadow-focus-error":wt,"--n-box-shadow-active-error":Ct,"--n-box-shadow-hover-error":xt,"--n-border-error":yt,"--n-border-focus-error":St,"--n-border-hover-error":Pt,"--n-border-active-error":Ot,"--n-clear-size":Ft,"--n-clear-color":Mt,"--n-clear-color-hover":It,"--n-clear-color-pressed":Rt,"--n-arrow-size":kt}}),te=we?qe("internal-selection",B(()=>e.size[0]),Ce,e):void 0;return{mergedTheme:C,mergedClearable:y,patternInputFocused:S,filterablePlaceholder:$,label:O,selected:A,showTagsPanel:M,isCompositing:Z,counterRef:s,counterWrapperRef:R,patternInputMirrorRef:r,patternInputRef:d,selfRef:f,multipleElRef:u,singleElRef:w,patternInputWrapperRef:g,overflowRef:p,inputTagElRef:b,handleMouseDown:ee,handleFocusin:ae,handleClear:ue,handleMouseEnter:ne,handleMouseLeave:ie,handleDeleteOption:le,handlePatternKeyDown:G,handlePatternInputInput:q,handlePatternInputBlur:L,handlePatternInputFocus:c,handleMouseEnterCounter:ke,handleMouseLeaveCounter:Te,handleFocusout:de,handleCompositionEnd:a,handleCompositionStart:X,onPopoverUpdateShow:ze,focus:Q,focusInput:me,blur:N,blurInput:ce,updateCounter:Ie,getCounter:Re,getTail:Fe,renderLabel:e.renderLabel,cssVars:we?void 0:Ce,themeClass:te==null?void 0:te.themeClass,onRender:te==null?void 0:te.onRender}},render(){const{status:e,multiple:r,size:d,disabled:f,filterable:u,maxTagCount:w,bordered:g,clsPrefix:s,onRender:R,renderTag:p,renderLabel:b}=this;R==null||R();const M=w==="responsive",S=typeof w=="number",P=M||S,C=n(Lt,{clsPrefix:s,loading:this.loading,showArrow:this.showArrow,showClear:this.mergedClearable&&this.selected,onClear:this.handleClear},{default:()=>{var $,O;return(O=($=this.$slots).arrow)===null||O===void 0?void 0:O.call($)}});let y;if(r){const $=I=>n("div",{class:`${s}-base-selection-tag-wrapper`,key:I.value},p?p({option:I,handleClose:()=>this.handleDeleteOption(I)}):n(He,{size:d,closable:!I.disabled,disabled:f,internalStopClickPropagation:!0,onClose:()=>this.handleDeleteOption(I)},{default:()=>b?b(I,!0):Ve(I.label,I,!0)})),O=(S?this.selectedOptions.slice(0,w):this.selectedOptions).map($),A=u?n("div",{class:`${s}-base-selection-input-tag`,ref:"inputTagElRef",key:"__input-tag__"},n("input",Object.assign({},this.inputProps,{ref:"patternInputRef",tabindex:-1,disabled:f,value:this.pattern,autofocus:this.autofocus,class:`${s}-base-selection-input-tag__input`,onBlur:this.handlePatternInputBlur,onFocus:this.handlePatternInputFocus,onKeydown:this.handlePatternKeyDown,onInput:this.handlePatternInputInput,onCompositionstart:this.handleCompositionStart,onCompositionend:this.handleCompositionEnd})),n("span",{ref:"patternInputMirrorRef",class:`${s}-base-selection-input-tag__mirror`},this.pattern)):null,j=M?()=>n("div",{class:`${s}-base-selection-tag-wrapper`,ref:"counterWrapperRef"},n(He,{size:d,ref:"counterRef",onMouseenter:this.handleMouseEnterCounter,onMouseleave:this.handleMouseLeaveCounter,disabled:f})):void 0;let K;if(S){const I=this.selectedOptions.length-w;I>0&&(K=n("div",{class:`${s}-base-selection-tag-wrapper`,key:"__counter__"},n(He,{size:d,ref:"counterRef",onMouseenter:this.handleMouseEnterCounter,disabled:f},{default:()=>`+${I}`})))}const E=M?u?n(at,{ref:"overflowRef",updateCounter:this.updateCounter,getCounter:this.getCounter,getTail:this.getTail,style:{width:"100%",display:"flex",overflow:"hidden"}},{default:()=>O,counter:j,tail:()=>A}):n(at,{ref:"overflowRef",updateCounter:this.updateCounter,getCounter:this.getCounter,style:{width:"100%",display:"flex",overflow:"hidden"}},{default:()=>O,counter:j}):S?O.concat(K):O,k=P?()=>n("div",{class:`${s}-base-selection-popover`},M?O:this.selectedOptions.map($)):void 0,W=P?{show:this.showTagsPanel,trigger:"hover",overlap:!0,placement:"top",width:"trigger",onUpdateShow:this.onPopoverUpdateShow,theme:this.mergedTheme.peers.Popover,themeOverrides:this.mergedTheme.peerOverrides.Popover}:null,V=(this.selected?!1:this.active?!this.pattern&&!this.isCompositing:!0)?n("div",{class:`${s}-base-selection-placeholder ${s}-base-selection-overlay`},this.placeholder):null;if(u){const I=n("div",{ref:"patternInputWrapperRef",class:`${s}-base-selection-tags`},E,M?null:A,C);y=n(Ge,null,P?n(Ye,Object.assign({},W),{trigger:()=>I,default:k}):I,V)}else{const I=n("div",{ref:"multipleElRef",class:`${s}-base-selection-tags`,tabindex:f?void 0:0},E,C);y=n(Ge,null,P?n(Ye,Object.assign({},W),{trigger:()=>I,default:k}):I,V)}}else if(u){const $=this.pattern||this.isCompositing,O=this.active?!$:!this.selected,A=this.active?!1:this.selected;y=n("div",{ref:"patternInputWrapperRef",class:`${s}-base-selection-label`},n("input",Object.assign({},this.inputProps,{ref:"patternInputRef",class:`${s}-base-selection-input`,value:this.active?this.pattern:"",placeholder:"",readonly:f,disabled:f,tabindex:-1,autofocus:this.autofocus,onFocus:this.handlePatternInputFocus,onBlur:this.handlePatternInputBlur,onInput:this.handlePatternInputInput,onCompositionstart:this.handleCompositionStart,onCompositionend:this.handleCompositionEnd})),A?n("div",{class:`${s}-base-selection-label__render-label ${s}-base-selection-overlay`,key:"input"},n("div",{class:`${s}-base-selection-overlay__wrapper`},p?p({option:this.selectedOption,handleClose:()=>{}}):b?b(this.selectedOption,!0):Ve(this.label,this.selectedOption,!0))):null,O?n("div",{class:`${s}-base-selection-placeholder ${s}-base-selection-overlay`,key:"placeholder"},n("div",{class:`${s}-base-selection-overlay__wrapper`},this.filterablePlaceholder)):null,C)}else y=n("div",{ref:"singleElRef",class:`${s}-base-selection-label`,tabindex:this.disabled?void 0:0},this.label!==void 0?n("div",{class:`${s}-base-selection-input`,title:Dt(this.label),key:"input"},n("div",{class:`${s}-base-selection-input__content`},p?p({option:this.selectedOption,handleClose:()=>{}}):b?b(this.selectedOption,!0):Ve(this.label,this.selectedOption,!0))):n("div",{class:`${s}-base-selection-placeholder ${s}-base-selection-overlay`,key:"placeholder"},this.placeholder),C);return n("div",{ref:"selfRef",class:[`${s}-base-selection`,this.themeClass,e&&`${s}-base-selection--${e}-status`,{[`${s}-base-selection--active`]:this.active,[`${s}-base-selection--selected`]:this.selected||this.active&&this.pattern,[`${s}-base-selection--disabled`]:this.disabled,[`${s}-base-selection--multiple`]:this.multiple,[`${s}-base-selection--focus`]:this.focused}],style:this.cssVars,onClick:this.onClick,onMouseenter:this.handleMouseEnter,onMouseleave:this.handleMouseLeave,onKeyup:this.onKeyup,onKeydown:this.onKeydown,onFocusin:this.handleFocusin,onFocusout:this.handleFocusout,onMousedown:this.handleMouseDown},y,g?n("div",{class:`${s}-base-selection__border`}):null,g?n("div",{class:`${s}-base-selection__state-border`}):null)}});function sn(e){return We(e)?e.name||e.key||"key-required":e.value}function We(e){return e.type==="group"}function ct(e){return e.type==="ignored"}const dn={getKey:sn,getIsGroup:We,getIgnored:ct};function it(e,r){try{return!!(1+r.toString().toLowerCase().indexOf(e.trim().toLowerCase()))}catch{return!1}}function un(e,r,d){if(!r)return e;function f(u){if(!Array.isArray(u))return[];const w=[];for(const g of u)if(We(g)){const s=f(g.children);s.length&&w.push(Object.assign({},g,{children:s}))}else{if(ct(g))continue;r(d,g)&&w.push(g)}return w}return f(e)}function cn(e){const r=new Map;return e.forEach(d=>{We(d)?d.children.forEach(f=>{r.set(f.value,f)}):r.set(d.value,d)}),r}function fn(e,r){return r?typeof r.label=="string"?it(e,r.label):r.value!==void 0?it(e,String(r.value)):!1:!1}var vn=re([x("select",` - z-index: auto; - outline: none; - width: 100%; - position: relative; - `),x("select-menu",` - margin: 4px 0; - box-shadow: var(--n-menu-box-shadow); - `,[jt()])]);const hn=Object.assign(Object.assign({},Me.props),{to:Je.propTo,bordered:{type:Boolean,default:void 0},clearable:Boolean,clearFilterAfterSelect:{type:Boolean,default:!0},options:{type:Array,default:()=>[]},defaultValue:{type:[String,Number,Array],default:null},value:[String,Number,Array],placeholder:String,menuProps:Object,multiple:Boolean,size:String,filterable:Boolean,disabled:{type:Boolean,default:void 0},remote:Boolean,loading:Boolean,filter:{type:Function,default:fn},placement:{type:String,default:"bottom-start"},widthMode:{type:String,default:"trigger"},tag:Boolean,onCreate:{type:Function,default:e=>({label:e,value:e})},fallbackOption:{type:[Function,Boolean],default:()=>e=>({label:String(e),value:e})},show:{type:Boolean,default:void 0},showArrow:{type:Boolean,default:!0},maxTagCount:[Number,String],consistentMenuWidth:{type:Boolean,default:!0},virtualScroll:{type:Boolean,default:!0},renderLabel:Function,renderOption:Function,renderTag:Function,"onUpdate:value":[Function,Array],inputProps:Object,onUpdateValue:[Function,Array],onBlur:[Function,Array],onClear:[Function,Array],onFocus:[Function,Array],onScroll:[Function,Array],onSearch:[Function,Array],onUpdateShow:[Function,Array],"onUpdate:show":[Function,Array],displayDirective:{type:String,default:"show"},resetMenuOnOptionsChange:{type:Boolean,default:!0},status:String,onChange:[Function,Array],items:Array});var bn=se({name:"Select",props:hn,setup(e){const{mergedClsPrefixRef:r,mergedBorderedRef:d,namespaceRef:f,inlineThemeDisabled:u}=dt(e),w=Me("Select","-select",vn,Vt,e,r),g=m(e.defaultValue),s=ve(e,"value"),R=Ne(s,g),p=m(!1),b=m(""),M=B(()=>Nt(I.value,dn)),S=B(()=>cn(V.value)),P=m(!1),C=Ne(ve(e,"show"),P),y=m(null),$=m(null),O=m(null),{localeRef:A}=ut("Select"),j=B(()=>{var t;return(t=e.placeholder)!==null&&t!==void 0?t:A.value.placeholder}),K=Wt(e,["items","options"]),E=m([]),k=m([]),W=m(new Map),H=B(()=>{const{fallbackOption:t}=e;return t?i=>Object.assign(t(i),{value:i}):!1}),V=B(()=>k.value.concat(E.value).concat(K.value)),I=B(()=>{if(e.remote)return K.value;{const{value:t}=V,{value:i}=b;if(!i.length||!e.filterable)return t;{const{filter:v}=e;return un(t,v,i)}}});function ae(t){const i=e.remote,{value:v}=W,{value:F}=S,{value:h}=H,T=[];return t.forEach(z=>{if(F.has(z))T.push(F.get(z));else if(i&&v.has(z))T.push(v.get(z));else if(h){const fe=h(z);fe&&T.push(fe)}}),T}const de=B(()=>{if(e.multiple){const{value:t}=R;return Array.isArray(t)?ae(t):[]}return null}),ue=B(()=>{const{value:t}=R;return!e.multiple&&!Array.isArray(t)?t===null?null:ae([t])[0]||null:null}),ne=Ut(e),{mergedSizeRef:ie,mergedDisabledRef:ee,mergedStatusRef:le}=ne;function G(t,i){const{onChange:v,"onUpdate:value":F,onUpdateValue:h}=e,{nTriggerFormChange:T,nTriggerFormInput:z}=ne;v&&U(v,t,i),h&&U(h,t,i),F&&U(F,t,i),g.value=t,T(),z()}function Z(t){const{onBlur:i}=e,{nTriggerFormBlur:v}=ne;i&&U(i,t),v()}function J(){const{onClear:t}=e;t&&U(t)}function q(t){const{onFocus:i}=e,{nTriggerFormFocus:v}=ne;i&&U(i,t),v()}function X(t){const{onSearch:i}=e;i&&U(i,t)}function a(t){const{onScroll:i}=e;i&&U(i,t)}function c(){var t;const{remote:i,multiple:v}=e;if(i){const{value:F}=W;if(v)(t=de.value)===null||t===void 0||t.forEach(h=>{F.set(h.value,h)});else{const h=ue.value;h&&F.set(h.value,h)}}}function L(t){const{onUpdateShow:i,"onUpdate:show":v}=e;i&&U(i,t),v&&U(v,t),P.value=t}function N(){ee.value||(L(!0),P.value=!0,e.filterable&&Ae())}function Q(){L(!1)}function me(){b.value="",k.value=[]}const ce=m(!1);function Ie(){e.filterable&&(ce.value=!0)}function Re(){e.filterable&&(ce.value=!1,C.value||me())}function Fe(){ee.value||(C.value?e.filterable||Q():N())}function he(t){var i,v;!((v=(i=O.value)===null||i===void 0?void 0:i.selfRef)===null||v===void 0)&&v.contains(t.relatedTarget)||(p.value=!1,Z(t),Q())}function be(t){q(t),p.value=!0}function ke(t){p.value=!0}function Te(t){var i;!((i=y.value)===null||i===void 0)&&i.$el.contains(t.relatedTarget)||(p.value=!1,Z(t),Q())}function ze(){var t;(t=y.value)===null||t===void 0||t.focus(),Q()}function we(t){var i;C.value&&(!((i=y.value)===null||i===void 0)&&i.$el.contains(t.target)||Q())}function Ce(t){if(!Array.isArray(t))return[];if(H.value)return Array.from(t);{const{remote:i}=e,{value:v}=S;if(i){const{value:F}=W;return t.filter(h=>v.has(h)||F.has(h))}else return t.filter(F=>v.has(F))}}function te(t){o(t.rawNode)}function o(t){if(ee.value)return;const{tag:i,remote:v,clearFilterAfterSelect:F}=e;if(i&&!v){const{value:h}=k,T=h[0]||null;T&&(E.value.push(T),k.value=[])}if(v&&W.value.set(t.value,t),e.multiple){const h=Ce(R.value),T=h.findIndex(z=>z===t.value);if(~T){if(h.splice(T,1),i&&!v){const z=l(t.value);~z&&(E.value.splice(z,1),F&&(b.value=""))}}else h.push(t.value),F&&(b.value="");G(h,ae(h))}else{if(i&&!v){const h=l(t.value);~h?E.value=[E.value[h]]:E.value=[]}ye(),Q(),G(t.value,t)}}function l(t){return E.value.findIndex(v=>v.value===t)}function _(t){C.value||N();const{value:i}=t.target;b.value=i;const{tag:v,remote:F}=e;if(X(i),v&&!F){if(!i){k.value=[];return}const h=e.onCreate(i);K.value.some(T=>T.value===h.value)||E.value.some(T=>T.value===h.value)?k.value=[]:k.value=[h]}}function Be(t){t.stopPropagation();const{multiple:i}=e;!i&&e.filterable&&Q(),J(),i?G([],[]):G(null,null)}function _e(t){Gt(t,"action")||t.preventDefault()}function $e(t){a(t)}function xe(t){var i,v,F,h,T;switch(t.code){case"Space":if(e.filterable)break;t.preventDefault();case"Enter":case"NumpadEnter":if(!(!((i=y.value)===null||i===void 0)&&i.isCompositing)){if(C.value){const z=(v=O.value)===null||v===void 0?void 0:v.getPendingTmNode();z?te(z):e.filterable||(Q(),ye())}else if(N(),e.tag&&ce.value){const z=k.value[0];if(z){const fe=z.value,{value:Pe}=R;e.multiple&&Array.isArray(Pe)&&Pe.some(Le=>Le===fe)||o(z)}}}t.preventDefault();break;case"ArrowUp":if(t.preventDefault(),e.loading)return;C.value&&((F=O.value)===null||F===void 0||F.prev());break;case"ArrowDown":if(t.preventDefault(),e.loading)return;C.value?(h=O.value)===null||h===void 0||h.next():N();break;case"Escape":Q(),(T=y.value)===null||T===void 0||T.focus();break}}function ye(){var t;(t=y.value)===null||t===void 0||t.focus()}function Ae(){var t;(t=y.value)===null||t===void 0||t.focusInput()}function ge(){var t;(t=$.value)===null||t===void 0||t.syncPosition()}c(),De(ve(e,"options"),c),De(I,()=>{!C.value||je(ge)}),De(R,()=>{!C.value||je(ge)});const Ee={focus:()=>{var t;(t=y.value)===null||t===void 0||t.focus()},blur:()=>{var t;(t=y.value)===null||t===void 0||t.blur()}},Se=B(()=>{const{self:{menuBoxShadow:t}}=w.value;return{"--n-menu-box-shadow":t}}),oe=u?qe("select",void 0,Se,e):void 0;return Object.assign(Object.assign({},Ee),{mergedStatus:le,mergedClsPrefix:r,mergedBordered:d,namespace:f,treeMate:M,isMounted:Kt(),triggerRef:y,menuRef:O,pattern:b,uncontrolledShow:P,mergedShow:C,adjustedTo:Je(e),uncontrolledValue:g,mergedValue:R,followerRef:$,localizedPlaceholder:j,selectedOption:ue,selectedOptions:de,mergedSize:ie,mergedDisabled:ee,focused:p,activeWithoutMenuOpen:ce,inlineThemeDisabled:u,onTriggerInputFocus:Ie,onTriggerInputBlur:Re,handleMenuFocus:ke,handleMenuBlur:Te,handleMenuTabOut:ze,handleTriggerClick:Fe,handleToggle:te,handleDeleteOption:o,handlePatternInput:_,handleClear:Be,handleTriggerBlur:he,handleTriggerFocus:be,handleKeydown:xe,syncPosition:ge,handleMenuAfterLeave:me,handleMenuClickOutside:we,handleMenuScroll:$e,handleMenuKeydown:xe,handleMenuMousedown:_e,mergedTheme:w,cssVars:u?void 0:Se,themeClass:oe==null?void 0:oe.themeClass,onRender:oe==null?void 0:oe.onRender})},render(){return n("div",{class:`${this.mergedClsPrefix}-select`},n(Ht,null,{default:()=>[n(Zt,null,{default:()=>n(ln,{ref:"triggerRef",inlineThemeDisabled:this.inlineThemeDisabled,status:this.mergedStatus,inputProps:this.inputProps,clsPrefix:this.mergedClsPrefix,showArrow:this.showArrow,maxTagCount:this.maxTagCount,bordered:this.mergedBordered,active:this.activeWithoutMenuOpen||this.mergedShow,pattern:this.pattern,placeholder:this.localizedPlaceholder,selectedOption:this.selectedOption,selectedOptions:this.selectedOptions,multiple:this.multiple,renderTag:this.renderTag,renderLabel:this.renderLabel,filterable:this.filterable,clearable:this.clearable,disabled:this.mergedDisabled,size:this.mergedSize,theme:this.mergedTheme.peers.InternalSelection,themeOverrides:this.mergedTheme.peerOverrides.InternalSelection,loading:this.loading,focused:this.focused,onClick:this.handleTriggerClick,onDeleteOption:this.handleDeleteOption,onPatternInput:this.handlePatternInput,onClear:this.handleClear,onBlur:this.handleTriggerBlur,onFocus:this.handleTriggerFocus,onKeydown:this.handleKeydown,onPatternBlur:this.onTriggerInputBlur,onPatternFocus:this.onTriggerInputFocus},{arrow:()=>{var e,r;return[(r=(e=this.$slots).arrow)===null||r===void 0?void 0:r.call(e)]}})}),n(Jt,{ref:"followerRef",show:this.mergedShow,to:this.adjustedTo,teleportDisabled:this.adjustedTo===Je.tdkey,containerClass:this.namespace,width:this.consistentMenuWidth?"target":void 0,minWidth:"target",placement:this.placement},{default:()=>n(qt,{name:"fade-in-scale-up-transition",appear:this.isMounted,onAfterLeave:this.handleMenuAfterLeave},{default:()=>{var e,r,d;return this.mergedShow||this.displayDirective==="show"?((e=this.onRender)===null||e===void 0||e.call(this),Qt(n(on,Object.assign({},this.menuProps,{ref:"menuRef",inlineThemeDisabled:this.inlineThemeDisabled,virtualScroll:this.consistentMenuWidth&&this.virtualScroll,class:[`${this.mergedClsPrefix}-select-menu`,this.themeClass,(r=this.menuProps)===null||r===void 0?void 0:r.class],clsPrefix:this.mergedClsPrefix,focusable:!0,autoPending:!0,theme:this.mergedTheme.peers.InternalSelectMenu,themeOverrides:this.mergedTheme.peerOverrides.InternalSelectMenu,treeMate:this.treeMate,multiple:this.multiple,size:"medium",renderOption:this.renderOption,renderLabel:this.renderLabel,value:this.mergedValue,style:[(d=this.menuProps)===null||d===void 0?void 0:d.style,this.cssVars],onToggle:this.handleToggle,onScroll:this.handleMenuScroll,onFocus:this.handleMenuFocus,onBlur:this.handleMenuBlur,onKeydown:this.handleMenuKeydown,onTabOut:this.handleMenuTabOut,onMousedown:this.handleMenuMousedown,show:this.mergedShow,resetMenuOnOptionsChange:this.resetMenuOnOptionsChange}),{empty:()=>{var f,u;return[(u=(f=this.$slots).empty)===null||u===void 0?void 0:u.call(f)]},action:()=>{var f,u;return[(u=(f=this.$slots).action)===null||u===void 0?void 0:u.call(f)]}}),this.displayDirective==="show"?[[Yt,this.mergedShow],[Xe,this.handleMenuClickOutside,void 0,{capture:!0}]]:[[Xe,this.handleMenuClickOutside,void 0,{capture:!0}]])):null}})})]}))}});function gn(e,r,d=9){if(r===1)return[1];if(r===2)return[1,2];const f=1,u=r;let w=e,g=e;const s=(d-5)/2;g+=Math.ceil(s),g=Math.min(Math.max(g,f+d-3),u-2),w-=Math.floor(s),w=Math.max(Math.min(w,u-d+3),f+2);let R=!1,p=!1;w>f+2&&(R=!0),g=f+1&&b.push(f+1);for(let M=w;M<=g;++M)b.push(M);return p?b.push(-1):g===u-2&&b[b.length-1]!==u-1&&b.push(u-1),b[b.length-1]!==u&&b.push(u),b}function pn(e,r){return e.map(d=>{switch(d){case-2:return{type:"fast-backward",active:!1};case-1:return{type:"fast-forward",active:!1};default:return d===r?{type:"page",label:d,active:!0}:{type:"page",label:d,active:!1}}})}function mn(e,r,d){const f=gn(e,r,d);return pn(f,e)}var wn=x("pagination",` - display: flex; - vertical-align: middle; - font-size: var(--n-item-font-size); - flex-wrap: nowrap; -`,[x("pagination-prefix",` - display: flex; - align-items: center; - margin: var(--n-prefix-margin); - `),x("pagination-suffix",` - display: flex; - align-items: center; - margin: var(--n-suffix-margin); - `),re("> *:not(:first-child)",{margin:"var(--n-item-margin)"}),x("select",{width:"var(--n-select-width)"}),re("&.transition-disabled",[x("pagination-item",{transition:"none!important"})]),x("pagination-quick-jumper",` - white-space: nowrap; - display: flex; - color: var(--n-jumper-text-color); - transition: color .3s var(--n-bezier); - align-items: center; - font-size: var(--n-jumter-font-size); - `,[x("input",` - margin: var(--n-input-margin); - width: var(--n-input-width); - `)]),x("pagination-item",` - position: relative; - cursor: pointer; - user-select: none; - display: flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - min-width: var(--n-item-size); - height: var(--n-item-size); - padding: var(--n-item-padding); - background-color: var(--n-item-color); - color: var(--n-item-text-color); - border-radius: var(--n-item-border-radius); - border: var(--n-item-border); - fill: var(--n-button-icon-color); - transition: - color .3s var(--n-bezier), - border-color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - fill .3s var(--n-bezier); - `,[Y("button",` - background: var(--n-button-color); - color: var(--n-button-icon-color); - border: var(--n-button-border); - `,[x("base-icon",` - font-size: var(--n-button-icon-size); - `)]),Ze("disabled",[re("&:hover",{background:"var(--n-item-color-hover)",color:"var(--n-item-text-color-hover)",border:"var(--n-item-border-hover)"},[Y("button",{background:"var(--n-button-color-hover)",border:"var(--n-button-border-hover)",color:"var(--n-button-icon-color-hover)"})]),re("&:active",{background:"var(--n-item-color-pressed)",color:"var(--n-item-text-color-pressed)",border:"var(--n-item-border-pressed)"},[Y("button",{background:"var(--n-button-color-pressed)",border:"var(--n-button-border-pressed)",color:"var(--n-button-icon-color-pressed)"})]),Y("active",{background:"var(--n-item-color-active)",color:"var(--n-item-text-color-active)",border:"var(--n-item-border-active)"},[re("&:hover",{background:"var(--n-item-color-active-hover)"})])]),Y("disabled",` - cursor: not-allowed; - color: var(--n-item-text-color-disabled); - `,[Y("active, button",{backgroundColor:"var(--n-item-color-disabled)",border:"var(--n-item-border-disabled)"})])]),Y("disabled",{cursor:"not-allowed"},[x("pagination-quick-jumper",{color:"var(--n-jumper-text-color-disabled)"})])]);const Cn=Object.assign(Object.assign({},Me.props),{page:Number,defaultPage:{type:Number,default:1},itemCount:Number,pageCount:Number,defaultPageCount:{type:Number,default:1},showSizePicker:Boolean,pageSize:Number,defaultPageSize:{type:Number,default:10},pageSizes:{type:Array,default(){return[10]}},showQuickJumper:Boolean,disabled:Boolean,pageSlot:{type:Number,default:9},prev:Function,next:Function,prefix:Function,suffix:Function,label:Function,"onUpdate:page":[Function,Array],onUpdatePage:[Function,Array],"onUpdate:pageSize":[Function,Array],onUpdatePageSize:[Function,Array],onPageSizeChange:[Function,Array],onChange:[Function,Array]});var Sn=se({name:"Pagination",props:Cn,setup(e){const{mergedComponentPropsRef:r,mergedClsPrefixRef:d,inlineThemeDisabled:f,mergedRtlRef:u}=dt(e),w=Me("Pagination","-pagination",wn,Xt,e,d),{localeRef:g}=ut("Pagination"),s=m(null),R=m(null),p=m(""),b=m(e.defaultPage),M=m(e.defaultPageSize),S=Ne(ve(e,"page"),b),P=Ne(ve(e,"pageSize"),M),C=B(()=>{const{itemCount:a}=e;if(a!==void 0)return Math.max(1,Math.ceil(a/P.value));const{pageCount:c}=e;return c!==void 0?c:1}),y=m(!1),$=m(!1),O=B(()=>{const a=g.value.selectionSuffix;return e.pageSizes.map(c=>typeof c=="number"?{label:`${c} / ${a}`,value:c}:c)}),A=B(()=>{var a,c;return((c=(a=r==null?void 0:r.value)===null||a===void 0?void 0:a.Pagination)===null||c===void 0?void 0:c.inputSize)||"small"}),j=B(()=>{var a,c;return((c=(a=r==null?void 0:r.value)===null||a===void 0?void 0:a.Pagination)===null||c===void 0?void 0:c.selectSize)||"small"}),K=B(()=>(S.value-1)*P.value),E=B(()=>{const a=S.value*P.value-1,{itemCount:c}=e;return c!==void 0&&a>c?c:a}),k=B(()=>{const{itemCount:a}=e;return a!==void 0?a:(e.pageCount||1)*P.value}),W=en("Pagination",u,d),H=()=>{je(()=>{var a;const{value:c}=s;!c||(c.classList.add("transition-disabled"),(a=s.value)===null||a===void 0||a.offsetWidth,c.classList.remove("transition-disabled"))})};function V(a){if(a===S.value)return;const{"onUpdate:page":c,onUpdatePage:L,onChange:N}=e;c&&U(c,a),L&&U(L,a),N&&U(N,a),b.value=a}function I(a){if(a===P.value)return;const{"onUpdate:pageSize":c,onUpdatePageSize:L,onPageSizeChange:N}=e;c&&U(c,a),L&&U(L,a),N&&U(N,a),M.value=a,C.value=1&&L<=C.value&&(V(L),p.value="",(c=R.value)===null||c===void 0||c.blur())}}function le(a){if(!e.disabled)switch(a.type){case"page":V(a.label);break;case"fast-backward":ne();break;case"fast-forward":ue();break}}function G(a){if(!e.disabled){switch(a.type){case"fast-backward":$.value=!0;break;case"fast-forward":y.value=!0;break;default:return}H()}}function Z(a){if(!e.disabled){switch(a.type){case"fast-backward":$.value=!1;break;case"fast-forward":y.value=!1;break;default:return}H()}}function J(a){p.value=a}st(()=>{S.value,P.value,H()});const q=B(()=>{const{self:{itemSize:a,itemPadding:c,itemMargin:L,itemMarginRtl:N,inputWidth:Q,selectWidth:me,inputMargin:ce,inputMarginRtl:Ie,selectMargin:Re,buttonBorder:Fe,buttonBorderHover:he,buttonBorderPressed:be,buttonIconColor:ke,buttonIconColorHover:Te,buttonIconColorPressed:ze,buttonIconSize:we,itemTextColor:Ce,itemTextColorHover:te,itemTextColorPressed:o,itemTextColorActive:l,itemTextColorDisabled:_,itemColor:Be,itemColorHover:_e,itemColorPressed:$e,itemColorActive:xe,itemColorActiveHover:ye,itemColorDisabled:Ae,itemBorder:ge,itemBorderHover:Ee,itemBorderPressed:Se,itemBorderActive:oe,itemBorderDisabled:t,itemBorderRadius:i,itemFontSize:v,jumperFontSize:F,jumperTextColor:h,jumperTextColorDisabled:T,prefixMargin:z,suffixMargin:fe,buttonColor:Pe,buttonColorHover:Le,buttonColorPressed:Ue},common:{cubicBezierEaseInOut:Ke}}=w.value;return{"--n-prefix-margin":z,"--n-suffix-margin":fe,"--n-item-font-size":v,"--n-select-width":me,"--n-select-margin":Re,"--n-input-width":Q,"--n-input-margin":ce,"--n-input-margin-rtl":Ie,"--n-item-size":a,"--n-item-text-color":Ce,"--n-item-text-color-disabled":_,"--n-item-text-color-hover":te,"--n-item-text-color-active":l,"--n-item-text-color-pressed":o,"--n-item-color":Be,"--n-item-color-hover":_e,"--n-item-color-disabled":Ae,"--n-item-color-active":xe,"--n-item-color-active-hover":ye,"--n-item-color-pressed":$e,"--n-item-border":ge,"--n-item-border-hover":Ee,"--n-item-border-disabled":t,"--n-item-border-active":oe,"--n-item-border-pressed":Se,"--n-item-padding":c,"--n-item-border-radius":i,"--n-bezier":Ke,"--n-jumper-font-size":F,"--n-jumper-text-color":h,"--n-jumper-text-color-disabled":T,"--n-item-margin":L,"--n-item-margin-rtl":N,"--n-button-icon-size":we,"--n-button-icon-color":ke,"--n-button-icon-color-hover":Te,"--n-button-icon-color-pressed":ze,"--n-button-color-hover":Le,"--n-button-color":Pe,"--n-button-color-pressed":Ue,"--n-button-border":Fe,"--n-button-border-hover":he,"--n-button-border-pressed":be}}),X=f?qe("pagination",void 0,q,e):void 0;return{rtlEnabled:W,mergedClsPrefix:d,locale:g,selfRef:s,jumperRef:R,mergedPage:S,showFastBackward:$,showFastForward:y,pageItems:B(()=>mn(S.value,C.value,e.pageSlot)),mergedItemCount:k,jumperValue:p,pageSizeOptions:O,mergedPageSize:P,inputSize:A,selectSize:j,mergedTheme:w,mergedPageCount:C,startIndex:K,endIndex:E,handleJumperInput:J,handleBackwardClick:de,handleForwardClick:ae,handlePageItemClick:le,handleSizePickerChange:ie,handleQuickJumperKeyUp:ee,handlePageItemMouseEnter:G,handlePageItemMouseLeave:Z,cssVars:f?void 0:q,themeClass:X==null?void 0:X.themeClass,onRender:X==null?void 0:X.onRender}},render(){const{$slots:e,mergedClsPrefix:r,disabled:d,cssVars:f,mergedPage:u,mergedPageCount:w,pageItems:g,showFastBackward:s,showFastForward:R,showSizePicker:p,showQuickJumper:b,mergedTheme:M,locale:S,inputSize:P,selectSize:C,mergedPageSize:y,pageSizeOptions:$,jumperValue:O,prev:A,next:j,prefix:K,suffix:E,label:k,handleJumperInput:W,handleSizePickerChange:H,handleBackwardClick:V,handlePageItemClick:I,handlePageItemMouseEnter:ae,handlePageItemMouseLeave:de,handleForwardClick:ue,handleQuickJumperKeyUp:ne,onRender:ie}=this;ie==null||ie();const ee=e.prefix||K,le=e.suffix||E,G=A||e.prev,Z=j||e.next,J=k||e.label;return n("div",{ref:"selfRef",class:[`${r}-pagination`,this.themeClass,this.rtlEnabled&&`${r}-pagination--rtl`,d&&`${r}-pagination--disabled`],style:f},ee?n("div",{class:`${r}-pagination-prefix`},ee({page:u,pageSize:y,pageCount:w,startIndex:this.startIndex,endIndex:this.endIndex,itemCount:this.mergedItemCount})):null,n("div",{class:[`${r}-pagination-item`,!G&&`${r}-pagination-item--button`,(u<=1||u>w||d)&&`${r}-pagination-item--disabled`],onClick:V},G?G({page:u,pageSize:y,pageCount:w,startIndex:this.startIndex,endIndex:this.endIndex,itemCount:this.mergedItemCount}):n(Oe,{clsPrefix:r},{default:()=>this.rtlEnabled?n(ot,null):n(et,null)})),g.map((q,X)=>{let a;switch(q.type){case"page":const c=q.label;J?a=J({type:"page",node:c,active:q.active}):a=c;break;case"fast-forward":const L=R?n(Oe,{clsPrefix:r},{default:()=>this.rtlEnabled?n(tt,null):n(nt,null)}):n(Oe,{clsPrefix:r},{default:()=>n(rt,null)});J?a=J({type:"fast-forward",node:L,active:R}):a=L;break;case"fast-backward":const N=s?n(Oe,{clsPrefix:r},{default:()=>this.rtlEnabled?n(nt,null):n(tt,null)}):n(Oe,{clsPrefix:r},{default:()=>n(rt,null)});J?a=J({type:"fast-backward",node:N,active:s}):a=N;break}return n("div",{key:X,class:[`${r}-pagination-item`,{[`${r}-pagination-item--active`]:q.active,[`${r}-pagination-item--disabled`]:d}],onClick:()=>I(q),onMouseenter:()=>ae(q),onMouseleave:()=>de(q)},a)}),n("div",{class:[`${r}-pagination-item`,!Z&&`${r}-pagination-item--button`,{[`${r}-pagination-item--disabled`]:u<1||u>=w||d}],onClick:ue},Z?Z({page:u,pageSize:y,pageCount:w,itemCount:this.mergedItemCount,startIndex:this.startIndex,endIndex:this.endIndex}):n(Oe,{clsPrefix:r},{default:()=>this.rtlEnabled?n(et,null):n(ot,null)})),p?n(bn,{size:C,placeholder:"",options:$,value:y,disabled:d,theme:M.peers.Select,themeOverrides:M.peerOverrides.Select,onUpdateValue:H}):null,b?n("div",{class:`${r}-pagination-quick-jumper`},tn(this.$slots.goto,()=>[S.goto]),n(nn,{ref:"jumperRef",value:O,onUpdateValue:W,size:P,placeholder:"",disabled:d,theme:M.peers.Input,themeOverrides:M.peerOverrides.Input,onKeyup:ne})):null,le?n("div",{class:`${r}-pagination-suffix`},le({page:u,pageSize:y,pageCount:w,startIndex:this.startIndex,endIndex:this.endIndex,itemCount:this.mergedItemCount})):null)}});export{Sn as _}; diff --git a/web/dist/assets/Post.db4b62c9.js b/web/dist/assets/Post.db4b62c9.js deleted file mode 100644 index f1fe2217..00000000 --- a/web/dist/assets/Post.db4b62c9.js +++ /dev/null @@ -1,57 +0,0 @@ -var Ne=Object.defineProperty,je=Object.defineProperties;var Me=Object.getOwnPropertyDescriptors;var be=Object.getOwnPropertySymbols;var Ve=Object.prototype.hasOwnProperty,qe=Object.prototype.propertyIsEnumerable;var we=(i,l,t)=>l in i?Ne(i,l,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[l]=t,X=(i,l)=>{for(var t in l||(l={}))Ve.call(l,t)&&we(i,t,l[t]);if(be)for(var t of be(l))qe.call(l,t)&&we(i,t,l[t]);return i},ee=(i,l)=>je(i,Me(l));import{l as he,p as ve,m as j,o as q,d as T,u as fe,q as ue,bC as Le,s as L,y as De,h as z,aa as se,e as He,I as xe,i as Ke,t as $e,K as Ee,J as W,z as We,N as Je,bu as Ge,bD as Qe,n as Be,bE as Ye,r as k,A as Ze,bF as Xe,bG as et,aM as tt,bH as st,k as Fe,V as c,W as g,Y as C,bI as ot,ah as oe,a6 as $,a3 as a,a4 as r,a8 as E,bJ as nt,_ as at,Z as re,al as ge,a9 as D,a5 as I,a2 as e,bK as it,ae as ce,aj as Ae,am as lt,ab as ie,a7 as J,bL as ut,ad as ye,$ as rt,a1 as ke,bM as ct,bN as pt,bO as dt,af as _t,bP as mt,bQ as vt,bR as ht,bS as ft,bT as gt,bU as yt,bV as kt,bW as Ct,an as bt,bX as wt,bp as xt,ag as $t,ai as Et,S as Bt,bY as Ft,bZ as Pt,b_ as Dt}from"./index.f480f018.js";import{_ as At}from"./InputGroup.f69c4956.js";import{f as le}from"./formatTime.02109bf5.js";import{p as Ce,a as Ie,H as It,C as zt,B as Rt,_ as Tt,b as St,c as Ot}from"./content.ef1e095a.js";import{_ as ze}from"./Thing.eef6b133.js";import{_ as Ut}from"./post-skeleton.39a35f5b.js";import{l as Nt,I as jt,_ as Mt,V as te}from"./IEnum.bfd96c78.js";import{_ as Vt,a as qt,b as Lt,c as Ht}from"./Upload.efe3adfd.js";import{M as Kt}from"./MoreHorizFilled.80db5156.js";import{_ as Wt}from"./main-nav.9110259b.js";import{_ as Jt}from"./List.49bcdf81.js";import{a as Gt,_ as Qt}from"./Skeleton.57e98fe3.js";var Yt=he("divider",` - position: relative; - display: flex; - width: 100%; - box-sizing: border-box; - font-size: 16px; - color: var(--n-text-color); - transition: - color .3s var(--n-bezier), - background-color .3s var(--n-bezier); -`,[ve("vertical",` - margin-top: 24px; - margin-bottom: 24px; - `,[ve("no-title",` - display: flex; - align-items: center; - `)]),j("title",` - display: flex; - align-items: center; - margin-left: 12px; - margin-right: 12px; - white-space: nowrap; - font-weight: var(--n-font-weight); - `),q("title-position-left",[j("line",[q("left",{width:"28px"})])]),q("title-position-right",[j("line",[q("right",{width:"28px"})])]),q("dashed",[j("line",` - background-color: #0000; - height: 0px; - width: 100%; - border-style: dashed; - border-width: 1px 0 0; - `)]),q("vertical",` - display: inline-block; - height: 1em; - margin: 0 8px; - vertical-align: middle; - width: 1px; - `),j("line",` - border: none; - transition: background-color .3s var(--n-bezier), border-color .3s var(--n-bezier); - height: 1px; - width: 100%; - margin: 0; - `),ve("dashed",[j("line",{backgroundColor:"var(--n-color)"})]),q("dashed",[j("line",{borderColor:"var(--n-color)"})]),q("vertical",{backgroundColor:"var(--n-color)"})]);const Zt=Object.assign(Object.assign({},ue.props),{titlePlacement:{type:String,default:"center"},dashed:Boolean,vertical:Boolean});var Xt=T({name:"Divider",props:Zt,setup(i){const{mergedClsPrefixRef:l,inlineThemeDisabled:t}=fe(i),u=ue("Divider","-divider",Yt,Le,i,l),f=L(()=>{const{common:{cubicBezierEaseInOut:p},self:{color:_,textColor:n,fontWeight:b}}=u.value;return{"--n-bezier":p,"--n-color":_,"--n-text-color":n,"--n-font-weight":b}}),d=t?De("divider",void 0,f,i):void 0;return{mergedClsPrefix:l,cssVars:t?void 0:f,themeClass:d==null?void 0:d.themeClass,onRender:d==null?void 0:d.onRender}},render(){var i;const{$slots:l,titlePlacement:t,vertical:u,dashed:f,cssVars:d,mergedClsPrefix:p}=this;return(i=this.onRender)===null||i===void 0||i.call(this),z("div",{role:"separator",class:[`${p}-divider`,this.themeClass,{[`${p}-divider--vertical`]:u,[`${p}-divider--no-title`]:!l.default,[`${p}-divider--dashed`]:f,[`${p}-divider--title-position-${t}`]:l.default&&t}],style:d},u?null:z("div",{class:`${p}-divider__line ${p}-divider__line--left`}),!u&&l.default?z(se,null,z("div",{class:`${p}-divider__title`},this.$slots),z("div",{class:`${p}-divider__line ${p}-divider__line--right`})):null)}});const Re=He("n-popconfirm"),Te={positiveText:String,negativeText:String,showIcon:{type:Boolean,default:!0},onPositiveClick:{type:Function,required:!0},onNegativeClick:{type:Function,required:!0}},Pe=Qe(Te);var es=T({name:"NPopconfirmPanel",props:Te,setup(i){const{localeRef:l}=xe("Popconfirm"),{inlineThemeDisabled:t}=fe(),{mergedClsPrefixRef:u,mergedThemeRef:f,props:d}=Ke(Re),p=L(()=>{const{common:{cubicBezierEaseInOut:n},self:{fontSize:b,iconSize:h,iconColor:v}}=f.value;return{"--n-bezier":n,"--n-font-size":b,"--n-icon-size":h,"--n-icon-color":v}}),_=t?De("popconfirm-panel",void 0,p,d):void 0;return Object.assign(Object.assign({},xe("Popconfirm")),{mergedClsPrefix:u,cssVars:t?void 0:p,localizedPositiveText:L(()=>i.positiveText||l.value.positiveText),localizedNegativeText:L(()=>i.negativeText||l.value.negativeText),positiveButtonProps:$e(d,"positiveButtonProps"),negativeButtonProps:$e(d,"negativeButtonProps"),handlePositiveClick(n){i.onPositiveClick(n)},handleNegativeClick(n){i.onNegativeClick(n)},themeClass:_==null?void 0:_.themeClass,onRender:_==null?void 0:_.onRender})},render(){var i;const{mergedClsPrefix:l,showIcon:t,$slots:u}=this,f=Ee(u.action,()=>this.negativeText===null&&this.positiveText===null?[]:[this.negativeText!==null&&z(W,Object.assign({size:"small",onClick:this.handleNegativeClick},this.negativeButtonProps),{default:()=>this.localizedNegativeText}),this.positiveText!==null&&z(W,Object.assign({size:"small",type:"primary",onClick:this.handlePositiveClick},this.positiveButtonProps),{default:()=>this.localizedPositiveText})]);return(i=this.onRender)===null||i===void 0||i.call(this),z("div",{class:[`${l}-popconfirm__panel`,this.themeClass],style:this.cssVars},We(u.default,d=>t||d?z("div",{class:`${l}-popconfirm__body`},t?z("div",{class:`${l}-popconfirm__icon`},Ee(u.icon,()=>[z(Je,{clsPrefix:l},{default:()=>z(Ge,null)})])):null,d):null),f?z("div",{class:[`${l}-popconfirm__action`]},f):null)}}),ts=he("popconfirm",[j("body",` - font-size: var(--n-font-size); - display: flex; - align-items: center; - flex-wrap: nowrap; - position: relative; - `,[j("icon",` - display: flex; - font-size: var(--n-icon-size); - color: var(--n-icon-color); - transition: color .3s var(--n-bezier); - margin: 0 8px 0 0; - `)]),j("action",` - display: flex; - justify-content: flex-end; - `,[Be("&:not(:first-child)","margin-top: 8px"),he("button",[Be("&:not(:last-child)","margin-right: 8px;")])])]);const ss=Object.assign(Object.assign(Object.assign({},ue.props),st),{positiveText:String,negativeText:String,showIcon:{type:Boolean,default:!0},trigger:{type:String,default:"click"},positiveButtonProps:Object,negativeButtonProps:Object,onPositiveClick:Function,onNegativeClick:Function});var Se=T({name:"Popconfirm",props:ss,__popover__:!0,setup(i){const{mergedClsPrefixRef:l}=fe(),t=ue("Popconfirm","-popconfirm",ts,Ye,i,l),u=k(null);function f(_){const{onPositiveClick:n,"onUpdate:show":b}=i;Promise.resolve(n?n(_):!0).then(h=>{var v;h!==!1&&((v=u.value)===null||v===void 0||v.setShow(!1),b&&Fe(b,!1))})}function d(_){const{onNegativeClick:n,"onUpdate:show":b}=i;Promise.resolve(n?n(_):!0).then(h=>{var v;h!==!1&&((v=u.value)===null||v===void 0||v.setShow(!1),b&&Fe(b,!1))})}return Ze(Re,{mergedThemeRef:t,mergedClsPrefixRef:l,props:i}),Object.assign(Object.assign({},{setShow(_){var n;(n=u.value)===null||n===void 0||n.setShow(_)},syncPosition(){var _;(_=u.value)===null||_===void 0||_.syncPosition()}}),{mergedTheme:t,popoverInstRef:u,handlePositiveClick:f,handleNegativeClick:d})},render(){const{$slots:i,$props:l,mergedTheme:t}=this;return z(tt,et(l,Pe,{theme:t.peers.Popover,themeOverrides:t.peerOverrides.Popover,internalExtraClass:["popconfirm"],ref:"popoverInstRef"}),{trigger:i.activator||i.trigger,default:()=>{const u=Xe(l,Pe);return z(es,Object.assign(Object.assign({},u),{onPositiveClick:this.handlePositiveClick,onNegativeClick:this.handleNegativeClick}),i)}})}});const os={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},ns=C("path",{d:"M400 480a16 16 0 0 1-10.63-4L256 357.41L122.63 476A16 16 0 0 1 96 464V96a64.07 64.07 0 0 1 64-64h192a64.07 64.07 0 0 1 64 64v368a16 16 0 0 1-16 16z",fill:"currentColor"},null,-1),as=[ns];var is=T({name:"Bookmark",render:function(l,t){return c(),g("svg",os,as)}});const ls={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},us=C("path",{d:"M256 448a32 32 0 0 1-18-5.57c-78.59-53.35-112.62-89.93-131.39-112.8c-40-48.75-59.15-98.8-58.61-153C48.63 114.52 98.46 64 159.08 64c44.08 0 74.61 24.83 92.39 45.51a6 6 0 0 0 9.06 0C278.31 88.81 308.84 64 352.92 64c60.62 0 110.45 50.52 111.08 112.64c.54 54.21-18.63 104.26-58.61 153c-18.77 22.87-52.8 59.45-131.39 112.8a32 32 0 0 1-18 5.56z",fill:"currentColor"},null,-1),rs=[us];var cs=T({name:"Heart",render:function(l,t){return c(),g("svg",ls,rs)}});const ps={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},ds=ot('',1),_s=[ds];var Oe=T({name:"Trash",render:function(l,t){return c(),g("svg",ps,_s)}});const ms={class:"reply-compose-wrap"},vs={class:"reply-switch"},hs={key:0,class:"reply-input-wrap"},fs=E(" \u56DE\u590D "),gs=T({props:{commentId:{default:0},atUserid:{default:0},atUsername:{default:""}},emits:["reload","reset"],setup(i,{expose:l,emit:t}){const u=i,f=k(),d=k(!1),p=k(""),_=k(!1),n=h=>{d.value=h,h?setTimeout(()=>{var v;(v=f.value)==null||v.focus()},10):(_.value=!1,p.value="",t("reset"))},b=()=>{_.value=!0,nt({comment_id:u.commentId,at_user_id:u.atUserid,content:p.value}).then(h=>{n(!1),window.$message.success("\u8BC4\u8BBA\u6210\u529F"),t("reload")}).catch(h=>{_.value=!1})};return l({switchReply:n}),(h,v)=>{const A=at,s=W,B=At;return c(),g("div",ms,[C("div",vs,[d.value?$("",!0):(c(),g("span",{key:0,class:"show",onClick:v[0]||(v[0]=x=>n(!0))}," \u56DE\u590D ")),d.value?(c(),g("span",{key:1,class:"hide",onClick:v[1]||(v[1]=x=>n(!1))}," \u53D6\u6D88 ")):$("",!0)]),d.value?(c(),g("div",hs,[a(B,null,{default:r(()=>[a(A,{ref_key:"inputInstRef",ref:f,size:"small",placeholder:u.atUsername?"@"+u.atUsername:"\u8BF7\u8F93\u5165\u56DE\u590D\u5185\u5BB9..",maxlength:"100",value:p.value,"onUpdate:value":v[2]||(v[2]=x=>p.value=x),"show-count":"",clearable:""},null,8,["placeholder","value"]),a(s,{type:"primary",size:"small",ghost:"",loading:_.value,onClick:b},{default:r(()=>[fs]),_:1},8,["loading"])]),_:1})])):$("",!0)])}}});var ys=oe(gs,[["__scopeId","data-v-3616e66c"]]);const ks={class:"reply-item"},Cs={class:"header-wrap"},bs={class:"username"},ws={class:"reply-name"},xs={class:"timestamp"},$s=E(" \u662F\u5426\u786E\u8BA4\u5220\u9664\uFF1F "),Es={class:"base-wrap"},Bs={class:"content"},Fs={key:0,class:"reply-switch"},Ps=T({props:{reply:null},emits:["focusReply","reload"],setup(i,{emit:l}){const t=i,u=re(),f=()=>{l("focusReply",t.reply)},d=()=>{it({id:t.reply.id}).then(p=>{window.$message.success("\u5220\u9664\u6210\u529F"),setTimeout(()=>{l("reload")},50)}).catch(p=>{console.log(p)})};return(p,_)=>{const n=ge("router-link"),b=ce,h=W,v=Se;return c(),g("div",ks,[C("div",Cs,[C("div",bs,[a(n,{class:"user-link",to:{name:"user",query:{username:t.reply.user.username}}},{default:r(()=>[E(D(t.reply.user.username),1)]),_:1},8,["to"]),C("span",ws,D(t.reply.at_user_id>0?"\u56DE\u590D":":"),1),t.reply.at_user_id>0?(c(),I(n,{key:0,class:"user-link",to:{name:"user",query:{username:t.reply.at_user.username}}},{default:r(()=>[E(D(t.reply.at_user.username),1)]),_:1},8,["to"])):$("",!0)]),C("div",xs,[E(D(t.reply.ip_loc?t.reply.ip_loc+" \xB7 ":t.reply.ip_loc)+" "+D(e(le)(t.reply.created_on))+" ",1),e(u).state.userInfo.is_admin||e(u).state.userInfo.id===t.reply.user.id?(c(),I(v,{key:0,"negative-text":"\u53D6\u6D88","positive-text":"\u786E\u8BA4",onPositiveClick:d},{trigger:r(()=>[a(h,{quaternary:"",circle:"",size:"tiny",class:"del-btn"},{icon:r(()=>[a(b,null,{default:r(()=>[a(e(Oe))]),_:1})]),_:1})]),default:r(()=>[$s]),_:1})):$("",!0)])]),C("div",Es,[C("div",Bs,D(t.reply.content),1),e(u).state.userInfo.id>0?(c(),g("div",Fs,[C("span",{class:"show",onClick:f}," \u56DE\u590D ")])):$("",!0)])])}}});var Ds=oe(Ps,[["__scopeId","data-v-1e3df20d"]]);const As={class:"comment-item"},Is={class:"nickname-wrap"},zs={class:"username-wrap"},Rs={class:"opt-wrap"},Ts={class:"timestamp"},Ss=E(" \u662F\u5426\u786E\u8BA4\u5220\u9664\uFF1F "),Os=["innerHTML"],Us={class:"reply-wrap"},Ns=T({props:{comment:null},emits:["reload"],setup(i,{emit:l}){const t=i,u=re(),f=Ae(),d=k(0),p=k(""),_=k(),n=L(()=>{let B=Object.assign({texts:[],imgs:[]},t.comment);return B.contents.map(x=>{(+x.type==1||+x.type==2)&&B.texts.push(x),+x.type==3&&B.imgs.push(x)}),B}),b=(B,x)=>{let R=B.target;if(R.dataset.detail){const S=R.dataset.detail.split(":");S.length===2&&(u.commit("refresh"),S[0]==="tag"?window.$message.warning("\u8BC4\u8BBA\u5185\u7684\u65E0\u6548\u8BDD\u9898"):f.push({name:"user",query:{username:S[1]}}))}},h=B=>{var x,R;d.value=B.user_id,p.value=((x=B.user)==null?void 0:x.username)||"",(R=_.value)==null||R.switchReply(!0)},v=()=>{l("reload")},A=()=>{d.value=0,p.value=""},s=()=>{ut({id:n.value.id}).then(B=>{window.$message.success("\u5220\u9664\u6210\u529F"),setTimeout(()=>{v()},50)}).catch(B=>{})};return(B,x)=>{const R=ye,S=ge("router-link"),H=ce,K=W,M=Se,G=Ie,Q=Ds,Y=ys,o=ze;return c(),g("div",As,[a(o,{"content-indented":""},lt({avatar:r(()=>[a(R,{round:"",size:30,src:e(n).user.avatar},null,8,["src"])]),header:r(()=>[C("span",Is,[a(S,{onClick:x[0]||(x[0]=J(()=>{},["stop"])),class:"username-link",to:{name:"user",query:{username:e(n).user.username}}},{default:r(()=>[E(D(e(n).user.nickname),1)]),_:1},8,["to"])]),C("span",zs," @"+D(e(n).user.username),1)]),"header-extra":r(()=>[C("div",Rs,[C("span",Ts,D(e(n).ip_loc?e(n).ip_loc+" \xB7 ":e(n).ip_loc)+" "+D(e(le)(e(n).created_on)),1),e(u).state.userInfo.is_admin||e(u).state.userInfo.id===e(n).user.id?(c(),I(M,{key:0,"negative-text":"\u53D6\u6D88","positive-text":"\u786E\u8BA4",onPositiveClick:s},{trigger:r(()=>[a(K,{quaternary:"",circle:"",size:"tiny",class:"del-btn"},{icon:r(()=>[a(H,null,{default:r(()=>[a(e(Oe))]),_:1})]),_:1})]),default:r(()=>[Ss]),_:1})):$("",!0)])]),footer:r(()=>[e(n).imgs.length>0?(c(),I(G,{key:0,imgs:e(n).imgs},null,8,["imgs"])):$("",!0),C("div",Us,[(c(!0),g(se,null,ie(e(n).replies,m=>(c(),I(Q,{key:m.id,reply:m,onFocusReply:h,onReload:v},null,8,["reply"]))),128))]),e(u).state.userInfo.id>0?(c(),I(Y,{key:1,ref_key:"replyComposeRef",ref:_,"comment-id":e(n).id,"at-userid":d.value,"at-username":p.value,onReload:v,onReset:A},null,8,["comment-id","at-userid","at-username"])):$("",!0)]),_:2},[e(n).texts.length>0?{name:"description",fn:r(()=>[(c(!0),g(se,null,ie(e(n).texts,m=>(c(),g("span",{key:m.id,class:"comment-text",onClick:x[1]||(x[1]=J(U=>b(U,e(n).id),["stop"])),innerHTML:e(Ce)(m.content).content},null,8,Os))),128))])}:void 0]),1024)])}}});var js=oe(Ns,[["__scopeId","data-v-6b2cb186"]]);const Ms=i=>(ct("data-v-0702a552"),i=i(),pt(),i),Vs={key:0,class:"compose-wrap"},qs={class:"compose-line"},Ls={class:"compose-user"},Hs={class:"compose-line compose-options"},Ks={class:"attachment"},Ws={class:"submit-wrap"},Js=E(" \u53D6\u6D88 "),Gs=E(" \u53D1\u5E03 "),Qs={class:"attachment-list-wrap"},Ys={key:1,class:"compose-wrap"},Zs=Ms(()=>C("div",{class:"login-wrap"},[C("span",{class:"login-banner"}," \u767B\u5F55\u540E\uFF0C\u7CBE\u5F69\u66F4\u591A")],-1)),Xs={class:"login-wrap"},eo=E(" \u767B\u5F55 "),to=E(" \u6CE8\u518C "),so=T({props:{lock:{default:0},postId:{default:0}},emits:["post-success"],setup(i,{emit:l}){const t=i,u=re(),f=k([]),d=k(!1),p=k(!1),_=k(!1),n=k(""),b=k(),h=k("public/image"),v=k([]),A=k([]),s="/v1/attachment",B=k(),x=Nt.exports.debounce(y=>{rt({k:y}).then(w=>{let F=[];w.map(P=>{F.push({label:P,value:P})}),f.value=F,p.value=!1}).catch(w=>{p.value=!1})},200),R=(y,w)=>{p.value||(p.value=!0,w==="@"&&x(y))},S=y=>{y.length>200||(n.value=y)},H=y=>{h.value=y},K=y=>{v.value=y},M=async y=>{var w,F;return h.value==="public/image"&&!["image/png","image/jpg","image/jpeg","image/gif"].includes((w=y.file.file)==null?void 0:w.type)?(window.$message.warning("\u56FE\u7247\u4EC5\u5141\u8BB8 png/jpg/gif \u683C\u5F0F"),!1):h.value==="image"&&((F=y.file.file)==null?void 0:F.size)>10485760?(window.$message.warning("\u56FE\u7247\u5927\u5C0F\u4E0D\u80FD\u8D85\u8FC710MB"),!1):!0},G=({file:y,event:w})=>{var F;try{let P=JSON.parse((F=w.target)==null?void 0:F.response);P.code===0&&h.value==="public/image"&&A.value.push({id:y.id,content:P.data.content})}catch{window.$message.error("\u4E0A\u4F20\u5931\u8D25")}},Q=({file:y,event:w})=>{var F;try{let P=JSON.parse((F=w.target)==null?void 0:F.response);if(P.code!==0){let V=P.msg||"\u4E0A\u4F20\u5931\u8D25";P.details&&P.details.length>0&&P.details.map(N=>{V+=":"+N}),window.$message.error(V)}}catch{window.$message.error("\u4E0A\u4F20\u5931\u8D25")}},Y=({file:y})=>{let w=A.value.findIndex(F=>F.id===y.id);w>-1&&A.value.splice(w,1)},o=()=>{d.value=!0},m=()=>{var y;d.value=!1,(y=b.value)==null||y.clear(),v.value=[],n.value="",A.value=[]},U=()=>{if(n.value.trim().length===0){window.$message.warning("\u8BF7\u8F93\u5165\u5185\u5BB9\u54E6");return}let{users:y}=Ce(n.value);const w=[];let F=100;w.push({content:n.value,type:2,sort:F}),A.value.map(P=>{F++,w.push({content:P.content,type:3,sort:F})}),_.value=!0,dt({contents:w,post_id:t.postId,users:Array.from(new Set(y))}).then(P=>{window.$message.success("\u53D1\u5E03\u6210\u529F"),_.value=!1,l("post-success"),m()}).catch(P=>{_.value=!1})},ne=y=>{u.commit("triggerAuth",!0),u.commit("triggerAuthKey",y)};return ke(()=>{B.value="Bearer "+localStorage.getItem("PAOPAO_TOKEN")}),(y,w)=>{const F=ye,P=Mt,V=ce,N=W,pe=Vt,de=qt,_e=_t,ae=Lt,me=Ht;return c(),g("div",null,[e(u).state.userInfo.id>0?(c(),g("div",Vs,[C("div",qs,[C("div",Ls,[a(F,{round:"",size:30,src:e(u).state.userInfo.avatar},null,8,["src"])]),a(P,{type:"textarea",size:"large",autosize:"",bordered:!1,options:f.value,prefix:["@"],loading:p.value,value:n.value,disabled:t.lock===1,"onUpdate:value":S,onSearch:R,onFocus:o,placeholder:t.lock===1?"\u6CE1\u6CE1\u5DF2\u88AB\u9501\u5B9A\uFF0C\u56DE\u590D\u529F\u80FD\u5DF2\u5173\u95ED":"\u5FEB\u6765\u8BC4\u8BBA\u4E24\u53E5\u5427..."},null,8,["options","loading","value","disabled","placeholder"])]),d.value?(c(),I(me,{key:0,ref_key:"uploadRef",ref:b,abstract:"","list-type":"image",multiple:!0,max:9,action:s,headers:{Authorization:B.value},data:{type:h.value},onBeforeUpload:M,onFinish:G,onError:Q,onRemove:Y,"onUpdate:fileList":K},{default:r(()=>[C("div",Hs,[C("div",Ks,[a(pe,{abstract:""},{default:r(({handleClick:Z})=>[a(N,{disabled:v.value.length>0&&h.value==="public/video"||v.value.length===9,onClick:()=>{H("public/image"),Z()},quaternary:"",circle:"",type:"primary"},{icon:r(()=>[a(V,{size:"20",color:"var(--primary-color)"},{default:r(()=>[a(e(jt))]),_:1})]),_:2},1032,["disabled","onClick"])]),_:1}),a(_e,{trigger:"hover",placement:"bottom"},{trigger:r(()=>[a(de,{class:"text-statistic",type:"circle","show-indicator":!1,status:"success","stroke-width":10,percentage:n.value.length/200*100},null,8,["percentage"])]),default:r(()=>[E(" "+D(n.value.length)+" / 200 ",1)]),_:1})]),C("div",Ws,[a(N,{quaternary:"",round:"",type:"tertiary",class:"cancel-btn",size:"small",onClick:m},{default:r(()=>[Js]),_:1}),a(N,{loading:_.value,onClick:U,type:"primary",secondary:"",size:"small",round:""},{default:r(()=>[Gs]),_:1},8,["loading"])])]),C("div",Qs,[a(ae)])]),_:1},8,["headers","data"])):$("",!0)])):(c(),g("div",Ys,[Zs,C("div",Xs,[a(N,{strong:"",secondary:"",round:"",type:"primary",onClick:w[0]||(w[0]=Z=>ne("signin"))},{default:r(()=>[eo]),_:1}),a(N,{strong:"",secondary:"",round:"",type:"info",onClick:w[1]||(w[1]=Z=>ne("signup"))},{default:r(()=>[to]),_:1})])]))])}}});var oo=oe(so,[["__scopeId","data-v-0702a552"]]);const no={class:"username-wrap"},ao=E(" \u7F6E\u9876 "),io=E(" \u79C1\u5BC6 "),lo=E(" \u597D\u53CB\u53EF\u89C1 "),uo={key:0,class:"options"},ro={key:0},co=["innerHTML"],po={class:"timestamp"},_o={key:0},mo={key:1},vo={class:"opts-wrap"},ho=["onClick"],fo={class:"opt-item"},go=["onClick"],yo=T({props:{post:null},emits:["reload"],setup(i,{emit:l}){const t=i,u=re(),f=Ae(),d=k(!1),p=k(!1),_=k(!1),n=k(!1),b=k(!1),h=k(!1),v=k(!1),A=k(te.PUBLIC),s=L({get:()=>{let o=Object.assign({texts:[],imgs:[],videos:[],links:[],attachments:[],charge_attachments:[]},t.post);return o.contents.map(m=>{(+m.type==1||+m.type==2)&&o.texts.push(m),+m.type==3&&o.imgs.push(m),+m.type==4&&o.videos.push(m),+m.type==6&&o.links.push(m),+m.type==7&&o.attachments.push(m),+m.type==8&&o.charge_attachments.push(m)}),o},set:o=>{t.post.upvote_count=o.upvote_count,t.post.comment_count=o.comment_count,t.post.collection_count=o.collection_count}}),B=L(()=>{let o=[{label:"\u5220\u9664",key:"delete"}];return s.value.is_lock===0?o.push({label:"\u9501\u5B9A",key:"lock"}):o.push({label:"\u89E3\u9501",key:"unlock"}),u.state.userInfo.is_admin&&(s.value.is_top===0?o.push({label:"\u7F6E\u9876",key:"stick"}):o.push({label:"\u53D6\u6D88\u7F6E\u9876",key:"unstick"})),s.value.visibility===te.PUBLIC?o.push({label:"\u516C\u5F00",key:"vpublic",children:[{label:"\u79C1\u5BC6",key:"vprivate"},{label:"\u597D\u53CB\u53EF\u89C1",key:"vfriend"}]}):s.value.visibility===te.PRIVATE?o.push({label:"\u79C1\u5BC6",key:"vprivate",children:[{label:"\u516C\u5F00",key:"vpublic"},{label:"\u597D\u53CB\u53EF\u89C1",key:"vfriend"}]}):o.push({label:"\u597D\u53CB\u53EF\u89C1",key:"vfriend",children:[{label:"\u516C\u5F00",key:"vpublic"},{label:"\u79C1\u5BC6",key:"vprivate"}]}),o}),x=o=>{f.push({name:"post",query:{id:o}})},R=(o,m)=>{if(o.target.dataset.detail){const U=o.target.dataset.detail.split(":");if(U.length===2){u.commit("refresh"),U[0]==="tag"?f.push({name:"home",query:{q:U[1],t:"tag"}}):f.push({name:"user",query:{username:U[1]}});return}}x(m)},S=o=>{switch(o){case"delete":_.value=!0;break;case"lock":case"unlock":n.value=!0;break;case"stick":case"unstick":b.value=!0;break;case"vpublic":A.value=0,h.value=!0;break;case"vprivate":A.value=1,h.value=!0;break;case"vfriend":A.value=2,h.value=!0;break}},H=()=>{ht({id:s.value.id}).then(o=>{window.$message.success("\u5220\u9664\u6210\u529F"),f.replace("/"),setTimeout(()=>{u.commit("refresh")},50)}).catch(o=>{v.value=!1})},K=()=>{ft({id:s.value.id}).then(o=>{l("reload"),o.lock_status===1?window.$message.success("\u9501\u5B9A\u6210\u529F"):window.$message.success("\u89E3\u9501\u6210\u529F")}).catch(o=>{v.value=!1})},M=()=>{gt({id:s.value.id}).then(o=>{l("reload"),o.top_status===1?window.$message.success("\u7F6E\u9876\u6210\u529F"):window.$message.success("\u53D6\u6D88\u7F6E\u9876\u6210\u529F")}).catch(o=>{v.value=!1})},G=()=>{yt({id:s.value.id,visibility:A.value}).then(o=>{l("reload"),window.$message.success("\u4FEE\u6539\u53EF\u89C1\u6027\u6210\u529F")}).catch(o=>{v.value=!1})},Q=()=>{kt({id:s.value.id}).then(o=>{d.value=o.status,o.status?s.value=ee(X({},s.value),{upvote_count:s.value.upvote_count+1}):s.value=ee(X({},s.value),{upvote_count:s.value.upvote_count-1})}).catch(o=>{console.log(o)})},Y=()=>{Ct({id:s.value.id}).then(o=>{p.value=o.status,o.status?s.value=ee(X({},s.value),{collection_count:s.value.collection_count+1}):s.value=ee(X({},s.value),{collection_count:s.value.collection_count-1})}).catch(o=>{console.log(o)})};return ke(()=>{u.state.userInfo.id>0&&(mt({id:s.value.id}).then(o=>{d.value=o.status}).catch(o=>{console.log(o)}),vt({id:s.value.id}).then(o=>{p.value=o.status}).catch(o=>{console.log(o)}))}),(o,m)=>{const U=ye,ne=ge("router-link"),y=bt,w=ce,F=W,P=wt,V=xt,N=Tt,pe=Ie,de=St,_e=Ot,ae=Xt,me=$t,Z=ze;return c(),g("div",{class:"detail-item",onClick:m[6]||(m[6]=O=>x(e(s).id))},[a(Z,null,{avatar:r(()=>[a(U,{round:"",size:30,src:e(s).user.avatar},null,8,["src"])]),header:r(()=>[a(ne,{onClick:m[0]||(m[0]=J(()=>{},["stop"])),class:"username-link",to:{name:"user",query:{username:e(s).user.username}}},{default:r(()=>[E(D(e(s).user.nickname),1)]),_:1},8,["to"]),C("span",no," @"+D(e(s).user.username),1),e(s).is_top?(c(),I(y,{key:0,class:"top-tag",type:"warning",size:"small",round:""},{default:r(()=>[ao]),_:1})):$("",!0),e(s).visibility==e(te).PRIVATE?(c(),I(y,{key:1,class:"top-tag",type:"error",size:"small",round:""},{default:r(()=>[io]),_:1})):$("",!0),e(s).visibility==e(te).FRIEND?(c(),I(y,{key:2,class:"top-tag",type:"info",size:"small",round:""},{default:r(()=>[lo]),_:1})):$("",!0)]),"header-extra":r(()=>[e(u).state.userInfo.is_admin||e(u).state.userInfo.id===e(s).user.id?(c(),g("div",uo,[a(P,{placement:"bottom-end",trigger:"click",size:"small",options:e(B),onSelect:S},{default:r(()=>[a(F,{quaternary:"",circle:""},{icon:r(()=>[a(w,null,{default:r(()=>[a(e(Kt))]),_:1})]),_:1})]),_:1},8,["options"])])):$("",!0),a(V,{show:_.value,"onUpdate:show":m[1]||(m[1]=O=>_.value=O),"mask-closable":!1,preset:"dialog",title:"\u63D0\u793A",content:"\u786E\u5B9A\u5220\u9664\u8BE5\u6CE1\u6CE1\u52A8\u6001\u5417\uFF1F","positive-text":"\u786E\u8BA4","negative-text":"\u53D6\u6D88",onPositiveClick:H},null,8,["show"]),a(V,{show:n.value,"onUpdate:show":m[2]||(m[2]=O=>n.value=O),"mask-closable":!1,preset:"dialog",title:"\u63D0\u793A",content:"\u786E\u5B9A"+(e(s).is_lock?"\u89E3\u9501":"\u9501\u5B9A")+"\u8BE5\u6CE1\u6CE1\u52A8\u6001\u5417\uFF1F","positive-text":"\u786E\u8BA4","negative-text":"\u53D6\u6D88",onPositiveClick:K},null,8,["show","content"]),a(V,{show:b.value,"onUpdate:show":m[3]||(m[3]=O=>b.value=O),"mask-closable":!1,preset:"dialog",title:"\u63D0\u793A",content:"\u786E\u5B9A"+(e(s).is_top?"\u53D6\u6D88\u7F6E\u9876":"\u7F6E\u9876")+"\u8BE5\u6CE1\u6CE1\u52A8\u6001\u5417\uFF1F","positive-text":"\u786E\u8BA4","negative-text":"\u53D6\u6D88",onPositiveClick:M},null,8,["show","content"]),a(V,{show:h.value,"onUpdate:show":m[4]||(m[4]=O=>h.value=O),"mask-closable":!1,preset:"dialog",title:"\u63D0\u793A",content:"\u786E\u5B9A\u5C06\u8BE5\u6CE1\u6CE1\u52A8\u6001\u53EF\u89C1\u5EA6\u4FEE\u6539\u4E3A"+(A.value==0?"\u516C\u5F00":A.value==1?"\u79C1\u5BC6":"\u597D\u53CB\u53EF\u89C1")+"\u5417\uFF1F","positive-text":"\u786E\u8BA4","negative-text":"\u53D6\u6D88",onPositiveClick:G},null,8,["show","content"])]),footer:r(()=>[a(N,{attachments:e(s).attachments},null,8,["attachments"]),a(N,{attachments:e(s).charge_attachments,price:e(s).attachment_price},null,8,["attachments","price"]),a(pe,{imgs:e(s).imgs},null,8,["imgs"]),a(de,{videos:e(s).videos,full:!0},null,8,["videos"]),a(_e,{links:e(s).links},null,8,["links"]),C("div",po,[E(" \u53D1\u5E03\u4E8E "+D(e(le)(e(s).created_on))+" ",1),e(s).ip_loc?(c(),g("span",_o,[a(ae,{vertical:""}),E(" "+D(e(s).ip_loc),1)])):$("",!0),e(s).created_on!=e(s).latest_replied_on?(c(),g("span",mo,[a(ae,{vertical:""}),E(" \u6700\u540E\u56DE\u590D "+D(e(le)(e(s).latest_replied_on)),1)])):$("",!0)])]),action:r(()=>[C("div",vo,[a(me,{justify:"space-between"},{default:r(()=>[C("div",{class:"opt-item hover",onClick:J(Q,["stop"])},[a(w,{size:"20",class:"opt-item-icon"},{default:r(()=>[d.value?$("",!0):(c(),I(e(It),{key:0})),d.value?(c(),I(e(cs),{key:1,color:"red"})):$("",!0)]),_:1}),E(" "+D(e(s).upvote_count),1)],8,ho),C("div",fo,[a(w,{size:"20",class:"opt-item-icon"},{default:r(()=>[a(e(zt))]),_:1}),E(" "+D(e(s).comment_count),1)]),C("div",{class:"opt-item hover",onClick:J(Y,["stop"])},[a(w,{size:"20",class:"opt-item-icon"},{default:r(()=>[p.value?$("",!0):(c(),I(e(Rt),{key:0})),p.value?(c(),I(e(is),{key:1,color:"#ff7600"})):$("",!0)]),_:1}),E(" "+D(e(s).collection_count),1)],8,go)]),_:1})])]),default:r(()=>[e(s).texts.length>0?(c(),g("div",ro,[(c(!0),g(se,null,ie(e(s).texts,O=>(c(),g("span",{key:O.id,class:"post-text",onClick:m[5]||(m[5]=J(Ue=>R(Ue,e(s).id),["stop"])),innerHTML:e(Ce)(O.content).content},null,8,co))),128))])):$("",!0)]),_:1})])}}});const ko={key:0,class:"detail-wrap"},Co={key:1,class:"empty-wrap"},bo={key:1},wo={key:0,class:"skeleton-wrap"},xo={key:1},$o={key:0,class:"empty-wrap"},Eo=T({setup(i){const l=Et(),t=k({}),u=k(!1),f=k(!1),d=k([]),p=L(()=>+l.query.id),_=()=>{t.value={id:0},u.value=!0,Ft({id:p.value}).then(b=>{u.value=!1,t.value=b,n()}).catch(b=>{u.value=!1})},n=(b=!1)=>{d.value.length===0&&(f.value=!0),Pt({id:t.value.id}).then(h=>{d.value=h.list,f.value=!1,b&&setTimeout(()=>{window.scrollTo(0,99999)},50)}).catch(h=>{f.value=!1})};return ke(()=>{_()}),Bt(p,()=>{p.value>0&&l.name==="post"&&_()}),(b,h)=>{const v=Wt,A=yo,s=Gt,B=Dt,x=Qt,R=oo,S=Ut,H=js,K=Jt;return c(),g("div",null,[a(v,{title:"\u6CE1\u6CE1\u8BE6\u60C5",back:!0}),a(K,{class:"main-content-wrap",bordered:""},{default:r(()=>[a(x,null,{default:r(()=>[a(B,{show:u.value},{default:r(()=>[t.value.id>1?(c(),g("div",ko,[a(A,{post:t.value,onReload:_},null,8,["post"])])):(c(),g("div",Co,[a(s,{size:"large",description:"\u6682\u65E0\u6570\u636E"})]))]),_:1},8,["show"])]),_:1}),t.value.id>0?(c(),I(x,{key:0},{default:r(()=>[a(R,{lock:t.value.is_lock,"post-id":t.value.id,onPostSuccess:h[0]||(h[0]=M=>n(!0))},null,8,["lock","post-id"])]),_:1})):$("",!0),t.value.id>0?(c(),g("div",bo,[f.value?(c(),g("div",wo,[a(S,{num:5})])):(c(),g("div",xo,[d.value.length===0?(c(),g("div",$o,[a(s,{size:"large",description:"\u6682\u65E0\u8BC4\u8BBA\uFF0C\u5FEB\u6765\u62A2\u6C99\u53D1"})])):$("",!0),(c(!0),g(se,null,ie(d.value,M=>(c(),I(x,{key:M.id},{default:r(()=>[a(H,{comment:M,onReload:n},null,8,["comment"])]),_:2},1024))),128))]))])):$("",!0)]),_:1})])}}});var jo=oe(Eo,[["__scopeId","data-v-41747510"]]);export{jo as default}; diff --git a/web/dist/assets/Profile.75de1930.js b/web/dist/assets/Profile.75de1930.js deleted file mode 100644 index bab88572..00000000 --- a/web/dist/assets/Profile.75de1930.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as N}from"./post-item.03452002.js";import{_ as S}from"./post-skeleton.39a35f5b.js";import{_ as U}from"./main-nav.9110259b.js";import{ah as D,d as M,Z as R,ai as $,r as c,a1 as q,V as e,W as o,a3 as t,a2 as _,a5 as h,a4 as r,a6 as d,c4 as F,Y as s,a9 as f,aa as L,ab as T,ad as W,c1 as Y,c2 as Z}from"./index.f480f018.js";import{_ as j}from"./List.49bcdf81.js";import{_ as A}from"./Pagination.1263479e.js";import{a as G,_ as H}from"./Skeleton.57e98fe3.js";import"./content.ef1e095a.js";import"./formatTime.02109bf5.js";import"./Thing.eef6b133.js";const J={class:"profile-baseinfo"},K={class:"avatar"},O={class:"base-info"},Q={class:"username"},X={class:"uid"},ee={key:0,class:"pagination-wrap"},te={key:0,class:"skeleton-wrap"},ae={key:1},se={key:0,class:"empty-wrap"},ne=M({setup(oe){const a=R(),k=$(),l=c(!1),u=c([]),i=c(+k.query.p||1),p=c(20),m=c(0),v=()=>{l.value=!0,F({username:a.state.userInfo.username,page:i.value,page_size:p.value}).then(n=>{l.value=!1,u.value=n.list,m.value=Math.ceil(n.pager.total_rows/p.value),window.scrollTo(0,0)}).catch(n=>{l.value=!1})},y=n=>{i.value=n,v()};return q(()=>{v()}),(n,_e)=>{const w=U,b=W,I=A,E=Y,P=Z,x=S,B=G,C=N,z=H,V=j;return e(),o("div",null,[t(w,{title:"\u4E3B\u9875"}),_(a).state.userInfo.id>0?(e(),h(V,{key:0,class:"main-content-wrap profile-wrap",bordered:""},{footer:r(()=>[m.value>1?(e(),o("div",ee,[t(I,{page:i.value,"onUpdate:page":y,"page-slot":_(a).state.collapsedRight?5:8,"page-count":m.value},null,8,["page","page-slot","page-count"])])):d("",!0)]),default:r(()=>[s("div",J,[s("div",K,[t(b,{size:"large",src:_(a).state.userInfo.avatar},null,8,["src"])]),s("div",O,[s("div",Q,[s("strong",null,f(_(a).state.userInfo.nickname),1),s("span",null," @"+f(_(a).state.userInfo.username),1)]),s("div",X,"UID. "+f(_(a).state.userInfo.id),1)])]),t(P,{class:"profile-tabs-wrap",animated:""},{default:r(()=>[t(E,{name:"post",tab:"\u6CE1\u6CE1"})]),_:1}),l.value?(e(),o("div",te,[t(x,{num:p.value},null,8,["num"])])):(e(),o("div",ae,[u.value.length===0?(e(),o("div",se,[t(B,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):d("",!0),(e(!0),o(L,null,T(u.value,g=>(e(),h(z,{key:g.id},{default:r(()=>[t(C,{post:g},null,8,["post"])]),_:2},1024))),128))]))]),_:1})):d("",!0)])}}});var ge=D(ne,[["__scopeId","data-v-2fe5c266"]]);export{ge as default}; diff --git a/web/dist/assets/Setting.837d491b.js b/web/dist/assets/Setting.837d491b.js deleted file mode 100644 index 6f5e8ac7..00000000 --- a/web/dist/assets/Setting.837d491b.js +++ /dev/null @@ -1 +0,0 @@ -var ye=Object.defineProperty,ke=Object.defineProperties;var be=Object.getOwnPropertyDescriptors;var te=Object.getOwnPropertySymbols;var Ee=Object.prototype.hasOwnProperty,Ae=Object.prototype.propertyIsEnumerable;var ae=(_,v,g)=>v in _?ye(_,v,{enumerable:!0,configurable:!0,writable:!0,value:g}):_[v]=g,V=(_,v)=>{for(var g in v||(v={}))Ee.call(v,g)&&ae(_,g,v[g]);if(te)for(var g of te(v))Ae.call(v,g)&&ae(_,g,v[g]);return _},j=(_,v)=>ke(_,be(v));import{_ as Ie}from"./main-nav.9110259b.js";import{d as oe,V as r,W as h,Y as d,ah as $e,r as c,Z as Pe,ca as se,a1 as Ue,ae as xe,a3 as u,a4 as s,a5 as k,a6 as f,cw as ne,az as Re,a2 as t,a9 as U,aY as Se,aZ as qe,a8 as p,bj as x,a7 as R,bM as ze,bN as Ne,cx as Ke,cy as Me,cz as Ve,cA as je,cB as Te,cC as Le,ad as Oe,J as We,_ as Ge,cD as Je,cE as Ye,cF as Ze,cG as He}from"./index.f480f018.js";import{c as Qe}from"./Upload.efe3adfd.js";import{_ as Xe}from"./Alert.a854329b.js";import{_ as eu}from"./InputGroup.f69c4956.js";const uu={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},tu=d("g",{fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[d("path",{d:"M9 7H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-3"}),d("path",{d:"M9 15h3l8.5-8.5a1.5 1.5 0 0 0-3-3L9 12v3"}),d("path",{d:"M16 5l3 3"})],-1),au=[tu];var su=oe({name:"Edit",render:function(v,g){return r(),h("svg",uu,au)}});const T=_=>(ze("data-v-6eb93a4d"),_=_(),Ne(),_),nu={class:"base-line avatar"},ou=p("\u66F4\u6539\u5934\u50CF"),lu={class:"base-line"},ru=T(()=>d("span",{class:"base-label"},"\u6635\u79F0",-1)),iu={key:0},du={class:"base-line"},cu=T(()=>d("span",{class:"base-label"},"\u7528\u6237\u540D",-1)),pu={key:0},_u=p(" \u6362\u7ED1\u624B\u673A "),vu={key:1},mu=p(" \u6210\u529F\u7ED1\u5B9A\u624B\u673A\u540E\uFF0C\u624D\u80FD\u8FDB\u884C\u6362\u5934\u50CF\u3001\u53D1\u52A8\u6001\u3001\u56DE\u590D\u7B49\u4EA4\u4E92~"),fu=T(()=>d("br",null,null,-1)),hu={key:2,class:"phone-bind-wrap"},gu={class:"captcha-img-wrap"},Fu={class:"captcha-img"},Cu=["src"],wu={class:"form-submit-wrap"},Bu=p(" \u53D6\u6D88 "),Du=p(" \u7ED1\u5B9A "),yu={key:0},ku=p(" \u91CD\u65B0\u6FC0\u6D3B "),bu={key:1},Eu=p(" \u6210\u529F\u6FC0\u6D3B\u540E\u540E\uFF0C\u624D\u80FD\u53D1\uFF08\u516C\u5F00/\u597D\u53CB\u53EF\u89C1\uFF09\u52A8\u6001\u3001\u56DE\u590D~"),Au=T(()=>d("br",null,null,-1)),Iu={key:2,class:"phone-bind-wrap"},$u={class:"captcha-img-wrap"},Pu={class:"captcha-img"},Uu=["src"],xu={class:"form-submit-wrap"},Ru=p(" \u53D6\u6D88 "),Su=p(" \u6FC0\u6D3B "),qu=p(" \u60A8\u5DF2\u8BBE\u7F6E\u5BC6\u7801 "),zu=p(" \u91CD\u7F6E\u5BC6\u7801 "),Nu={key:1,class:"phone-bind-wrap"},Ku={class:"form-submit-wrap"},Mu=p(" \u53D6\u6D88 "),Vu=p(" \u66F4\u65B0 "),ju=oe({setup(_){const v="/v1/attachment",g="Bearer "+localStorage.getItem("PAOPAO_TOKEN"),S=c("public/avatar"),A="true".toLowerCase()==="true",le="false".toLowerCase()==="true",o=Pe(),I=c(!1),q=c(!1),z=c(!1),Y=c(),Z=c(),b=c(!1),N=c(!1),$=c(!1),P=c(!1),E=c(60),D=c(!1),y=c(!1),H=c(),Q=c(),X=c(),ee=c(),a=se({id:"",b64s:"",imgCaptcha:"",phone:"",phone_captcha:"",password:"",old_password:"",reenteredPassword:""}),i=se({id:"",b64s:"",imgCaptcha:"",activate_code:""}),re=async n=>{var e,F;return S.value==="public/avatar"&&!["image/png","image/jpg","image/jpeg"].includes((e=n.file.file)==null?void 0:e.type)?(window.$message.warning("\u5934\u50CF\u4EC5\u5141\u8BB8 png/jpg \u683C\u5F0F"),!1):S.value==="image"&&((F=n.file.file)==null?void 0:F.size)>1048576?(window.$message.warning("\u5934\u50CF\u5927\u5C0F\u4E0D\u80FD\u8D85\u8FC71MB"),!1):!0},ie=({file:n,event:e})=>{var F;try{let C=JSON.parse((F=e.target)==null?void 0:F.response);C.code===0&&S.value==="public/avatar"&&Ke({avatar:C.data.content}).then(m=>{var K;window.$message.success("\u5934\u50CF\u66F4\u65B0\u6210\u529F"),(K=Y.value)==null||K.clear(),o.commit("updateUserinfo",j(V({},o.state.userInfo),{avatar:C.data.content}))}).catch(m=>{console.log(m)})}catch{window.$message.error("\u4E0A\u4F20\u5931\u8D25")}},de=(n,e)=>!!a.password&&a.password.startsWith(e)&&a.password.length>=e.length,ce=(n,e)=>e===a.password,pe=()=>{var n;a.reenteredPassword&&((n=ee.value)==null||n.validate({trigger:"password-input"}))},_e=n=>{var e;n.preventDefault(),(e=X.value)==null||e.validate(F=>{F||(N.value=!0,Me({password:a.password,old_password:a.old_password}).then(C=>{N.value=!1,$.value=!1,window.$message.success("\u5BC6\u7801\u91CD\u7F6E\u6210\u529F"),o.commit("userLogout"),o.commit("triggerAuth",!0),o.commit("triggerAuthKey","signin")}).catch(C=>{N.value=!1}))})},ve=n=>{var e;n.preventDefault(),(e=H.value)==null||e.validate(F=>{F||(q.value=!0,Ve({phone:a.phone,captcha:a.phone_captcha}).then(C=>{q.value=!1,D.value=!1,window.$message.success("\u7ED1\u5B9A\u6210\u529F"),o.commit("updateUserinfo",j(V({},o.state.userInfo),{phone:a.phone})),a.id="",a.b64s="",a.imgCaptcha="",a.phone="",a.phone_captcha=""}).catch(C=>{q.value=!1}))})},me=n=>{var e;n.preventDefault(),(e=Q.value)==null||e.validate(F=>{if(i.imgCaptcha===""){window.$message.warning("\u8BF7\u8F93\u5165\u56FE\u7247\u9A8C\u8BC1\u7801");return}I.value=!0,F||(z.value=!0,je({activate_code:i.activate_code,captcha_id:i.id,imgCaptcha:i.imgCaptcha}).then(C=>{z.value=!1,y.value=!1,window.$message.success("\u6FC0\u6D3B\u6210\u529F"),o.commit("updateUserinfo",j(V({},o.state.userInfo),{activation:i.activate_code})),i.id="",i.b64s="",i.imgCaptcha="",i.activate_code=""}).catch(C=>{z.value=!1,C.code===20012&&O()}))})},L=()=>{ne().then(n=>{a.id=n.id,a.b64s=n.b64s}).catch(n=>{console.log(n)})},O=()=>{ne().then(n=>{i.id=n.id,i.b64s=n.b64s}).catch(n=>{console.log(n)})},fe=()=>{Te({nickname:o.state.userInfo.nickname||""}).then(n=>{b.value=!1,window.$message.success("\u6635\u79F0\u4FEE\u6539\u6210\u529F")}).catch(n=>{b.value=!0})},he=()=>{if(!(E.value>0&&P.value)){if(a.imgCaptcha===""){window.$message.warning("\u8BF7\u8F93\u5165\u56FE\u7247\u9A8C\u8BC1\u7801");return}I.value=!0,Le({phone:a.phone,img_captcha:a.imgCaptcha,img_captcha_id:a.id}).then(n=>{P.value=!0,I.value=!1,window.$message.success("\u53D1\u9001\u6210\u529F");let e=setInterval(()=>{E.value--,E.value===0&&(clearInterval(e),E.value=60,P.value=!1)},1e3)}).catch(n=>{I.value=!1,n.code===20012&&L(),console.log(n)})}},ge={phone:[{required:!0,message:"\u8BF7\u8F93\u5165\u624B\u673A\u53F7",trigger:["input"],validator:(n,e)=>/^[1]+[3-9]{1}\d{9}$/.test(e)}],phone_captcha:[{required:!0,message:"\u8BF7\u8F93\u5165\u624B\u673A\u9A8C\u8BC1\u7801"}]},Fe={activate_code:[{required:!0,message:"\u8BF7\u8F93\u5165\u6FC0\u6D3B\u7801",trigger:["input"],validator:(n,e)=>/\d{6}$/.test(e)}]},Ce={password:[{required:!0,message:"\u8BF7\u8F93\u5165\u65B0\u5BC6\u7801"}],old_password:[{required:!0,message:"\u8BF7\u8F93\u5165\u65E7\u5BC6\u7801"}],reenteredPassword:[{required:!0,message:"\u8BF7\u518D\u6B21\u8F93\u5165\u5BC6\u7801",trigger:["input","blur"]},{validator:de,message:"\u4E24\u6B21\u5BC6\u7801\u8F93\u5165\u4E0D\u4E00\u81F4",trigger:"input"},{validator:ce,message:"\u4E24\u6B21\u5BC6\u7801\u8F93\u5165\u4E0D\u4E00\u81F4",trigger:["blur","password-input"]}]},we=()=>{b.value=!0,setTimeout(()=>{var n;(n=Z.value)==null||n.focus()},30)};return Ue(()=>{o.state.userInfo.id===0&&(o.commit("triggerAuth",!0),o.commit("triggerAuthKey","signin")),L(),O()}),(n,e)=>{const F=Ie,C=Oe,m=We,K=Qe,w=Ge,Be=xe,M=Re,ue=Xe,B=Je,De=eu,W=Ye,G=Ze,J=He;return r(),h("div",null,[u(F,{title:"\u8BBE\u7F6E",theme:""}),u(M,{title:"\u57FA\u672C\u4FE1\u606F",size:"small",class:"setting-card"},{default:s(()=>[d("div",nu,[u(C,{class:"avatar-img",size:80,src:t(o).state.userInfo.avatar},null,8,["src"]),!A||A&&t(o).state.userInfo.phone&&t(o).state.userInfo.phone.length>0?(r(),k(K,{key:0,ref_key:"avatarRef",ref:Y,action:v,headers:{Authorization:g},data:{type:S.value},onBeforeUpload:re,onFinish:ie},{default:s(()=>[u(m,{size:"small"},{default:s(()=>[ou]),_:1})]),_:1},8,["headers","data"])):f("",!0)]),d("div",lu,[ru,b.value?f("",!0):(r(),h("div",iu,U(t(o).state.userInfo.nickname),1)),Se(u(w,{ref_key:"inputInstRef",ref:Z,class:"nickname-input",value:t(o).state.userInfo.nickname,"onUpdate:value":e[0]||(e[0]=l=>t(o).state.userInfo.nickname=l),type:"text",size:"small",placeholder:"\u8BF7\u8F93\u5165\u6635\u79F0",onBlur:fe,maxlength:16},null,8,["value"]),[[qe,b.value]]),!b.value&&(!A||A&&t(o).state.userInfo.phone&&t(o).state.userInfo.phone.length>0&&t(o).state.userInfo.status==1)?(r(),k(m,{key:1,quaternary:"",round:"",type:"success",size:"small",onClick:we},{icon:s(()=>[u(Be,null,{default:s(()=>[u(t(su))]),_:1})]),_:1})):f("",!0)]),d("div",du,[cu,p(" @"+U(t(o).state.userInfo.username),1)])]),_:1}),A?(r(),k(M,{key:0,title:"\u624B\u673A\u53F7",size:"small",class:"setting-card"},{default:s(()=>[t(o).state.userInfo.phone&&t(o).state.userInfo.phone.length>0?(r(),h("div",pu,[p(U(t(o).state.userInfo.phone)+" ",1),!D.value&&t(o).state.userInfo.status==1?(r(),k(m,{key:0,quaternary:"",round:"",type:"success",onClick:e[1]||(e[1]=l=>D.value=!0)},{default:s(()=>[_u]),_:1})):f("",!0)])):(r(),h("div",vu,[u(ue,{title:"\u624B\u673A\u7ED1\u5B9A\u63D0\u793A",type:"warning"},{default:s(()=>[mu,fu,D.value?f("",!0):(r(),h("a",{key:0,class:"hash-link",onClick:e[2]||(e[2]=l=>D.value=!0)}," \u7ACB\u5373\u7ED1\u5B9A "))]),_:1})])),D.value?(r(),h("div",hu,[u(J,{ref_key:"phoneFormRef",ref:H,model:t(a),rules:ge},{default:s(()=>[u(B,{path:"phone",label:"\u624B\u673A\u53F7"},{default:s(()=>[u(w,{value:t(a).phone,"onUpdate:value":e[3]||(e[3]=l=>t(a).phone=l.trim()),placeholder:"\u8BF7\u8F93\u5165\u4E2D\u56FD\u5927\u9646\u624B\u673A\u53F7",onKeydown:e[4]||(e[4]=x(R(()=>{},["prevent"]),["enter"]))},null,8,["value"])]),_:1}),u(B,{path:"img_captcha",label:"\u56FE\u5F62\u9A8C\u8BC1\u7801"},{default:s(()=>[d("div",gu,[u(w,{value:t(a).imgCaptcha,"onUpdate:value":e[5]||(e[5]=l=>t(a).imgCaptcha=l),placeholder:"\u8BF7\u8F93\u5165\u56FE\u5F62\u9A8C\u8BC1\u7801\u540E\u83B7\u53D6\u9A8C\u8BC1\u7801"},null,8,["value"]),d("div",Fu,[t(a).b64s?(r(),h("img",{key:0,src:t(a).b64s,onClick:L},null,8,Cu)):f("",!0)])])]),_:1}),u(B,{path:"phone_captcha",label:"\u77ED\u4FE1\u9A8C\u8BC1\u7801"},{default:s(()=>[u(De,null,{default:s(()=>[u(w,{value:t(a).phone_captcha,"onUpdate:value":e[6]||(e[6]=l=>t(a).phone_captcha=l),placeholder:"\u8BF7\u8F93\u5165\u6536\u5230\u7684\u77ED\u4FE1\u9A8C\u8BC1\u7801"},null,8,["value"]),u(m,{type:"primary",ghost:"",disabled:P.value,loading:I.value,onClick:he},{default:s(()=>[p(U(E.value>0&&P.value?E.value+"s\u540E\u91CD\u65B0\u53D1\u9001":"\u53D1\u9001\u9A8C\u8BC1\u7801"),1)]),_:1},8,["disabled","loading"])]),_:1})]),_:1}),u(G,{gutter:[0,24]},{default:s(()=>[u(W,{span:24},{default:s(()=>[d("div",wu,[u(m,{quaternary:"",round:"",onClick:e[7]||(e[7]=l=>D.value=!1)},{default:s(()=>[Bu]),_:1}),u(m,{secondary:"",round:"",type:"primary",loading:q.value,onClick:ve},{default:s(()=>[Du]),_:1},8,["loading"])])]),_:1})]),_:1})]),_:1},8,["model"])])):f("",!0)]),_:1})):f("",!0),le?(r(),k(M,{key:1,title:"\u6FC0\u6D3B\u7801",size:"small",class:"setting-card"},{default:s(()=>[t(o).state.userInfo.activation&&t(o).state.userInfo.activation.length>0?(r(),h("div",yu,[p(U(t(o).state.userInfo.activation)+" ",1),y.value?f("",!0):(r(),k(m,{key:0,quaternary:"",round:"",type:"success",onClick:e[8]||(e[8]=l=>y.value=!0)},{default:s(()=>[ku]),_:1}))])):(r(),h("div",bu,[u(ue,{title:"\u6FC0\u6D3B\u7801\u6FC0\u6D3B\u63D0\u793A",type:"warning"},{default:s(()=>[Eu,Au,y.value?f("",!0):(r(),h("a",{key:0,class:"hash-link",onClick:e[9]||(e[9]=l=>y.value=!0)}," \u7ACB\u5373\u6FC0\u6D3B "))]),_:1})])),y.value?(r(),h("div",Iu,[u(J,{ref_key:"activateFormRef",ref:Q,model:t(i),rules:Fe},{default:s(()=>[u(B,{path:"activate_code",label:"\u6FC0\u6D3B\u7801"},{default:s(()=>[u(w,{value:t(i).activate_code,"onUpdate:value":e[10]||(e[10]=l=>t(i).activate_code=l.trim()),placeholder:"\u8BF7\u8F93\u5165\u6FC0\u6D3B\u7801",onKeydown:e[11]||(e[11]=x(R(()=>{},["prevent"]),["enter"]))},null,8,["value"])]),_:1}),u(B,{path:"img_captcha",label:"\u56FE\u5F62\u9A8C\u8BC1\u7801"},{default:s(()=>[d("div",$u,[u(w,{value:t(i).imgCaptcha,"onUpdate:value":e[12]||(e[12]=l=>t(i).imgCaptcha=l),placeholder:"\u8BF7\u8F93\u5165\u56FE\u5F62\u9A8C\u8BC1\u7801\u540E\u83B7\u53D6\u9A8C\u8BC1\u7801"},null,8,["value"]),d("div",Pu,[t(i).b64s?(r(),h("img",{key:0,src:t(i).b64s,onClick:O},null,8,Uu)):f("",!0)])])]),_:1}),u(G,{gutter:[0,24]},{default:s(()=>[u(W,{span:24},{default:s(()=>[d("div",xu,[u(m,{quaternary:"",round:"",onClick:e[13]||(e[13]=l=>y.value=!1)},{default:s(()=>[Ru]),_:1}),u(m,{secondary:"",round:"",type:"primary",loading:z.value,onClick:me},{default:s(()=>[Su]),_:1},8,["loading"])])]),_:1})]),_:1})]),_:1},8,["model"])])):f("",!0)]),_:1})):f("",!0),u(M,{title:"\u8D26\u6237\u5B89\u5168",size:"small",class:"setting-card"},{default:s(()=>[qu,$.value?f("",!0):(r(),k(m,{key:0,quaternary:"",round:"",type:"success",onClick:e[14]||(e[14]=l=>$.value=!0)},{default:s(()=>[zu]),_:1})),$.value?(r(),h("div",Nu,[u(J,{ref_key:"formRef",ref:X,model:t(a),rules:Ce},{default:s(()=>[u(B,{path:"old_password",label:"\u65E7\u5BC6\u7801"},{default:s(()=>[u(w,{value:t(a).old_password,"onUpdate:value":e[15]||(e[15]=l=>t(a).old_password=l),type:"password",placeholder:"\u8BF7\u8F93\u5165\u5F53\u524D\u5BC6\u7801",onKeydown:e[16]||(e[16]=x(R(()=>{},["prevent"]),["enter"]))},null,8,["value"])]),_:1}),u(B,{path:"password",label:"\u65B0\u5BC6\u7801"},{default:s(()=>[u(w,{value:t(a).password,"onUpdate:value":e[17]||(e[17]=l=>t(a).password=l),type:"password",placeholder:"\u8BF7\u8F93\u5165\u65B0\u5BC6\u7801",onInput:pe,onKeydown:e[18]||(e[18]=x(R(()=>{},["prevent"]),["enter"]))},null,8,["value"])]),_:1}),u(B,{ref_key:"rPasswordFormItemRef",ref:ee,first:"",path:"reenteredPassword",label:"\u91CD\u590D\u5BC6\u7801"},{default:s(()=>[u(w,{value:t(a).reenteredPassword,"onUpdate:value":e[19]||(e[19]=l=>t(a).reenteredPassword=l),disabled:!t(a).password,type:"password",placeholder:"\u8BF7\u518D\u6B21\u8F93\u5165\u5BC6\u7801",onKeydown:e[20]||(e[20]=x(R(()=>{},["prevent"]),["enter"]))},null,8,["value","disabled"])]),_:1},512),u(G,{gutter:[0,24]},{default:s(()=>[u(W,{span:24},{default:s(()=>[d("div",Ku,[u(m,{quaternary:"",round:"",onClick:e[21]||(e[21]=l=>$.value=!1)},{default:s(()=>[Mu]),_:1}),u(m,{secondary:"",round:"",type:"primary",loading:N.value,onClick:_e},{default:s(()=>[Vu]),_:1},8,["loading"])])]),_:1})]),_:1})]),_:1},8,["model"])])):f("",!0)]),_:1})])}}});var Yu=$e(ju,[["__scopeId","data-v-6eb93a4d"]]);export{Yu as default}; diff --git a/web/dist/assets/Skeleton.57e98fe3.js b/web/dist/assets/Skeleton.57e98fe3.js deleted file mode 100644 index b1c2be91..00000000 --- a/web/dist/assets/Skeleton.57e98fe3.js +++ /dev/null @@ -1,135 +0,0 @@ -import{d as O,h as a,aD as Oe,aE as Be,a1 as ce,b1 as Fe,s as w,r as F,j as q,av as Y,au as D,b2 as ue,b3 as te,aH as J,b4 as Le,l as M,m as L,n as U,u as fe,q as K,b5 as $e,I as Ee,i as Z,b6 as He,v as H,y as ve,N as he,b7 as Q,aX as Ve,aJ as me,o as A,p as je,aO as Ae,t as B,b8 as De,b9 as Ke,S as ne,aF as Ge,ba as oe,A as ie,bb as We,z as qe,ay as Ue,bc as Ze,K as Xe,bd as Je,a$ as le,be as Ye,c as Qe,aa as et}from"./index.f480f018.js";import{l as tt}from"./List.49bcdf81.js";let re=!1;function nt(){if(typeof window!="undefined"&&!!window.CSS&&!re&&(re=!0,"registerProperty"in(window==null?void 0:window.CSS)))try{CSS.registerProperty({name:"--n-color-start",syntax:"",inherits:!1,initialValue:"#0000"}),CSS.registerProperty({name:"--n-color-end",syntax:"",inherits:!1,initialValue:"#0000"})}catch{}}var ot=O({name:"Checkmark",render(){return a("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 16 16"},a("g",{fill:"none"},a("path",{d:"M14.046 3.486a.75.75 0 0 1-.032 1.06l-7.93 7.474a.85.85 0 0 1-1.188-.022l-2.68-2.72a.75.75 0 1 1 1.068-1.053l2.234 2.267l7.468-7.038a.75.75 0 0 1 1.06.032z",fill:"currentColor"})))}}),it=O({name:"Empty",render(){return a("svg",{viewBox:"0 0 28 28",fill:"none",xmlns:"http://www.w3.org/2000/svg"},a("path",{d:"M26 7.5C26 11.0899 23.0899 14 19.5 14C15.9101 14 13 11.0899 13 7.5C13 3.91015 15.9101 1 19.5 1C23.0899 1 26 3.91015 26 7.5ZM16.8536 4.14645C16.6583 3.95118 16.3417 3.95118 16.1464 4.14645C15.9512 4.34171 15.9512 4.65829 16.1464 4.85355L18.7929 7.5L16.1464 10.1464C15.9512 10.3417 15.9512 10.6583 16.1464 10.8536C16.3417 11.0488 16.6583 11.0488 16.8536 10.8536L19.5 8.20711L22.1464 10.8536C22.3417 11.0488 22.6583 11.0488 22.8536 10.8536C23.0488 10.6583 23.0488 10.3417 22.8536 10.1464L20.2071 7.5L22.8536 4.85355C23.0488 4.65829 23.0488 4.34171 22.8536 4.14645C22.6583 3.95118 22.3417 3.95118 22.1464 4.14645L19.5 6.79289L16.8536 4.14645Z",fill:"currentColor"}),a("path",{d:"M25 22.75V12.5991C24.5572 13.0765 24.053 13.4961 23.5 13.8454V16H17.5L17.3982 16.0068C17.0322 16.0565 16.75 16.3703 16.75 16.75C16.75 18.2688 15.5188 19.5 14 19.5C12.4812 19.5 11.25 18.2688 11.25 16.75L11.2432 16.6482C11.1935 16.2822 10.8797 16 10.5 16H4.5V7.25C4.5 6.2835 5.2835 5.5 6.25 5.5H12.2696C12.4146 4.97463 12.6153 4.47237 12.865 4H6.25C4.45507 4 3 5.45507 3 7.25V22.75C3 24.5449 4.45507 26 6.25 26H21.75C23.5449 26 25 24.5449 25 22.75ZM4.5 22.75V17.5H9.81597L9.85751 17.7041C10.2905 19.5919 11.9808 21 14 21L14.215 20.9947C16.2095 20.8953 17.842 19.4209 18.184 17.5H23.5V22.75C23.5 23.7165 22.7165 24.5 21.75 24.5H6.25C5.2835 24.5 4.5 23.7165 4.5 22.75Z",fill:"currentColor"}))}}),lt=O({props:{onFocus:Function,onBlur:Function},setup(e){return()=>a("div",{style:"width: 0; height: 0",tabindex:0,onFocus:e.onFocus,onBlur:e.onBlur})}});function se(e){return e&-e}class rt{constructor(t,o){this.l=t,this.min=o;const i=new Array(t+1);for(let r=0;rr)throw new Error("[FinweckTree.sum]: `i` is larger than length.");let d=t*i;for(;t>0;)d+=o[t],t-=se(t);return d}getBound(t){let o=0,i=this.l;for(;i>o;){const r=Math.floor((o+i)/2),d=this.sum(r);if(d>t){i=r;continue}else if(d[]},itemSize:{type:Number,required:!0},itemResizable:Boolean,itemsStyle:[String,Object],visibleItemsTag:{type:[String,Object],default:"div"},visibleItemsProps:Object,ignoreItemResize:Boolean,onScroll:Function,onWheel:Function,onResize:Function,defaultScrollKey:[Number,String],defaultScrollIndex:Number,keyField:{type:String,default:"key"},paddingTop:{type:[Number,String],default:0},paddingBottom:{type:[Number,String],default:0}},setup(e){const t=Oe();st.mount({id:"vueuc/virtual-list",head:!0,anchorMetaName:Be,ssr:t}),ce(()=>{const{defaultScrollIndex:s,defaultScrollKey:c}=e;s!=null?m({index:s}):c!=null&&m({key:c})}),Fe(()=>{m({top:k.value})});const o=w(()=>{const s=new Map,{keyField:c}=e;return e.items.forEach((R,S)=>{s.set(R[c],S)}),s}),i=F(null),r=F(void 0),d=new Map,u=w(()=>{const{items:s,itemSize:c,keyField:R}=e,S=new rt(s.length,c);return s.forEach((C,z)=>{const b=C[R],_=d.get(b);_!==void 0&&S.add(z,_)}),S}),h=F(0),k=F(0),f=q(()=>Math.max(u.value.getBound(k.value-Y(e.paddingTop))-1,0)),v=w(()=>{const{value:s}=r;if(s===void 0)return[];const{items:c,itemSize:R}=e,S=f.value,C=Math.min(S+Math.ceil(s/R+1),c.length-1),z=[];for(let b=S;b<=C;++b)z.push(c[b]);return z}),m=s=>{const{left:c,top:R,index:S,key:C,position:z,behavior:b,debounce:_=!0}=s;if(c!==void 0||R!==void 0)g(c,R,b);else if(S!==void 0)y(S,b,_);else if(C!==void 0){const V=o.value.get(C);V!==void 0&&y(V,b,_)}else z==="bottom"?g(0,Number.MAX_SAFE_INTEGER,b):z==="top"&&g(0,0,b)};function y(s,c,R){const{value:S}=u,C=S.sum(s)+Y(e.paddingTop);if(!R)i.value.scrollTo({left:0,top:C,behavior:c});else{const{scrollTop:z,offsetHeight:b}=i.value;if(C>z){const _=S.get(s);C+_<=z+b||i.value.scrollTo({left:0,top:C+_-b,behavior:c})}else i.value.scrollTo({left:0,top:C,behavior:c})}I=s}function g(s,c,R){i.value.scrollTo({left:s,top:c,behavior:R})}function p(s,c){var R,S,C,z;if(e.ignoreItemResize||E(c.target))return;const{value:b}=u,_=o.value.get(s),V=b.get(_),j=(C=(S=(R=c.borderBoxSize)===null||R===void 0?void 0:R[0])===null||S===void 0?void 0:S.blockSize)!==null&&C!==void 0?C:c.contentRect.height;if(j===V)return;j-e.itemSize===0?d.delete(s):d.set(s,j-e.itemSize);const P=j-V;P!==0&&($!==void 0&&_<=$&&((z=i.value)===null||z===void 0||z.scrollBy(0,P)),b.add(_,P),h.value++)}function x(s){Le(G);const{onScroll:c}=e;c!==void 0&&c(s)}function N(s){if(E(s.target)||s.contentRect.height===r.value)return;r.value=s.contentRect.height;const{onResize:c}=e;c!==void 0&&c(s)}let I,$;function G(){const{value:s}=i;s!=null&&($=I!=null?I:f.value,I=void 0,k.value=i.value.scrollTop)}function E(s){let c=s;for(;c!==null;){if(c.style.display==="none")return!0;c=c.parentElement}return!1}return{listHeight:r,listStyle:{overflow:"auto"},keyToIndex:o,itemsStyle:w(()=>{const{itemResizable:s}=e,c=D(u.value.sum());return h.value,[e.itemsStyle,{boxSizing:"content-box",height:s?"":c,minHeight:s?c:"",paddingTop:D(e.paddingTop),paddingBottom:D(e.paddingBottom)}]}),visibleItemsStyle:w(()=>(h.value,{transform:`translateY(${D(u.value.sum(f.value))})`})),viewportItems:v,listElRef:i,itemsElRef:F(null),scrollTo:m,handleListResize:N,handleListScroll:x,handleItemResize:p}},render(){const{itemResizable:e,keyField:t,keyToIndex:o,visibleItemsTag:i}=this;return a(te,{onResize:this.handleListResize},{default:()=>{var r,d;return a("div",ue(this.$attrs,{class:["v-vl",this.showScrollbar&&"v-vl--show-scrollbar"],onScroll:this.handleListScroll,onWheel:this.onWheel,ref:"listElRef"}),[this.items.length!==0?a("div",{ref:"itemsElRef",class:"v-vl-items",style:this.itemsStyle},[a(i,Object.assign({class:"v-vl-visible-items",style:this.visibleItemsStyle},this.visibleItemsProps),{default:()=>this.viewportItems.map(u=>{const h=u[t],k=o.get(h),f=this.$slots.default({item:u,index:k})[0];return e?a(te,{key:h,onResize:v=>this.handleItemResize(h,v)},{default:()=>f}):(f.key=h,f)})})]):(d=(r=this.$slots).empty)===null||d===void 0?void 0:d.call(r)])}})}}),dt=M("empty",` - display: flex; - flex-direction: column; - align-items: center; - font-size: var(--n-font-size); -`,[L("icon",` - width: var(--n-icon-size); - height: var(--n-icon-size); - font-size: var(--n-icon-size); - line-height: var(--n-icon-size); - color: var(--n-icon-color); - transition: - color .3s var(--n-bezier); - `,[U("+",[L("description",` - margin-top: 8px; - `)])]),L("description",` - transition: color .3s var(--n-bezier); - color: var(--n-text-color); - `),L("extra",` - text-align: center; - transition: color .3s var(--n-bezier); - margin-top: 12px; - color: var(--n-extra-text-color); - `)]);const ct=Object.assign(Object.assign({},K.props),{description:String,showDescription:{type:Boolean,default:!0},showIcon:{type:Boolean,default:!0},size:{type:String,default:"medium"},renderIcon:Function});var ut=O({name:"Empty",props:ct,setup(e){const{mergedClsPrefixRef:t,inlineThemeDisabled:o}=fe(e),i=K("Empty","-empty",dt,$e,e,t),{localeRef:r}=Ee("Empty"),d=Z(He,null),u=w(()=>{var v,m,y;return(v=e.description)!==null&&v!==void 0?v:(y=(m=d==null?void 0:d.mergedComponentPropsRef.value)===null||m===void 0?void 0:m.Empty)===null||y===void 0?void 0:y.description}),h=w(()=>{var v,m;return((m=(v=d==null?void 0:d.mergedComponentPropsRef.value)===null||v===void 0?void 0:v.Empty)===null||m===void 0?void 0:m.renderIcon)||(()=>a(it,null))}),k=w(()=>{const{size:v}=e,{common:{cubicBezierEaseInOut:m},self:{[H("iconSize",v)]:y,[H("fontSize",v)]:g,textColor:p,iconColor:x,extraTextColor:N}}=i.value;return{"--n-icon-size":y,"--n-font-size":g,"--n-bezier":m,"--n-text-color":p,"--n-icon-color":x,"--n-extra-text-color":N}}),f=o?ve("empty",w(()=>{let v="";const{size:m}=e;return v+=m[0],v}),k,e):void 0;return{mergedClsPrefix:t,mergedRenderIcon:h,localizedDescription:w(()=>u.value||r.value.description),cssVars:o?void 0:k,themeClass:f==null?void 0:f.themeClass,onRender:f==null?void 0:f.onRender}},render(){const{$slots:e,mergedClsPrefix:t,onRender:o}=this;return o==null||o(),a("div",{class:[`${t}-empty`,this.themeClass],style:this.cssVars},this.showIcon?a("div",{class:`${t}-empty__icon`},e.icon?e.icon():a(he,{clsPrefix:t},{default:this.mergedRenderIcon})):null,this.showDescription?a("div",{class:`${t}-empty__description`},e.default?e.default():this.localizedDescription):null,e.extra?a("div",{class:`${t}-empty__extra`},e.extra()):null)}});const ft=a(ot);function vt(e,t){return a(Ve,{name:"fade-in-scale-up-transition"},{default:()=>e?a(he,{clsPrefix:t,class:`${t}-base-select-option__check`},{default:()=>ft}):null})}var ae=O({name:"NBaseSelectOption",props:{clsPrefix:{type:String,required:!0},tmNode:{type:Object,required:!0}},setup(e){const{valueRef:t,pendingTmNodeRef:o,multipleRef:i,valueSetRef:r,renderLabelRef:d,renderOptionRef:u,handleOptionClick:h,handleOptionMouseEnter:k}=Z(Q),f=q(()=>{const{value:g}=o;return g?e.tmNode.key===g.key:!1});function v(g){const{tmNode:p}=e;p.disabled||h(g,p)}function m(g){const{tmNode:p}=e;p.disabled||k(g,p)}function y(g){const{tmNode:p}=e,{value:x}=f;p.disabled||x||k(g,p)}return{multiple:i,isGrouped:q(()=>{const{tmNode:g}=e,{parent:p}=g;return p&&p.rawNode.type==="group"}),isPending:f,isSelected:q(()=>{const{value:g}=t,{value:p}=i;if(g===null)return!1;const x=e.tmNode.rawNode.value;if(p){const{value:N}=r;return N.has(x)}else return g===x}),renderLabel:d,renderOption:u,handleMouseMove:y,handleMouseEnter:m,handleClick:v}},render(){const{clsPrefix:e,tmNode:{rawNode:t},isSelected:o,isPending:i,isGrouped:r,multiple:d,renderOption:u,renderLabel:h,handleClick:k,handleMouseEnter:f,handleMouseMove:v}=this,y=vt(d&&o,e),g=h?[h(t,o),y]:[me(t.label,t,o),y],p=a("div",{class:[`${e}-base-select-option`,t.class,{[`${e}-base-select-option--disabled`]:t.disabled,[`${e}-base-select-option--selected`]:o,[`${e}-base-select-option--grouped`]:r,[`${e}-base-select-option--pending`]:i}],style:t.style,onClick:k,onMouseenter:f,onMousemove:v},a("div",{class:`${e}-base-select-option__content`},g));return t.render?t.render({node:p,option:t,selected:o}):u?u({node:p,option:t,selected:o}):p}}),de=O({name:"NBaseSelectGroupHeader",props:{clsPrefix:{type:String,required:!0},tmNode:{type:Object,required:!0}},setup(){const{renderLabelRef:e,renderOptionRef:t}=Z(Q);return{renderLabel:e,renderOption:t}},render(){const{clsPrefix:e,renderLabel:t,renderOption:o,tmNode:{rawNode:i}}=this,r=t?t(i,!1):me(i.label,i,!1),d=a("div",{class:`${e}-base-select-group-header`},r);return i.render?i.render({node:d,option:i}):o?o({node:d,option:i,selected:!1}):d}}),ht=M("base-select-menu",` - line-height: 1.5; - outline: none; - z-index: 0; - position: relative; - border-radius: var(--n-border-radius); - transition: - background-color .3s var(--n-bezier), - box-shadow .3s var(--n-bezier); - background-color: var(--n-color); -`,[A("multiple",[M("base-select-option",` - padding-right: 28px; - `)]),M("scrollbar",` - max-height: var(--n-height); - `),M("virtual-list",` - max-height: var(--n-height); - `),M("base-select-option",` - min-height: var(--n-option-height); - font-size: var(--n-option-font-size); - display: flex; - align-items: center; - `,[L("content",` - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - `)]),M("base-select-group-header",` - min-height: var(--n-option-height); - font-size: .93em; - display: flex; - align-items: center; - `),M("base-select-menu-option-wrapper",` - position: relative; - width: 100%; - `),L("loading, empty",` - display: flex; - padding: 12px 32px; - flex: 1; - justify-content: center; - `),L("loading",` - color: var(--n-loading-color); - font-size: var(--n-loading-size); - `),L("action",` - padding: 8px var(--n-option-padding-left); - font-size: var(--n-option-font-size); - transition: - color .3s var(--n-bezier); - border-color .3s var(--n-bezier); - border-top: 1px solid var(--n-action-divider-color); - color: var(--n-action-text-color); - `),M("base-select-group-header",` - position: relative; - cursor: default; - padding: var(--n-option-padding); - color: var(--n-group-header-text-color); - `),M("base-select-option",` - cursor: pointer; - position: relative; - padding: var(--n-option-padding); - transition: - background-color .3s var(--n-bezier), - color .3s var(--n-bezier), - opacity .3s var(--n-bezier); - box-sizing: border-box; - color: var(--n-option-text-color); - opacity: 1; - `,[U("&:active",` - color: var(--n-option-text-color-pressed); - `),A("grouped",` - padding-left: calc(var(--n-option-padding-left) * 1.5); - `),A("pending",` - background-color: var(--n-option-color-pending); - `),A("selected",` - color: var(--n-option-text-color-active); - background-color: var(--n-option-color-active); - `),A("disabled",` - cursor: not-allowed; - `,[je("selected",` - color: var(--n-option-text-color-disabled); - `),A("selected",` - opacity: var(--n-option-opacity-disabled); - `)]),L("check",` - font-size: 16px; - position: absolute; - right: 8px; - top: calc(50% - 7px); - color: var(--n-option-check-color); - transition: color .3s var(--n-bezier); - `,[Ae({enterScale:"0.5"})])])]),St=O({name:"InternalSelectMenu",props:Object.assign(Object.assign({},K.props),{clsPrefix:{type:String,required:!0},scrollable:{type:Boolean,default:!0},treeMate:{type:Object,required:!0},multiple:Boolean,size:{type:String,default:"medium"},value:{type:[String,Number,Array],default:null},width:[Number,String],autoPending:Boolean,virtualScroll:{type:Boolean,default:!0},show:{type:Boolean,default:!0},loading:Boolean,focusable:Boolean,renderLabel:Function,renderOption:Function,onMousedown:Function,onScroll:Function,onFocus:Function,onBlur:Function,onKeyup:Function,onKeydown:Function,onTabOut:Function,onMouseenter:Function,onMouseleave:Function,resetMenuOnOptionsChange:{type:Boolean,default:!0},inlineThemeDisabled:Boolean,onToggle:Function}),setup(e){const t=K("InternalSelectMenu","-internal-select-menu",ht,De,e,B(e,"clsPrefix")),o=F(null),i=F(null),r=F(null),d=w(()=>e.treeMate.getFlattenedNodes()),u=w(()=>Ke(d.value)),h=F(null);function k(){const{treeMate:n}=e;let l=null;if(e.autoPending){const{value:T}=e;T===null?l=n.getFirstAvailableNode():(e.multiple?l=n.getNode((T||[])[(T||[]).length-1]):l=n.getNode(T),(!l||l.disabled)&&(l=n.getFirstAvailableNode())),l&&z(l)}}let f;ne(B(e,"show"),n=>{n?f=ne(e.resetMenuOnOptionsChange?[B(e,"treeMate"),B(e,"multiple")]:[B(e,"multiple")],()=>{k(),Ge(b)},{immediate:!0}):f==null||f()},{immediate:!0});const v=w(()=>Y(t.value.self[H("optionHeight",e.size)])),m=w(()=>oe(t.value.self[H("padding",e.size)])),y=w(()=>e.multiple&&Array.isArray(e.value)?new Set(e.value):new Set),g=w(()=>{const n=d.value;return n&&n.length===0});function p(n){const{onToggle:l}=e;l&&l(n)}function x(n){const{onScroll:l}=e;l&&l(n)}function N(n){var l;(l=r.value)===null||l===void 0||l.sync(),x(n)}function I(){var n;(n=r.value)===null||n===void 0||n.sync()}function $(){const{value:n}=h;return n||null}function G(n,l){l.disabled||z(l,!1)}function E(n,l){l.disabled||p(l)}function s(n){var l;le(n,"action")||(l=e.onKeyup)===null||l===void 0||l.call(e,n)}function c(n){var l;le(n,"action")||(l=e.onKeydown)===null||l===void 0||l.call(e,n)}function R(n){var l;(l=e.onMousedown)===null||l===void 0||l.call(e,n),!e.focusable&&n.preventDefault()}function S(){const{value:n}=h;n&&z(n.getNext({loop:!0}),!0)}function C(){const{value:n}=h;n&&z(n.getPrev({loop:!0}),!0)}function z(n,l=!1){h.value=n,l&&b()}function b(){var n,l;const T=h.value;if(!T)return;const W=u.value(T.key);W!==null&&(e.virtualScroll?(n=i.value)===null||n===void 0||n.scrollTo({index:W}):(l=r.value)===null||l===void 0||l.scrollTo({index:W,elSize:v.value}))}function _(n){var l,T;!((l=o.value)===null||l===void 0)&&l.contains(n.target)&&((T=e.onFocus)===null||T===void 0||T.call(e,n))}function V(n){var l,T;!((l=o.value)===null||l===void 0)&&l.contains(n.relatedTarget)||(T=e.onBlur)===null||T===void 0||T.call(e,n)}ie(Q,{handleOptionMouseEnter:G,handleOptionClick:E,valueSetRef:y,multipleRef:B(e,"multiple"),valueRef:B(e,"value"),renderLabelRef:B(e,"renderLabel"),renderOptionRef:B(e,"renderOption"),pendingTmNodeRef:h}),ie(We,o),ce(()=>{const{value:n}=r;n&&n.sync()});const j=w(()=>{const{size:n}=e,{common:{cubicBezierEaseInOut:l},self:{height:T,borderRadius:W,color:pe,groupHeaderTextColor:be,actionDividerColor:ye,optionTextColorPressed:xe,optionTextColor:Se,optionTextColorDisabled:ze,optionTextColorActive:we,optionOpacityDisabled:Re,optionCheckColor:Ce,actionTextColor:ke,optionColorPending:Te,optionColorActive:_e,loadingColor:Ne,loadingSize:Me,[H("optionFontSize",n)]:Ie,[H("optionHeight",n)]:Pe,[H("optionPadding",n)]:ee}}=t.value;return{"--n-height":T,"--n-action-divider-color":ye,"--n-action-text-color":ke,"--n-bezier":l,"--n-border-radius":W,"--n-color":pe,"--n-option-font-size":Ie,"--n-group-header-text-color":be,"--n-option-check-color":Ce,"--n-option-color-pending":Te,"--n-option-color-active":_e,"--n-option-height":Pe,"--n-option-opacity-disabled":Re,"--n-option-text-color":Se,"--n-option-text-color-active":we,"--n-option-text-color-disabled":ze,"--n-option-text-color-pressed":xe,"--n-option-padding":ee,"--n-option-padding-left":oe(ee,"left"),"--n-loading-color":Ne,"--n-loading-size":Me}}),{inlineThemeDisabled:X}=e,P=X?ve("internal-select-menu",w(()=>e.size[0]),j,e):void 0,ge={selfRef:o,next:S,prev:C,getPendingTmNode:$};return Object.assign({mergedTheme:t,virtualListRef:i,scrollbarRef:r,itemSize:v,padding:m,flattenedNodes:d,empty:g,virtualListContainer(){const{value:n}=i;return n==null?void 0:n.listElRef},virtualListContent(){const{value:n}=i;return n==null?void 0:n.itemsElRef},doScroll:x,handleFocusin:_,handleFocusout:V,handleKeyUp:s,handleKeyDown:c,handleMouseDown:R,handleVirtualListResize:I,handleVirtualListScroll:N,cssVars:X?void 0:j,themeClass:P==null?void 0:P.themeClass,onRender:P==null?void 0:P.onRender},ge)},render(){const{$slots:e,virtualScroll:t,clsPrefix:o,mergedTheme:i,themeClass:r,onRender:d}=this;return d==null||d(),a("div",{ref:"selfRef",tabindex:this.focusable?0:-1,class:[`${o}-base-select-menu`,r,this.multiple&&`${o}-base-select-menu--multiple`],style:[{width:Je(this.width)},this.cssVars],onFocusin:this.handleFocusin,onFocusout:this.handleFocusout,onKeyup:this.handleKeyUp,onKeydown:this.handleKeyDown,onMousedown:this.handleMouseDown,onMouseenter:this.onMouseenter,onMouseleave:this.onMouseleave},this.loading?a("div",{class:`${o}-base-select-menu__loading`},a(Ue,{clsPrefix:o,strokeWidth:20})):this.empty?a("div",{class:`${o}-base-select-menu__empty`},Xe(e.empty,()=>[a(ut,{theme:i.peers.Empty,themeOverrides:i.peerOverrides.Empty})])):a(Ze,{ref:"scrollbarRef",theme:i.peers.Scrollbar,themeOverrides:i.peerOverrides.Scrollbar,scrollable:this.scrollable,container:t?this.virtualListContainer:void 0,content:t?this.virtualListContent:void 0,onScroll:t?void 0:this.doScroll},{default:()=>t?a(at,{ref:"virtualListRef",class:`${o}-virtual-list`,items:this.flattenedNodes,itemSize:this.itemSize,showScrollbar:!1,paddingTop:this.padding.top,paddingBottom:this.padding.bottom,onResize:this.handleVirtualListResize,onScroll:this.handleVirtualListScroll,itemResizable:!0},{default:({item:u})=>u.isGroup?a(de,{key:u.key,clsPrefix:o,tmNode:u}):u.ignored?null:a(ae,{clsPrefix:o,key:u.key,tmNode:u})}):a("div",{class:`${o}-base-select-menu-option-wrapper`,style:{paddingTop:this.padding.top,paddingBottom:this.padding.bottom}},this.flattenedNodes.map(u=>u.isGroup?a(de,{key:u.key,clsPrefix:o,tmNode:u}):a(ae,{clsPrefix:o,key:u.key,tmNode:u})))}),qe(e.action,u=>u&&[a("div",{class:`${o}-base-select-menu__action`,"data-action":!0,key:"action"},u),a(lt,{onFocus:this.onTabOut,key:"focus-detector"})]))}}),zt=O({name:"ListItem",setup(){const e=Z(tt,null);return e||Ye("list-item","`n-list-item` must be placed in `n-list`."),{mergedClsPrefix:e.mergedClsPrefixRef}},render(){const{$slots:e,mergedClsPrefix:t}=this;return a("li",{class:`${t}-list-item`},e.prefix?a("div",{class:`${t}-list-item__prefix`},e.prefix()):null,e.default?a("div",{class:`${t}-list-item__main`},e):null,e.suffix?a("div",{class:`${t}-list-item__suffix`},e.suffix()):null)}});const mt=e=>{const{heightSmall:t,heightMedium:o,heightLarge:i,borderRadius:r}=e;return{color:"#eee",colorEnd:"#ddd",borderRadius:r,heightSmall:t,heightMedium:o,heightLarge:i}},gt={name:"Skeleton",common:Qe,self:mt};var pt=U([M("skeleton",` - height: 1em; - width: 100%; - transition: background-color .3s var(--n-bezier); - transition: - --n-color-start .3s var(--n-bezier), - --n-color-end .3s var(--n-bezier), - background-color .3s var(--n-bezier); - animation: 2s skeleton-loading infinite cubic-bezier(0.36, 0, 0.64, 1); - background-color: var(--n-color-start); - `),U("@keyframes skeleton-loading",` - 0% { - background: var(--n-color-start); - } - 40% { - background: var(--n-color-end); - } - 80% { - background: var(--n-color-start); - } - 100% { - background: var(--n-color-start); - } - `)]);const bt=Object.assign(Object.assign({},K.props),{text:Boolean,round:Boolean,circle:Boolean,height:[String,Number],width:[String,Number],size:String,repeat:{type:Number,default:1},animated:{type:Boolean,default:!0},sharp:{type:Boolean,default:!0}});var wt=O({name:"Skeleton",inheritAttrs:!1,props:bt,setup(e){nt();const{mergedClsPrefixRef:t}=fe(e),o=K("Skeleton","-skeleton",pt,gt,e,t);return{mergedClsPrefix:t,style:w(()=>{var i,r;const d=o.value,{common:{cubicBezierEaseInOut:u}}=d,h=d.self,{color:k,colorEnd:f,borderRadius:v}=h;let m;const{circle:y,sharp:g,round:p,width:x,height:N,size:I,text:$,animated:G}=e;I!==void 0&&(m=h[H("height",I)]);const E=y?(i=x!=null?x:N)!==null&&i!==void 0?i:m:x,s=(r=y&&x!=null?x:N)!==null&&r!==void 0?r:m;return{display:$?"inline-block":"",verticalAlign:$?"-0.125em":"",borderRadius:y?"50%":p?"4096px":g?"":v,width:typeof E=="number"?D(E):E,height:typeof s=="number"?D(s):s,animation:G?"":"none","--n-bezier":u,"--n-color-start":k,"--n-color-end":f}})}},render(){const{repeat:e,style:t,mergedClsPrefix:o,$attrs:i}=this,r=a("div",ue({class:`${o}-skeleton`,style:t},i));return e>1?a(et,null,Array.apply(null,{length:e}).map(d=>[r,` -`])):r}});export{St as N,zt as _,ut as a,wt as b,nt as u}; diff --git a/web/dist/assets/Thing.eef6b133.js b/web/dist/assets/Thing.eef6b133.js deleted file mode 100644 index 9a4ec7d5..00000000 --- a/web/dist/assets/Thing.eef6b133.js +++ /dev/null @@ -1,34 +0,0 @@ -import{l as r,m as l,n as c,d as _,u as s,q as v,bq as $,s as b,y as w,h as i,aa as E}from"./index.f480f018.js";var z=r("thing",` - display: flex; - transition: color .3s var(--n-bezier); - font-size: var(--n-font-size); - color: var(--n-text-color); -`,[r("thing-avatar",` - margin-right: 12px; - margin-top: 2px; - `),r("thing-avatar-header-wrapper",` - display: flex; - flex-wrap: nowrap; - `,[r("thing-header-wrapper",` - flex: 1; - `)]),r("thing-main",` - flex-grow: 1; - `,[r("thing-header",` - display: flex; - margin-bottom: 4px; - justify-content: space-between; - align-items: center; - `,[l("title",` - font-size: 16px; - font-weight: var(--n-title-font-weight); - transition: color .3s var(--n-bezier); - color: var(--n-title-text-color); - `)]),l("description",[c("&:not(:last-child)",` - margin-bottom: 4px; - `)]),l("content",[c("&:not(:first-child)",` - margin-top: 12px; - `)]),l("footer",[c("&:not(:first-child)",` - margin-top: 12px; - `)]),l("action",[c("&:not(:first-child)",` - margin-top: 12px; - `)])])]);const C=Object.assign(Object.assign({},v.props),{title:String,titleExtra:String,description:String,content:String,contentIndented:{type:Boolean,default:!1}});var T=_({name:"Thing",props:C,setup(t,{slots:e}){const{mergedClsPrefixRef:h,inlineThemeDisabled:g}=s(t),x=v("Thing","-thing",z,$,t,h),o=b(()=>{const{self:{titleTextColor:d,textColor:n,titleFontWeight:u,fontSize:f},common:{cubicBezierEaseInOut:m}}=x.value;return{"--n-bezier":m,"--n-font-size":f,"--n-text-color":n,"--n-title-font-weight":u,"--n-title-text-color":d}}),a=g?w("thing",void 0,o,t):void 0;return()=>{var d;const{value:n}=h;return(d=a==null?void 0:a.onRender)===null||d===void 0||d.call(a),i("div",{class:[`${n}-thing`,a==null?void 0:a.themeClass],style:g?void 0:o.value},e.avatar&&t.contentIndented?i("div",{class:`${n}-thing-avatar`},e.avatar()):null,i("div",{class:`${n}-thing-main`},!t.contentIndented&&(e.header||t.title||e["header-extra"]||t.titleExtra||e.avatar)?i("div",{class:`${n}-thing-avatar-header-wrapper`},e.avatar?i("div",{class:`${n}-thing-avatar`},e.avatar()):null,e.header||t.title||e["header-extra"]||t.titleExtra?i("div",{class:`${n}-thing-header-wrapper`},i("div",{class:`${n}-thing-header`},e.header||t.title?i("div",{class:`${n}-thing-header__title`},e.header?e.header():t.title):null,e["header-extra"]||t.titleExtra?i("div",{class:`${n}-thing-header__extra`},e["header-extra"]?e["header-extra"]():t.titleExtra):null),e.description||t.description?i("div",{class:`${n}-thing-main__description`},e.description?e.description():t.description):null):null):i(E,null,e.header||t.title||e["header-extra"]||t.titleExtra?i("div",{class:`${n}-thing-header`},e.header||t.title?i("div",{class:`${n}-thing-header__title`},e.header?e.header():t.title):null,e["header-extra"]||t.titleExtra?i("div",{class:`${n}-thing-header__extra`},e["header-extra"]?e["header-extra"]():t.titleExtra):null):null,e.description||t.description?i("div",{class:`${n}-thing-main__description`},e.description?e.description():t.description):null),e.default||t.content?i("div",{class:`${n}-thing-main__content`},e.default?e.default():t.content):null,e.footer?i("div",{class:`${n}-thing-main__footer`},e.footer()):null,e.action?i("div",{class:`${n}-thing-main__action`},e.action()):null))}}});export{T as _}; diff --git a/web/dist/assets/Topic.9a2ef7f9.css b/web/dist/assets/Topic.9a2ef7f9.css deleted file mode 100644 index 989189ad..00000000 --- a/web/dist/assets/Topic.9a2ef7f9.css +++ /dev/null @@ -1 +0,0 @@ -.tags-wrap[data-v-ec1d2778]{padding:20px}.tags-wrap .tag-item .tag-hot[data-v-ec1d2778]{margin-left:12px;font-size:12px;opacity:.75} diff --git a/web/dist/assets/Topic.c6bdf01d.js b/web/dist/assets/Topic.c6bdf01d.js deleted file mode 100644 index d4a28c39..00000000 --- a/web/dist/assets/Topic.c6bdf01d.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as T}from"./main-nav.9110259b.js";import{ah as w,d as x,r as s,a1 as B,al as D,V as _,W as r,a3 as a,a4 as n,c0 as V,aa as q,ab as C,c1 as E,c2 as N,ag as F,b_ as I,a5 as L,a8 as M,a9 as m,Y as S,ad as U,an as W}from"./index.f480f018.js";import{_ as Y}from"./List.49bcdf81.js";const $={class:"tag-hot"},j=x({setup(z){const c=s([]),u=s("hot"),o=s(!1),l=()=>{o.value=!0,V({type:u.value,num:50}).then(e=>{c.value=e,o.value=!1}).catch(e=>{o.value=!1})},i=e=>{u.value=e,l()};return B(()=>{l()}),(e,A)=>{const d=T,p=E,g=N,v=D("router-link"),f=U,h=W,y=F,b=I,k=Y;return _(),r("div",null,[a(d,{title:"\u8BDD\u9898"}),a(k,{class:"main-content-wrap tags-wrap",bordered:""},{default:n(()=>[a(g,{type:"line",animated:"","onUpdate:value":i},{default:n(()=>[a(p,{name:"hot",tab:"\u70ED\u95E8"}),a(p,{name:"new",tab:"\u6700\u65B0"})]),_:1}),a(b,{show:o.value},{default:n(()=>[a(y,null,{default:n(()=>[(_(!0),r(q,null,C(c.value,t=>(_(),L(h,{class:"tag-item",type:"success",round:"",key:t.id},{avatar:n(()=>[a(f,{src:t.user.avatar},null,8,["src"])]),default:n(()=>[a(v,{class:"hash-link",to:{name:"home",query:{q:t.tag,t:"tag"}}},{default:n(()=>[M(" #"+m(t.tag),1)]),_:2},1032,["to"]),S("span",$,"("+m(t.quote_num)+")",1)]),_:2},1024))),128))]),_:1})]),_:1},8,["show"])]),_:1})])}}});var K=w(j,[["__scopeId","data-v-ec1d2778"]]);export{K as default}; diff --git a/web/dist/assets/Upload.efe3adfd.js b/web/dist/assets/Upload.efe3adfd.js deleted file mode 100644 index 3ec3cd50..00000000 --- a/web/dist/assets/Upload.efe3adfd.js +++ /dev/null @@ -1,382 +0,0 @@ -import{br as q,h as t,n as $,l as f,o as C,d as A,s as R,bd as E,N as j,bs as re,bt as ie,bu as ne,bv as oe,u as ae,q as G,bw as be,v as J,y as le,e as ye,i as W,be as Y,L as we,bx as se,r as M,aK as xe,bl as Ce,J as V,by as Re,ax as ke,w as Be,bm as Pe,m as I,bz as Q,at as $e,bA as Le,f as Te,t as D,g as Se,A as ze,bB as De,aa as _e,R as Ie,aF as Oe,k as ee}from"./index.f480f018.js";var Fe=q("attach",t("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},t("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},t("g",{fill:"currentColor","fill-rule":"nonzero"},t("path",{d:"M3.25735931,8.70710678 L7.85355339,4.1109127 C8.82986412,3.13460197 10.4127766,3.13460197 11.3890873,4.1109127 C12.365398,5.08722343 12.365398,6.67013588 11.3890873,7.64644661 L6.08578644,12.9497475 C5.69526215,13.3402718 5.06209717,13.3402718 4.67157288,12.9497475 C4.28104858,12.5592232 4.28104858,11.9260582 4.67157288,11.5355339 L9.97487373,6.23223305 C10.1701359,6.0369709 10.1701359,5.72038841 9.97487373,5.52512627 C9.77961159,5.32986412 9.4630291,5.32986412 9.26776695,5.52512627 L3.96446609,10.8284271 C3.18341751,11.6094757 3.18341751,12.8758057 3.96446609,13.6568542 C4.74551468,14.4379028 6.01184464,14.4379028 6.79289322,13.6568542 L12.0961941,8.35355339 C13.4630291,6.98671837 13.4630291,4.77064094 12.0961941,3.40380592 C10.7293591,2.0369709 8.51328163,2.0369709 7.14644661,3.40380592 L2.55025253,8 C2.35499039,8.19526215 2.35499039,8.51184464 2.55025253,8.70710678 C2.74551468,8.90236893 3.06209717,8.90236893 3.25735931,8.70710678 Z"}))))),je=q("trash",t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},t("path",{d:"M432,144,403.33,419.74A32,32,0,0,1,371.55,448H140.46a32,32,0,0,1-31.78-28.26L80,144",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),t("rect",{x:"32",y:"64",width:"448",height:"80",rx:"16",ry:"16",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),t("line",{x1:"312",y1:"240",x2:"200",y2:"352",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}),t("line",{x1:"312",y1:"352",x2:"200",y2:"240",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}))),Ue=q("download",t("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},t("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},t("g",{fill:"currentColor","fill-rule":"nonzero"},t("path",{d:"M3.5,13 L12.5,13 C12.7761424,13 13,13.2238576 13,13.5 C13,13.7454599 12.8231248,13.9496084 12.5898756,13.9919443 L12.5,14 L3.5,14 C3.22385763,14 3,13.7761424 3,13.5 C3,13.2545401 3.17687516,13.0503916 3.41012437,13.0080557 L3.5,13 L12.5,13 L3.5,13 Z M7.91012437,1.00805567 L8,1 C8.24545989,1 8.44960837,1.17687516 8.49194433,1.41012437 L8.5,1.5 L8.5,10.292 L11.1819805,7.6109127 C11.3555469,7.43734635 11.6249713,7.4180612 11.8198394,7.55305725 L11.8890873,7.6109127 C12.0626536,7.78447906 12.0819388,8.05390346 11.9469427,8.2487716 L11.8890873,8.31801948 L8.35355339,11.8535534 C8.17998704,12.0271197 7.91056264,12.0464049 7.7156945,11.9114088 L7.64644661,11.8535534 L4.1109127,8.31801948 C3.91565056,8.12275734 3.91565056,7.80617485 4.1109127,7.6109127 C4.28447906,7.43734635 4.55390346,7.4180612 4.7487716,7.55305725 L4.81801948,7.6109127 L7.5,10.292 L7.5,1.5 C7.5,1.25454011 7.67687516,1.05039163 7.91012437,1.00805567 L8,1 L7.91012437,1.00805567 Z"}))))),Ae=q("cancel",t("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},t("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},t("g",{fill:"currentColor","fill-rule":"nonzero"},t("path",{d:"M2.58859116,2.7156945 L2.64644661,2.64644661 C2.82001296,2.47288026 3.08943736,2.45359511 3.2843055,2.58859116 L3.35355339,2.64644661 L8,7.293 L12.6464466,2.64644661 C12.8417088,2.45118446 13.1582912,2.45118446 13.3535534,2.64644661 C13.5488155,2.84170876 13.5488155,3.15829124 13.3535534,3.35355339 L8.707,8 L13.3535534,12.6464466 C13.5271197,12.820013 13.5464049,13.0894374 13.4114088,13.2843055 L13.3535534,13.3535534 C13.179987,13.5271197 12.9105626,13.5464049 12.7156945,13.4114088 L12.6464466,13.3535534 L8,8.707 L3.35355339,13.3535534 C3.15829124,13.5488155 2.84170876,13.5488155 2.64644661,13.3535534 C2.45118446,13.1582912 2.45118446,12.8417088 2.64644661,12.6464466 L7.293,8 L2.64644661,3.35355339 C2.47288026,3.17998704 2.45359511,2.91056264 2.58859116,2.7156945 L2.64644661,2.64644661 L2.58859116,2.7156945 Z"}))))),Ne=q("retry",t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},t("path",{d:"M320,146s24.36-12-64-12A160,160,0,1,0,416,294",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-miterlimit: 10; stroke-width: 32px;"}),t("polyline",{points:"256 58 336 138 256 218",style:"fill: none; stroke: currentcolor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 32px;"}))),Ee=$([f("progress",{display:"inline-block"},[f("progress-icon",` - color: var(--n-icon-color); - transition: color .3s var(--n-bezier); - `),C("line",` - width: 100%; - display: block; - `,[f("progress-content",` - display: flex; - align-items: center; - `,[f("progress-graph",{flex:1})]),f("progress-custom-content",{marginLeft:"14px"}),f("progress-icon",` - width: 30px; - padding-left: 14px; - height: var(--n-icon-size-line); - line-height: var(--n-icon-size-line); - font-size: var(--n-icon-size-line); - `,[C("as-text",` - color: var(--n-text-color-line-outer); - text-align: center; - width: 40px; - font-size: var(--n-font-size); - padding-left: 4px; - transition: color .3s var(--n-bezier); - `)])]),C("circle, dashboard",{width:"120px"},[f("progress-custom-content",` - position: absolute; - left: 50%; - top: 50%; - transform: translateX(-50%) translateY(-50%); - display: flex; - align-items: center; - justify-content: center; - `),f("progress-text",` - position: absolute; - left: 50%; - top: 50%; - transform: translateX(-50%) translateY(-50%); - display: flex; - align-items: center; - color: inherit; - font-size: var(--n-font-size-circle); - color: var(--n-text-color-circle); - font-weight: var(--n-font-weight-circle); - transition: color .3s var(--n-bezier); - white-space: nowrap; - `),f("progress-icon",` - position: absolute; - left: 50%; - top: 50%; - transform: translateX(-50%) translateY(-50%); - display: flex; - align-items: center; - color: var(--n-icon-color); - font-size: var(--n-icon-size-circle); - `)]),C("multiple-circle",` - width: 200px; - color: inherit; - `,[f("progress-text",` - font-weight: var(--n-font-weight-circle); - color: var(--n-text-color-circle); - position: absolute; - left: 50%; - top: 50%; - transform: translateX(-50%) translateY(-50%); - display: flex; - align-items: center; - justify-content: center; - transition: color .3s var(--n-bezier); - `)]),f("progress-content",{position:"relative"}),f("progress-graph",{position:"relative"},[f("progress-graph-circle",[$("svg",{verticalAlign:"bottom"}),f("progress-graph-circle-fill",` - stroke: var(--n-fill-color); - transition: - opacity .3s var(--n-bezier), - stroke .3s var(--n-bezier), - stroke-dasharray .3s var(--n-bezier); - `,[C("empty",{opacity:0})]),f("progress-graph-circle-rail",` - transition: stroke .3s var(--n-bezier); - overflow: hidden; - stroke: var(--n-rail-color); - `)]),f("progress-graph-line",[C("indicator-inside",[f("progress-graph-line-rail",` - height: 16px; - line-height: 16px; - border-radius: 10px; - `,[f("progress-graph-line-fill",` - height: inherit; - border-radius: 10px; - `),f("progress-graph-line-indicator",` - background: #0000; - white-space: nowrap; - text-align: right; - margin-left: 14px; - margin-right: 14px; - height: inherit; - font-size: 12px; - color: var(--n-text-color-line-inner); - transition: color .3s var(--n-bezier); - `)])]),C("indicator-inside-label",` - height: 16px; - display: flex; - align-items: center; - `,[f("progress-graph-line-rail",` - flex: 1; - transition: background-color .3s var(--n-bezier); - `),f("progress-graph-line-indicator",` - background: var(--n-fill-color); - font-size: 12px; - transform: translateZ(0); - display: flex; - vertical-align: middle; - height: 16px; - line-height: 16px; - padding: 0 10px; - border-radius: 10px; - position: absolute; - white-space: nowrap; - color: var(--n-text-color-line-inner); - transition: - right .2s var(--n-bezier), - color .3s var(--n-bezier), - background-color .3s var(--n-bezier); - `)]),f("progress-graph-line-rail",` - position: relative; - overflow: hidden; - height: var(--n-rail-height); - border-radius: 5px; - background-color: var(--n-rail-color); - transition: background-color .3s var(--n-bezier); - `,[f("progress-graph-line-fill",` - background: var(--n-fill-color); - position: relative; - border-radius: 5px; - height: inherit; - width: 100%; - max-width: 0%; - transition: - background-color .3s var(--n-bezier), - max-width .2s var(--n-bezier); - `,[C("processing",[$("&::after",` - content: ""; - background-image: var(--n-line-bg-processing); - animation: progress-processing-animation 2s var(--n-bezier) infinite; - `)])])])])])]),$("@keyframes progress-processing-animation",` - 0% { - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 100%; - opacity: 1; - } - 66% { - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; - opacity: 0; - } - 100% { - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; - opacity: 0; - } - `)]);const He={success:t(re,null),error:t(ie,null),warning:t(ne,null),info:t(oe,null)};var Me=A({name:"ProgressLine",props:{clsPrefix:{type:String,required:!0},percentage:{type:Number,default:0},railColor:String,railStyle:[String,Object],fillColor:String,status:{type:String,required:!0},indicatorPlacement:{type:String,required:!0},indicatorTextColor:String,unit:{type:String,default:"%"},processing:{type:Boolean,required:!0},showIndicator:{type:Boolean,required:!0},height:[String,Number],railBorderRadius:[String,Number],fillBorderRadius:[String,Number]},setup(e,{slots:n}){const i=R(()=>E(e.height)),r=R(()=>e.railBorderRadius!==void 0?E(e.railBorderRadius):e.height!==void 0?E(e.height,{c:.5}):""),l=R(()=>e.fillBorderRadius!==void 0?E(e.fillBorderRadius):e.railBorderRadius!==void 0?E(e.railBorderRadius):e.height!==void 0?E(e.height,{c:.5}):"");return()=>{const{indicatorPlacement:o,railColor:c,railStyle:g,percentage:s,unit:d,indicatorTextColor:a,status:u,showIndicator:b,fillColor:h,processing:k,clsPrefix:y}=e;return t("div",{class:`${y}-progress-content`,role:"none"},t("div",{class:`${y}-progress-graph`,"aria-hidden":!0},t("div",{class:[`${y}-progress-graph-line`,{[`${y}-progress-graph-line--indicator-${o}`]:!0}]},t("div",{class:`${y}-progress-graph-line-rail`,style:[{backgroundColor:c,height:i.value,borderRadius:r.value},g]},t("div",{class:[`${y}-progress-graph-line-fill`,k&&`${y}-progress-graph-line-fill--processing`],style:{maxWidth:`${e.percentage}%`,backgroundColor:h,height:i.value,lineHeight:i.value,borderRadius:l.value}},o==="inside"?t("div",{class:`${y}-progress-graph-line-indicator`},s,d):null)))),b&&o==="outside"?t("div",null,n.default?t("div",{class:`${y}-progress-custom-content`,style:{color:a},role:"none"},n.default()):u==="default"?t("div",{role:"none",class:`${y}-progress-icon ${y}-progress-icon--as-text`,style:{color:a}},s,d):t("div",{class:`${y}-progress-icon`,"aria-hidden":!0},t(j,{clsPrefix:y},{default:()=>He[u]}))):null)}}});const qe={success:t(re,null),error:t(ie,null),warning:t(ne,null),info:t(oe,null)};var We=A({name:"ProgressCircle",props:{clsPrefix:{type:String,required:!0},status:{type:String,required:!0},strokeWidth:{type:Number,required:!0},fillColor:String,railColor:String,railStyle:[String,Object],percentage:{type:Number,default:0},offsetDegree:{type:Number,default:0},showIndicator:{type:Boolean,required:!0},indicatorTextColor:String,unit:String,viewBoxWidth:{type:Number,required:!0},gapDegree:{type:Number,required:!0},gapOffsetDegree:{type:Number,default:0}},setup(e,{slots:n}){function i(r,l,o){const{gapDegree:c,viewBoxWidth:g}=e,s=50,d=0,a=s,u=0,b=2*s,h=`M 55,55 m ${d},${a} - a ${s},${s} 0 1 1 ${u},${-b} - a ${s},${s} 0 1 1 ${-u},${b}`,k=Math.PI*2*s,y={stroke:o,strokeDasharray:`${r/100*(k-c)}px ${g*8}px`,strokeDashoffset:`-${c/2+Math.PI/3.6*l}px`};return{pathString:h,pathStyle:y}}return()=>{const{fillColor:r,railColor:l,strokeWidth:o,offsetDegree:c,status:g,percentage:s,showIndicator:d,indicatorTextColor:a,unit:u,gapOffsetDegree:b,clsPrefix:h}=e,{pathString:k,pathStyle:y}=i(100,0,l),{pathString:B,pathStyle:w}=i(s,c,r);return t("div",{class:`${h}-progress-content`,role:"none"},t("div",{class:`${h}-progress-graph`,"aria-hidden":!0},t("div",{class:`${h}-progress-graph-circle`,style:{transform:b?`rotate(${b}deg)`:void 0}},t("svg",{viewBox:"0 0 110 110"},t("g",null,t("path",{class:`${h}-progress-graph-circle-rail`,d:k,"stroke-width":o,"stroke-linecap":"round",fill:"none",style:y})),t("g",null,t("path",{class:[`${h}-progress-graph-circle-fill`,s===0&&`${h}-progress-graph-circle-fill--empty`],d:B,"stroke-width":o,"stroke-linecap":"round",fill:"none",style:w}))))),d?t("div",null,n.default?t("div",{class:`${h}-progress-custom-content`,role:"none"},n.default()):g!=="default"?t("div",{class:`${h}-progress-icon`,"aria-hidden":!0},t(j,{clsPrefix:h},{default:()=>qe[g]})):t("div",{class:`${h}-progress-text`,style:{color:a},role:"none"},t("span",{class:`${h}-progress-text__percentage`},s),t("span",{class:`${h}-progress-text__unit`},u))):null)}}});function te(e,n,i=100){return`m ${i/2} ${i/2-e} a ${e} ${e} 0 1 1 0 ${2*e} a ${e} ${e} 0 1 1 0 -${2*e}`}var Xe=A({name:"ProgressMultipleCircle",props:{clsPrefix:{type:String,required:!0},viewBoxWidth:{type:Number,required:!0},percentage:{type:Array,default:[0]},strokeWidth:{type:Number,required:!0},circleGap:{type:Number,required:!0},showIndicator:{type:Boolean,required:!0},fillColor:{type:Array,default:()=>[]},railColor:{type:Array,default:()=>[]},railStyle:{type:Array,default:()=>[]}},setup(e,{slots:n}){const i=R(()=>e.percentage.map((l,o)=>`${Math.PI*l/100*(e.viewBoxWidth/2-e.strokeWidth/2*(1+2*o)-e.circleGap*o)*2}, ${e.viewBoxWidth*8}`));return()=>{const{viewBoxWidth:r,strokeWidth:l,circleGap:o,showIndicator:c,fillColor:g,railColor:s,railStyle:d,percentage:a,clsPrefix:u}=e;return t("div",{class:`${u}-progress-content`,role:"none"},t("div",{class:`${u}-progress-graph`,"aria-hidden":!0},t("div",{class:`${u}-progress-graph-circle`},t("svg",{viewBox:`0 0 ${r} ${r}`},a.map((b,h)=>t("g",{key:h},t("path",{class:`${u}-progress-graph-circle-rail`,d:te(r/2-l/2*(1+2*h)-o*h,l,r),"stroke-width":l,"stroke-linecap":"round",fill:"none",style:[{strokeDashoffset:0,stroke:s[h]},d[h]]}),t("path",{class:[`${u}-progress-graph-circle-fill`,b===0&&`${u}-progress-graph-circle-fill--empty`],d:te(r/2-l/2*(1+2*h)-o*h,l,r),"stroke-width":l,"stroke-linecap":"round",fill:"none",style:{strokeDasharray:i.value[h],strokeDashoffset:0,stroke:g[h]}})))))),c&&n.default?t("div",null,t("div",{class:`${u}-progress-text`},n.default())):null)}}});const Ve=Object.assign(Object.assign({},G.props),{processing:Boolean,type:{type:String,default:"line"},gapDegree:Number,gapOffsetDegree:Number,status:{type:String,default:"default"},railColor:[String,Array],railStyle:[String,Array],color:[String,Array],viewBoxWidth:{type:Number,default:100},strokeWidth:{type:Number,default:7},percentage:[Number,Array],unit:{type:String,default:"%"},showIndicator:{type:Boolean,default:!0},indicatorPosition:{type:String,default:"outside"},indicatorPlacement:{type:String,default:"outside"},indicatorTextColor:String,circleGap:{type:Number,default:1},height:Number,borderRadius:[String,Number],fillBorderRadius:[String,Number],offsetDegree:Number});var Ge=A({name:"Progress",props:Ve,setup(e){const n=R(()=>e.indicatorPlacement||e.indicatorPosition),i=R(()=>{if(e.gapDegree||e.gapDegree===0)return e.gapDegree;if(e.type==="dashboard")return 75}),{mergedClsPrefixRef:r,inlineThemeDisabled:l}=ae(e),o=G("Progress","-progress",Ee,be,e,r),c=R(()=>{const{status:s}=e,{common:{cubicBezierEaseInOut:d},self:{fontSize:a,fontSizeCircle:u,railColor:b,railHeight:h,iconSizeCircle:k,iconSizeLine:y,textColorCircle:B,textColorLineInner:w,textColorLineOuter:x,lineBgProcessing:O,fontWeightCircle:p,[J("iconColor",s)]:v,[J("fillColor",s)]:T}}=o.value;return{"--n-bezier":d,"--n-fill-color":T,"--n-font-size":a,"--n-font-size-circle":u,"--n-font-weight-circle":p,"--n-icon-color":v,"--n-icon-size-circle":k,"--n-icon-size-line":y,"--n-line-bg-processing":O,"--n-rail-color":b,"--n-rail-height":h,"--n-text-color-circle":B,"--n-text-color-line-inner":w,"--n-text-color-line-outer":x}}),g=l?le("progress",R(()=>e.status[0]),c,e):void 0;return{mergedClsPrefix:r,mergedIndicatorPlacement:n,gapDeg:i,cssVars:l?void 0:c,themeClass:g==null?void 0:g.themeClass,onRender:g==null?void 0:g.onRender}},render(){const{type:e,cssVars:n,indicatorTextColor:i,showIndicator:r,status:l,railColor:o,railStyle:c,color:g,percentage:s,viewBoxWidth:d,strokeWidth:a,mergedIndicatorPlacement:u,unit:b,borderRadius:h,fillBorderRadius:k,height:y,processing:B,circleGap:w,mergedClsPrefix:x,gapDeg:O,gapOffsetDegree:p,themeClass:v,$slots:T,onRender:m}=this;return m==null||m(),t("div",{class:[v,`${x}-progress`,`${x}-progress--${e}`,`${x}-progress--${l}`],style:n,"aria-valuemax":100,"aria-valuemin":0,"aria-valuenow":s,role:e==="circle"||e==="line"||e==="dashboard"?"progressbar":"none"},e==="circle"||e==="dashboard"?t(We,{clsPrefix:x,status:l,showIndicator:r,indicatorTextColor:i,railColor:o,fillColor:g,railStyle:c,offsetDegree:this.offsetDegree,percentage:s,viewBoxWidth:d,strokeWidth:a,gapDegree:O===void 0?e==="dashboard"?75:0:O,gapOffsetDegree:p,unit:b},T):e==="line"?t(Me,{clsPrefix:x,status:l,showIndicator:r,indicatorTextColor:i,railColor:o,fillColor:g,railStyle:c,percentage:s,processing:B,indicatorPlacement:u,unit:b,fillBorderRadius:k,railBorderRadius:h,height:y},T):e==="multiple-circle"?t(Xe,{clsPrefix:x,strokeWidth:a,railColor:o,fillColor:g,railStyle:c,viewBoxWidth:d,percentage:s,showIndicator:r,circleGap:w},T):null)}});const H=ye("n-upload"),de="__UPLOAD_DRAGGER__";var Ye=A({name:"UploadDragger",[de]:!0,setup(e,{slots:n}){const i=W(H,null);return i||Y("upload-dragger","`n-upload-dragger` must be placed inside `n-upload`."),()=>{const{mergedClsPrefixRef:{value:r},mergedDisabledRef:{value:l}}=i;return t("div",{class:[`${r}-upload-dragger`,l&&`${r}-upload-dragger--disabled`]},n)}}}),Ke=globalThis&&globalThis.__awaiter||function(e,n,i,r){function l(o){return o instanceof i?o:new i(function(c){c(o)})}return new(i||(i=Promise))(function(o,c){function g(a){try{d(r.next(a))}catch(u){c(u)}}function s(a){try{d(r.throw(a))}catch(u){c(u)}}function d(a){a.done?o(a.value):l(a.value).then(g,s)}d((r=r.apply(e,n||[])).next())})};const ce=e=>e.includes("image/"),Ze=(e="")=>{const n=e.split("/"),r=n[n.length-1].split(/#|\?/)[0];return(/\.[^./\\]*$/.exec(r)||[""])[0]},Je=e=>{if(e.type)return ce(e.type);const n=e.thumbnailUrl||e.url||"",i=Ze(n);return/^data:image\//.test(n)||/(webp|svg|png|gif|jpg|jpeg|jfif|bmp|dpg|ico)$/i.test(i)?!0:!(/^data:/.test(n)||i)};function Qe(e){return Ke(this,void 0,void 0,function*(){return yield new Promise(n=>{if(!e.type||!ce(e.type)){n("");return}const i=new Image;i.src=window.URL.createObjectURL(e),i.onload=()=>{const{width:r,height:l}=i,o=document.createElement("canvas"),c=o.getContext("2d");o.width=r,o.height=l,o.style.cssText=`position: fixed; left: 0; top: 0; width: ${r}px; height: ${l}px; z-index: 9999; display: none;`,document.body.appendChild(o),c==null||c.drawImage(i,0,0,r,l);const g=o.toDataURL();document.body.removeChild(o),n(g)}})})}const et=typeof document!="undefined"&&typeof window!="undefined"&&window.FileReader&&window.File;var ue=A({name:"UploadTrigger",props:{abstract:Boolean},setup(e,{slots:n}){const i=W(H,null);i||Y("upload-trigger","`n-upload-trigger` must be placed inside `n-upload`.");const{mergedClsPrefixRef:r,mergedDisabledRef:l,maxReachedRef:o,listTypeRef:c,dragOverRef:g,openOpenFileDialog:s,draggerInsideRef:d,handleFileAddition:a}=i,u=R(()=>c.value==="image-card");function b(){l.value||o.value||s()}function h(w){w.preventDefault(),g.value=!0}function k(w){w.preventDefault(),g.value=!0}function y(w){w.preventDefault(),g.value=!1}function B(w){if(w.preventDefault(),!d.value||l.value||o.value)return;const x=w.dataTransfer,O=x==null?void 0:x.files;O&&a(O),g.value=!1}return()=>{var w;const{value:x}=r;return e.abstract?(w=n.default)===null||w===void 0?void 0:w.call(n,{handleClick:b,handleDrop:B,handleDragOver:h,handleDragEnter:k,handleDragLeave:y}):t("div",{class:[`${x}-upload-trigger`,(l.value||o.value)&&`${x}-upload-trigger--disabled`,u.value&&`${x}-upload-trigger--image-card`],onClick:b,onDrop:B,onDragover:h,onDragenter:k,onDragleave:y},u.value?t(Ye,null,{default:n.default||(()=>t(j,{clsPrefix:x},{default:()=>t(we,null)}))}):n)}}}),tt=A({name:"UploadProgress",props:{show:Boolean,percentage:{type:Number,required:!0},status:{type:String,required:!0}},setup(){return{mergedTheme:W(H).mergedThemeRef}},render(){return t(se,null,{default:()=>this.show?t(Ge,{type:"line",showIndicator:!1,percentage:this.percentage,status:this.status,height:2,theme:this.mergedTheme.peers.Progress,themeOverrides:this.mergedTheme.peerOverrides.Progress}):null})}});const rt=t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 28 28"},t("g",{fill:"none"},t("path",{d:"M21.75 3A3.25 3.25 0 0 1 25 6.25v15.5A3.25 3.25 0 0 1 21.75 25H6.25A3.25 3.25 0 0 1 3 21.75V6.25A3.25 3.25 0 0 1 6.25 3h15.5zm.583 20.4l-7.807-7.68a.75.75 0 0 0-.968-.07l-.084.07l-7.808 7.68c.183.065.38.1.584.1h15.5c.204 0 .4-.035.583-.1l-7.807-7.68l7.807 7.68zM21.75 4.5H6.25A1.75 1.75 0 0 0 4.5 6.25v15.5c0 .208.036.408.103.593l7.82-7.692a2.25 2.25 0 0 1 3.026-.117l.129.117l7.82 7.692c.066-.185.102-.385.102-.593V6.25a1.75 1.75 0 0 0-1.75-1.75zm-3.25 3a2.5 2.5 0 1 1 0 5a2.5 2.5 0 0 1 0-5zm0 1.5a1 1 0 1 0 0 2a1 1 0 0 0 0-2z",fill:"currentColor"}))),it=t("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 28 28"},t("g",{fill:"none"},t("path",{d:"M6.4 2A2.4 2.4 0 0 0 4 4.4v19.2A2.4 2.4 0 0 0 6.4 26h15.2a2.4 2.4 0 0 0 2.4-2.4V11.578c0-.729-.29-1.428-.805-1.944l-6.931-6.931A2.4 2.4 0 0 0 14.567 2H6.4zm-.9 2.4a.9.9 0 0 1 .9-.9H14V10a2 2 0 0 0 2 2h6.5v11.6a.9.9 0 0 1-.9.9H6.4a.9.9 0 0 1-.9-.9V4.4zm16.44 6.1H16a.5.5 0 0 1-.5-.5V4.06l6.44 6.44z",fill:"currentColor"})));var nt=globalThis&&globalThis.__awaiter||function(e,n,i,r){function l(o){return o instanceof i?o:new i(function(c){c(o)})}return new(i||(i=Promise))(function(o,c){function g(a){try{d(r.next(a))}catch(u){c(u)}}function s(a){try{d(r.throw(a))}catch(u){c(u)}}function d(a){a.done?o(a.value):l(a.value).then(g,s)}d((r=r.apply(e,n||[])).next())})},ot=A({name:"UploadFile",props:{clsPrefix:{type:String,required:!0},file:{type:Object,required:!0},listType:{type:String,required:!0}},setup(e){const n=W(H),i=M(null),r=M(""),l=R(()=>{const{file:p}=e;return p.status==="finished"?"success":p.status==="error"?"error":"info"}),o=R(()=>{const{file:p}=e;if(p.status==="error")return"error"}),c=R(()=>{const{file:p}=e;return p.status==="uploading"}),g=R(()=>{if(!n.showCancelButtonRef.value)return!1;const{file:p}=e;return["uploading","pending","error"].includes(p.status)}),s=R(()=>{if(!n.showRemoveButtonRef.value)return!1;const{file:p}=e;return["finished"].includes(p.status)}),d=R(()=>{if(!n.showDownloadButtonRef.value)return!1;const{file:p}=e;return["finished"].includes(p.status)}),a=R(()=>{if(!n.showRetryButtonRef.value)return!1;const{file:p}=e;return["error"].includes(p.status)}),u=R(()=>{if(!n.showPreviewButtonRef.value)return!1;const{file:{status:p,url:v},listType:T}=e;return["finished"].includes(p)&&(v||r.value)&&T==="image-card"});function b(){n.submit(e.file.id)}function h(p){p.preventDefault();const{file:v}=e;["finished","pending","error"].includes(v.status)?y(v):["uploading"].includes(v.status)?w(v):Be("upload","The button clicked type is unknown.")}function k(p){p.preventDefault(),B(e.file)}function y(p){const{XhrMap:v,doChange:T,onRemoveRef:{value:m},mergedFileListRef:{value:P}}=n;Promise.resolve(m?m({file:Object.assign({},p),fileList:P}):!0).then(S=>{if(S===!1)return;const _=Object.assign({},p,{status:"removed"});v.delete(p.id),T(_,void 0,{remove:!0})})}function B(p){const{onDownloadRef:{value:v}}=n;Promise.resolve(v?v(Object.assign({},p)):!0).then(T=>{})}function w(p){const{XhrMap:v}=n,T=v.get(p.id);T==null||T.abort(),y(Object.assign({},p))}function x(){const{onPreviewRef:{value:p}}=n;if(p)p(e.file);else if(e.listType==="image-card"){const{value:v}=i;if(!v)return;v.click()}}const O=()=>nt(this,void 0,void 0,function*(){const{listType:p}=e;p!=="image"&&p!=="image-card"||!et||!(e.file.file instanceof File)||(r.value=yield n.getFileThumbnailUrl(e.file))});return xe(()=>{O()}),{mergedTheme:n.mergedThemeRef,progressStatus:l,buttonType:o,showProgress:c,disabled:n.mergedDisabledRef,showCancelButton:g,showRemoveButton:s,showDownloadButton:d,showRetryButton:a,showPreviewButton:u,thumbnailUrl:r,imageRef:i,handleRemoveOrCancelClick:h,handleDownloadClick:k,handleRetryClick:b,handlePreviewClick:x}},render(){const{clsPrefix:e,mergedTheme:n,listType:i,file:r}=this;let l;const o=i==="image";o||i==="image-card"?l=Je(r)?(r.url||this.thumbnailUrl)&&r.status!=="error"?t("a",{rel:"noopener noreferer",target:"_blank",href:r.url||void 0,class:`${e}-upload-file-info__thumbnail`,onClick:this.handlePreviewClick},i==="image-card"?t(Ce,{src:this.thumbnailUrl||r.thumbnailUrl||r.url||void 0,previewSrc:r.url||void 0,alt:r.name,ref:"imageRef"}):t("img",{src:this.thumbnailUrl||r.thumbnailUrl||r.url||void 0,alt:r.name})):t("span",{class:`${e}-upload-file-info__thumbnail`},t(j,{clsPrefix:e},{default:()=>rt})):t("span",{class:`${e}-upload-file-info__thumbnail`},t(j,{clsPrefix:e},{default:()=>it})):l=t("span",{class:`${e}-upload-file-info__thumbnail`},t(j,{clsPrefix:e},{default:()=>t(Fe,null)}));const g=t(tt,{show:this.showProgress,percentage:r.percentage||0,status:this.progressStatus}),s=i==="text"||i==="image";return t("div",{class:[`${e}-upload-file`,`${e}-upload-file--${this.progressStatus}-status`,r.url&&r.status!=="error"&&i!=="image-card"&&`${e}-upload-file--with-url`,`${e}-upload-file--${i}-type`]},t("div",{class:`${e}-upload-file-info`},l,t("div",{class:`${e}-upload-file-info__name`},s&&(r.url&&r.status!=="error"?t("a",{rel:"noopener noreferer",target:"_blank",href:r.url||void 0,onClick:this.handlePreviewClick},r.name):t("span",{onClick:this.handlePreviewClick},r.name)),o&&g),t("div",{class:[`${e}-upload-file-info__action`,`${e}-upload-file-info__action--${i}-type`]},this.showPreviewButton?t(V,{key:"preview",text:!0,type:this.buttonType,onClick:this.handlePreviewClick,theme:n.peers.Button,themeOverrides:n.peerOverrides.Button},{icon:()=>t(j,{clsPrefix:e},{default:()=>t(Re,null)})}):null,(this.showRemoveButton||this.showCancelButton)&&!this.disabled&&t(V,{key:"cancelOrTrash",theme:n.peers.Button,themeOverrides:n.peerOverrides.Button,text:!0,type:this.buttonType,onClick:this.handleRemoveOrCancelClick},{icon:()=>t(ke,null,{default:()=>this.showRemoveButton?t(j,{clsPrefix:e,key:"trash"},{default:()=>t(je,null)}):t(j,{clsPrefix:e,key:"cancel"},{default:()=>t(Ae,null)})})}),this.showRetryButton&&!this.disabled&&t(V,{key:"retry",text:!0,type:this.buttonType,onClick:this.handleRetryClick,theme:n.peers.Button,themeOverrides:n.peerOverrides.Button},{icon:()=>t(j,{clsPrefix:e},{default:()=>t(Ne,null)})}),this.showDownloadButton?t(V,{key:"download",text:!0,type:this.buttonType,onClick:this.handleDownloadClick,theme:n.peers.Button,themeOverrides:n.peerOverrides.Button},{icon:()=>t(j,{clsPrefix:e},{default:()=>t(Ue,null)})}):null)),!o&&g)}}),at=A({name:"UploadFileList",setup(e,{slots:n}){const i=W(H,null);i||Y("upload-file-list","`n-upload-file-list` must be placed inside `n-upload`.");const{abstractRef:r,mergedClsPrefixRef:l,listTypeRef:o,mergedFileListRef:c,fileListStyleRef:g,cssVarsRef:s,themeClassRef:d,maxReachedRef:a,showTriggerRef:u,imageGroupPropsRef:b}=i,h=R(()=>o.value==="image-card"),k=()=>c.value.map(B=>t(ot,{clsPrefix:l.value,key:B.id,file:B,listType:o.value})),y=()=>h.value?t(Pe,Object.assign({},b.value),{default:k}):t(se,{group:!0},{default:k});return()=>{const{value:B}=l,{value:w}=r;return t("div",{class:[`${B}-upload-file-list`,h.value&&`${B}-upload-file-list--grid`,w?d==null?void 0:d.value:void 0],style:[w&&s?s.value:"",g.value]},y(),u.value&&!a.value&&h.value&&t(ue,null,n))}}}),lt=$([f("upload","width: 100%;",[C("dragger-inside",[I("trigger",` - display: block; - `)]),C("drag-over",[f("upload-dragger",` - border: var(--n-dragger-border-hover); - `)])]),f("upload-dragger",` - cursor: pointer; - box-sizing: border-box; - width: 100%; - text-align: center; - border-radius: var(--n-border-radius); - padding: 24px; - opacity: 1; - transition: - opacity .3s var(--n-bezier), - border-color .3s var(--n-bezier), - background-color .3s var(--n-bezier); - background-color: var(--n-dragger-color); - border: var(--n-dragger-border); - `,[$("&:hover",` - border: var(--n-dragger-border-hover); - `),C("disabled",` - opacity: var(--n-item-disabled-opacity); - cursor: not-allowed; - `)]),f("upload-trigger",` - display: inline-block; - box-sizing: border-box; - opacity: 1; - transition: opacity .3s var(--n-bezier); - `,[$("+",[f("upload-file-list","margin-top: 8px;")]),C("disabled",` - opacity: var(--n-item-disabled-opacity); - cursor: not-allowed; - `),C("image-card",` - width: 96px; - height: 96px; - `,[f("base-icon",` - font-size: 24px; - `),f("upload-dragger",` - padding: 0; - height: 100%; - width: 100%; - display: flex; - align-items: center; - justify-content: center; - `)])]),f("upload-file-list",` - line-height: var(--n-line-height); - opacity: 1; - transition: opacity .3s var(--n-bezier); - `,[C("disabled",` - opacity: var(--n-item-disabled-opacity); - cursor: not-allowed; - `,[f("upload-file","cursor: not-allowed;")]),C("grid",` - display: grid; - grid-template-columns: repeat(auto-fill, 96px); - grid-gap: 8px; - margin-top: 0; - `),f("upload-file",` - display: block; - box-sizing: border-box; - cursor: default; - padding: 0px 12px 0 6px; - transition: background-color .3s var(--n-bezier); - border-radius: var(--n-border-radius); - `,[Q(),f("progress",[Q({foldPadding:!0})]),$("&:hover",` - background-color: var(--n-item-color-hover); - `,[f("upload-file-info",[I("action",` - opacity: 1; - `)])]),C("image-type",` - border-radius: var(--n-border-radius); - text-decoration: underline; - text-decoration-color: #0000; - `,[f("upload-file-info",` - padding-top: 0px; - padding-bottom: 0px; - width: 100%; - height: 100%; - display: flex; - justify-content: space-between; - align-items: center; - padding: 6px 0; - `,[f("progress",` - padding: 2px 0; - margin-bottom: 0; - `),I("name",` - padding: 0 8px; - `),I("thumbnail",` - width: 32px; - height: 32px; - font-size: 28px; - display: flex; - justify-content: center; - align-items: center; - `,[$("img",` - width: 100%; - `)])])]),C("text-type",[f("progress",` - box-sizing: border-box; - padding-bottom: 6px; - margin-bottom: 6px; - `)]),C("image-card-type",` - position: relative; - width: 96px; - height: 96px; - border: var(--n-item-border-image-card); - border-radius: var(--n-border-radius); - padding: 0; - display: flex; - align-items: center; - justify-content: center; - transition: border-color .3s var(--n-bezier), background-color .3s var(--n-bezier); - border-radius: var(--n-border-radius); - `,[f("progress",` - position: absolute; - left: 8px; - bottom: 8px; - right: 8px; - width: unset; - `),f("upload-file-info",` - padding: 0; - width: 100%; - height: 100%; - `,[I("thumbnail",` - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: 36px; - `,[$("img",` - width: 100%; - `)])]),$("&::before",` - position: absolute; - z-index: 1; - left: 0; - right: 0; - top: 0; - bottom: 0; - border-radius: inherit; - opacity: 0; - transition: opacity .2s var(--n-bezier); - content: ""; - `),$("&:hover",[$("&::before","opacity: 1;"),f("upload-file-info",[I("thumbnail","opacity: .12;")])])]),C("error-status",[$("&:hover",` - background-color: var(--n-item-color-hover-error); - `),f("upload-file-info",[I("name","color: var(--n-item-text-color-error);"),I("thumbnail","color: var(--n-item-text-color-error);")]),C("image-card-type",` - border: var(--n-item-border-image-card-error); - `)]),C("with-url",` - cursor: pointer; - `,[f("upload-file-info",[I("name",` - color: var(--n-item-text-color-success); - text-decoration-color: var(--n-item-text-color-success); - `,[$("a",` - text-decoration: underline; - `)])])]),f("upload-file-info",` - position: relative; - padding-top: 6px; - padding-bottom: 6px; - display: flex; - flex-wrap: nowrap; - `,[I("thumbnail",` - font-size: 18px; - opacity: 1; - transition: opacity .2s var(--n-bezier); - color: var(--n-item-icon-color); - `,[f("base-icon",` - margin-right: 2px; - vertical-align: middle; - transition: color .3s var(--n-bezier); - `)]),I("action",` - padding-top: inherit; - padding-bottom: inherit; - position: absolute; - right: 0; - top: 0; - bottom: 0; - width: 80px; - display: flex; - align-items: center; - transition: opacity .2s var(--n-bezier); - justify-content: flex-end; - opacity: 0; - `,[f("button",[$("&:not(:last-child)",{marginRight:"4px"}),f("base-icon",[$("svg",[$e()])])]),C("image-type",` - position: relative; - max-width: 80px; - width: auto; - `),C("image-card-type",` - z-index: 2; - position: absolute; - width: 100%; - height: 100%; - left: 0; - right: 0; - bottom: 0; - top: 0; - display: flex; - justify-content: center; - align-items: center; - `)]),I("name",` - color: var(--n-item-text-color); - flex: 1; - display: flex; - justify-content: center; - text-overflow: ellipsis; - overflow: hidden; - flex-direction: column; - text-decoration-color: #0000; - font-size: var(--n-font-size); - transition: - color .3s var(--n-bezier), - text-decoration-color .3s var(--n-bezier); - `,[$("a",` - color: inherit; - text-decoration: underline; - `)])])])]),f("upload-file-input",` - display: block; - width: 0; - height: 0; - opacity: 0; - `)]),Z=globalThis&&globalThis.__awaiter||function(e,n,i,r){function l(o){return o instanceof i?o:new i(function(c){c(o)})}return new(i||(i=Promise))(function(o,c){function g(a){try{d(r.next(a))}catch(u){c(u)}}function s(a){try{d(r.throw(a))}catch(u){c(u)}}function d(a){a.done?o(a.value):l(a.value).then(g,s)}d((r=r.apply(e,n||[])).next())})};function st(e,n,i){const{doChange:r,XhrMap:l}=e;let o=0;function c(s){var d;let a=Object.assign({},n,{status:"error",percentage:o});l.delete(n.id),a=((d=e.onError)===null||d===void 0?void 0:d.call(e,{file:a,event:s}))||a,r(a,s)}function g(s){var d;if(i.status<200||i.status>=300){c(s);return}let a=Object.assign({},n,{status:"finished",percentage:o,file:null});l.delete(n.id),a=((d=e.onFinish)===null||d===void 0?void 0:d.call(e,{file:a,event:s}))||a,r(a,s)}return{handleXHRLoad:g,handleXHRError:c,handleXHRAbort(s){const d=Object.assign({},n,{status:"removed",file:null,percentage:o});l.delete(n.id),r(d,s)},handleXHRProgress(s){const d=Object.assign({},n,{status:"uploading"});if(s.lengthComputable){const a=Math.ceil(s.loaded/s.total*100);d.percentage=a,o=a}r(d,s)}}}function dt(e){const{inst:n,file:i,data:r,headers:l,withCredentials:o,action:c,customRequest:g}=e,{doChange:s}=e.inst;let d=0;g({file:i,data:r,headers:l,withCredentials:o,action:c,onProgress(a){const u=Object.assign({},i,{status:"uploading"}),b=a.percent;u.percentage=b,d=b,s(u)},onFinish(){var a;let u=Object.assign({},i,{status:"finished",percentage:d,file:null});u=((a=n.onFinish)===null||a===void 0?void 0:a.call(n,{file:u}))||u,s(u)},onError(){var a;let u=Object.assign({},i,{status:"error",percentage:d});u=((a=n.onError)===null||a===void 0?void 0:a.call(n,{file:u}))||u,s(u)}})}function ct(e,n,i){const r=st(e,n,i);i.onabort=r.handleXHRAbort,i.onerror=r.handleXHRError,i.onload=r.handleXHRLoad,i.upload&&(i.upload.onprogress=r.handleXHRProgress)}function ge(e,n){return typeof e=="function"?e({file:n}):e||{}}function ut(e,n,i){const r=ge(n,i);!r||Object.keys(r).forEach(l=>{e.setRequestHeader(l,r[l])})}function gt(e,n,i){const r=ge(n,i);!r||Object.keys(r).forEach(l=>{e.append(l,r[l])})}function ft(e,n,i,{method:r,action:l,withCredentials:o,headers:c,data:g}){const s=new XMLHttpRequest;e.XhrMap.set(i.id,s),s.withCredentials=o;const d=new FormData;if(gt(d,g,i),d.append(n,i.file),ct(e,i,s),l!==void 0){s.open(r.toUpperCase(),l),ut(s,c,i),s.send(d);const a=Object.assign({},i,{status:"uploading"});e.doChange(a)}}const pt=Object.assign(Object.assign({},G.props),{name:{type:String,default:"file"},accept:String,action:String,customRequest:Function,method:{type:String,default:"POST"},multiple:Boolean,showFileList:{type:Boolean,default:!0},data:[Object,Function],headers:[Object,Function],withCredentials:Boolean,disabled:{type:Boolean,default:void 0},onChange:Function,onRemove:Function,onFinish:Function,onError:Function,onBeforeUpload:Function,onDownload:Function,defaultUpload:{type:Boolean,default:!0},fileList:Array,"onUpdate:fileList":[Function,Array],onUpdateFileList:[Function,Array],fileListStyle:[String,Object],defaultFileList:{type:Array,default:()=>[]},showCancelButton:{type:Boolean,default:!0},showRemoveButton:{type:Boolean,default:!0},showDownloadButton:Boolean,showRetryButton:{type:Boolean,default:!0},showPreviewButton:{type:Boolean,default:!0},listType:{type:String,default:"text"},onPreview:Function,createThumbnailUrl:Function,abstract:Boolean,max:Number,showTrigger:{type:Boolean,default:!0},imageGroupProps:Object,inputProps:Object});var mt=A({name:"Upload",props:pt,setup(e){e.abstract&&e.listType==="image-card"&&Y("upload","when the list-type is image-card, abstract is not supported.");const{mergedClsPrefixRef:n,inlineThemeDisabled:i}=ae(e),r=G("Upload","-upload",lt,Le,e,n),l=Te(e),o=R(()=>{const{max:m}=e;return m!==void 0?b.value.length>=m:!1}),c=M(e.defaultFileList),g=D(e,"fileList"),s=M(null),d={value:!1},a=M(!1),u=new Map,b=Se(g,c);function h(){var m;(m=s.value)===null||m===void 0||m.click()}function k(m){const P=m.target;B(P.files,m),P.value=""}function y(m){const{"onUpdate:fileList":P,onUpdateFileList:S}=e;P&&ee(P,m),S&&ee(S,m),c.value=m}function B(m,P){if(!m||m.length===0)return;const{onBeforeUpload:S}=e;let _=e.multiple?Array.from(m):[m[0]];const{max:U}=e;U&&(_=_.slice(0,U-b.value.length)),Promise.all(_.map(L=>Z(this,void 0,void 0,function*(){const z={id:Ie(),name:L.name,status:"pending",percentage:0,file:L,url:null,type:L.type,thumbnailUrl:null};return!S||(yield S({file:z,fileList:b.value}))!==!1?z:null}))).then(L=>Z(this,void 0,void 0,function*(){let z=Promise.resolve();return L.forEach(F=>{z=z.then(Oe).then(()=>{F&&x(F,P,{append:!0})})}),yield z})).then(()=>{e.defaultUpload&&w()})}function w(m){const{method:P,action:S,withCredentials:_,headers:U,data:L,name:z}=e,F=m!==void 0?b.value.filter(N=>N.id===m):b.value,K=m!==void 0;F.forEach(N=>{const{status:X}=N;(X==="pending"||X==="error"&&K)&&(e.customRequest?dt({inst:{doChange:x,XhrMap:u,onFinish:e.onFinish,onError:e.onError},file:N,action:S,withCredentials:_,headers:U,data:L,customRequest:e.customRequest}):ft({doChange:x,XhrMap:u,onFinish:e.onFinish,onError:e.onError},z,N,{method:P,action:S,withCredentials:_,headers:U,data:L}))})}const x=(m,P,S={append:!1,remove:!1})=>{const{append:_,remove:U}=S,L=Array.from(b.value),z=L.findIndex(F=>F.id===m.id);if(_||U||~z){_?L.push(m):U?L.splice(z,1):L.splice(z,1,m);const{onChange:F}=e;F&&F({file:m,fileList:L,event:P}),y(L)}};function O(m){return Z(this,void 0,void 0,function*(){const{createThumbnailUrl:P}=e;return P?yield P(m.file):yield Qe(m.file)})}const p=R(()=>{const{common:{cubicBezierEaseInOut:m},self:{draggerColor:P,draggerBorder:S,draggerBorderHover:_,itemColorHover:U,itemColorHoverError:L,itemTextColorError:z,itemTextColorSuccess:F,itemTextColor:K,itemIconColor:N,itemDisabledOpacity:X,lineHeight:fe,borderRadius:pe,fontSize:he,itemBorderImageCardError:me,itemBorderImageCard:ve}}=r.value;return{"--n-bezier":m,"--n-border-radius":pe,"--n-dragger-border":S,"--n-dragger-border-hover":_,"--n-dragger-color":P,"--n-font-size":he,"--n-item-color-hover":U,"--n-item-color-hover-error":L,"--n-item-disabled-opacity":X,"--n-item-icon-color":N,"--n-item-text-color":K,"--n-item-text-color-error":z,"--n-item-text-color-success":F,"--n-line-height":fe,"--n-item-border-image-card-error":me,"--n-item-border-image-card":ve}}),v=i?le("upload",void 0,p,e):void 0;ze(H,{mergedClsPrefixRef:n,mergedThemeRef:r,showCancelButtonRef:D(e,"showCancelButton"),showDownloadButtonRef:D(e,"showDownloadButton"),showRemoveButtonRef:D(e,"showRemoveButton"),showRetryButtonRef:D(e,"showRetryButton"),onRemoveRef:D(e,"onRemove"),onDownloadRef:D(e,"onDownload"),mergedFileListRef:b,XhrMap:u,submit:w,doChange:x,showPreviewButtonRef:D(e,"showPreviewButton"),onPreviewRef:D(e,"onPreview"),getFileThumbnailUrl:O,listTypeRef:D(e,"listType"),dragOverRef:a,openOpenFileDialog:h,draggerInsideRef:d,handleFileAddition:B,mergedDisabledRef:l.mergedDisabledRef,maxReachedRef:o,fileListStyleRef:D(e,"fileListStyle"),abstractRef:D(e,"abstract"),cssVarsRef:i?void 0:p,themeClassRef:v==null?void 0:v.themeClass,onRender:v==null?void 0:v.onRender,showTriggerRef:D(e,"showTrigger"),imageGroupPropsRef:D(e,"imageGroupProps")});const T={clear:()=>{c.value=[]},submit:w,openOpenFileDialog:h};return Object.assign({mergedClsPrefix:n,draggerInsideRef:d,inputElRef:s,mergedTheme:r,dragOver:a,handleFileInputChange:k,cssVars:i?void 0:p,themeClass:v==null?void 0:v.themeClass,onRender:v==null?void 0:v.onRender},T)},render(){var e,n;const{draggerInsideRef:i,mergedClsPrefix:r,$slots:l,onRender:o}=this;if(l.default&&!this.abstract){const g=l.default()[0];!((e=g==null?void 0:g.type)===null||e===void 0)&&e[de]&&(i.value=!0)}const c=t("input",Object.assign({},this.inputProps,{ref:"inputElRef",type:"file",class:`${r}-upload-file-input`,accept:this.accept,multiple:this.multiple,onChange:this.handleFileInputChange}));return this.abstract?t(_e,null,(n=l.default)===null||n===void 0?void 0:n.call(l),t(De,{to:"body"},c)):(o==null||o(),t("div",{class:[`${r}-upload`,i.value&&`${r}-upload--dragger-inside`,this.dragOver&&`${r}-upload--drag-over`,this.themeClass],style:this.cssVars},c,this.showTrigger&&this.listType!=="image-card"&&t(ue,null,l),this.showFileList&&t(at,null,l)))}});export{ue as _,Ge as a,at as b,mt as c}; diff --git a/web/dist/assets/User.695fa64f.js b/web/dist/assets/User.695fa64f.js deleted file mode 100644 index de15fe8c..00000000 --- a/web/dist/assets/User.695fa64f.js +++ /dev/null @@ -1,22 +0,0 @@ -import{_ as ye}from"./post-item.03452002.js";import{_ as be}from"./post-skeleton.39a35f5b.js";import{D as Ce,c as V,c5 as ke,l as H,p as xe,o as j,d as R,u as G,q as A,r as h,s as E,h as I,af as Be,b2 as Fe,i as Ee,c6 as Se,be as De,b as T,bd as $e,v as q,y as Te,ah as W,V as C,a5 as z,a4 as _,Y as k,a3 as l,a8 as S,a9 as D,c7 as ze,_ as K,J as P,bp as J,c8 as Re,c9 as Ae,Z as Ie,ai as We,ca as Pe,S as Oe,a1 as Ue,ae as Le,W as F,cb as je,a2 as m,a6 as $,aa as qe,ab as Me,c4 as Ne,cc as Ve,cd as He,ad as Ge,an as Ke,bX as Je,b_ as Xe,c1 as Ye,c2 as Ze}from"./index.f480f018.js";import{u as Qe,a as es,_ as ss}from"./Skeleton.57e98fe3.js";import{_ as X}from"./Alert.a854329b.js";import{_ as ts}from"./main-nav.9110259b.js";import{M as ns}from"./MoreHorizFilled.80db5156.js";import{_ as os}from"./List.49bcdf81.js";import{_ as as}from"./Pagination.1263479e.js";import"./content.ef1e095a.js";import"./formatTime.02109bf5.js";import"./Thing.eef6b133.js";const ls=Ce({name:"Ellipsis",common:V,peers:{Tooltip:ke}});var is=ls,us=H("ellipsis",{overflow:"hidden"},[xe("line-clamp",` - white-space: nowrap; - display: inline-block; - vertical-align: bottom; - max-width: 100%; - `),j("line-clamp",` - display: -webkit-inline-box; - -webkit-box-orient: vertical; - `),j("cursor-pointer",` - cursor: pointer; - `)]);function M(e){return`${e}-ellipsis--line-clamp`}function N(e,u){return`${e}-ellipsis--cursor-${u}`}const rs=Object.assign(Object.assign({},A.props),{expandTrigger:String,lineClamp:[Number,String],tooltip:{type:[Boolean,Object],default:!0}});var Y=R({name:"Ellipsis",inheritAttrs:!1,props:rs,setup(e,{slots:u,attrs:r}){const{mergedClsPrefixRef:n}=G(e),i=A("Ellipsis","-ellipsis",us,is,e,n),s=h(null),c=h(null),f=h(!1),p=E(()=>{const{lineClamp:t}=e,{value:d}=f;return t!==void 0?{textOverflow:"","-webkit-line-clamp":d?"":t}:{textOverflow:d?"":"ellipsis","-webkit-line-clamp":""}});function a(){let t=!1;const{value:d}=f;if(d)return!0;const{value:g}=s;if(g){const{lineClamp:B}=e;b(g),B!==void 0?t=g.scrollHeight<=g.offsetHeight:t=g.scrollWidth<=g.offsetWidth,x(g,t)}return t}const v=E(()=>e.expandTrigger==="click"?()=>{var t;const{value:d}=f;d&&((t=c.value)===null||t===void 0||t.setShow(!1)),f.value=!d}:void 0),y=()=>I("span",Object.assign({},Fe(r,{class:[`${n.value}-ellipsis`,e.lineClamp!==void 0?M(n.value):void 0,e.expandTrigger==="click"?N(n.value,"pointer"):void 0],style:p.value}),{ref:"triggerRef",onClick:v.value,onMouseenter:e.expandTrigger==="click"?a:void 0}),u);function b(t){if(!t)return;const d=p.value,g=M(n.value);e.lineClamp!==void 0?w(t,g,"add"):w(t,g,"remove");for(const B in d)t.style[B]!==d[B]&&(t.style[B]=d[B])}function x(t,d){const g=N(n.value,"pointer");e.expandTrigger==="click"&&!d?w(t,g,"add"):w(t,g,"remove")}function w(t,d,g){g==="add"?t.classList.contains(d)||t.classList.add(d):t.classList.contains(d)&&t.classList.remove(d)}return{mergedTheme:i,triggerRef:s,tooltipRef:c,handleClick:v,renderTrigger:y,getTooltipDisabled:a}},render(){var e;const{tooltip:u,renderTrigger:r,$slots:n}=this;if(u){const{mergedTheme:i}=this;return I(Be,Object.assign({ref:"tooltipRef",placement:"top"},u,{getDisabled:this.getTooltipDisabled,theme:i.peers.Tooltip,themeOverrides:i.peerOverrides.Tooltip}),{trigger:r,default:(e=n.tooltip)!==null&&e!==void 0?e:n.default})}else return r()}});function cs(){const e=Ee(Se,null);return e===null&&De("use-dialog","No outer founded."),e}const ds=e=>{const{primaryColor:u,successColor:r,warningColor:n,errorColor:i,infoColor:s,fontWeightStrong:c}=e;return{fontWeight:c,rotate:"252deg",colorStartPrimary:T(u,{alpha:.6}),colorEndPrimary:u,colorStartInfo:T(s,{alpha:.6}),colorEndInfo:s,colorStartWarning:T(n,{alpha:.6}),colorEndWarning:n,colorStartError:T(i,{alpha:.6}),colorEndError:i,colorStartSuccess:T(r,{alpha:.6}),colorEndSuccess:r}},_s={name:"GradientText",common:V,self:ds};var ps=_s,ms=H("gradient-text",` - display: inline-block; - font-weight: var(--n-font-weight); - -webkit-background-clip: text; - background-clip: text; - color: #0000; - white-space: nowrap; - background-image: linear-gradient(var(--n-rotate), var(--n-color-start) 0%, var(--n-color-end) 100%); - transition: - --n-color-start .3s var(--n-bezier), - --n-color-end .3s var(--n-bezier); -`);const fs=Object.assign(Object.assign({},A.props),{size:[String,Number],fontSize:[String,Number],type:{type:String,default:"primary"},color:[Object,String],gradient:[Object,String]});var Z=R({name:"GradientText",props:fs,setup(e){Qe();const{mergedClsPrefixRef:u,inlineThemeDisabled:r}=G(e),n=E(()=>{const{type:a}=e;return a==="danger"?"error":a}),i=E(()=>{let a=e.size||e.fontSize;return a&&(a=$e(a)),a||void 0}),s=E(()=>{const a=e.color||e.gradient;if(typeof a=="string")return a;if(a){const v=a.deg||0,y=a.from,b=a.to;return`linear-gradient(${v}deg, ${y} 0%, ${b} 100%)`}}),c=A("GradientText","-gradient-text",ms,ps,e,u),f=E(()=>{const{value:a}=n,{common:{cubicBezierEaseInOut:v},self:{rotate:y,[q("colorStart",a)]:b,[q("colorEnd",a)]:x,fontWeight:w}}=c.value;return{"--n-bezier":v,"--n-rotate":y,"--n-color-start":b,"--n-color-end":x,"--n-font-weight":w}}),p=r?Te("gradient-text",E(()=>n.value[0]),f,e):void 0;return{mergedClsPrefix:u,compatibleType:n,styleFontSize:i,styleBgImage:s,cssVars:r?void 0:f,themeClass:p==null?void 0:p.themeClass,onRender:p==null?void 0:p.onRender}},render(){const{mergedClsPrefix:e,onRender:u}=this;return u==null||u(),I("span",{class:[`${e}-gradient-text`,`${e}-gradient-text--${this.compatibleType}-type`,this.themeClass],style:[{fontSize:this.styleFontSize,backgroundImage:this.styleBgImage},this.cssVars]},this.$slots)}});const gs={class:"whisper-wrap"},hs=S(" \u5373\u5C06\u53D1\u9001\u79C1\u4FE1\u7ED9: "),vs={class:"whisper-line"},ws={class:"whisper-line send-wrap"},ys=S(" \u53D1\u9001 "),bs=R({props:{show:{type:Boolean,default:!1},user:null},emits:["success"],setup(e,{emit:u}){const r=e,n=h(""),i=h(!1),s=()=>{u("success")},c=()=>{i.value=!0,ze({user_id:r.user.id,content:n.value}).then(f=>{window.$message.success("\u53D1\u9001\u6210\u529F"),i.value=!1,n.value="",s()}).catch(f=>{i.value=!1})};return(f,p)=>{const a=Z,v=Y,y=X,b=K,x=P,w=J;return C(),z(w,{show:e.show,"onUpdate:show":s,class:"whisper-card",preset:"card",size:"small",title:"\u79C1\u4FE1","mask-closable":!1,bordered:!1,style:{width:"360px"}},{default:_(()=>[k("div",gs,[l(y,{"show-icon":!1},{default:_(()=>[hs,l(v,{style:{"max-width":"100%"}},{default:_(()=>[l(a,{type:"success"},{default:_(()=>[S(D(e.user.nickname)+"@"+D(e.user.username),1)]),_:1})]),_:1})]),_:1}),k("div",vs,[l(b,{type:"textarea",placeholder:"\u8BF7\u8F93\u5165\u79C1\u4FE1\u5185\u5BB9\uFF08\u8BF7\u52FF\u53D1\u9001\u4E0D\u548C\u8C10\u5185\u5BB9\uFF0C\u5426\u5219\u5C06\u4F1A\u88AB\u5C01\u53F7\uFF09",autosize:{minRows:5,maxRows:10},value:n.value,"onUpdate:value":p[0]||(p[0]=t=>n.value=t),maxlength:"200","show-count":""},null,8,["value"])]),k("div",ws,[l(x,{strong:"",secondary:"",type:"primary",loading:i.value,onClick:c},{default:_(()=>[ys]),_:1},8,["loading"])])])]),_:1},8,["show"])}}});var Cs=W(bs,[["__scopeId","data-v-3e021430"]]);const ks={class:"whisper-wrap"},xs=S(" \u53D1\u9001\u6DFB\u52A0\u670B\u53CB\u7533\u8BF7\u7ED9: "),Bs={class:"whisper-line"},Fs={class:"whisper-line send-wrap"},Es=S(" \u53D1\u9001 "),Ss=R({props:{show:{type:Boolean,default:!1},user:null},emits:["success"],setup(e,{emit:u}){const r=e,n=h(""),i=h(!1),s=()=>{u("success")},c=()=>{i.value=!0,Re({user_id:r.user.id,greetings:n.value}).then(f=>{window.$message.success("\u53D1\u9001\u6210\u529F"),i.value=!1,n.value="",s()}).catch(f=>{i.value=!1})};return(f,p)=>{const a=Z,v=Y,y=X,b=K,x=P,w=J;return C(),z(w,{show:e.show,"onUpdate:show":s,class:"whisper-card",preset:"card",size:"small",title:"\u7533\u8BF7\u6DFB\u52A0\u670B\u53CB","mask-closable":!1,bordered:!1,style:{width:"360px"}},{default:_(()=>[k("div",ks,[l(y,{"show-icon":!1},{default:_(()=>[xs,l(v,{style:{"max-width":"100%"}},{default:_(()=>[l(a,{type:"success"},{default:_(()=>[S(D(e.user.nickname)+"@"+D(e.user.username),1)]),_:1})]),_:1})]),_:1}),k("div",Bs,[l(b,{type:"textarea",placeholder:"\u8BF7\u8F93\u5165\u771F\u631A\u7684\u95EE\u5019\u8BED",autosize:{minRows:5,maxRows:10},value:n.value,"onUpdate:value":p[0]||(p[0]=t=>n.value=t),maxlength:"120","show-count":""},null,8,["value"])]),k("div",Fs,[l(x,{strong:"",secondary:"",type:"primary",loading:i.value,onClick:c},{default:_(()=>[Es]),_:1},8,["loading"])])])]),_:1},8,["show"])}}});var Ds=W(Ss,[["__scopeId","data-v-bf9bc04e"]]);const $s={key:0,class:"profile-baseinfo"},Ts={class:"avatar"},zs={class:"base-info"},Rs={class:"username"},As=S(" \u597D\u53CB "),Is=S(" \u7BA1\u7406\u5458 "),Ws={class:"uid"},Ps={key:0,class:"user-opts"},Os={key:0,class:"pagination-wrap"},Us={key:0,class:"skeleton-wrap"},Ls={key:1},js={key:0,class:"empty-wrap"},qs=R({setup(e){Ae();const u=cs(),r=Ie(),n=We(),i=h(!1),s=Pe({id:0,avatar:"",username:"",nickname:"",is_admin:!1,is_friend:!0,status:1}),c=h(!1),f=h(!1),p=h(!1),a=h([]),v=h(n.query.username||""),y=h(+n.query.p||1),b=h(20),x=h(0),w=()=>{i.value=!0,Ne({username:v.value,page:y.value,page_size:b.value}).then(o=>{i.value=!1,a.value=o.list,x.value=Math.ceil(o.pager.total_rows/b.value),window.scrollTo(0,0)}).catch(o=>{i.value=!1})},t=()=>{c.value=!0,je({username:v.value}).then(o=>{c.value=!1,s.id=o.id,s.avatar=o.avatar,s.username=o.username,s.nickname=o.nickname,s.is_admin=o.is_admin,s.is_friend=o.is_friend,s.status=o.status,w()}).catch(o=>{c.value=!1,console.log(o)})},d=o=>{y.value=o,w()},g=()=>{f.value=!0},B=()=>{p.value=!0},Q=()=>{f.value=!1},ee=()=>{p.value=!1},se=E(()=>{let o=[{label:"\u79C1\u4FE1",key:"whisper"}];return r.state.userInfo.is_admin&&(s.status===1?o.push({label:"\u7981\u8A00",key:"banned"}):o.push({label:"\u89E3\u5C01",key:"deblocking"})),s.is_friend?o.push({label:"\u5220\u9664\u597D\u53CB",key:"delete"}):o.push({label:"\u6DFB\u52A0\u670B\u53CB",key:"requesting"}),o}),te=o=>{switch(o){case"whisper":g();break;case"delete":ne();break;case"requesting":B();break;case"banned":case"deblocking":oe();break}},ne=()=>{u.warning({title:"\u5220\u9664\u597D\u53CB",content:"\u5C06\u597D\u53CB \u201C"+s.nickname+"\u201D \u5220\u9664\uFF0C\u5C06\u540C\u65F6\u5220\u9664 \u70B9\u8D5E/\u6536\u85CF \u5217\u8868\u4E2D\u5173\u4E8E\u8BE5\u670B\u53CB\u7684 \u201C\u597D\u53CB\u53EF\u89C1\u201D \u63A8\u6587",positiveText:"\u786E\u5B9A",negativeText:"\u53D6\u6D88",onPositiveClick:()=>{c.value=!0,Ve({user_id:s.id}).then(o=>{c.value=!1,s.is_friend=!1,w()}).catch(o=>{c.value=!1,console.log(o)})}})},oe=()=>{u.warning({title:"\u8B66\u544A",content:"\u786E\u5B9A\u5BF9\u8BE5\u7528\u6237\u8FDB\u884C"+(s.status===1?"\u7981\u8A00":"\u89E3\u5C01")+"\u5904\u7406\u5417\uFF1F",positiveText:"\u786E\u5B9A",negativeText:"\u53D6\u6D88",onPositiveClick:()=>{c.value=!0,He({id:s.id,status:s.status===1?2:1}).then(o=>{c.value=!1,t()}).catch(o=>{c.value=!1,console.log(o)})}})};return Oe(()=>({path:n.path,query:n.query}),(o,O)=>{O.path==="/user"&&o.path==="/user"&&(v.value=n.query.username||"",t())}),Ue(()=>{t()}),(o,O)=>{const ae=ts,le=Ge,U=Ke,ie=Le,ue=P,re=Je,ce=Cs,de=Xe,_e=as,pe=Ye,me=Ze,fe=be,ge=es,he=ye,ve=ss,we=os;return C(),F("div",null,[l(ae,{title:"\u7528\u6237\u8BE6\u60C5"}),l(we,{class:"main-content-wrap profile-wrap",bordered:""},{footer:_(()=>[x.value>0?(C(),F("div",Os,[l(_e,{page:y.value,"onUpdate:page":d,"page-slot":m(r).state.collapsedRight?5:8,"page-count":x.value},null,8,["page","page-slot","page-count"])])):$("",!0)]),default:_(()=>[l(de,{show:c.value},{default:_(()=>[m(s).id>0?(C(),F("div",$s,[k("div",Ts,[l(le,{size:"large",src:m(s).avatar},null,8,["src"])]),k("div",zs,[k("div",Rs,[k("strong",null,D(m(s).nickname),1),k("span",null," @"+D(m(s).username),1),m(r).state.userInfo.id>0&&m(r).state.userInfo.username!=m(s).username&&m(s).is_friend?(C(),z(U,{key:0,class:"top-tag",type:"info",size:"small",round:""},{default:_(()=>[As]),_:1})):$("",!0),m(s).is_admin?(C(),z(U,{key:1,class:"top-tag",type:"error",size:"small",round:""},{default:_(()=>[Is]),_:1})):$("",!0)]),k("div",Ws,"UID. "+D(m(s).id),1)]),m(r).state.userInfo.id>0&&m(r).state.userInfo.username!=m(s).username?(C(),F("div",Ps,[l(re,{placement:"bottom-end",trigger:"click",size:"small",options:m(se),onSelect:te},{default:_(()=>[l(ue,{quaternary:"",circle:""},{icon:_(()=>[l(ie,null,{default:_(()=>[l(m(ns))]),_:1})]),_:1})]),_:1},8,["options"])])):$("",!0)])):$("",!0),l(ce,{show:f.value,user:m(s),onSuccess:Q},null,8,["show","user"]),l(Ds,{show:p.value,user:m(s),onSuccess:ee},null,8,["show","user"])]),_:1},8,["show"]),l(me,{class:"profile-tabs-wrap",animated:""},{default:_(()=>[l(pe,{name:"post",tab:"\u6CE1\u6CE1"})]),_:1}),i.value?(C(),F("div",Us,[l(fe,{num:b.value},null,8,["num"])])):(C(),F("div",Ls,[a.value.length===0?(C(),F("div",js,[l(ge,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):$("",!0),(C(!0),F(qe,null,Me(a.value,L=>(C(),z(ve,{key:L.id},{default:_(()=>[l(he,{post:L},null,8,["post"])]),_:2},1024))),128))]))]),_:1})])}}});var st=W(qs,[["__scopeId","data-v-7a6aaa02"]]);export{st as default}; diff --git a/web/dist/assets/Wallet.b8e2b626.js b/web/dist/assets/Wallet.b8e2b626.js deleted file mode 100644 index 81bbc1a3..00000000 --- a/web/dist/assets/Wallet.b8e2b626.js +++ /dev/null @@ -1,30 +0,0 @@ -import{_ as se}from"./post-skeleton.39a35f5b.js";import{_ as ae}from"./main-nav.9110259b.js";import{co as Lt,cp as It,cq as ue,d as st,I as ce,r as D,s as _t,a1 as kt,aK as le,l as W,m as Z,u as fe,q as Ut,cr as de,y as ge,h as x,z as X,V as P,W as L,Y as S,ah as he,Z as me,ai as pe,ae as _e,a3 as b,a4 as I,cs as we,bp as ye,a2 as tt,a6 as et,aa as St,ab as Tt,aY as Ce,aZ as ve,a9 as $,a8 as at,bM as Ee,bN as Be,ct as be,cu as Ae,cv as Ne,J as Ie,ag as Se,ck as Te,az as Me,a5 as Mt,c3 as Pe,a7 as Re}from"./index.f480f018.js";import{f as Fe}from"./formatTime.02109bf5.js";import{_ as De}from"./List.49bcdf81.js";import{_ as Le}from"./Pagination.1263479e.js";import{a as ke,_ as Ue}from"./Skeleton.57e98fe3.js";var Pt=1/0,ze=17976931348623157e292;function Ve(e){if(!e)return e===0?e:0;if(e=Lt(e),e===Pt||e===-Pt){var t=e<0?-1:1;return t*ze}return e===e?e:0}function xe(e){var t=Ve(e),i=t%1;return t===t?i?t-i:t:0}var $e=ue.isFinite,He=Math.min;function Ke(e){var t=Math[e];return function(i,r){if(i=Lt(i),r=r==null?0:He(xe(r),292),r&&$e(i)){var o=(It(i)+"e").split("e"),n=t(o[0]+"e"+(+o[1]+r));return o=(It(n)+"e").split("e"),+(o[0]+"e"+(+o[1]-r))}return t(i)}}var Oe=Ke("round"),Je=Oe;const Ye=e=>1-Math.pow(1-e,5);function qe(e){const{from:t,to:i,duration:r,onUpdate:o,onFinish:n}=e,s=()=>{const a=performance.now(),c=Math.min(a-u,r),l=t+(i-t)*Ye(c/r);if(c===r){n();return}o(l),requestAnimationFrame(s)},u=performance.now();s()}const je={to:{type:Number,default:0},precision:{type:Number,default:0},showSeparator:Boolean,locale:String,from:{type:Number,default:0},active:{type:Boolean,default:!0},duration:{type:Number,default:2e3}};var Ge=st({name:"NumberAnimation",props:je,setup(e){const{localeRef:t}=ce("name"),{duration:i}=e,r=D(e.from),o=_t(()=>{const{locale:f}=e;return f!==void 0?f:t.value});let n=!1;const s=f=>{r.value=f},u=()=>{r.value=e.to,n=!1},a=(f=e.from,g=e.to)=>{n=!0,r.value=e.from,f!==g&&qe({from:f,to:g,duration:i,onUpdate:s,onFinish:u})},c=_t(()=>{var f;const p=Je(r.value,e.precision).toFixed(e.precision).split("."),_=new Intl.NumberFormat(o.value),E=(f=_.formatToParts(.5).find(d=>d.type==="decimal"))===null||f===void 0?void 0:f.value,m=e.showSeparator?_.format(Number(p[0])):p[0],w=p[1];return{integer:m,decimal:w,decimalSeparator:E}});function l(){n||a()}return kt(()=>{le(()=>{e.active&&a()})}),Object.assign({formattedValue:c},{play:l})},render(){const{formattedValue:{integer:e,decimal:t,decimalSeparator:i}}=this;return[e,t?i:null,t]}}),Qe=W("statistic",[Z("label",` - font-weight: var(--n-label-font-weight); - transition: .3s color var(--n-bezier); - font-size: var(--n-label-font-size); - color: var(--n-label-text-color); - `),W("statistic-value",` - margin-top: 4px; - font-weight: var(--n-value-font-weight); - `,[Z("prefix",` - margin: 0 4px 0 0; - font-size: 24px; - transition: .3s color var(--n-bezier); - color: var(--n-value-prefix-text-color); - `,[W("icon",{verticalAlign:"-0.125em"})]),Z("content",` - font-size: 24px; - transition: .3s color var(--n-bezier); - color: var(--n-value-text-color); - `),Z("suffix",` - margin: 0 0 0 4px; - font-size: 24px; - transition: .3s color var(--n-bezier); - color: var(--n-value-suffix-text-color); - `,[W("icon",{verticalAlign:"-0.125em"})])])]);const We=Object.assign(Object.assign({},Ut.props),{tabularNums:Boolean,label:String,value:[String,Number]});var Ze=st({name:"Statistic",props:We,setup(e){const{mergedClsPrefixRef:t,inlineThemeDisabled:i}=fe(e),r=Ut("Statistic","-statistic",Qe,de,e,t),o=_t(()=>{const{self:{labelFontWeight:s,valueFontWeight:u,valuePrefixTextColor:a,labelTextColor:c,valueSuffixTextColor:l,valueTextColor:y,labelFontSize:f},common:{cubicBezierEaseInOut:g}}=r.value;return{"--n-bezier":g,"--n-label-font-size":f,"--n-label-font-weight":s,"--n-label-text-color":c,"--n-value-font-weight":u,"--n-value-prefix-text-color":a,"--n-value-suffix-text-color":l,"--n-value-text-color":y}}),n=i?ge("statistic",void 0,o,e):void 0;return{mergedClsPrefix:t,cssVars:i?void 0:o,themeClass:n==null?void 0:n.themeClass,onRender:n==null?void 0:n.onRender}},render(){var e;const{mergedClsPrefix:t,$slots:{default:i,label:r,prefix:o,suffix:n}}=this;return(e=this.onRender)===null||e===void 0||e.call(this),x("div",{class:[`${t}-statistic`,this.themeClass],style:this.cssVars},X(r,s=>x("div",{class:`${t}-statistic__label`},this.label||s)),x("div",{class:`${t}-statistic-value`,style:{fontVariantNumeric:this.tabularNums?"tabular-nums":""}},X(o,s=>s&&x("span",{class:`${t}-statistic-value__prefix`},s)),this.value!==void 0?x("span",{class:`${t}-statistic-value__content`},this.value):X(i,s=>s&&x("span",{class:`${t}-statistic-value__content`},s)),X(n,s=>s&&x("span",{class:`${t}-statistic-value__suffix`},s))))}});const Xe={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},tn=S("path",{d:"M102.41 32C62.38 32 32 64.12 32 103.78v304.45C32 447.86 64.38 480 104.41 480h303.2c40 0 72.39-32.14 72.39-71.77v-3.11c-1.35-.56-115.47-48.57-174.5-76.7c-39.82 48.57-91.18 78-144.5 78c-90.18 0-120.8-78.22-78.1-129.72c9.31-11.22 25.15-21.94 49.73-28c38.45-9.36 99.64 5.85 157 24.61a309.41 309.41 0 0 0 25.46-61.67H138.34V194h91.13v-31.83H119.09v-17.75h110.38V99s0-7.65 7.82-7.65h44.55v53H391v17.75H281.84V194h89.08a359.41 359.41 0 0 1-37.72 94.43c27 9.69 49.31 18.88 67.39 24.89c60.32 20 77.23 22.45 79.41 22.7V103.78C480 64.12 447.6 32 407.61 32h-305.2zM152 274.73q-5.81.06-11.67.63c-11.3 1.13-32.5 6.07-44.09 16.23c-34.74 30-13.94 84.93 56.37 84.93c40.87 0 81.71-25.9 113.79-67.37c-41.36-20-77-34.85-114.4-34.42z",fill:"currentColor"},null,-1),en=[tn];var nn=st({name:"LogoAlipay",render:function(t,i){return P(),L("svg",Xe,en)}}),G={},on=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then},zt={},T={};let Et;const rn=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];T.getSymbolSize=function(t){if(!t)throw new Error('"version" cannot be null or undefined');if(t<1||t>40)throw new Error('"version" should be in range from 1 to 40');return t*4+17};T.getSymbolTotalCodewords=function(t){return rn[t]};T.getBCHDigit=function(e){let t=0;for(;e!==0;)t++,e>>>=1;return t};T.setToSJISFunction=function(t){if(typeof t!="function")throw new Error('"toSJISFunc" is not a valid function.');Et=t};T.isKanjiModeEnabled=function(){return typeof Et!="undefined"};T.toSJIS=function(t){return Et(t)};var ut={};(function(e){e.L={bit:1},e.M={bit:0},e.Q={bit:3},e.H={bit:2};function t(i){if(typeof i!="string")throw new Error("Param is not a string");switch(i.toLowerCase()){case"l":case"low":return e.L;case"m":case"medium":return e.M;case"q":case"quartile":return e.Q;case"h":case"high":return e.H;default:throw new Error("Unknown EC Level: "+i)}}e.isValid=function(r){return r&&typeof r.bit!="undefined"&&r.bit>=0&&r.bit<4},e.from=function(r,o){if(e.isValid(r))return r;try{return t(r)}catch{return o}}})(ut);function Vt(){this.buffer=[],this.length=0}Vt.prototype={get:function(e){const t=Math.floor(e/8);return(this.buffer[t]>>>7-e%8&1)===1},put:function(e,t){for(let i=0;i>>t-i-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(e){const t=Math.floor(this.length/8);this.buffer.length<=t&&this.buffer.push(0),e&&(this.buffer[t]|=128>>>this.length%8),this.length++}};var sn=Vt;function Q(e){if(!e||e<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=e,this.data=new Uint8Array(e*e),this.reservedBit=new Uint8Array(e*e)}Q.prototype.set=function(e,t,i,r){const o=e*this.size+t;this.data[o]=i,r&&(this.reservedBit[o]=!0)};Q.prototype.get=function(e,t){return this.data[e*this.size+t]};Q.prototype.xor=function(e,t,i){this.data[e*this.size+t]^=i};Q.prototype.isReserved=function(e,t){return this.reservedBit[e*this.size+t]};var an=Q,xt={};(function(e){const t=T.getSymbolSize;e.getRowColCoords=function(r){if(r===1)return[];const o=Math.floor(r/7)+2,n=t(r),s=n===145?26:Math.ceil((n-13)/(2*o-2))*2,u=[n-7];for(let a=1;a=0&&o<=7},e.from=function(o){return e.isValid(o)?parseInt(o,10):void 0},e.getPenaltyN1=function(o){const n=o.size;let s=0,u=0,a=0,c=null,l=null;for(let y=0;y=5&&(s+=t.N1+(u-5)),c=g,u=1),g=o.get(f,y),g===l?a++:(a>=5&&(s+=t.N1+(a-5)),l=g,a=1)}u>=5&&(s+=t.N1+(u-5)),a>=5&&(s+=t.N1+(a-5))}return s},e.getPenaltyN2=function(o){const n=o.size;let s=0;for(let u=0;u=10&&(u===1488||u===93)&&s++,a=a<<1&2047|o.get(l,c),l>=10&&(a===1488||a===93)&&s++}return s*t.N3},e.getPenaltyN4=function(o){let n=0;const s=o.data.length;for(let a=0;a=0;){const s=n[0];for(let a=0;a0){const n=new Uint8Array(this.degree);return n.set(r,o),n}return r};var cn=Bt,Jt={},z={},bt={};bt.isValid=function(t){return!isNaN(t)&&t>=1&&t<=40};var k={};const Yt="[0-9]+",ln="[A-Z $%*+\\-./:]+";let j="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";j=j.replace(/u/g,"\\u");const fn="(?:(?![A-Z0-9 $%*+\\-./:]|"+j+`)(?:.|[\r -]))+`;k.KANJI=new RegExp(j,"g");k.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g");k.BYTE=new RegExp(fn,"g");k.NUMERIC=new RegExp(Yt,"g");k.ALPHANUMERIC=new RegExp(ln,"g");const dn=new RegExp("^"+j+"$"),gn=new RegExp("^"+Yt+"$"),hn=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");k.testKanji=function(t){return dn.test(t)};k.testNumeric=function(t){return gn.test(t)};k.testAlphanumeric=function(t){return hn.test(t)};(function(e){const t=bt,i=k;e.NUMERIC={id:"Numeric",bit:1<<0,ccBits:[10,12,14]},e.ALPHANUMERIC={id:"Alphanumeric",bit:1<<1,ccBits:[9,11,13]},e.BYTE={id:"Byte",bit:1<<2,ccBits:[8,16,16]},e.KANJI={id:"Kanji",bit:1<<3,ccBits:[8,10,12]},e.MIXED={bit:-1},e.getCharCountIndicator=function(n,s){if(!n.ccBits)throw new Error("Invalid mode: "+n);if(!t.isValid(s))throw new Error("Invalid version: "+s);return s>=1&&s<10?n.ccBits[0]:s<27?n.ccBits[1]:n.ccBits[2]},e.getBestModeForData=function(n){return i.testNumeric(n)?e.NUMERIC:i.testAlphanumeric(n)?e.ALPHANUMERIC:i.testKanji(n)?e.KANJI:e.BYTE},e.toString=function(n){if(n&&n.id)return n.id;throw new Error("Invalid mode")},e.isValid=function(n){return n&&n.bit&&n.ccBits};function r(o){if(typeof o!="string")throw new Error("Param is not a string");switch(o.toLowerCase()){case"numeric":return e.NUMERIC;case"alphanumeric":return e.ALPHANUMERIC;case"kanji":return e.KANJI;case"byte":return e.BYTE;default:throw new Error("Unknown mode: "+o)}}e.from=function(n,s){if(e.isValid(n))return n;try{return r(n)}catch{return s}}})(z);(function(e){const t=T,i=ct,r=ut,o=z,n=bt,s=1<<12|1<<11|1<<10|1<<9|1<<8|1<<5|1<<2|1<<0,u=t.getBCHDigit(s);function a(f,g,p){for(let _=1;_<=40;_++)if(g<=e.getCapacity(_,p,f))return _}function c(f,g){return o.getCharCountIndicator(f,g)+4}function l(f,g){let p=0;return f.forEach(function(_){p+=c(_.mode,g)+_.getBitsLength()}),p}function y(f,g){for(let p=1;p<=40;p++)if(l(f,p)<=e.getCapacity(p,g,o.MIXED))return p}e.from=function(g,p){return n.isValid(g)?parseInt(g,10):p},e.getCapacity=function(g,p,_){if(!n.isValid(g))throw new Error("Invalid QR Code version");typeof _=="undefined"&&(_=o.BYTE);const E=t.getSymbolTotalCodewords(g),m=i.getTotalCodewordsCount(g,p),w=(E-m)*8;if(_===o.MIXED)return w;const d=w-c(_,g);switch(_){case o.NUMERIC:return Math.floor(d/10*3);case o.ALPHANUMERIC:return Math.floor(d/11*2);case o.KANJI:return Math.floor(d/13);case o.BYTE:default:return Math.floor(d/8)}},e.getBestVersionForData=function(g,p){let _;const E=r.from(p,r.M);if(Array.isArray(g)){if(g.length>1)return y(g,E);if(g.length===0)return 1;_=g[0]}else _=g;return a(_.mode,_.getLength(),E)},e.getEncodedBits=function(g){if(!n.isValid(g)||g<7)throw new Error("Invalid QR Code version");let p=g<<12;for(;t.getBCHDigit(p)-u>=0;)p^=s<=0;)o^=jt<0&&(r=this.data.substr(i),o=parseInt(r,10),t.put(o,n*3+1))};var _n=H;const wn=z,dt=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function K(e){this.mode=wn.ALPHANUMERIC,this.data=e}K.getBitsLength=function(t){return 11*Math.floor(t/2)+6*(t%2)};K.prototype.getLength=function(){return this.data.length};K.prototype.getBitsLength=function(){return K.getBitsLength(this.data.length)};K.prototype.write=function(t){let i;for(i=0;i+2<=this.data.length;i+=2){let r=dt.indexOf(this.data[i])*45;r+=dt.indexOf(this.data[i+1]),t.put(r,11)}this.data.length%2&&t.put(dt.indexOf(this.data[i]),6)};var yn=K,Cn=function(t){for(var i=[],r=t.length,o=0;o=55296&&n<=56319&&r>o+1){var s=t.charCodeAt(o+1);s>=56320&&s<=57343&&(n=(n-55296)*1024+s-56320+65536,o+=1)}if(n<128){i.push(n);continue}if(n<2048){i.push(n>>6|192),i.push(n&63|128);continue}if(n<55296||n>=57344&&n<65536){i.push(n>>12|224),i.push(n>>6&63|128),i.push(n&63|128);continue}if(n>=65536&&n<=1114111){i.push(n>>18|240),i.push(n>>12&63|128),i.push(n>>6&63|128),i.push(n&63|128);continue}i.push(239,191,189)}return new Uint8Array(i).buffer};const vn=Cn,En=z;function O(e){this.mode=En.BYTE,this.data=new Uint8Array(vn(e))}O.getBitsLength=function(t){return t*8};O.prototype.getLength=function(){return this.data.length};O.prototype.getBitsLength=function(){return O.getBitsLength(this.data.length)};O.prototype.write=function(e){for(let t=0,i=this.data.length;t=33088&&i<=40956)i-=33088;else if(i>=57408&&i<=60351)i-=49472;else throw new Error("Invalid SJIS character: "+this.data[t]+` -Make sure your charset is UTF-8`);i=(i>>>8&255)*192+(i&255),e.put(i,13)}};var Nn=J,Qt={exports:{}};(function(e){var t={single_source_shortest_paths:function(i,r,o){var n={},s={};s[r]=0;var u=t.PriorityQueue.make();u.push(r,0);for(var a,c,l,y,f,g,p,_,E;!u.empty();){a=u.pop(),c=a.value,y=a.cost,f=i[c]||{};for(l in f)f.hasOwnProperty(l)&&(g=f[l],p=y+g,_=s[l],E=typeof s[l]=="undefined",(E||_>p)&&(s[l]=p,u.push(l,p),n[l]=c))}if(typeof o!="undefined"&&typeof s[o]=="undefined"){var m=["Could not find a path from ",r," to ",o,"."].join("");throw new Error(m)}return n},extract_shortest_path_from_predecessor_list:function(i,r){for(var o=[],n=r;n;)o.push(n),n=i[n];return o.reverse(),o},find_path:function(i,r,o){var n=t.single_source_shortest_paths(i,r,o);return t.extract_shortest_path_from_predecessor_list(n,o)},PriorityQueue:{make:function(i){var r=t.PriorityQueue,o={},n;i=i||{};for(n in r)r.hasOwnProperty(n)&&(o[n]=r[n]);return o.queue=[],o.sorter=i.sorter||r.default_sorter,o},default_sorter:function(i,r){return i.cost-r.cost},push:function(i,r){var o={value:i,cost:r};this.queue.push(o),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};e.exports=t})(Qt);(function(e){const t=z,i=_n,r=yn,o=Bn,n=Nn,s=k,u=T,a=Qt.exports;function c(m){return unescape(encodeURIComponent(m)).length}function l(m,w,d){const h=[];let C;for(;(C=m.exec(d))!==null;)h.push({data:C[0],index:C.index,mode:w,length:C[0].length});return h}function y(m){const w=l(s.NUMERIC,t.NUMERIC,m),d=l(s.ALPHANUMERIC,t.ALPHANUMERIC,m);let h,C;return u.isKanjiModeEnabled()?(h=l(s.BYTE,t.BYTE,m),C=l(s.KANJI,t.KANJI,m)):(h=l(s.BYTE_KANJI,t.BYTE,m),C=[]),w.concat(d,h,C).sort(function(B,A){return B.index-A.index}).map(function(B){return{data:B.data,mode:B.mode,length:B.length}})}function f(m,w){switch(w){case t.NUMERIC:return i.getBitsLength(m);case t.ALPHANUMERIC:return r.getBitsLength(m);case t.KANJI:return n.getBitsLength(m);case t.BYTE:return o.getBitsLength(m)}}function g(m){return m.reduce(function(w,d){const h=w.length-1>=0?w[w.length-1]:null;return h&&h.mode===d.mode?(w[w.length-1].data+=d.data,w):(w.push(d),w)},[])}function p(m){const w=[];for(let d=0;d=0&&u<=6&&(a===0||a===6)||a>=0&&a<=6&&(u===0||u===6)||u>=2&&u<=4&&a>=2&&a<=4?e.set(n+u,s+a,!0,!0):e.set(n+u,s+a,!1,!0))}}function Ln(e){const t=e.size;for(let i=8;i>u&1)===1,e.set(o,n,s,!0),e.set(n,o,s,!0)}function mt(e,t,i){const r=e.size,o=Rn.getEncodedBits(t,i);let n,s;for(n=0;n<15;n++)s=(o>>n&1)===1,n<6?e.set(n,8,s,!0):n<8?e.set(n+1,8,s,!0):e.set(r-15+n,8,s,!0),n<8?e.set(8,r-n-1,s,!0):n<9?e.set(8,15-n-1+1,s,!0):e.set(8,15-n-1,s,!0);e.set(r-8,8,1,!0)}function zn(e,t){const i=e.size;let r=-1,o=i-1,n=7,s=0;for(let u=i-1;u>0;u-=2)for(u===6&&u--;;){for(let a=0;a<2;a++)if(!e.isReserved(o,u-a)){let c=!1;s>>n&1)===1),e.set(o,u-a,c),n--,n===-1&&(s++,n=7)}if(o+=r,o<0||i<=o){o-=r,r=-r;break}}}function Vn(e,t,i){const r=new In;i.forEach(function(a){r.put(a.mode.bit,4),r.put(a.getLength(),Fn.getCharCountIndicator(a.mode,e)),a.write(r)});const o=ft.getSymbolTotalCodewords(e),n=Ct.getTotalCodewordsCount(e,t),s=(o-n)*8;for(r.getLengthInBits()+4<=s&&r.put(0,4);r.getLengthInBits()%8!==0;)r.putBit(0);const u=(s-r.getLengthInBits())/8;for(let a=0;a=7&&Un(a,t),zn(a,s),isNaN(r)&&(r=yt.getBestMask(a,mt.bind(null,a,i))),yt.applyMask(r,a),mt(a,i,r),{modules:a,version:t,errorCorrectionLevel:i,maskPattern:r,segments:o}}zt.create=function(t,i){if(typeof t=="undefined"||t==="")throw new Error("No input text");let r=gt.M,o,n;return typeof i!="undefined"&&(r=gt.from(i.errorCorrectionLevel,gt.M),o=it.from(i.version),n=yt.from(i.maskPattern),i.toSJISFunc&&ft.setToSJISFunction(i.toSJISFunc)),$n(t,o,r,n)};var Wt={},At={};(function(e){function t(i){if(typeof i=="number"&&(i=i.toString()),typeof i!="string")throw new Error("Color should be defined as hex string");let r=i.slice().replace("#","").split("");if(r.length<3||r.length===5||r.length>8)throw new Error("Invalid hex color: "+i);(r.length===3||r.length===4)&&(r=Array.prototype.concat.apply([],r.map(function(n){return[n,n]}))),r.length===6&&r.push("F","F");const o=parseInt(r.join(""),16);return{r:o>>24&255,g:o>>16&255,b:o>>8&255,a:o&255,hex:"#"+r.slice(0,6).join("")}}e.getOptions=function(r){r||(r={}),r.color||(r.color={});const o=typeof r.margin=="undefined"||r.margin===null||r.margin<0?4:r.margin,n=r.width&&r.width>=21?r.width:void 0,s=r.scale||4;return{width:n,scale:n?4:s,margin:o,color:{dark:t(r.color.dark||"#000000ff"),light:t(r.color.light||"#ffffffff")},type:r.type,rendererOpts:r.rendererOpts||{}}},e.getScale=function(r,o){return o.width&&o.width>=r+o.margin*2?o.width/(r+o.margin*2):o.scale},e.getImageWidth=function(r,o){const n=e.getScale(r,o);return Math.floor((r+o.margin*2)*n)},e.qrToImageData=function(r,o,n){const s=o.modules.size,u=o.modules.data,a=e.getScale(s,n),c=Math.floor((s+n.margin*2)*a),l=n.margin*a,y=[n.color.light,n.color.dark];for(let f=0;f=l&&g>=l&&f0&&a>0&&e[u-1]||(r+=n?pt("M",a+i,.5+c+i):pt("m",o,0),o=0,n=!1),a+1':"",c="',l='viewBox="0 0 '+u+" "+u+'"',y=o.width?'width="'+o.width+'" height="'+o.width+'" ':"",f=''+a+c+` -`;return typeof r=="function"&&r(null,f),f};const On=on,vt=zt,Xt=Wt,Jn=Zt;function Nt(e,t,i,r,o){const n=[].slice.call(arguments,1),s=n.length,u=typeof n[s-1]=="function";if(!u&&!On())throw new Error("Callback required as last argument");if(u){if(s<2)throw new Error("Too few arguments provided");s===2?(o=i,i=t,t=r=void 0):s===3&&(t.getContext&&typeof o=="undefined"?(o=r,r=void 0):(o=r,r=i,i=t,t=void 0))}else{if(s<1)throw new Error("Too few arguments provided");return s===1?(i=t,t=r=void 0):s===2&&!t.getContext&&(r=i,i=t,t=void 0),new Promise(function(a,c){try{const l=vt.create(i,r);a(e(l,t,r))}catch(l){c(l)}})}try{const a=vt.create(i,r);o(null,e(a,t,r))}catch(a){o(a)}}G.create=vt.create;G.toCanvas=Nt.bind(null,Xt.render);G.toDataURL=Nt.bind(null,Xt.renderToDataURL);G.toString=Nt.bind(null,function(e,t,i){return Jn.render(e,i)});const te=e=>(Ee("data-v-4ef16ff5"),e=e(),Be(),e),Yn={class:"balance-wrap"},qn={class:"balance-line"},jn={class:"balance-opts"},Gn=at(" \u5145\u503C "),Qn=at(" \u63D0\u73B0 "),Wn={key:0,class:"pagination-wrap"},Zn={key:0,class:"skeleton-wrap"},Xn={key:1},to={key:0,class:"empty-wrap"},eo={class:"bill-line"},no={key:0,class:"amount-options"},oo={key:1,style:{"margin-top":"10px"}},ro=at(" \u524D\u5F80\u652F\u4ED8 "),io={class:"qrcode-wrap"},so=te(()=>S("canvas",{id:"qrcode-container"},null,-1)),ao={class:"pay-tips"},uo={class:"pay-sub-tips"},co=te(()=>S("span",{style:{"margin-left":"6px"}}," \u652F\u4ED8\u7ED3\u679C\u5B9E\u65F6\u540C\u6B65\u4E2D... ",-1)),lo=st({setup(e){const t=me(),i=pe(),r=D(!1),o=D(100),n=D(!1),s=D(""),u=D(!1),a=D([]),c=D(+i.query.p||1),l=D(20),y=D(0),f=D([100,200,300,500,1e3,3e3,5e3,1e4,5e4]),g=()=>{u.value=!0,be({page:c.value,page_size:l.value}).then(d=>{u.value=!1,a.value=d.list,y.value=Math.ceil(d.pager.total_rows/l.value),window.scrollTo(0,0)}).catch(d=>{u.value=!1})},p=d=>{c.value=d,g()},_=()=>{const d=localStorage.getItem("PAOPAO_TOKEN")||"";d?we(d).then(h=>{t.commit("updateUserinfo",h),t.commit("triggerAuth",!1),g()}).catch(h=>{t.commit("triggerAuth",!0),t.commit("userLogout")}):(t.commit("triggerAuth",!0),t.commit("userLogout"))},E=()=>{r.value=!0},m=d=>{n.value=!0,Ae({amount:o.value}).then(h=>{n.value=!1,s.value=h.pay,G.toCanvas(document.querySelector("#qrcode-container"),h.pay,{width:150,margin:2});const C=setInterval(()=>{Ne({id:h.id}).then(v=>{v.status==="TRADE_SUCCESS"&&(clearInterval(C),window.$message.success("\u5145\u503C\u6210\u529F"),r.value=!1,s.value="",_())}).catch(v=>{console.log(v)})},2e3)}).catch(h=>{n.value=!1})},w=()=>{t.state.userInfo.balance==0?window.$message.warning("\u60A8\u6682\u65E0\u53EF\u63D0\u73B0\u8D44\u91D1"):window.$message.warning("\u8BE5\u529F\u80FD\u5373\u5C06\u5F00\u653E")};return kt(()=>{_()}),(d,h)=>{const C=ae,v=Ge,B=Ze,A=Ie,R=Se,M=Le,V=se,Y=ke,F=Ue,ee=De,ne=_e,oe=Te,re=Me,ie=ye;return P(),L("div",null,[b(C,{title:"\u94B1\u5305"}),b(ee,{class:"main-content-wrap",bordered:""},{footer:I(()=>[y.value>1?(P(),L("div",Wn,[b(M,{page:c.value,"onUpdate:page":p,"page-slot":tt(t).state.collapsedRight?5:8,"page-count":y.value},null,8,["page","page-slot","page-count"])])):et("",!0)]),default:I(()=>[S("div",Yn,[S("div",qn,[b(B,{label:"\u8D26\u6237\u4F59\u989D (\u5143)"},{default:I(()=>[b(v,{from:0,to:(tt(t).state.userInfo.balance||0)/100,duration:500,precision:2},null,8,["from","to"])]),_:1}),S("div",jn,[b(R,{vertical:""},{default:I(()=>[b(A,{size:"small",secondary:"",type:"primary",onClick:E},{default:I(()=>[Gn]),_:1}),b(A,{size:"small",secondary:"",type:"tertiary",onClick:w},{default:I(()=>[Qn]),_:1})]),_:1})])])]),u.value?(P(),L("div",Zn,[b(V,{num:l.value},null,8,["num"])])):(P(),L("div",Xn,[a.value.length===0?(P(),L("div",to,[b(Y,{size:"large",description:"\u6682\u65E0\u6570\u636E"})])):et("",!0),(P(!0),L(St,null,Tt(a.value,N=>(P(),Mt(F,{key:N.id},{default:I(()=>[S("div",eo,[S("div",null,"NO."+$(N.id),1),S("div",null,$(N.reason),1),S("div",{class:Pe({income:N.change_amount>=0,out:N.change_amount<0})},$((N.change_amount>0?"+":"")+(N.change_amount/100).toFixed(2)),3),S("div",null,$(tt(Fe)(N.created_on)),1)])]),_:2},1024))),128))]))]),_:1}),b(ie,{show:r.value,"onUpdate:show":h[0]||(h[0]=N=>r.value=N)},{default:I(()=>[b(re,{bordered:!1,title:"\u8BF7\u9009\u62E9\u5145\u503C\u91D1\u989D",role:"dialog","aria-modal":"true",style:{width:"100%","max-width":"330px"}},{default:I(()=>[s.value.length===0?(P(),L("div",no,[b(R,{align:"baseline"},{default:I(()=>[(P(!0),L(St,null,Tt(f.value,N=>(P(),Mt(A,{key:N,size:"small",secondary:"",type:o.value===N?"info":"default",onClick:Re(fo=>o.value=N,["stop"])},{default:I(()=>[at($(N/100)+"\u5143 ",1)]),_:2},1032,["type","onClick"]))),128))]),_:1})])):et("",!0),o.value>0&&s.value.length===0?(P(),L("div",oo,[b(A,{loading:n.value,strong:"",secondary:"",type:"info",style:{width:"100%"},onClick:m},{icon:I(()=>[b(ne,null,{default:I(()=>[b(tt(nn))]),_:1})]),default:I(()=>[ro]),_:1},8,["loading"])])):et("",!0),Ce(S("div",io,[so,S("div",ao," \u8BF7\u4F7F\u7528\u652F\u4ED8\u5B9D\u626B\u7801\u652F\u4ED8"+$((o.value/100).toFixed(2))+"\u5143 ",1),S("div",uo,[b(oe,{value:100,type:"info",dot:"",processing:""}),co])],512),[[ve,s.value.length>0]])]),_:1})]),_:1},8,["show"])])}}});var Co=he(lo,[["__scopeId","data-v-4ef16ff5"]]);export{Co as default}; diff --git a/web/dist/assets/content.ef1e095a.js b/web/dist/assets/content.ef1e095a.js deleted file mode 100644 index d32e5755..00000000 --- a/web/dist/assets/content.ef1e095a.js +++ /dev/null @@ -1,810 +0,0 @@ -import{bf as oe,s as F,r as I,ar as ie,e as se,d as $,i as ae,au as G,h as R,bg as le,u as ue,j as q,A as de,t as pe,b3 as ce,b4 as ve,B as fe,C as me,bh as ye,b2 as he,V as s,W as c,Y as S,ah as H,aa as h,ab as k,a3 as i,a4 as p,a2 as m,a9 as N,a7 as x,ae as Y,a5 as y,aY as M,aZ as O,bi as X,a6 as g,bj as Q,bk as ge,bl as we,bm as be,a8 as ke,bn as xe,bo as $e,J as Ce,bp as Se}from"./index.f480f018.js";function Ee(e){if(typeof e=="number")return{"":e.toString()};const n={};return e.split(/ +/).forEach(l=>{if(l==="")return;const[a,u]=l.split(":");u===void 0?n[""]=a:n[a]=u}),n}function D(e,n){var l;if(e==null)return;const a=Ee(e);if(n===void 0)return a[""];if(typeof n=="string")return(l=a[n])!==null&&l!==void 0?l:a[""];if(Array.isArray(n)){for(let u=n.length-1;u>=0;--u){const r=n[u];if(r in a)return a[r]}return a[""]}else{let u,r=-1;return Object.keys(a).forEach(t=>{const d=Number(t);!Number.isNaN(d)&&n>=d&&d>=r&&(r=d,u=a[t])}),u}}const _e={xs:0,s:640,m:1024,l:1280,xl:1536,"2xl":1920};function Be(e){return`(min-width: ${e}px)`}const T={};function ze(e=_e){if(!oe)return F(()=>[]);if(typeof window.matchMedia!="function")return F(()=>[]);const n=I({}),l=Object.keys(e),a=(u,r)=>{u.matches?n.value[r]=!0:n.value[r]=!1};return l.forEach(u=>{const r=e[u];let t,d;T[r]===void 0?(t=window.matchMedia(Be(r)),t.addEventListener?t.addEventListener("change",v=>{d.forEach(w=>{w(v,u)})}):t.addListener&&t.addListener(v=>{d.forEach(w=>{w(v,u)})}),d=new Set,T[r]={mql:t,cbs:d}):(t=T[r].mql,d=T[r].cbs),d.add(a),t.matches&&d.forEach(v=>{v(t,u)})}),ie(()=>{l.forEach(u=>{const{cbs:r}=T[e[u]];r.has(a)&&r.delete(a)})}),F(()=>{const{value:u}=n;return l.filter(r=>u[r])})}const L=1,W=se("n-grid"),Z=1,je={span:{type:[Number,String],default:Z},offset:{type:[Number,String],default:0},suffix:Boolean,privateOffset:Number,privateSpan:Number,privateColStart:Number,privateShow:{type:Boolean,default:!0}};var J=$({__GRID_ITEM__:!0,name:"GridItem",alias:["Gi"],props:je,setup(){const{xGapRef:e,itemStyleRef:n,overflowRef:l}=ae(W),a=le();return{overflow:l,itemStyle:n,deriveStyle:()=>{const{privateSpan:u=Z,privateShow:r=!0,privateColStart:t=void 0,privateOffset:d=0}=a.vnode.props,{value:v}=e,w=G(v||0);return{display:r?"":"none",gridColumn:`${t!=null?t:`span ${u}`} / span ${u}`,marginLeft:d?`calc((100% - (${u} - 1) * ${w}) / ${u} * ${d} + ${w} * ${d})`:""}}}},render(){var e,n;return R("div",{style:[this.itemStyle,this.deriveStyle()]},(n=(e=this.$slots).default)===null||n===void 0?void 0:n.call(e,{overflow:this.overflow}))}});const Re={xs:0,s:640,m:1024,l:1280,xl:1536,xxl:1920},K=24,Fe={responsive:{type:[String,Boolean],default:"self"},cols:{type:[Number,String],default:K},itemResponsive:Boolean,collapsed:Boolean,collapsedRows:{type:Number,default:1},itemStyle:[Object,String],xGap:{type:[Number,String],default:0},yGap:{type:[Number,String],default:0}};var ee=$({name:"Grid",inheritAttrs:!1,props:Fe,setup(e){const{mergedClsPrefixRef:n,mergedBreakpointsRef:l}=ue(e),a=/^\d+$/,u=I(void 0),r=ze((l==null?void 0:l.value)||Re),t=q(()=>!!(e.itemResponsive||!a.test(e.cols.toString())||!a.test(e.xGap.toString())||!a.test(e.yGap.toString()))),d=F(()=>{if(!!t.value)return e.responsive==="self"?u.value:r.value}),v=q(()=>{var C;return(C=Number(D(e.cols.toString(),d.value)))!==null&&C!==void 0?C:K}),w=q(()=>D(e.xGap.toString(),d.value)),o=q(()=>D(e.yGap.toString(),d.value)),f=C=>{u.value=C.contentRect.width},E=C=>{ve(f,C)},z=I(!1),_=F(()=>{if(e.responsive==="self")return E});return de(W,{itemStyleRef:pe(e,"itemStyle"),xGapRef:w,overflowRef:z}),{mergedClsPrefix:n,style:F(()=>({width:"100%",display:"grid",gridTemplateColumns:`repeat(${v.value}, minmax(0, 1fr))`,columnGap:G(w.value),rowGap:G(o.value)})),isResponsive:t,responsiveQuery:d,responsiveCols:v,handleResize:_,overflow:z}},render(){const e=()=>{var n,l,a,u,r,t;this.overflow=!1;const d=fe(me(this)),v=[],{collapsed:w,collapsedRows:o,responsiveCols:f,responsiveQuery:E}=this;d.forEach(b=>{var A,j,B;if(((A=b==null?void 0:b.type)===null||A===void 0?void 0:A.__GRID_ITEM__)!==!0)return;const P=ye(b),U=Number((B=D((j=P.props)===null||j===void 0?void 0:j.span,E))!==null&&B!==void 0?B:L);U!==0&&v.push({child:P,rawChildSpan:U})});let z=0;const _=(n=v[v.length-1])===null||n===void 0?void 0:n.child;if(_!=null&&_.props){const b=(l=_.props)===null||l===void 0?void 0:l.suffix;b!==void 0&&b!==!1&&(z=(u=(a=_.props)===null||a===void 0?void 0:a.span)!==null&&u!==void 0?u:L,_.props.privateSpan=z,_.props.privateColStart=f+1-z,_.props.privateShow=!0)}let C=0,V=!1;for(const{child:b,rawChildSpan:A}of v){if(V&&(this.overflow=!0),!V){const j=Number((t=D((r=b.props)===null||r===void 0?void 0:r.offset,E))!==null&&t!==void 0?t:0),B=Math.min(A+j,f)||1;if(b.props?(b.props.privateSpan=B,b.props.privateOffset=j):b.props={privateSpan:B,privateOffset:j},w){const P=C%f;B+P>f&&(C+=f-P),B+C+z>o*f?V=!0:C+=B}}V&&(b.props?b.props.privateShow!==!0&&(b.props.privateShow=!1):b.props={privateShow:!1})}return R("div",he({class:`${this.mergedClsPrefix}-grid`,style:this.style},this.$attrs),v.map(({child:b})=>b))};return this.isResponsive&&this.responsive==="self"?R(ce,{onResize:this.handleResize},{default:e}):e()}});const Ie={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Me=S("path",{d:"M352 48H160a48 48 0 0 0-48 48v368l144-128l144 128V96a48 48 0 0 0-48-48z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),Ne=[Me];var jn=$({name:"BookmarkOutline",render:function(n,l){return s(),c("svg",Ie,Ne)}});const Ae={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Pe=S("path",{d:"M408 64H104a56.16 56.16 0 0 0-56 56v192a56.16 56.16 0 0 0 56 56h40v80l93.72-78.14a8 8 0 0 1 5.13-1.86H408a56.16 56.16 0 0 0 56-56V120a56.16 56.16 0 0 0-56-56z",fill:"none",stroke:"currentColor","stroke-linejoin":"round","stroke-width":"32"},null,-1),De=[Pe];var Rn=$({name:"ChatboxOutline",render:function(n,l){return s(),c("svg",Ae,De)}});const Te={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Ve=S("path",{d:"M320 336h76c55 0 100-21.21 100-75.6s-53-73.47-96-75.6C391.11 99.74 329 48 256 48c-69 0-113.44 45.79-128 91.2c-60 5.7-112 35.88-112 98.4S70 336 136 336h56",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),qe=S("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M192 400.1l64 63.9l64-63.9"},null,-1),Oe=S("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M256 224v224.03"},null,-1),Ge=[Ve,qe,Oe];var Ue=$({name:"CloudDownloadOutline",render:function(n,l){return s(),c("svg",Te,Ge)}});const Le={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},He=S("path",{d:"M352.92 80C288 80 256 144 256 144s-32-64-96.92-64c-52.76 0-94.54 44.14-95.08 96.81c-1.1 109.33 86.73 187.08 183 252.42a16 16 0 0 0 18 0c96.26-65.34 184.09-143.09 183-252.42c-.54-52.67-42.32-96.81-95.08-96.81z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),Ye=[He];var Fn=$({name:"HeartOutline",render:function(n,l){return s(),c("svg",Le,Ye)}});const Xe={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Qe=S("path",{d:"M208 352h-64a96 96 0 0 1 0-192h64",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"36"},null,-1),We=S("path",{d:"M304 160h64a96 96 0 0 1 0 192h-64",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"36"},null,-1),Ze=S("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"36",d:"M163.29 256h187.42"},null,-1),Je=[Qe,We,Ze];var Ke=$({name:"LinkOutline",render:function(n,l){return s(),c("svg",Xe,Je)}});const en={class:"link-wrap"},nn=["href"],tn={class:"link-txt"},rn=$({props:{links:{default:()=>[]}},setup(e){const n=e;return(l,a)=>{const u=Y;return s(),c("div",en,[(s(!0),c(h,null,k(n.links,r=>(s(),c("div",{class:"link-item",key:r.id},[i(u,{class:"hash-link"},{default:p(()=>[i(m(Ke))]),_:1}),S("a",{href:r.content,class:"hash-link",target:"_blank",onClick:a[0]||(a[0]=x(()=>{},["stop"]))},[S("span",tn,N(r.content),1)],8,nn)]))),128))])}}});var In=H(rn,[["__scopeId","data-v-4c9a59cc"]]),ne=$({name:"BasicTheme",props:{uuid:{type:String,required:!0},src:{type:String,required:!0},autoplay:{type:Boolean,required:!0},loop:{type:Boolean,required:!0},controls:{type:Boolean,required:!0},hoverable:{type:Boolean,required:!0},mask:{type:Boolean,required:!0},colors:{type:[String,Array],required:!0},time:{type:Object,required:!0},playing:{type:Boolean,default:!1},duration:{type:[String,Number],required:!0}},data(){return{hovered:!1,volume:!1,amount:1}},computed:{colorFrom(){var e;return typeof this.colors=="string"?this.colors?this.colors:"#fbbf24":(e=this.colors)!==null&&e!==void 0&&e[0]?this.colors[0]:"#fbbf24"},colorTo(){var e;return typeof this.colors=="string"?this.colors?this.colors:"#fbbf24":(e=this.colors)!==null&&e!==void 0&&e[1]?this.colors[1]:"#ec4899"}},mounted(){this.$emit("setPlayer",this.$refs[this.uuid])},methods:{setVolume(){this.$refs[this.uuid].volume=this.amount},stopVolume(){return this.amount>0?this.amount=0:this.amount=1}}});const on={class:"relative"},sn={class:"flex items-center justify-start w-full"},an={class:"font-sans text-white text-xs w-24"},ln={class:"mr-3 ml-2"},un={class:"relative"},dn={class:"px-3 py-2 rounded-lg flex items-center transform translate-x-2",style:{"background-color":"rgba(0, 0, 0, .8)"}},pn=i("img",{src:"https://en-zo.dev/vue-videoplayer/play.svg",alt:"Icon play video",class:"transform translate-x-0.5 w-12"},null,-1);function cn(e,n,l,a,u,r){return s(),y("div",{class:"shadow-xl rounded-xl overflow-hidden relative",onMouseenter:n[15]||(n[15]=t=>e.hovered=!0),onMouseleave:n[16]||(n[16]=t=>e.hovered=!1),onKeydown:n[17]||(n[17]=Q(t=>e.$emit("play"),["left"]))},[i("div",on,[i("video",{ref:e.uuid,class:"w-full",loop:e.loop,autoplay:e.autoplay,muted:e.autoplay,onTimeupdate:n[1]||(n[1]=t=>e.$emit("timeupdate",t.target)),onPause:n[2]||(n[2]=t=>e.$emit("isPlaying",!1)),onPlay:n[3]||(n[3]=t=>e.$emit("isPlaying",!0)),onClick:n[4]||(n[4]=t=>e.$emit("play"))},[i("source",{src:e.src,type:"video/mp4"},null,8,["src"])],40,["loop","autoplay","muted"]),e.controls?(s(),y("div",{key:0,class:[{"opacity-0 translate-y-full":!e.hoverable&&e.hovered,"opacity-0 translate-y-full":e.hoverable&&!e.hovered},"transition duration-300 transform absolute w-full bottom-0 left-0 flex items-center justify-between overlay px-5 pt-3 pb-5"]},[i("div",sn,[i("p",an,N(e.time.display)+"/"+N(e.duration),1),i("div",ln,[M(i("img",{src:"https://en-zo.dev/vue-videoplayer/pause.svg",alt:"Icon pause video",class:"w-5 cursor-pointer",onClick:n[5]||(n[5]=t=>e.$emit("play"))},null,512),[[O,e.playing]]),M(i("img",{src:"https://en-zo.dev/vue-videoplayer/play.svg",alt:"Icon play video",class:"w-5 cursor-pointer",onClick:n[6]||(n[6]=t=>e.$emit("play"))},null,512),[[O,!e.playing]])]),i("div",{class:"w-full h-1 bg-white bg-opacity-60 rounded-sm cursor-pointer",onClick:n[7]||(n[7]=t=>e.$emit("position",t))},[i("div",{class:"relative h-full pointer-events-none",style:`width: ${e.time.progress}%; transition: width .2s ease-in-out;`},[i("div",{class:"w-full rounded-sm h-full gradient-variable bg-gradient-to-r pointer-events-none absolute top-0 left-0",style:`--tw-gradient-from: ${e.colorFrom};--tw-gradient-to: ${e.colorTo};transition: width .2s ease-in-out`},null,4),i("div",{class:"w-full rounded-sm filter blur-sm h-full gradient-variable bg-gradient-to-r pointer-events-none absolute top-0 left-0",style:`--tw-gradient-from: ${e.colorFrom};--tw-gradient-to: ${e.colorTo};transition: width .2s ease-in-out`},null,4)],4)])]),i("div",{class:"ml-5 flex items-center justify-end",onMouseleave:n[13]||(n[13]=t=>e.volume=!1)},[i("div",un,[i("div",{class:`w-128 origin-left translate-x-2 -rotate-90 w-128 transition duration-200 absolute transform top-0 py-2 ${e.volume?"-translate-y-4":"opacity-0 -translate-y-1 pointer-events-none"}`},[i("div",dn,[M(i("input",{"onUpdate:modelValue":n[8]||(n[8]=t=>e.amount=t),type:"range",step:"0.05",min:"0",max:"1",class:"rounded-lg overflow-hidden appearance-none bg-white bg-opacity-30 h-1 w-128 vertical-range",onInput:n[9]||(n[9]=(...t)=>e.setVolume&&e.setVolume(...t))},null,544),[[X,e.amount]])])],2),i("img",{src:`https://en-zo.dev/vue-videoplayer/volume-${Math.ceil(e.amount*2)}.svg`,alt:"High volume video",class:"w-5 cursor-pointer relative",style:{"z-index":"2"},onClick:n[10]||(n[10]=(...t)=>e.stopVolume&&e.stopVolume(...t)),onMouseenter:n[11]||(n[11]=t=>e.volume=!0)},null,40,["src"])]),i("img",{src:"https://en-zo.dev/vue-videoplayer/maximize.svg",alt:"Fullscreen",class:"w-3 ml-4 cursor-pointer",onClick:n[12]||(n[12]=t=>e.$emit("fullScreen"))})],32)],2)):g("",!0),!e.autoplay&&e.mask&&e.time.current===0?(s(),y("div",{key:1,class:`transition transform duration-300 absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 backdrop-filter z-10 flex items-center justify-center ${e.playing?"opacity-0 pointer-events-none":""}`},[i("div",{class:"w-20 h-20 rounded-full bg-white bg-opacity-20 transition duration-200 hover:bg-opacity-40 flex items-center justify-center cursor-pointer",onClick:n[14]||(n[14]=t=>e.$emit("play"))},[pn])],2)):g("",!0)])],32)}ne.render=cn;var te=$({name:"BasicTheme",props:{uuid:{type:String,required:!0},src:{type:String,required:!0},autoplay:{type:Boolean,required:!0},loop:{type:Boolean,required:!0},controls:{type:Boolean,required:!0},hoverable:{type:Boolean,required:!0},mask:{type:Boolean,required:!0},colors:{type:[String,Array],required:!0},time:{type:Object,required:!0},playing:{type:Boolean,default:!1},duration:{type:[String,Number],required:!0}},data(){return{hovered:!1,volume:!1,amount:1}},computed:{color(){var e;return typeof this.colors=="string"?this.colors?this.colors:"#8B5CF6":(e=this.colors)!==null&&e!==void 0&&e[0]?this.colors[0]:"#8B5CF6"}},mounted(){this.$emit("setPlayer",this.$refs[this.uuid])},methods:{setVolume(){this.$refs[this.uuid].volume=this.amount},stopVolume(){return this.amount>0?this.amount=0:this.amount=1}}});const vn={class:"relative"},fn={class:"mr-5"},mn={class:"relative mr-6"},yn={class:"px-3 py-3 rounded-xl flex items-center transform translate-x-9 bg-black bg-opacity-30"},hn=i("img",{src:"https://en-zo.dev/vue-videoplayer/play.svg",alt:"Icon play video",class:"transform translate-x-0.5 w-12"},null,-1);function gn(e,n,l,a,u,r){return s(),y("div",{class:"shadow-xl rounded-3xl overflow-hidden relative",onMouseenter:n[14]||(n[14]=t=>e.hovered=!0),onMouseleave:n[15]||(n[15]=t=>e.hovered=!1),onKeydown:n[16]||(n[16]=Q(t=>e.$emit("play"),["left"]))},[i("div",vn,[i("video",{ref:e.uuid,class:"w-full",loop:e.loop,autoplay:e.autoplay,muted:e.autoplay,onTimeupdate:n[1]||(n[1]=t=>e.$emit("timeupdate",t.target)),onPause:n[2]||(n[2]=t=>e.$emit("isPlaying",!1)),onPlay:n[3]||(n[3]=t=>e.$emit("isPlaying",!0)),onClick:n[4]||(n[4]=t=>e.$emit("play"))},[i("source",{src:e.src,type:"video/mp4"},null,8,["src"])],40,["loop","autoplay","muted"]),e.controls?(s(),y("div",{key:0,class:[{"opacity-0 translate-y-full":!e.hoverable&&e.hovered,"opacity-0 translate-y-full":e.hoverable&&!e.hovered},"absolute px-5 pb-5 bottom-0 left-0 w-full transition duration-300 transform"]},[i("div",{class:"w-full bg-black bg-opacity-30 px-5 py-4 rounded-xl flex items-center justify-between",onMouseleave:n[12]||(n[12]=t=>e.volume=!1)},[i("div",{class:"font-sans py-1 px-2 text-white rounded-md text-xs mr-5 whitespace-nowrap font-medium w-32 text-center",style:`font-size: 11px; background-color: ${e.color}`},N(e.time.display)+"\xA0/\xA0"+N(e.duration),5),i("div",fn,[M(i("img",{src:"https://en-zo.dev/vue-videoplayer/basic/pause.svg",alt:"Icon pause video",class:"w-4 cursor-pointer filter-white transition duration-300",onClick:n[5]||(n[5]=t=>e.$emit("play"))},null,512),[[O,e.playing]]),M(i("img",{src:"https://en-zo.dev/vue-videoplayer/basic/play.svg",alt:"Icon play video",class:"w-4 cursor-pointer filter-white transition duration-300",onClick:n[6]||(n[6]=t=>e.$emit("play"))},null,512),[[O,!e.playing]])]),i("div",{class:"w-full h-1 bg-white bg-opacity-40 rounded-sm cursor-pointer mr-6",onClick:n[7]||(n[7]=t=>e.$emit("position",t))},[i("div",{class:"w-full rounded-sm h-full bg-white pointer-events-none",style:`width: ${e.time.progress}%; transition: width .2s ease-in-out;`},null,4)]),i("div",mn,[i("div",{class:`w-128 origin-left translate-x-2 -rotate-90 w-128 transition duration-200 absolute transform top-0 py-2 ${e.volume?"-translate-y-4":"opacity-0 -translate-y-1 pointer-events-none"}`},[i("div",yn,[M(i("input",{"onUpdate:modelValue":n[8]||(n[8]=t=>e.amount=t),type:"range",step:"0.05",min:"0",max:"1",class:"rounded-lg overflow-hidden appearance-none bg-white bg-opacity-30 h-1.5 w-128 vertical-range"},null,512),[[X,e.amount]])])],2),i("img",{src:`https://en-zo.dev/vue-videoplayer/basic/volume_${Math.ceil(e.amount*2)}.svg`,alt:"High volume video",class:"w-5 cursor-pointer filter-white transition duration-300 relative",style:{"z-index":"2"},onClick:n[9]||(n[9]=(...t)=>e.stopVolume&&e.stopVolume(...t)),onMouseenter:n[10]||(n[10]=t=>e.volume=!0)},null,40,["src"])]),i("img",{src:"https://en-zo.dev/vue-videoplayer/basic/fullscreen.svg",alt:"Fullscreen",class:"w-4 cursor-pointer filter-white transition duration-300",onClick:n[11]||(n[11]=t=>e.$emit("fullScreen"))})],32)],2)):g("",!0),!e.autoplay&&e.mask&&e.time.current===0?(s(),y("div",{key:1,class:`transition transform duration-300 absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 backdrop-filter z-10 flex items-center justify-center ${e.playing?"opacity-0 pointer-events-none":""}`},[i("div",{class:"w-20 h-20 rounded-full bg-white bg-opacity-20 transition duration-200 hover:bg-opacity-40 flex items-center justify-center cursor-pointer",onClick:n[13]||(n[13]=t=>e.$emit("play"))},[hn])],2)):g("",!0)])],32)}te.render=gn;var re=$({name:"Vue3PlayerVideo",components:{basic:te,gradient:ne},props:{src:{type:String,required:!0},autoplay:{type:Boolean,default:!1},loop:{type:Boolean,default:!1},controls:{type:Boolean,default:!0},mask:{type:Boolean,default:!0},colors:{type:[String,Array],default(){return["#8B5CF6","#ec4899"]}},hoverable:{type:Boolean,default:!1},theme:{type:String,default:"basic"}},data(){return{uuid:Math.random().toString(36).substr(2,18),player:null,duration:0,playing:!1,time:{progress:0,display:0,current:0}}},watch:{"time.current"(e){this.time.display=this.format(Number(e)),this.time.progress=e*100/this.player.duration}},methods:{isPlaying(e){this.playing=e},play(){return this.playing?this.player.pause():this.player.play()},setPlayer(e){this.player=e,this.player.addEventListener("loadeddata",()=>{this.player.readyState>=3&&(this.duration=this.format(Number(this.player.duration)),this.time.display=this.format(0))})},stop(){this.player.pause(),this.player.currentTime=0},fullScreen(){this.player.webkitEnterFullscreen()},position(e){this.player.pause();const n=e.target.getBoundingClientRect(),a=(e.clientX-n.left)*100/e.target.offsetWidth;this.player.currentTime=a*this.player.duration/100,this.player.play()},format(e){const n=Math.floor(e/3600),l=Math.floor(e%3600/60),a=Math.round(e%60);return[n,l>9?l:n?"0"+l:l||"00",a>9?a:"0"+a].filter(Boolean).join(":")}}});const wn={class:"vue3-player-video"};function bn(e,n,l,a,u,r){return s(),y("div",wn,[(s(),y(ge(e.theme),{uuid:e.uuid,src:e.src,autoplay:e.autoplay,loop:e.loop,controls:e.controls,mask:e.mask,colors:e.colors,time:e.time,playing:e.playing,duration:e.duration,hoverable:e.hoverable,onPlay:e.play,onStop:e.stop,onTimeupdate:n[1]||(n[1]=({currentTime:t})=>e.time.current=t),onPosition:e.position,onFullScreen:e.fullScreen,onSetPlayer:e.setPlayer,onIsPlaying:e.isPlaying},null,8,["uuid","src","autoplay","loop","controls","mask","colors","time","playing","duration","hoverable","onPlay","onStop","onPosition","onFullScreen","onSetPlayer","onIsPlaying"]))])}function kn(e,n){n===void 0&&(n={});var l=n.insertAt;if(!(!e||typeof document=="undefined")){var a=document.head||document.getElementsByTagName("head")[0],u=document.createElement("style");u.type="text/css",l==="top"&&a.firstChild?a.insertBefore(u,a.firstChild):a.appendChild(u),u.styleSheet?u.styleSheet.cssText=e:u.appendChild(document.createTextNode(e))}}var xn=`/*! tailwindcss v2.1.2 | MIT License | https://tailwindcss.com */ - -/*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */ - -/* -Document -======== -*/ - -/** -Use a better box model (opinionated). -*/ - -*, -::before, -::after { - box-sizing: border-box; -} - -/** -Use a more readable tab size (opinionated). -*/ - -/** -1. Correct the line height in all browsers. -2. Prevent adjustments of font size after orientation changes in iOS. -*/ - -/* -Sections -======== -*/ - -/** -Remove the margin in all browsers. -*/ - -/** -Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) -*/ - -/* -Grouping content -================ -*/ - -/** -1. Add the correct height in Firefox. -2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) -*/ - -/* -Text-level semantics -==================== -*/ - -/** -Add the correct text decoration in Chrome, Edge, and Safari. -*/ - -/** -Add the correct font weight in Edge and Safari. -*/ - -/** -1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) -2. Correct the odd 'em' font sizing in all browsers. -*/ - -/** -Add the correct font size in all browsers. -*/ - -/** -Prevent 'sub' and 'sup' elements from affecting the line height in all browsers. -*/ - -/* -Tabular data -============ -*/ - -/** -1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) -2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) -*/ - -/* -Forms -===== -*/ - -/** -1. Change the font styles in all browsers. -2. Remove the margin in Firefox and Safari. -*/ - - -input { - font-family: inherit; /* 1 */ - font-size: 100%; /* 1 */ - line-height: 1.15; /* 1 */ - margin: 0; /* 2 */ -} - -/** -Remove the inheritance of text transform in Edge and Firefox. -1. Remove the inheritance of text transform in Firefox. -*/ - -/** -Correct the inability to style clickable types in iOS and Safari. -*/ - - -[type='button'], -[type='reset'], -[type='submit'] { - -webkit-appearance: button; -} - -/** -Remove the inner border and padding in Firefox. -*/ - -::-moz-focus-inner { - border-style: none; - padding: 0; -} - -/** -Restore the focus styles unset by the previous rule. -*/ - -:-moz-focusring { - outline: 1px dotted ButtonText; -} - -/** -Remove the additional ':invalid' styles in Firefox. -See: https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737 -*/ - -:-moz-ui-invalid { - box-shadow: none; -} - -/** -Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers. -*/ - -/** -Add the correct vertical alignment in Chrome and Firefox. -*/ - -progress { - vertical-align: baseline; -} - -/** -Correct the cursor style of increment and decrement buttons in Safari. -*/ - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto; -} - -/** -1. Correct the odd appearance in Chrome and Safari. -2. Correct the outline style in Safari. -*/ - -[type='search'] { - -webkit-appearance: textfield; /* 1 */ - outline-offset: -2px; /* 2 */ -} - -/** -Remove the inner padding in Chrome and Safari on macOS. -*/ - -::-webkit-search-decoration { - -webkit-appearance: none; -} - -/** -1. Correct the inability to style clickable types in iOS and Safari. -2. Change font properties to 'inherit' in Safari. -*/ - -::-webkit-file-upload-button { - -webkit-appearance: button; /* 1 */ - font: inherit; /* 2 */ -} - -/* -Interactive -=========== -*/ - -/* -Add the correct display in Chrome and Safari. -*/ - -/** - * Manually forked from SUIT CSS Base: https://github.com/suitcss/base - * A thin layer on top of normalize.css that provides a starting point more - * suitable for web applications. - */ - -/** - * Removes the default spacing and border for appropriate elements. - */ - - -p { - margin: 0; -} - -/** - * Work around a Firefox/IE bug where the transparent \`button\` background - * results in a loss of the default \`button\` focus styles. - */ - -/** - * Tailwind custom reset styles - */ - -/** - * 1. Use the user's configured \`sans\` font-family (with Tailwind's default - * sans-serif font stack as a fallback) as a sane default. - * 2. Use Tailwind's default "normal" line-height so the user isn't forced - * to override it to ensure consistency even when using the default theme. - */ - -/** - * Inherit font-family and line-height from \`html\` so users can set them as - * a class directly on the \`html\` element. - */ - -/** - * 1. Prevent padding and border from affecting element width. - * - * We used to set this in the html element and inherit from - * the parent element for everything else. This caused issues - * in shadow-dom-enhanced elements like

where the content - * is wrapped by a div with box-sizing set to \`content-box\`. - * - * https://github.com/mozdevs/cssremedy/issues/4 - * - * - * 2. Allow adding a border to an element by just adding a border-width. - * - * By default, the way the browser specifies that an element should have no - * border is by setting it's border-style to \`none\` in the user-agent - * stylesheet. - * - * In order to easily add borders to elements by just setting the \`border-width\` - * property, we change the default border-style for all elements to \`solid\`, and - * use border-width to hide them instead. This way our \`border\` utilities only - * need to set the \`border-width\` property instead of the entire \`border\` - * shorthand, making our border utilities much more straightforward to compose. - * - * https://github.com/tailwindcss/tailwindcss/pull/116 - */ - -*, -::before, -::after { - box-sizing: border-box; /* 1 */ - border-width: 0; /* 2 */ - border-style: solid; /* 2 */ - border-color: #e5e7eb; /* 2 */ -} - -/* - * Ensure horizontal rules are visible by default - */ - -/** - * Undo the \`border-style: none\` reset that Normalize applies to images so that - * our \`border-{width}\` utilities have the expected effect. - * - * The Normalize reset is unnecessary for us since we default the border-width - * to 0 on all elements. - * - * https://github.com/tailwindcss/tailwindcss/issues/362 - */ - -img { - border-style: solid; -} - -input:-ms-input-placeholder { - opacity: 1; - color: #9ca3af; -} - -input::placeholder { - opacity: 1; - color: #9ca3af; -} - - -[role="button"] { - cursor: pointer; -} - -/** - * Reset links to optimize for opt-in styling instead of - * opt-out. - */ - -/** - * Reset form element properties that are easy to forget to - * style explicitly so you don't inadvertently introduce - * styles that deviate from your design system. These styles - * supplement a partial reset that is already applied by - * normalize.css. - */ - - -input { - padding: 0; - line-height: inherit; - color: inherit; -} - -/** - * Use the configured 'mono' font family for elements that - * are expected to be rendered with a monospace font, falling - * back to the system monospace stack if there is no configured - * 'mono' font family. - */ - -/** - * Make replaced elements \`display: block\` by default as that's - * the behavior you want almost all of the time. Inspired by - * CSS Remedy, with \`svg\` added as well. - * - * https://github.com/mozdevs/cssremedy/issues/14 - */ - -img, -svg, -video { - display: block; - vertical-align: middle; -} - -/** - * Constrain images and videos to the parent width and preserve - * their intrinsic aspect ratio. - * - * https://github.com/mozdevs/cssremedy/issues/14 - */ - -img, -video { - max-width: 100%; - height: auto; -} - -.vue3-player-video .appearance-none{ - -webkit-appearance: none; - appearance: none; -} - -.vue3-player-video .bg-black{ - --tw-bg-opacity: 1; - background-color: rgba(0, 0, 0, var(--tw-bg-opacity)); -} - -.vue3-player-video .bg-white{ - --tw-bg-opacity: 1; - background-color: rgba(255, 255, 255, var(--tw-bg-opacity)); -} - -.vue3-player-video .bg-gradient-to-r{ - background-image: linear-gradient(to right, var(--tw-gradient-stops)); -} - -.vue3-player-video .bg-opacity-20{ - --tw-bg-opacity: 0.2; -} - -.vue3-player-video .bg-opacity-30{ - --tw-bg-opacity: 0.3; -} - -.vue3-player-video .bg-opacity-40{ - --tw-bg-opacity: 0.4; -} - -.vue3-player-video .bg-opacity-50{ - --tw-bg-opacity: 0.5; -} - -.vue3-player-video .bg-opacity-60{ - --tw-bg-opacity: 0.6; -} - -.vue3-player-video .hover\\:bg-opacity-40:hover{ - --tw-bg-opacity: 0.4; -} - -.vue3-player-video .rounded-sm{ - border-radius: 0.125rem; -} - -.vue3-player-video .rounded-md{ - border-radius: 0.375rem; -} - -.vue3-player-video .rounded-lg{ - border-radius: 0.5rem; -} - -.vue3-player-video .rounded-xl{ - border-radius: 0.75rem; -} - -.vue3-player-video .rounded-3xl{ - border-radius: 1.5rem; -} - -.vue3-player-video .rounded-full{ - border-radius: 9999px; -} - -.vue3-player-video .cursor-pointer{ - cursor: pointer; -} - -.vue3-player-video .flex{ - display: flex; -} - -.vue3-player-video .items-center{ - align-items: center; -} - -.vue3-player-video .justify-start{ - justify-content: flex-start; -} - -.vue3-player-video .justify-end{ - justify-content: flex-end; -} - -.vue3-player-video .justify-center{ - justify-content: center; -} - -.vue3-player-video .justify-between{ - justify-content: space-between; -} - -.vue3-player-video .font-sans{ - font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; -} - -.vue3-player-video .font-medium{ - font-weight: 500; -} - -.vue3-player-video .h-1{ - height: 0.25rem; -} - -.vue3-player-video .h-20{ - height: 5rem; -} - -.vue3-player-video .h-full{ - height: 100%; -} - -.vue3-player-video .text-xs{ - font-size: 0.75rem; - line-height: 1rem; -} - -.vue3-player-video .ml-2{ - margin-left: 0.5rem; -} - -.vue3-player-video .mr-3{ - margin-right: 0.75rem; -} - -.vue3-player-video .ml-4{ - margin-left: 1rem; -} - -.vue3-player-video .mr-5{ - margin-right: 1.25rem; -} - -.vue3-player-video .ml-5{ - margin-left: 1.25rem; -} - -.vue3-player-video .mr-6{ - margin-right: 1.5rem; -} - -.vue3-player-video .opacity-0{ - opacity: 0; -} - -.vue3-player-video .overflow-hidden{ - overflow: hidden; -} - -.vue3-player-video .py-1{ - padding-top: 0.25rem; - padding-bottom: 0.25rem; -} - -.vue3-player-video .py-2{ - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -.vue3-player-video .px-2{ - padding-left: 0.5rem; - padding-right: 0.5rem; -} - -.vue3-player-video .py-3{ - padding-top: 0.75rem; - padding-bottom: 0.75rem; -} - -.vue3-player-video .px-3{ - padding-left: 0.75rem; - padding-right: 0.75rem; -} - -.vue3-player-video .py-4{ - padding-top: 1rem; - padding-bottom: 1rem; -} - -.vue3-player-video .px-5{ - padding-left: 1.25rem; - padding-right: 1.25rem; -} - -.vue3-player-video .pt-3{ - padding-top: 0.75rem; -} - -.vue3-player-video .pb-5{ - padding-bottom: 1.25rem; -} - -.vue3-player-video .pointer-events-none{ - pointer-events: none; -} - -.vue3-player-video .absolute{ - position: absolute; -} - -.vue3-player-video .relative{ - position: relative; -} - -.vue3-player-video .top-0{ - top: 0px; -} - -.vue3-player-video .bottom-0{ - bottom: 0px; -} - -.vue3-player-video .left-0{ - left: 0px; -} - -*{ - --tw-shadow: 0 0 #0000; -} - -.vue3-player-video .shadow-xl{ - --tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - -*{ - --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgba(59, 130, 246, 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; -} - -.vue3-player-video .text-center{ - text-align: center; -} - -.vue3-player-video .text-white{ - --tw-text-opacity: 1; - color: rgba(255, 255, 255, var(--tw-text-opacity)); -} - -.vue3-player-video .whitespace-nowrap{ - white-space: nowrap; -} - -.vue3-player-video .w-3{ - width: 0.75rem; -} - -.vue3-player-video .w-4{ - width: 1rem; -} - -.vue3-player-video .w-5{ - width: 1.25rem; -} - -.vue3-player-video .w-12{ - width: 3rem; -} - -.vue3-player-video .w-20{ - width: 5rem; -} - -.vue3-player-video .w-24{ - width: 6rem; -} - -.vue3-player-video .w-32{ - width: 8rem; -} - -.vue3-player-video .w-full{ - width: 100%; -} - -.vue3-player-video .z-10{ - z-index: 10; -} - -.vue3-player-video .transform{ - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.vue3-player-video .origin-left{ - transform-origin: left; -} - -.vue3-player-video .-rotate-90{ - --tw-rotate: -90deg; -} - -.vue3-player-video .translate-x-0{ - --tw-translate-x: 0px; -} - -.vue3-player-video .translate-x-2{ - --tw-translate-x: 0.5rem; -} - -.vue3-player-video .translate-x-9{ - --tw-translate-x: 2.25rem; -} - -.vue3-player-video .-translate-y-1{ - --tw-translate-y: -0.25rem; -} - -.vue3-player-video .-translate-y-4{ - --tw-translate-y: -1rem; -} - -.vue3-player-video .translate-y-full{ - --tw-translate-y: 100%; -} - -.vue3-player-video .transition{ - transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; - transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; - transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.vue3-player-video .ease-in-out{ - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); -} - -.vue3-player-video .duration-200{ - transition-duration: 200ms; -} - -.vue3-player-video .duration-300{ - transition-duration: 300ms; -} - -@keyframes spin{ - to{ - transform: rotate(360deg); - } -} - -@keyframes ping{ - 75%, 100%{ - transform: scale(2); - opacity: 0; - } -} - -@keyframes pulse{ - 50%{ - opacity: .5; - } -} - -@keyframes bounce{ - 0%, 100%{ - transform: translateY(-25%); - animation-timing-function: cubic-bezier(0.8,0,1,1); - } - - 50%{ - transform: none; - animation-timing-function: cubic-bezier(0,0,0.2,1); - } -} - -.vue3-player-video .filter{ - --tw-blur: var(--tw-empty,/*!*/ /*!*/); - --tw-brightness: var(--tw-empty,/*!*/ /*!*/); - --tw-contrast: var(--tw-empty,/*!*/ /*!*/); - --tw-grayscale: var(--tw-empty,/*!*/ /*!*/); - --tw-hue-rotate: var(--tw-empty,/*!*/ /*!*/); - --tw-invert: var(--tw-empty,/*!*/ /*!*/); - --tw-saturate: var(--tw-empty,/*!*/ /*!*/); - --tw-sepia: var(--tw-empty,/*!*/ /*!*/); - --tw-drop-shadow: var(--tw-empty,/*!*/ /*!*/); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -.vue3-player-video .blur-sm{ - --tw-blur: blur(4px); -} - -.vue3-player-video .blur{ - --tw-blur: blur(8px); -} - -.vue3-player-video .backdrop-filter{ - --tw-backdrop-blur: var(--tw-empty,/*!*/ /*!*/); - --tw-backdrop-brightness: var(--tw-empty,/*!*/ /*!*/); - --tw-backdrop-contrast: var(--tw-empty,/*!*/ /*!*/); - --tw-backdrop-grayscale: var(--tw-empty,/*!*/ /*!*/); - --tw-backdrop-hue-rotate: var(--tw-empty,/*!*/ /*!*/); - --tw-backdrop-invert: var(--tw-empty,/*!*/ /*!*/); - --tw-backdrop-opacity: var(--tw-empty,/*!*/ /*!*/); - --tw-backdrop-saturate: var(--tw-empty,/*!*/ /*!*/); - --tw-backdrop-sepia: var(--tw-empty,/*!*/ /*!*/); - -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); - backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); -} - -.overlay { - background: linear-gradient(0deg, rgba(0,0,0,0.41961), transparent) -} - -.vertical-range::-webkit-slider-thumb { - width: 6px; - -webkit-appearance: none; - appearance: none; - height: 6px; - background-color: white; - cursor: ns-resize; - box-shadow: -405px 0 0 400px rgba(255, 255, 255, .6); - border-radius: 50%; -} - -.backdrop-filter { - -webkit-backdrop-filter: blur(15px) !important; - backdrop-filter: blur(15px) !important; -} - -.filter-white:hover { - filter: brightness(2); -} - -.gradient-variable { - --tw-gradient-from: #fbbf24; - --tw-gradient-to: #ec4899; - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgba(251, 191, 36, 0)) -} - -`;kn(xn);re.render=bn;var $n=(()=>{const e=re;return e.install=n=>{n.component("Vue3PlayerVideo",e)},e})(),Cn=$n;const Sn={key:0},Mn=$({props:{videos:{default:()=>[]},full:{type:Boolean,default:!1}},setup(e){const n=e;return(l,a)=>{const u=J,r=ee;return n.videos.length>0?(s(),c("div",Sn,[i(r,{"x-gap":4,"y-gap":4,cols:e.full?1:5},{default:p(()=>[i(u,{span:e.full?1:3},{default:p(()=>[(s(!0),c(h,null,k(n.videos,t=>(s(),y(m(Cn),{onClick:a[0]||(a[0]=x(()=>{},["stop"])),key:t.id,src:t.content,colors:["#18a058","#2aca75"],hoverable:!0,theme:"gradient"},null,8,["src"]))),128))]),_:1},8,["span"])]),_:1},8,["cols"])])):g("",!0)}}});const En={class:"images-wrap"},Nn=$({props:{imgs:{default:()=>[]}},setup(e){const n=e,l="https://paopao-assets.oss-cn-shanghai.aliyuncs.com/public/404.png",a="?x-oss-process=image/resize,m_fill,w_300,h_300,limit_0/auto-orient,1/format,png";return(u,r)=>{const t=we,d=J,v=ee,w=be;return s(),c("div",En,[[1].includes(n.imgs.length)?(s(),y(w,{key:0},{default:p(()=>[i(v,{"x-gap":4,"y-gap":4,cols:2},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,o=>(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[0]||(r[0]=x(()=>{},["stop"])),class:"post-img x1","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024))),128))]),_:1})]),_:1})):g("",!0),[2,3].includes(n.imgs.length)?(s(),y(w,{key:1},{default:p(()=>[i(v,{"x-gap":4,"y-gap":4,cols:3},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,o=>(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[1]||(r[1]=x(()=>{},["stop"])),class:"post-img x2","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024))),128))]),_:1})]),_:1})):g("",!0),[4].includes(n.imgs.length)?(s(),y(w,{key:2},{default:p(()=>[i(v,{"x-gap":4,"y-gap":4,cols:4},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,o=>(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[2]||(r[2]=x(()=>{},["stop"])),class:"post-img x3","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024))),128))]),_:1})]),_:1})):g("",!0),[5].includes(n.imgs.length)?(s(),y(w,{key:3},{default:p(()=>[i(v,{"x-gap":4,"y-gap":4,cols:3},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,{key:o.id},[f<3?(s(),y(d,{key:0},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[3]||(r[3]=x(()=>{},["stop"])),class:"post-img x2","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),128))]),_:1}),i(v,{"x-gap":4,"y-gap":4,cols:2,style:{"margin-top":"4px"}},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,{key:o.id},[f>=3?(s(),y(d,{key:0},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[4]||(r[4]=x(()=>{},["stop"])),class:"post-img x1","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),128))]),_:1})]),_:1})):g("",!0),[6].includes(n.imgs.length)?(s(),y(w,{key:4},{default:p(()=>[i(v,{"x-gap":4,"y-gap":4,cols:3},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,{key:o.id},[f<3?(s(),y(d,{key:0},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[5]||(r[5]=x(()=>{},["stop"])),class:"post-img x2","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),128))]),_:1}),i(v,{"x-gap":4,"y-gap":4,cols:3,style:{"margin-top":"4px"}},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,{key:o.id},[f>=3?(s(),y(d,{key:0},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[6]||(r[6]=x(()=>{},["stop"])),class:"post-img x2","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),128))]),_:1})]),_:1})):g("",!0),n.imgs.length===7?(s(),y(w,{key:5},{default:p(()=>[i(v,{"x-gap":4,"y-gap":4,cols:4},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,null,[f<4?(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[7]||(r[7]=x(()=>{},["stop"])),class:"post-img x3","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),256))]),_:1}),i(v,{"x-gap":4,"y-gap":4,cols:3,style:{"margin-top":"4px"}},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,null,[f>=4?(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[8]||(r[8]=x(()=>{},["stop"])),class:"post-img x2","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),256))]),_:1})]),_:1})):g("",!0),n.imgs.length===8?(s(),y(w,{key:6},{default:p(()=>[i(v,{"x-gap":4,"y-gap":4,cols:4},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,null,[f<4?(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[9]||(r[9]=x(()=>{},["stop"])),class:"post-img x3","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),256))]),_:1}),i(v,{"x-gap":4,"y-gap":4,cols:4,style:{"margin-top":"4px"}},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,null,[f>=4?(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[10]||(r[10]=x(()=>{},["stop"])),class:"post-img x3","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),256))]),_:1})]),_:1})):g("",!0),n.imgs.length===9?(s(),y(w,{key:7},{default:p(()=>[i(v,{"x-gap":4,"y-gap":4,cols:3},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,null,[f<3?(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[11]||(r[11]=x(()=>{},["stop"])),class:"post-img x2","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),256))]),_:1}),i(v,{"x-gap":4,"y-gap":4,cols:3,style:{"margin-top":"4px"}},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,null,[f>=3&&f<6?(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[12]||(r[12]=x(()=>{},["stop"])),class:"post-img x2","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),256))]),_:1}),i(v,{"x-gap":4,"y-gap":4,cols:3,style:{"margin-top":"4px"}},{default:p(()=>[(s(!0),c(h,null,k(n.imgs,(o,f)=>(s(),c(h,null,[f>=6?(s(),y(d,{key:o.id},{default:p(()=>[i(t,{onError:()=>o.content=m(l),onClick:r[13]||(r[13]=x(()=>{},["stop"])),class:"post-img x2","object-fit":"cover",src:o.content+m(a),"preview-src":o.content},null,8,["onError","src","preview-src"])]),_:2},1024)):g("",!0)],64))),256))]),_:1})]),_:1})):g("",!0)])}}});const _n={class:"attachment-wrap"},Bn=$({props:{attachments:{default:()=>[]},price:{default:0}},setup(e){const n=e,l=I(!1),a=I(""),u=I(0),r=d=>{l.value=!0,u.value=d.id,a.value="\u8FD9\u662F\u4E00\u4E2A\u514D\u8D39\u9644\u4EF6\uFF0C\u60A8\u53EF\u4EE5\u76F4\u63A5\u4E0B\u8F7D\uFF1F",d.type===8&&(a.value=()=>R("div",{},[R("p",{},"\u8FD9\u662F\u4E00\u4E2A\u6536\u8D39\u9644\u4EF6\uFF0C\u4E0B\u8F7D\u5C06\u6536\u53D6"+(n.price/100).toFixed(2)+"\u5143")]),xe({id:u.value}).then(v=>{v.paid&&(a.value=()=>R("div",{},[R("p",{},"\u6B64\u6B21\u4E0B\u8F7D\u60A8\u5DF2\u652F\u4ED8\u6216\u65E0\u9700\u4ED8\u8D39\uFF0C\u8BF7\u786E\u8BA4\u4E0B\u8F7D")]))}).catch(v=>{l.value=!1}))},t=()=>{$e({id:u.value}).then(d=>{window.open(d.replace("http://","https://"),"_blank")}).catch(d=>{console.log(d)})};return(d,v)=>{const w=Y,o=Ce,f=Se;return s(),c("div",_n,[(s(!0),c(h,null,k(e.attachments,E=>(s(),c("div",{class:"attach-item",key:E.id},[i(o,{onClick:x(z=>r(E),["stop"]),type:"primary",size:"tiny",dashed:""},{icon:p(()=>[i(w,null,{default:p(()=>[i(m(Ue))]),_:1})]),default:p(()=>[ke(" "+N(E.type===8?"\u6536\u8D39":"\u514D\u8D39")+"\u9644\u4EF6 ",1)]),_:2},1032,["onClick"])]))),128)),i(f,{show:l.value,"onUpdate:show":v[0]||(v[0]=E=>l.value=E),"mask-closable":!1,preset:"dialog",title:"\u4E0B\u8F7D\u63D0\u793A",content:a.value,"positive-text":"\u786E\u8BA4\u4E0B\u8F7D","negative-text":"\u53D6\u6D88","icon-placement":"top",onPositiveClick:t},null,8,["show","content"])])}}});var An=H(Bn,[["__scopeId","data-v-ca4bb796"]]);const Pn=e=>{const n=[],l=[];var a=/(#|#)([^#@])+?\s+?/g,u=/@([a-zA-Z0-9])+?\s+?/g;return e=e.replace(/<[^>]*?>/gi,"").replace(/(.*?)<\/[^>]*?>/gi,"").replace(a,r=>(n.push(r.substr(1).trim()),''+r.trim()+" ")).replace(u,r=>(l.push(r.substr(1).trim()),''+r.trim()+" ")),{content:e,tags:n,users:l}};export{jn as B,Rn as C,Fn as H,An as _,Nn as a,Mn as b,In as c,Pn as p}; diff --git a/web/dist/assets/content.ef781517.css b/web/dist/assets/content.ef781517.css deleted file mode 100644 index a2bccb17..00000000 --- a/web/dist/assets/content.ef781517.css +++ /dev/null @@ -1 +0,0 @@ -.link-wrap[data-v-4c9a59cc]{margin-bottom:10px}.link-wrap .link-item[data-v-4c9a59cc]{display:flex;align-items:center}.link-wrap .link-item .hash-link .link-txt[data-v-4c9a59cc]{margin-left:4px;word-break:break-all}.images-wrap{margin-top:10px}.post-img{display:flex;margin:0;border-radius:3px;overflow:hidden;background:rgba(0,0,0,.1);border:1px solid #eee}.post-img img{width:100%;height:100%}.x1{height:140px}.x2{height:90px}.x3{height:80px}.dark .post-img{border:1px solid #333}@media screen and (max-width: 821px){.x1{height:100px}.x2{height:70px}.x3{height:50px}}.attach-item[data-v-ca4bb796]{margin:10px 0} diff --git a/web/dist/assets/formatTime.02109bf5.js b/web/dist/assets/formatTime.02109bf5.js deleted file mode 100644 index ec43b2ec..00000000 --- a/web/dist/assets/formatTime.02109bf5.js +++ /dev/null @@ -1,11 +0,0 @@ -//! moment.js -//! version : 2.29.3 -//! authors : Tim Wood, Iskren Chernev, Moment.js contributors -//! license : MIT -//! momentjs.com -var Wt;function l(){return Wt.apply(null,arguments)}function Ds(e){Wt=e}function I(e){return e instanceof Array||Object.prototype.toString.call(e)==="[object Array]"}function ae(e){return e!=null&&Object.prototype.toString.call(e)==="[object Object]"}function y(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function nt(e){if(Object.getOwnPropertyNames)return Object.getOwnPropertyNames(e).length===0;var t;for(t in e)if(y(e,t))return!1;return!0}function b(e){return e===void 0}function q(e){return typeof e=="number"||Object.prototype.toString.call(e)==="[object Number]"}function De(e){return e instanceof Date||Object.prototype.toString.call(e)==="[object Date]"}function Nt(e,t){var s=[],r,a=e.length;for(r=0;r>>0,r;for(r=0;r0)for(s=0;s=0;return(n?s?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+r}var ut=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,pe=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,qe={},ue={};function h(e,t,s,r){var a=r;typeof r=="string"&&(a=function(){return this[r]()}),e&&(ue[e]=a),t&&(ue[t[0]]=function(){return E(a.apply(this,arguments),t[1],t[2])}),s&&(ue[s]=function(){return this.localeData().ordinal(a.apply(this,arguments),e)})}function Os(e){return e.match(/\[[\s\S]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"")}function Ts(e){var t=e.match(ut),s,r;for(s=0,r=t.length;s=0&&pe.test(e);)e=e.replace(pe,r),pe.lastIndex=0,s-=1;return e}var xs={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function bs(e){var t=this._longDateFormat[e],s=this._longDateFormat[e.toUpperCase()];return t||!s?t:(this._longDateFormat[e]=s.match(ut).map(function(r){return r==="MMMM"||r==="MM"||r==="DD"||r==="dddd"?r.slice(1):r}).join(""),this._longDateFormat[e])}var Ws="Invalid date";function Ns(){return this._invalidDate}var Ps="%d",Rs=/\d{1,2}/;function Fs(e){return this._ordinal.replace("%d",e)}var Ls={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function Is(e,t,s,r){var a=this._relativeTime[s];return V(a)?a(e,t,s,r):a.replace(/%d/i,e)}function Cs(e,t){var s=this._relativeTime[e>0?"future":"past"];return V(s)?s(t):s.replace(/%s/i,t)}var ye={};function O(e,t){var s=e.toLowerCase();ye[s]=ye[s+"s"]=ye[t]=e}function F(e){return typeof e=="string"?ye[e]||ye[e.toLowerCase()]:void 0}function dt(e){var t={},s,r;for(r in e)y(e,r)&&(s=F(r),s&&(t[s]=e[r]));return t}var Lt={};function T(e,t){Lt[e]=t}function Us(e){var t=[],s;for(s in e)y(e,s)&&t.push({unit:s,priority:Lt[s]});return t.sort(function(r,a){return r.priority-a.priority}),t}function Ce(e){return e%4===0&&e%100!==0||e%400===0}function P(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function _(e){var t=+e,s=0;return t!==0&&isFinite(t)&&(s=P(t)),s}function fe(e,t){return function(s){return s!=null?(It(this,e,s),l.updateOffset(this,t),this):We(this,e)}}function We(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function It(e,t,s){e.isValid()&&!isNaN(s)&&(t==="FullYear"&&Ce(e.year())&&e.month()===1&&e.date()===29?(s=_(s),e._d["set"+(e._isUTC?"UTC":"")+t](s,e.month(),Ge(s,e.month()))):e._d["set"+(e._isUTC?"UTC":"")+t](s))}function Hs(e){return e=F(e),V(this[e])?this[e]():this}function Es(e,t){if(typeof e=="object"){e=dt(e);var s=Us(e),r,a=s.length;for(r=0;r68?1900:2e3)};var Zt=fe("FullYear",!0);function nr(){return Ce(this.year())}function ir(e,t,s,r,a,n,i){var d;return e<100&&e>=0?(d=new Date(e+400,t,s,r,a,n,i),isFinite(d.getFullYear())&&d.setFullYear(e)):d=new Date(e,t,s,r,a,n,i),d}function ke(e){var t,s;return e<100&&e>=0?(s=Array.prototype.slice.call(arguments),s[0]=e+400,t=new Date(Date.UTC.apply(null,s)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)):t=new Date(Date.UTC.apply(null,arguments)),t}function Pe(e,t,s){var r=7+t-s,a=(7+ke(e,0,r).getUTCDay()-t)%7;return-a+r-1}function $t(e,t,s,r,a){var n=(7+s-r)%7,i=Pe(e,r,a),d=1+7*(t-1)+n+i,c,k;return d<=0?(c=e-1,k=we(c)+d):d>we(e)?(c=e+1,k=d-we(e)):(c=e,k=d),{year:c,dayOfYear:k}}function Me(e,t,s){var r=Pe(e.year(),t,s),a=Math.floor((e.dayOfYear()-r-1)/7)+1,n,i;return a<1?(i=e.year()-1,n=a+B(i,t,s)):a>B(e.year(),t,s)?(n=a-B(e.year(),t,s),i=e.year()+1):(i=e.year(),n=a),{week:n,year:i}}function B(e,t,s){var r=Pe(e,t,s),a=Pe(e+1,t,s);return(we(e)-r+a)/7}h("w",["ww",2],"wo","week");h("W",["WW",2],"Wo","isoWeek");O("week","w");O("isoWeek","W");T("week",5);T("isoWeek",5);u("w",D);u("ww",D,N);u("W",D);u("WW",D,N);ve(["w","ww","W","WW"],function(e,t,s,r){t[r.substr(0,1)]=_(e)});function or(e){return Me(e,this._week.dow,this._week.doy).week}var lr={dow:0,doy:6};function ur(){return this._week.dow}function dr(){return this._week.doy}function hr(e){var t=this.localeData().week(this);return e==null?t:this.add((e-t)*7,"d")}function fr(e){var t=Me(this,1,4).week;return e==null?t:this.add((e-t)*7,"d")}h("d",0,"do","day");h("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)});h("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)});h("dddd",0,0,function(e){return this.localeData().weekdays(this,e)});h("e",0,0,"weekday");h("E",0,0,"isoWeekday");O("day","d");O("weekday","e");O("isoWeekday","E");T("day",11);T("weekday",11);T("isoWeekday",11);u("d",D);u("e",D);u("E",D);u("dd",function(e,t){return t.weekdaysMinRegex(e)});u("ddd",function(e,t){return t.weekdaysShortRegex(e)});u("dddd",function(e,t){return t.weekdaysRegex(e)});ve(["dd","ddd","dddd"],function(e,t,s,r){var a=s._locale.weekdaysParse(e,r,s._strict);a!=null?t.d=a:f(s).invalidWeekday=e});ve(["d","e","E"],function(e,t,s,r){t[r]=_(e)});function cr(e,t){return typeof e!="string"?e:isNaN(e)?(e=t.weekdaysParse(e),typeof e=="number"?e:null):parseInt(e,10)}function _r(e,t){return typeof e=="string"?t.weekdaysParse(e)%7||7:isNaN(e)?null:e}function ct(e,t){return e.slice(t,7).concat(e.slice(0,t))}var mr="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Bt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),yr="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),wr=ge,kr=ge,Mr=ge;function Sr(e,t){var s=I(this._weekdays)?this._weekdays:this._weekdays[e&&e!==!0&&this._weekdays.isFormat.test(t)?"format":"standalone"];return e===!0?ct(s,this._week.dow):e?s[e.day()]:s}function Dr(e){return e===!0?ct(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort}function Yr(e){return e===!0?ct(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin}function gr(e,t,s){var r,a,n,i=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],r=0;r<7;++r)n=A([2e3,1]).day(r),this._minWeekdaysParse[r]=this.weekdaysMin(n,"").toLocaleLowerCase(),this._shortWeekdaysParse[r]=this.weekdaysShort(n,"").toLocaleLowerCase(),this._weekdaysParse[r]=this.weekdays(n,"").toLocaleLowerCase();return s?t==="dddd"?(a=g.call(this._weekdaysParse,i),a!==-1?a:null):t==="ddd"?(a=g.call(this._shortWeekdaysParse,i),a!==-1?a:null):(a=g.call(this._minWeekdaysParse,i),a!==-1?a:null):t==="dddd"?(a=g.call(this._weekdaysParse,i),a!==-1||(a=g.call(this._shortWeekdaysParse,i),a!==-1)?a:(a=g.call(this._minWeekdaysParse,i),a!==-1?a:null)):t==="ddd"?(a=g.call(this._shortWeekdaysParse,i),a!==-1||(a=g.call(this._weekdaysParse,i),a!==-1)?a:(a=g.call(this._minWeekdaysParse,i),a!==-1?a:null)):(a=g.call(this._minWeekdaysParse,i),a!==-1||(a=g.call(this._weekdaysParse,i),a!==-1)?a:(a=g.call(this._shortWeekdaysParse,i),a!==-1?a:null))}function vr(e,t,s){var r,a,n;if(this._weekdaysParseExact)return gr.call(this,e,t,s);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),r=0;r<7;r++){if(a=A([2e3,1]).day(r),s&&!this._fullWeekdaysParse[r]&&(this._fullWeekdaysParse[r]=new RegExp("^"+this.weekdays(a,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[r]=new RegExp("^"+this.weekdaysShort(a,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[r]=new RegExp("^"+this.weekdaysMin(a,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[r]||(n="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[r]=new RegExp(n.replace(".",""),"i")),s&&t==="dddd"&&this._fullWeekdaysParse[r].test(e))return r;if(s&&t==="ddd"&&this._shortWeekdaysParse[r].test(e))return r;if(s&&t==="dd"&&this._minWeekdaysParse[r].test(e))return r;if(!s&&this._weekdaysParse[r].test(e))return r}}function pr(e){if(!this.isValid())return e!=null?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return e!=null?(e=cr(e,this.localeData()),this.add(e-t,"d")):t}function Or(e){if(!this.isValid())return e!=null?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return e==null?t:this.add(e-t,"d")}function Tr(e){if(!this.isValid())return e!=null?this:NaN;if(e!=null){var t=_r(e,this.localeData());return this.day(this.day()%7?t:t-7)}else return this.day()||7}function xr(e){return this._weekdaysParseExact?(y(this,"_weekdaysRegex")||_t.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(y(this,"_weekdaysRegex")||(this._weekdaysRegex=wr),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)}function br(e){return this._weekdaysParseExact?(y(this,"_weekdaysRegex")||_t.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(y(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=kr),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Wr(e){return this._weekdaysParseExact?(y(this,"_weekdaysRegex")||_t.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(y(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Mr),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function _t(){function e(x,G){return G.length-x.length}var t=[],s=[],r=[],a=[],n,i,d,c,k;for(n=0;n<7;n++)i=A([2e3,1]).day(n),d=W(this.weekdaysMin(i,"")),c=W(this.weekdaysShort(i,"")),k=W(this.weekdays(i,"")),t.push(d),s.push(c),r.push(k),a.push(d),a.push(c),a.push(k);t.sort(e),s.sort(e),r.sort(e),a.sort(e),this._weekdaysRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+r.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+t.join("|")+")","i")}function mt(){return this.hours()%12||12}function Nr(){return this.hours()||24}h("H",["HH",2],0,"hour");h("h",["hh",2],0,mt);h("k",["kk",2],0,Nr);h("hmm",0,0,function(){return""+mt.apply(this)+E(this.minutes(),2)});h("hmmss",0,0,function(){return""+mt.apply(this)+E(this.minutes(),2)+E(this.seconds(),2)});h("Hmm",0,0,function(){return""+this.hours()+E(this.minutes(),2)});h("Hmmss",0,0,function(){return""+this.hours()+E(this.minutes(),2)+E(this.seconds(),2)});function qt(e,t){h(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}qt("a",!0);qt("A",!1);O("hour","h");T("hour",13);function Jt(e,t){return t._meridiemParse}u("a",Jt);u("A",Jt);u("H",D);u("h",D);u("k",D);u("HH",D,N);u("hh",D,N);u("kk",D,N);u("hmm",Ht);u("hmmss",Et);u("Hmm",Ht);u("Hmmss",Et);M(["H","HH"],v);M(["k","kk"],function(e,t,s){var r=_(e);t[v]=r===24?0:r});M(["a","A"],function(e,t,s){s._isPm=s._locale.isPM(e),s._meridiem=e});M(["h","hh"],function(e,t,s){t[v]=_(e),f(s).bigHour=!0});M("hmm",function(e,t,s){var r=e.length-2;t[v]=_(e.substr(0,r)),t[L]=_(e.substr(r)),f(s).bigHour=!0});M("hmmss",function(e,t,s){var r=e.length-4,a=e.length-2;t[v]=_(e.substr(0,r)),t[L]=_(e.substr(r,2)),t[$]=_(e.substr(a)),f(s).bigHour=!0});M("Hmm",function(e,t,s){var r=e.length-2;t[v]=_(e.substr(0,r)),t[L]=_(e.substr(r))});M("Hmmss",function(e,t,s){var r=e.length-4,a=e.length-2;t[v]=_(e.substr(0,r)),t[L]=_(e.substr(r,2)),t[$]=_(e.substr(a))});function Pr(e){return(e+"").toLowerCase().charAt(0)==="p"}var Rr=/[ap]\.?m?\.?/i,Fr=fe("Hours",!0);function Lr(e,t,s){return e>11?s?"pm":"PM":s?"am":"AM"}var Qt={calendar:vs,longDateFormat:xs,invalidDate:Ws,ordinal:Ps,dayOfMonthOrdinalParse:Rs,relativeTime:Ls,months:qs,monthsShort:At,week:lr,weekdays:mr,weekdaysMin:yr,weekdaysShort:Bt,meridiemParse:Rr},Y={},_e={},Se;function Ir(e,t){var s,r=Math.min(e.length,t.length);for(s=0;s0;){if(a=je(n.slice(0,s).join("-")),a)return a;if(r&&r.length>=s&&Ir(n,r)>=s-1)break;s--}t++}return Se}function Ur(e){return e.match("^[^/\\\\]*$")!=null}function je(e){var t=null,s;if(Y[e]===void 0&&typeof module!="undefined"&&module&&module.exports&&Ur(e))try{t=Se._abbr,s=require,s("./locale/"+e),te(t)}catch{Y[e]=null}return Y[e]}function te(e,t){var s;return e&&(b(t)?s=J(e):s=yt(e,t),s?Se=s:typeof console!="undefined"&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),Se._abbr}function yt(e,t){if(t!==null){var s,r=Qt;if(t.abbr=e,Y[e]!=null)Rt("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),r=Y[e]._config;else if(t.parentLocale!=null)if(Y[t.parentLocale]!=null)r=Y[t.parentLocale]._config;else if(s=je(t.parentLocale),s!=null)r=s._config;else return _e[t.parentLocale]||(_e[t.parentLocale]=[]),_e[t.parentLocale].push({name:e,config:t}),null;return Y[e]=new lt(Ke(r,t)),_e[e]&&_e[e].forEach(function(a){yt(a.name,a.config)}),te(e),Y[e]}else return delete Y[e],null}function Hr(e,t){if(t!=null){var s,r,a=Qt;Y[e]!=null&&Y[e].parentLocale!=null?Y[e].set(Ke(Y[e]._config,t)):(r=je(e),r!=null&&(a=r._config),t=Ke(a,t),r==null&&(t.abbr=e),s=new lt(t),s.parentLocale=Y[e],Y[e]=s),te(e)}else Y[e]!=null&&(Y[e].parentLocale!=null?(Y[e]=Y[e].parentLocale,e===te()&&te(e)):Y[e]!=null&&delete Y[e]);return Y[e]}function J(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return Se;if(!I(e)){if(t=je(e),t)return t;e=[e]}return Cr(e)}function Er(){return et(Y)}function wt(e){var t,s=e._a;return s&&f(e).overflow===-2&&(t=s[Z]<0||s[Z]>11?Z:s[H]<1||s[H]>Ge(s[p],s[Z])?H:s[v]<0||s[v]>24||s[v]===24&&(s[L]!==0||s[$]!==0||s[re]!==0)?v:s[L]<0||s[L]>59?L:s[$]<0||s[$]>59?$:s[re]<0||s[re]>999?re:-1,f(e)._overflowDayOfYear&&(tH)&&(t=H),f(e)._overflowWeeks&&t===-1&&(t=Zs),f(e)._overflowWeekday&&t===-1&&(t=$s),f(e).overflow=t),e}var Ar=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Vr=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Gr=/Z|[+-]\d\d(?::?\d\d)?/,Oe=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],Je=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],jr=/^\/?Date\((-?\d+)/i,zr=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Zr={UT:0,GMT:0,EDT:-4*60,EST:-5*60,CDT:-5*60,CST:-6*60,MDT:-6*60,MST:-7*60,PDT:-7*60,PST:-8*60};function Xt(e){var t,s,r=e._i,a=Ar.exec(r)||Vr.exec(r),n,i,d,c,k=Oe.length,x=Je.length;if(a){for(f(e).iso=!0,t=0,s=k;twe(i)||e._dayOfYear===0)&&(f(e)._overflowDayOfYear=!0),s=ke(i,0,e._dayOfYear),e._a[Z]=s.getUTCMonth(),e._a[H]=s.getUTCDate()),t=0;t<3&&e._a[t]==null;++t)e._a[t]=r[t]=a[t];for(;t<7;t++)e._a[t]=r[t]=e._a[t]==null?t===2?1:0:e._a[t];e._a[v]===24&&e._a[L]===0&&e._a[$]===0&&e._a[re]===0&&(e._nextDay=!0,e._a[v]=0),e._d=(e._useUTC?ke:ir).apply(null,r),n=e._useUTC?e._d.getUTCDay():e._d.getDay(),e._tzm!=null&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[v]=24),e._w&&typeof e._w.d!="undefined"&&e._w.d!==n&&(f(e).weekdayMismatch=!0)}}function ea(e){var t,s,r,a,n,i,d,c,k;t=e._w,t.GG!=null||t.W!=null||t.E!=null?(n=1,i=4,s=oe(t.GG,e._a[p],Me(S(),1,4).year),r=oe(t.W,1),a=oe(t.E,1),(a<1||a>7)&&(c=!0)):(n=e._locale._week.dow,i=e._locale._week.doy,k=Me(S(),n,i),s=oe(t.gg,e._a[p],k.year),r=oe(t.w,k.week),t.d!=null?(a=t.d,(a<0||a>6)&&(c=!0)):t.e!=null?(a=t.e+n,(t.e<0||t.e>6)&&(c=!0)):a=n),r<1||r>B(s,n,i)?f(e)._overflowWeeks=!0:c!=null?f(e)._overflowWeekday=!0:(d=$t(s,r,a,n,i),e._a[p]=d.year,e._dayOfYear=d.dayOfYear)}l.ISO_8601=function(){};l.RFC_2822=function(){};function Mt(e){if(e._f===l.ISO_8601){Xt(e);return}if(e._f===l.RFC_2822){Kt(e);return}e._a=[],f(e).empty=!0;var t=""+e._i,s,r,a,n,i,d=t.length,c=0,k,x;for(a=Ft(e._f,e._locale).match(ut)||[],x=a.length,s=0;s0&&f(e).unusedInput.push(i),t=t.slice(t.indexOf(r)+r.length),c+=r.length),ue[n]?(r?f(e).empty=!1:f(e).unusedTokens.push(n),zs(n,r,e)):e._strict&&!r&&f(e).unusedTokens.push(n);f(e).charsLeftOver=d-c,t.length>0&&f(e).unusedInput.push(t),e._a[v]<=12&&f(e).bigHour===!0&&e._a[v]>0&&(f(e).bigHour=void 0),f(e).parsedDateParts=e._a.slice(0),f(e).meridiem=e._meridiem,e._a[v]=ta(e._locale,e._a[v],e._meridiem),k=f(e).era,k!==null&&(e._a[p]=e._locale.erasConvertYear(k,e._a[p])),kt(e),wt(e)}function ta(e,t,s){var r;return s==null?t:e.meridiemHour!=null?e.meridiemHour(t,s):(e.isPM!=null&&(r=e.isPM(s),r&&t<12&&(t+=12),!r&&t===12&&(t=0)),t)}function sa(e){var t,s,r,a,n,i,d=!1,c=e._f.length;if(c===0){f(e).invalidFormat=!0,e._d=new Date(NaN);return}for(a=0;athis?this:e:Ie()});function ss(e,t){var s,r;if(t.length===1&&I(t[0])&&(t=t[0]),!t.length)return S();for(s=t[0],r=1;rthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function ga(){if(!b(this._isDSTShifted))return this._isDSTShifted;var e={},t;return ot(e,this),e=es(e),e._a?(t=e._isUTC?A(e._a):S(e._a),this._isDSTShifted=this.isValid()&&_a(e._a,t.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function va(){return this.isValid()?!this._isUTC:!1}function pa(){return this.isValid()?this._isUTC:!1}function as(){return this.isValid()?this._isUTC&&this._offset===0:!1}var Oa=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,Ta=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function U(e,t){var s=e,r=null,a,n,i;return xe(e)?s={ms:e._milliseconds,d:e._days,M:e._months}:q(e)||!isNaN(+e)?(s={},t?s[t]=+e:s.milliseconds=+e):(r=Oa.exec(e))?(a=r[1]==="-"?-1:1,s={y:0,d:_(r[H])*a,h:_(r[v])*a,m:_(r[L])*a,s:_(r[$])*a,ms:_(st(r[re]*1e3))*a}):(r=Ta.exec(e))?(a=r[1]==="-"?-1:1,s={y:se(r[2],a),M:se(r[3],a),w:se(r[4],a),d:se(r[5],a),h:se(r[6],a),m:se(r[7],a),s:se(r[8],a)}):s==null?s={}:typeof s=="object"&&("from"in s||"to"in s)&&(i=xa(S(s.from),S(s.to)),s={},s.ms=i.milliseconds,s.M=i.months),n=new ze(s),xe(e)&&y(e,"_locale")&&(n._locale=e._locale),xe(e)&&y(e,"_isValid")&&(n._isValid=e._isValid),n}U.fn=ze.prototype;U.invalid=ca;function se(e,t){var s=e&&parseFloat(e.replace(",","."));return(isNaN(s)?0:s)*t}function xt(e,t){var s={};return s.months=t.month()-e.month()+(t.year()-e.year())*12,e.clone().add(s.months,"M").isAfter(t)&&--s.months,s.milliseconds=+t-+e.clone().add(s.months,"M"),s}function xa(e,t){var s;return e.isValid()&&t.isValid()?(t=Dt(t,e),e.isBefore(t)?s=xt(e,t):(s=xt(t,e),s.milliseconds=-s.milliseconds,s.months=-s.months),s):{milliseconds:0,months:0}}function ns(e,t){return function(s,r){var a,n;return r!==null&&!isNaN(+r)&&(Rt(t,"moment()."+t+"(period, number) is deprecated. Please use moment()."+t+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=s,s=r,r=n),a=U(s,r),is(this,a,e),this}}function is(e,t,s,r){var a=t._milliseconds,n=st(t._days),i=st(t._months);!e.isValid()||(r=r==null?!0:r,i&&Gt(e,We(e,"Month")+i*s),n&&It(e,"Date",We(e,"Date")+n*s),a&&e._d.setTime(e._d.valueOf()+a*s),r&&l.updateOffset(e,n||i))}var ba=ns(1,"add"),Wa=ns(-1,"subtract");function os(e){return typeof e=="string"||e instanceof String}function Na(e){return C(e)||De(e)||os(e)||q(e)||Ra(e)||Pa(e)||e===null||e===void 0}function Pa(e){var t=ae(e)&&!nt(e),s=!1,r=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],a,n,i=r.length;for(a=0;as.valueOf():s.valueOf()9999?Te(s,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):V(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+this.utcOffset()*60*1e3).toISOString().replace("Z",Te(s,"Z")):Te(s,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function $a(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="",s,r,a,n;return this.isLocal()||(e=this.utcOffset()===0?"moment.utc":"moment.parseZone",t="Z"),s="["+e+'("]',r=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",a="-MM-DD[T]HH:mm:ss.SSS",n=t+'[")]',this.format(s+r+a+n)}function Ba(e){e||(e=this.isUtc()?l.defaultFormatUtc:l.defaultFormat);var t=Te(this,e);return this.localeData().postformat(t)}function qa(e,t){return this.isValid()&&(C(e)&&e.isValid()||S(e).isValid())?U({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()}function Ja(e){return this.from(S(),e)}function Qa(e,t){return this.isValid()&&(C(e)&&e.isValid()||S(e).isValid())?U({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()}function Xa(e){return this.to(S(),e)}function ls(e){var t;return e===void 0?this._locale._abbr:(t=J(e),t!=null&&(this._locale=t),this)}var us=R("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return e===void 0?this.localeData():this.locale(e)});function ds(){return this._locale}var Re=1e3,de=60*Re,Fe=60*de,hs=(365*400+97)*24*Fe;function he(e,t){return(e%t+t)%t}function fs(e,t,s){return e<100&&e>=0?new Date(e+400,t,s)-hs:new Date(e,t,s).valueOf()}function cs(e,t,s){return e<100&&e>=0?Date.UTC(e+400,t,s)-hs:Date.UTC(e,t,s)}function Ka(e){var t,s;if(e=F(e),e===void 0||e==="millisecond"||!this.isValid())return this;switch(s=this._isUTC?cs:fs,e){case"year":t=s(this.year(),0,1);break;case"quarter":t=s(this.year(),this.month()-this.month()%3,1);break;case"month":t=s(this.year(),this.month(),1);break;case"week":t=s(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=s(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=s(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=he(t+(this._isUTC?0:this.utcOffset()*de),Fe);break;case"minute":t=this._d.valueOf(),t-=he(t,de);break;case"second":t=this._d.valueOf(),t-=he(t,Re);break}return this._d.setTime(t),l.updateOffset(this,!0),this}function en(e){var t,s;if(e=F(e),e===void 0||e==="millisecond"||!this.isValid())return this;switch(s=this._isUTC?cs:fs,e){case"year":t=s(this.year()+1,0,1)-1;break;case"quarter":t=s(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=s(this.year(),this.month()+1,1)-1;break;case"week":t=s(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=s(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=s(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=Fe-he(t+(this._isUTC?0:this.utcOffset()*de),Fe)-1;break;case"minute":t=this._d.valueOf(),t+=de-he(t,de)-1;break;case"second":t=this._d.valueOf(),t+=Re-he(t,Re)-1;break}return this._d.setTime(t),l.updateOffset(this,!0),this}function tn(){return this._d.valueOf()-(this._offset||0)*6e4}function sn(){return Math.floor(this.valueOf()/1e3)}function rn(){return new Date(this.valueOf())}function an(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]}function nn(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}}function on(){return this.isValid()?this.toISOString():null}function ln(){return it(this)}function un(){return K({},f(this))}function dn(){return f(this).overflow}function hn(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}h("N",0,0,"eraAbbr");h("NN",0,0,"eraAbbr");h("NNN",0,0,"eraAbbr");h("NNNN",0,0,"eraName");h("NNNNN",0,0,"eraNarrow");h("y",["y",1],"yo","eraYear");h("y",["yy",2],0,"eraYear");h("y",["yyy",3],0,"eraYear");h("y",["yyyy",4],0,"eraYear");u("N",Yt);u("NN",Yt);u("NNN",Yt);u("NNNN",Yn);u("NNNNN",gn);M(["N","NN","NNN","NNNN","NNNNN"],function(e,t,s,r){var a=s._locale.erasParse(e,r,s._strict);a?f(s).era=a:f(s).invalidEra=e});u("y",ce);u("yy",ce);u("yyy",ce);u("yyyy",ce);u("yo",vn);M(["y","yy","yyy","yyyy"],p);M(["yo"],function(e,t,s,r){var a;s._locale._eraYearOrdinalRegex&&(a=e.match(s._locale._eraYearOrdinalRegex)),s._locale.eraYearOrdinalParse?t[p]=s._locale.eraYearOrdinalParse(e,a):t[p]=parseInt(e,10)});function fn(e,t){var s,r,a,n=this._eras||J("en")._eras;for(s=0,r=n.length;s=0)return n[r]}function _n(e,t){var s=e.since<=e.until?1:-1;return t===void 0?l(e.since).year():l(e.since).year()+(t-e.offset)*s}function mn(){var e,t,s,r=this.localeData().eras();for(e=0,t=r.length;en&&(t=n),Nn.call(this,e,t,s,r,a))}function Nn(e,t,s,r,a){var n=$t(e,t,s,r,a),i=ke(n.year,0,n.dayOfYear);return this.year(i.getUTCFullYear()),this.month(i.getUTCMonth()),this.date(i.getUTCDate()),this}h("Q",0,"Qo","quarter");O("quarter","Q");T("quarter",7);u("Q",Ct);M("Q",function(e,t){t[Z]=(_(e)-1)*3});function Pn(e){return e==null?Math.ceil((this.month()+1)/3):this.month((e-1)*3+this.month()%3)}h("D",["DD",2],"Do","date");O("date","D");T("date",9);u("D",D);u("DD",D,N);u("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient});M(["D","DD"],H);M("Do",function(e,t){t[H]=_(e.match(D)[0])});var ms=fe("Date",!0);h("DDD",["DDDD",3],"DDDo","dayOfYear");O("dayOfYear","DDD");T("dayOfYear",4);u("DDD",He);u("DDDD",Ut);M(["DDD","DDDD"],function(e,t,s){s._dayOfYear=_(e)});function Rn(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return e==null?t:this.add(e-t,"d")}h("m",["mm",2],0,"minute");O("minute","m");T("minute",14);u("m",D);u("mm",D,N);M(["m","mm"],L);var Fn=fe("Minutes",!1);h("s",["ss",2],0,"second");O("second","s");T("second",15);u("s",D);u("ss",D,N);M(["s","ss"],$);var Ln=fe("Seconds",!1);h("S",0,0,function(){return~~(this.millisecond()/100)});h(0,["SS",2],0,function(){return~~(this.millisecond()/10)});h(0,["SSS",3],0,"millisecond");h(0,["SSSS",4],0,function(){return this.millisecond()*10});h(0,["SSSSS",5],0,function(){return this.millisecond()*100});h(0,["SSSSSS",6],0,function(){return this.millisecond()*1e3});h(0,["SSSSSSS",7],0,function(){return this.millisecond()*1e4});h(0,["SSSSSSSS",8],0,function(){return this.millisecond()*1e5});h(0,["SSSSSSSSS",9],0,function(){return this.millisecond()*1e6});O("millisecond","ms");T("millisecond",16);u("S",He,Ct);u("SS",He,N);u("SSS",He,Ut);var ee,ys;for(ee="SSSS";ee.length<=9;ee+="S")u(ee,ce);function In(e,t){t[re]=_(("0."+e)*1e3)}for(ee="S";ee.length<=9;ee+="S")M(ee,In);ys=fe("Milliseconds",!1);h("z",0,0,"zoneAbbr");h("zz",0,0,"zoneName");function Cn(){return this._isUTC?"UTC":""}function Un(){return this._isUTC?"Coordinated Universal Time":""}var o=Ye.prototype;o.add=ba;o.calendar=Ia;o.clone=Ca;o.diff=ja;o.endOf=en;o.format=Ba;o.from=qa;o.fromNow=Ja;o.to=Qa;o.toNow=Xa;o.get=Hs;o.invalidAt=dn;o.isAfter=Ua;o.isBefore=Ha;o.isBetween=Ea;o.isSame=Aa;o.isSameOrAfter=Va;o.isSameOrBefore=Ga;o.isValid=ln;o.lang=us;o.locale=ls;o.localeData=ds;o.max=oa;o.min=ia;o.parsingFlags=un;o.set=Es;o.startOf=Ka;o.subtract=Wa;o.toArray=an;o.toObject=nn;o.toDate=rn;o.toISOString=Za;o.inspect=$a;typeof Symbol!="undefined"&&Symbol.for!=null&&(o[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"});o.toJSON=on;o.toString=za;o.unix=sn;o.valueOf=tn;o.creationData=hn;o.eraName=mn;o.eraNarrow=yn;o.eraAbbr=wn;o.eraYear=kn;o.year=Zt;o.isLeapYear=nr;o.weekYear=pn;o.isoWeekYear=On;o.quarter=o.quarters=Pn;o.month=jt;o.daysInMonth=sr;o.week=o.weeks=hr;o.isoWeek=o.isoWeeks=fr;o.weeksInYear=bn;o.weeksInWeekYear=Wn;o.isoWeeksInYear=Tn;o.isoWeeksInISOWeekYear=xn;o.date=ms;o.day=o.days=pr;o.weekday=Or;o.isoWeekday=Tr;o.dayOfYear=Rn;o.hour=o.hours=Fr;o.minute=o.minutes=Fn;o.second=o.seconds=Ln;o.millisecond=o.milliseconds=ys;o.utcOffset=ya;o.utc=ka;o.local=Ma;o.parseZone=Sa;o.hasAlignedHourOffset=Da;o.isDST=Ya;o.isLocal=va;o.isUtcOffset=pa;o.isUtc=as;o.isUTC=as;o.zoneAbbr=Cn;o.zoneName=Un;o.dates=R("dates accessor is deprecated. Use date instead.",ms);o.months=R("months accessor is deprecated. Use month instead",jt);o.years=R("years accessor is deprecated. Use year instead",Zt);o.zone=R("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",wa);o.isDSTShifted=R("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",ga);function Hn(e){return S(e*1e3)}function En(){return S.apply(null,arguments).parseZone()}function ws(e){return e}var w=lt.prototype;w.calendar=ps;w.longDateFormat=bs;w.invalidDate=Ns;w.ordinal=Fs;w.preparse=ws;w.postformat=ws;w.relativeTime=Is;w.pastFuture=Cs;w.set=gs;w.eras=fn;w.erasParse=cn;w.erasConvertYear=_n;w.erasAbbrRegex=Sn;w.erasNameRegex=Mn;w.erasNarrowRegex=Dn;w.months=Xs;w.monthsShort=Ks;w.monthsParse=tr;w.monthsRegex=ar;w.monthsShortRegex=rr;w.week=or;w.firstDayOfYear=dr;w.firstDayOfWeek=ur;w.weekdays=Sr;w.weekdaysMin=Yr;w.weekdaysShort=Dr;w.weekdaysParse=vr;w.weekdaysRegex=xr;w.weekdaysShortRegex=br;w.weekdaysMinRegex=Wr;w.isPM=Pr;w.meridiem=Lr;function Le(e,t,s,r){var a=J(),n=A().set(r,t);return a[s](n,e)}function ks(e,t,s){if(q(e)&&(t=e,e=void 0),e=e||"",t!=null)return Le(e,t,s,"month");var r,a=[];for(r=0;r<12;r++)a[r]=Le(e,r,s,"month");return a}function vt(e,t,s,r){typeof e=="boolean"?(q(t)&&(s=t,t=void 0),t=t||""):(t=e,s=t,e=!1,q(t)&&(s=t,t=void 0),t=t||"");var a=J(),n=e?a._week.dow:0,i,d=[];if(s!=null)return Le(t,(s+n)%7,r,"day");for(i=0;i<7;i++)d[i]=Le(t,(i+n)%7,r,"day");return d}function An(e,t){return ks(e,t,"months")}function Vn(e,t){return ks(e,t,"monthsShort")}function Gn(e,t,s){return vt(e,t,s,"weekdays")}function jn(e,t,s){return vt(e,t,s,"weekdaysShort")}function zn(e,t,s){return vt(e,t,s,"weekdaysMin")}te("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10,s=_(e%100/10)===1?"th":t===1?"st":t===2?"nd":t===3?"rd":"th";return e+s}});l.lang=R("moment.lang is deprecated. Use moment.locale instead.",te);l.langData=R("moment.langData is deprecated. Use moment.localeData instead.",J);var j=Math.abs;function Zn(){var e=this._data;return this._milliseconds=j(this._milliseconds),this._days=j(this._days),this._months=j(this._months),e.milliseconds=j(e.milliseconds),e.seconds=j(e.seconds),e.minutes=j(e.minutes),e.hours=j(e.hours),e.months=j(e.months),e.years=j(e.years),this}function Ms(e,t,s,r){var a=U(t,s);return e._milliseconds+=r*a._milliseconds,e._days+=r*a._days,e._months+=r*a._months,e._bubble()}function $n(e,t){return Ms(this,e,t,1)}function Bn(e,t){return Ms(this,e,t,-1)}function bt(e){return e<0?Math.floor(e):Math.ceil(e)}function qn(){var e=this._milliseconds,t=this._days,s=this._months,r=this._data,a,n,i,d,c;return e>=0&&t>=0&&s>=0||e<=0&&t<=0&&s<=0||(e+=bt(at(s)+t)*864e5,t=0,s=0),r.milliseconds=e%1e3,a=P(e/1e3),r.seconds=a%60,n=P(a/60),r.minutes=n%60,i=P(n/60),r.hours=i%24,t+=P(i/24),c=P(Ss(t)),s+=c,t-=bt(at(c)),d=P(s/12),s%=12,r.days=t,r.months=s,r.years=d,this}function Ss(e){return e*4800/146097}function at(e){return e*146097/4800}function Jn(e){if(!this.isValid())return NaN;var t,s,r=this._milliseconds;if(e=F(e),e==="month"||e==="quarter"||e==="year")switch(t=this._days+r/864e5,s=this._months+Ss(t),e){case"month":return s;case"quarter":return s/3;case"year":return s/12}else switch(t=this._days+Math.round(at(this._months)),e){case"week":return t/7+r/6048e5;case"day":return t+r/864e5;case"hour":return t*24+r/36e5;case"minute":return t*1440+r/6e4;case"second":return t*86400+r/1e3;case"millisecond":return Math.floor(t*864e5)+r;default:throw new Error("Unknown unit "+e)}}function Qn(){return this.isValid()?this._milliseconds+this._days*864e5+this._months%12*2592e6+_(this._months/12)*31536e6:NaN}function Q(e){return function(){return this.as(e)}}var Xn=Q("ms"),Kn=Q("s"),ei=Q("m"),ti=Q("h"),si=Q("d"),ri=Q("w"),ai=Q("M"),ni=Q("Q"),ii=Q("y");function oi(){return U(this)}function li(e){return e=F(e),this.isValid()?this[e+"s"]():NaN}function ne(e){return function(){return this.isValid()?this._data[e]:NaN}}var ui=ne("milliseconds"),di=ne("seconds"),hi=ne("minutes"),fi=ne("hours"),ci=ne("days"),_i=ne("months"),mi=ne("years");function yi(){return P(this.days()/7)}var z=Math.round,le={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function wi(e,t,s,r,a){return a.relativeTime(t||1,!!s,e,r)}function ki(e,t,s,r){var a=U(e).abs(),n=z(a.as("s")),i=z(a.as("m")),d=z(a.as("h")),c=z(a.as("d")),k=z(a.as("M")),x=z(a.as("w")),G=z(a.as("y")),X=n<=s.ss&&["s",n]||n0,X[4]=r,wi.apply(null,X)}function Mi(e){return e===void 0?z:typeof e=="function"?(z=e,!0):!1}function Si(e,t){return le[e]===void 0?!1:t===void 0?le[e]:(le[e]=t,e==="s"&&(le.ss=t-1),!0)}function Di(e,t){if(!this.isValid())return this.localeData().invalidDate();var s=!1,r=le,a,n;return typeof e=="object"&&(t=e,e=!1),typeof e=="boolean"&&(s=e),typeof t=="object"&&(r=Object.assign({},le,t),t.s!=null&&t.ss==null&&(r.ss=t.s-1)),a=this.localeData(),n=ki(this,!s,r,a),s&&(n=a.pastFuture(+this,n)),a.postformat(n)}var Qe=Math.abs;function ie(e){return(e>0)-(e<0)||+e}function $e(){if(!this.isValid())return this.localeData().invalidDate();var e=Qe(this._milliseconds)/1e3,t=Qe(this._days),s=Qe(this._months),r,a,n,i,d=this.asSeconds(),c,k,x,G;return d?(r=P(e/60),a=P(r/60),e%=60,r%=60,n=P(s/12),s%=12,i=e?e.toFixed(3).replace(/\.?0+$/,""):"",c=d<0?"-":"",k=ie(this._months)!==ie(d)?"-":"",x=ie(this._days)!==ie(d)?"-":"",G=ie(this._milliseconds)!==ie(d)?"-":"",c+"P"+(n?k+n+"Y":"")+(s?k+s+"M":"")+(t?x+t+"D":"")+(a||r||e?"T":"")+(a?G+a+"H":"")+(r?G+r+"M":"")+(e?G+i+"S":"")):"P0D"}var m=ze.prototype;m.isValid=fa;m.abs=Zn;m.add=$n;m.subtract=Bn;m.as=Jn;m.asMilliseconds=Xn;m.asSeconds=Kn;m.asMinutes=ei;m.asHours=ti;m.asDays=si;m.asWeeks=ri;m.asMonths=ai;m.asQuarters=ni;m.asYears=ii;m.valueOf=Qn;m._bubble=qn;m.clone=oi;m.get=li;m.milliseconds=ui;m.seconds=di;m.minutes=hi;m.hours=fi;m.days=ci;m.weeks=yi;m.months=_i;m.years=mi;m.humanize=Di;m.toISOString=$e;m.toString=$e;m.toJSON=$e;m.locale=ls;m.localeData=ds;m.toIsoString=R("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",$e);m.lang=us;h("X",0,0,"unix");h("x",0,0,"valueOf");u("x",Ae);u("X",Vs);M("X",function(e,t,s){s._d=new Date(parseFloat(e)*1e3)});M("x",function(e,t,s){s._d=new Date(_(e))});//! moment.js -l.version="2.29.3";Ds(S);l.fn=o;l.min=la;l.max=ua;l.now=da;l.utc=A;l.unix=Hn;l.months=An;l.isDate=De;l.locale=te;l.invalid=Ie;l.duration=U;l.isMoment=C;l.weekdays=Gn;l.parseZone=En;l.localeData=J;l.isDuration=xe;l.monthsShort=Vn;l.weekdaysMin=zn;l.defineLocale=yt;l.updateLocale=Hr;l.locales=Er;l.weekdaysShort=jn;l.normalizeUnits=F;l.relativeTimeRounding=Mi;l.relativeTimeThreshold=Si;l.calendarFormat=La;l.prototype=o;l.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"};//! moment.js locale configuration -l.defineLocale("zh-cn",{months:"\u4E00\u6708_\u4E8C\u6708_\u4E09\u6708_\u56DB\u6708_\u4E94\u6708_\u516D\u6708_\u4E03\u6708_\u516B\u6708_\u4E5D\u6708_\u5341\u6708_\u5341\u4E00\u6708_\u5341\u4E8C\u6708".split("_"),monthsShort:"1\u6708_2\u6708_3\u6708_4\u6708_5\u6708_6\u6708_7\u6708_8\u6708_9\u6708_10\u6708_11\u6708_12\u6708".split("_"),weekdays:"\u661F\u671F\u65E5_\u661F\u671F\u4E00_\u661F\u671F\u4E8C_\u661F\u671F\u4E09_\u661F\u671F\u56DB_\u661F\u671F\u4E94_\u661F\u671F\u516D".split("_"),weekdaysShort:"\u5468\u65E5_\u5468\u4E00_\u5468\u4E8C_\u5468\u4E09_\u5468\u56DB_\u5468\u4E94_\u5468\u516D".split("_"),weekdaysMin:"\u65E5_\u4E00_\u4E8C_\u4E09_\u56DB_\u4E94_\u516D".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY\u5E74M\u6708D\u65E5",LLL:"YYYY\u5E74M\u6708D\u65E5Ah\u70B9mm\u5206",LLLL:"YYYY\u5E74M\u6708D\u65E5ddddAh\u70B9mm\u5206",l:"YYYY/M/D",ll:"YYYY\u5E74M\u6708D\u65E5",lll:"YYYY\u5E74M\u6708D\u65E5 HH:mm",llll:"YYYY\u5E74M\u6708D\u65E5dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,t){return e===12&&(e=0),t==="\u51CC\u6668"||t==="\u65E9\u4E0A"||t==="\u4E0A\u5348"?e:t==="\u4E0B\u5348"||t==="\u665A\u4E0A"?e+12:e>=11?e:e+12},meridiem:function(e,t,s){var r=e*100+t;return r<600?"\u51CC\u6668":r<900?"\u65E9\u4E0A":r<1130?"\u4E0A\u5348":r<1230?"\u4E2D\u5348":r<1800?"\u4E0B\u5348":"\u665A\u4E0A"},calendar:{sameDay:"[\u4ECA\u5929]LT",nextDay:"[\u660E\u5929]LT",nextWeek:function(e){return e.week()!==this.week()?"[\u4E0B]dddLT":"[\u672C]dddLT"},lastDay:"[\u6628\u5929]LT",lastWeek:function(e){return this.week()!==e.week()?"[\u4E0A]dddLT":"[\u672C]dddLT"},sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|周)/,ordinal:function(e,t){switch(t){case"d":case"D":case"DDD":return e+"\u65E5";case"M":return e+"\u6708";case"w":case"W":return e+"\u5468";default:return e}},relativeTime:{future:"%s\u540E",past:"%s\u524D",s:"\u51E0\u79D2",ss:"%d \u79D2",m:"1 \u5206\u949F",mm:"%d \u5206\u949F",h:"1 \u5C0F\u65F6",hh:"%d \u5C0F\u65F6",d:"1 \u5929",dd:"%d \u5929",w:"1 \u5468",ww:"%d \u5468",M:"1 \u4E2A\u6708",MM:"%d \u4E2A\u6708",y:"1 \u5E74",yy:"%d \u5E74"},week:{dow:1,doy:4}});l.locale("zh-cn");const Yi=e=>l.unix(e).fromNow();export{Yi as f}; diff --git a/web/dist/assets/index.2a3b289f.css b/web/dist/assets/index.2a3b289f.css deleted file mode 100644 index f880c3ff..00000000 --- a/web/dist/assets/index.2a3b289f.css +++ /dev/null @@ -1 +0,0 @@ -.auth-wrap[data-v-66895776]{margin-top:-30px}.rightbar-wrap[data-v-0dc4cb5d]{width:240px;position:fixed;left:calc(50% + var(--content-main) / 2 + 10px)}.rightbar-wrap .search-wrap[data-v-0dc4cb5d]{margin:12px 0}.rightbar-wrap .hot-tag-item[data-v-0dc4cb5d]{line-height:2;position:relative}.rightbar-wrap .hot-tag-item .hash-link[data-v-0dc4cb5d]{width:calc(100% - 60px);text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block}.rightbar-wrap .hot-tag-item .post-num[data-v-0dc4cb5d]{position:absolute;right:0;top:0;width:60px;text-align:right;line-height:2;opacity:.5}.rightbar-wrap .copyright-wrap[data-v-0dc4cb5d]{margin-top:10px}.rightbar-wrap .copyright-wrap .copyright[data-v-0dc4cb5d]{font-size:12px;opacity:.75}.rightbar-wrap .copyright-wrap .hash-link[data-v-0dc4cb5d]{font-size:12px}.sidebar-wrap{z-index:99;width:200px;height:100vh;position:fixed;right:calc(50% + var(--content-main) / 2 + 10px);padding:12px 0;box-sizing:border-box}.sidebar-wrap .n-menu .n-menu-item-content:before{border-radius:21px}.logo-wrap{display:flex;justify-content:flex-start;margin-bottom:12px}.logo-wrap .logo-img{margin-left:24px}.logo-wrap .logo-img:hover{cursor:pointer}.user-wrap{display:flex;align-items:center;position:absolute;bottom:12px;left:12px;right:12px}.user-wrap .user-mini-wrap{display:none}.user-wrap .user-avatar{margin-right:8px}.user-wrap .user-info{display:flex;flex-direction:column}.user-wrap .user-info .nickname{font-size:16px;font-weight:700;line-height:16px;height:16px;margin-bottom:2px;display:flex;align-items:center}.user-wrap .user-info .nickname .nickname-txt{max-width:90px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.user-wrap .user-info .nickname .logout{margin-left:6px}.user-wrap .user-info .username{font-size:14px;line-height:16px;height:16px;width:120px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;opacity:.75}.user-wrap .login-wrap{display:flex;justify-content:center;width:100%}.user-wrap .login-wrap button{margin:0 4px}.auth-card .n-card-header{z-index:999}@media screen and (max-width: 821px){.sidebar-wrap{width:65px;right:calc(100% - 60px)}.logo-wrap .logo-img{margin-left:12px!important}.user-wrap .user-avatar,.user-wrap .user-info,.user-wrap .login-wrap{display:none}.user-wrap .user-mini-wrap{display:block!important}}:root{--content-main: 500px}.app-container{margin:0}.app-container .app-wrap{width:100%;margin:0 auto}.main-wrap{min-height:100vh;display:flex;flex-direction:row;justify-content:center}.main-wrap .content-wrap{width:100%;max-width:var(--content-main);position:relative}.main-wrap .main-content-wrap{margin:0;border-top:none;border-radius:0}.main-wrap .main-content-wrap .n-list-item{padding:0}.empty-wrap{min-height:300px;display:flex;align-items:center;justify-content:center}.hash-link,.user-link{color:#18a058;text-decoration:none;cursor:pointer}.hash-link:hover,.user-link:hover{opacity:.8}.beian-link{color:#333;text-decoration:none}.beian-link:hover{opacity:.75}.username-link{color:#000;color:none;text-decoration:none;cursor:pointer}.username-link:hover{text-decoration:underline}.dark .hash-link,.dark .user-link{color:#63e2b7}.dark .username-link{color:#eee}.dark .beian-link{color:#ddd}@media screen and (max-width: 821px){.content-wrap{top:0;left:60px;position:absolute!important;width:calc(100% - 60px)!important}}@font-face{font-family:v-sans;font-weight:400;src:url(/assets/LatoLatin-Regular.ddd4ef7f.woff2)}@font-face{font-family:v-sans;font-weight:600;src:url(/assets/LatoLatin-Semibold.267eef30.woff2)}@font-face{font-family:v-mono;font-weight:400;src:url(/assets/FiraCode-Regular.f13d1ece.woff2)} diff --git a/web/dist/assets/index.f480f018.js b/web/dist/assets/index.f480f018.js deleted file mode 100644 index 58d64e21..00000000 --- a/web/dist/assets/index.f480f018.js +++ /dev/null @@ -1,1771 +0,0 @@ -const ib=function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))o(n);new MutationObserver(n=>{for(const i of n)if(i.type==="childList")for(const a of i.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&o(a)}).observe(document,{childList:!0,subtree:!0});function r(n){const i={};return n.integrity&&(i.integrity=n.integrity),n.referrerpolicy&&(i.referrerPolicy=n.referrerpolicy),n.crossorigin==="use-credentials"?i.credentials="include":n.crossorigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function o(n){if(n.ep)return;n.ep=!0;const i=r(n);fetch(n.href,i)}};ib();function As(e,t){const r=Object.create(null),o=e.split(",");for(let n=0;n!!r[n.toLowerCase()]:n=>!!r[n]}const ab="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",lb=As(ab);function Ef(e){return!!e||e===""}function Os(e){if(Pe(e)){const t={};for(let r=0;r{if(r){const o=r.split(cb);o.length>1&&(t[o[0].trim()]=o[1].trim())}}),t}function ya(e){let t="";if(ft(e))t=e;else if(Pe(e))for(let r=0;rft(e)?e:e==null?"":Pe(e)||pt(e)&&(e.toString===Of||!Ie(e.toString))?JSON.stringify(e,Rf,2):String(e),Rf=(e,t)=>t&&t.__v_isRef?Rf(e,t.value):en(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((r,[o,n])=>(r[`${o} =>`]=n,r),{})}:zf(t)?{[`Set(${t.size})`]:[...t.values()]}:pt(t)&&!Pe(t)&&!If(t)?String(t):t,tt={},Qo=[],ir=()=>{},ub=()=>!1,fb=/^on[^a-z]/,wa=e=>fb.test(e),Is=e=>e.startsWith("onUpdate:"),St=Object.assign,Ms=(e,t)=>{const r=e.indexOf(t);r>-1&&e.splice(r,1)},hb=Object.prototype.hasOwnProperty,Ve=(e,t)=>hb.call(e,t),Pe=Array.isArray,en=e=>Sa(e)==="[object Map]",zf=e=>Sa(e)==="[object Set]",Ie=e=>typeof e=="function",ft=e=>typeof e=="string",Bs=e=>typeof e=="symbol",pt=e=>e!==null&&typeof e=="object",Af=e=>pt(e)&&Ie(e.then)&&Ie(e.catch),Of=Object.prototype.toString,Sa=e=>Of.call(e),pb=e=>Sa(e).slice(8,-1),If=e=>Sa(e)==="[object Object]",Ls=e=>ft(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Yi=As(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),_a=e=>{const t=Object.create(null);return r=>t[r]||(t[r]=e(r))},mb=/-(\w)/g,vr=_a(e=>e.replace(mb,(t,r)=>r?r.toUpperCase():"")),vb=/\B([A-Z])/g,Po=_a(e=>e.replace(vb,"-$1").toLowerCase()),$a=_a(e=>e.charAt(0).toUpperCase()+e.slice(1)),il=_a(e=>e?`on${$a(e)}`:""),ei=(e,t)=>!Object.is(e,t),tn=(e,t)=>{for(let r=0;r{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:r})},ra=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let rd;const gb=()=>rd||(rd=typeof globalThis!="undefined"?globalThis:typeof self!="undefined"?self:typeof window!="undefined"?window:typeof global!="undefined"?global:{});let hr;class bb{constructor(t=!1){this.active=!0,this.effects=[],this.cleanups=[],!t&&hr&&(this.parent=hr,this.index=(hr.scopes||(hr.scopes=[])).push(this)-1)}run(t){if(this.active){const r=hr;try{return hr=this,t()}finally{hr=r}}}on(){hr=this}off(){hr=this.parent}stop(t){if(this.active){let r,o;for(r=0,o=this.effects.length;r{const t=new Set(e);return t.w=0,t.n=0,t},Mf=e=>(e.w&Vr)>0,Bf=e=>(e.n&Vr)>0,Cb=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let r=0;for(let o=0;o{(d==="length"||d>=o)&&l.push(s)});else switch(r!==void 0&&l.push(a.get(r)),t){case"add":Pe(e)?Ls(r)&&l.push(a.get("length")):(l.push(a.get(Co)),en(e)&&l.push(a.get(Hl)));break;case"delete":Pe(e)||(l.push(a.get(Co)),en(e)&&l.push(a.get(Hl)));break;case"set":en(e)&&l.push(a.get(Co));break}if(l.length===1)l[0]&&jl(l[0]);else{const s=[];for(const d of l)d&&s.push(...d);jl(Ds(s))}}function jl(e,t){for(const r of Pe(e)?e:[...e])(r!==nr||r.allowRecurse)&&(r.scheduler?r.scheduler():r.run())}const wb=As("__proto__,__v_isRef,__isVue"),Ff=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(Bs)),Sb=Hs(),_b=Hs(!1,!0),$b=Hs(!0),nd=Pb();function Pb(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...r){const o=Ge(this);for(let i=0,a=this.length;i{e[t]=function(...r){bn();const o=Ge(this)[t].apply(this,r);return xn(),o}}),e}function Hs(e=!1,t=!1){return function(o,n,i){if(n==="__v_isReactive")return!e;if(n==="__v_isReadonly")return e;if(n==="__v_isShallow")return t;if(n==="__v_raw"&&i===(e?t?Nb:Vf:t?Wf:Nf).get(o))return o;const a=Pe(o);if(!e&&a&&Ve(nd,n))return Reflect.get(nd,n,i);const l=Reflect.get(o,n,i);return(Bs(n)?Ff.has(n):wb(n))||(e||Kt(o,"get",n),t)?l:wt(l)?!a||!Ls(n)?l.value:l:pt(l)?e?gr(l):ar(l):l}}const kb=Hf(),Tb=Hf(!0);function Hf(e=!1){return function(r,o,n,i){let a=r[o];if(ti(a)&&wt(a)&&!wt(n))return!1;if(!e&&!ti(n)&&(Kf(n)||(n=Ge(n),a=Ge(a)),!Pe(r)&&wt(a)&&!wt(n)))return a.value=n,!0;const l=Pe(r)&&Ls(o)?Number(o)e,Pa=e=>Reflect.getPrototypeOf(e);function Ai(e,t,r=!1,o=!1){e=e.__v_raw;const n=Ge(e),i=Ge(t);t!==i&&!r&&Kt(n,"get",t),!r&&Kt(n,"get",i);const{has:a}=Pa(n),l=o?js:r?Vs:ri;if(a.call(n,t))return l(e.get(t));if(a.call(n,i))return l(e.get(i));e!==n&&e.get(t)}function Oi(e,t=!1){const r=this.__v_raw,o=Ge(r),n=Ge(e);return e!==n&&!t&&Kt(o,"has",e),!t&&Kt(o,"has",n),e===n?r.has(e):r.has(e)||r.has(n)}function Ii(e,t=!1){return e=e.__v_raw,!t&&Kt(Ge(e),"iterate",Co),Reflect.get(e,"size",e)}function id(e){e=Ge(e);const t=Ge(this);return Pa(t).has.call(t,e)||(t.add(e),kr(t,"add",e,e)),this}function ad(e,t){t=Ge(t);const r=Ge(this),{has:o,get:n}=Pa(r);let i=o.call(r,e);i||(e=Ge(e),i=o.call(r,e));const a=n.call(r,e);return r.set(e,t),i?ei(t,a)&&kr(r,"set",e,t):kr(r,"add",e,t),this}function ld(e){const t=Ge(this),{has:r,get:o}=Pa(t);let n=r.call(t,e);n||(e=Ge(e),n=r.call(t,e)),o&&o.call(t,e);const i=t.delete(e);return n&&kr(t,"delete",e,void 0),i}function sd(){const e=Ge(this),t=e.size!==0,r=e.clear();return t&&kr(e,"clear",void 0,void 0),r}function Mi(e,t){return function(o,n){const i=this,a=i.__v_raw,l=Ge(a),s=t?js:e?Vs:ri;return!e&&Kt(l,"iterate",Co),a.forEach((d,c)=>o.call(n,s(d),s(c),i))}}function Bi(e,t,r){return function(...o){const n=this.__v_raw,i=Ge(n),a=en(i),l=e==="entries"||e===Symbol.iterator&&a,s=e==="keys"&&a,d=n[e](...o),c=r?js:t?Vs:ri;return!t&&Kt(i,"iterate",s?Hl:Co),{next(){const{value:u,done:f}=d.next();return f?{value:u,done:f}:{value:l?[c(u[0]),c(u[1])]:c(u),done:f}},[Symbol.iterator](){return this}}}}function Or(e){return function(...t){return e==="delete"?!1:this}}function Ib(){const e={get(i){return Ai(this,i)},get size(){return Ii(this)},has:Oi,add:id,set:ad,delete:ld,clear:sd,forEach:Mi(!1,!1)},t={get(i){return Ai(this,i,!1,!0)},get size(){return Ii(this)},has:Oi,add:id,set:ad,delete:ld,clear:sd,forEach:Mi(!1,!0)},r={get(i){return Ai(this,i,!0)},get size(){return Ii(this,!0)},has(i){return Oi.call(this,i,!0)},add:Or("add"),set:Or("set"),delete:Or("delete"),clear:Or("clear"),forEach:Mi(!0,!1)},o={get(i){return Ai(this,i,!0,!0)},get size(){return Ii(this,!0)},has(i){return Oi.call(this,i,!0)},add:Or("add"),set:Or("set"),delete:Or("delete"),clear:Or("clear"),forEach:Mi(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(i=>{e[i]=Bi(i,!1,!1),r[i]=Bi(i,!0,!1),t[i]=Bi(i,!1,!0),o[i]=Bi(i,!0,!0)}),[e,r,t,o]}const[Mb,Bb,Lb,Db]=Ib();function Ns(e,t){const r=t?e?Db:Lb:e?Bb:Mb;return(o,n,i)=>n==="__v_isReactive"?!e:n==="__v_isReadonly"?e:n==="__v_raw"?o:Reflect.get(Ve(r,n)&&n in o?r:o,n,i)}const Fb={get:Ns(!1,!1)},Hb={get:Ns(!1,!0)},jb={get:Ns(!0,!1)},Nf=new WeakMap,Wf=new WeakMap,Vf=new WeakMap,Nb=new WeakMap;function Wb(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Vb(e){return e.__v_skip||!Object.isExtensible(e)?0:Wb(pb(e))}function ar(e){return ti(e)?e:Ws(e,!1,jf,Fb,Nf)}function Kb(e){return Ws(e,!1,Ob,Hb,Wf)}function gr(e){return Ws(e,!0,Ab,jb,Vf)}function Ws(e,t,r,o,n){if(!pt(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=n.get(e);if(i)return i;const a=Vb(e);if(a===0)return e;const l=new Proxy(e,a===2?o:r);return n.set(e,l),l}function rn(e){return ti(e)?rn(e.__v_raw):!!(e&&e.__v_isReactive)}function ti(e){return!!(e&&e.__v_isReadonly)}function Kf(e){return!!(e&&e.__v_isShallow)}function Uf(e){return rn(e)||ti(e)}function Ge(e){const t=e&&e.__v_raw;return t?Ge(t):e}function oa(e){return ta(e,"__v_skip",!0),e}const ri=e=>pt(e)?ar(e):e,Vs=e=>pt(e)?gr(e):e;function qf(e){Nr&&nr&&(e=Ge(e),Df(e.dep||(e.dep=Ds())))}function Gf(e,t){e=Ge(e),e.dep&&jl(e.dep)}function wt(e){return!!(e&&e.__v_isRef===!0)}function W(e){return Yf(e,!1)}function Ub(e){return Yf(e,!0)}function Yf(e,t){return wt(e)?e:new qb(e,t)}class qb{constructor(t,r){this.__v_isShallow=r,this.dep=void 0,this.__v_isRef=!0,this._rawValue=r?t:Ge(t),this._value=r?t:ri(t)}get value(){return qf(this),this._value}set value(t){t=this.__v_isShallow?t:Ge(t),ei(t,this._rawValue)&&(this._rawValue=t,this._value=this.__v_isShallow?t:ri(t),Gf(this))}}function Me(e){return wt(e)?e.value:e}const Gb={get:(e,t,r)=>Me(Reflect.get(e,t,r)),set:(e,t,r,o)=>{const n=e[t];return wt(n)&&!wt(r)?(n.value=r,!0):Reflect.set(e,t,r,o)}};function Xf(e){return rn(e)?e:new Proxy(e,Gb)}class Yb{constructor(t,r,o){this._object=t,this._key=r,this._defaultValue=o,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}}function Oe(e,t,r){const o=e[t];return wt(o)?o:new Yb(e,t,r)}class Xb{constructor(t,r,o,n){this._setter=r,this.dep=void 0,this.__v_isRef=!0,this._dirty=!0,this.effect=new Fs(t,()=>{this._dirty||(this._dirty=!0,Gf(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!n,this.__v_isReadonly=o}get value(){const t=Ge(this);return qf(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function Zb(e,t,r=!1){let o,n;const i=Ie(e);return i?(o=e,n=ir):(o=e.get,n=e.set),new Xb(o,n,i||!n,r)}function Wr(e,t,r,o){let n;try{n=o?e(...o):e()}catch(i){ka(i,t,r)}return n}function Jt(e,t,r,o){if(Ie(e)){const i=Wr(e,t,r,o);return i&&Af(i)&&i.catch(a=>{ka(a,t,r)}),i}const n=[];for(let i=0;i>>1;oi(Nt[o])Pr&&Nt.splice(t,1)}function eh(e,t,r,o){Pe(e)?r.push(...e):(!t||!t.includes(e,e.allowRecurse?o+1:o))&&r.push(e),Qf()}function t0(e){eh(e,Dn,Vn,Ko)}function r0(e){eh(e,Fr,Kn,Uo)}function Us(e,t=null){if(Vn.length){for(Wl=t,Dn=[...new Set(Vn)],Vn.length=0,Ko=0;Kooi(r)-oi(o)),Uo=0;Uoe.id==null?1/0:e.id;function rh(e){Nl=!1,na=!0,Us(e),Nt.sort((r,o)=>oi(r)-oi(o));const t=ir;try{for(Pr=0;Prh.trim()):u&&(n=r.map(ra))}let l,s=o[l=il(t)]||o[l=il(vr(t))];!s&&i&&(s=o[l=il(Po(t))]),s&&Jt(s,e,6,n);const d=o[l+"Once"];if(d){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,Jt(d,e,6,n)}}function oh(e,t,r=!1){const o=t.emitsCache,n=o.get(e);if(n!==void 0)return n;const i=e.emits;let a={},l=!1;if(!Ie(e)){const s=d=>{const c=oh(d,t,!0);c&&(l=!0,St(a,c))};!r&&t.mixins.length&&t.mixins.forEach(s),e.extends&&s(e.extends),e.mixins&&e.mixins.forEach(s)}return!i&&!l?(o.set(e,null),null):(Pe(i)?i.forEach(s=>a[s]=null):St(a,i),o.set(e,a),a)}function Ta(e,t){return!e||!wa(t)?!1:(t=t.slice(2).replace(/Once$/,""),Ve(e,t[0].toLowerCase()+t.slice(1))||Ve(e,Po(t))||Ve(e,t))}let zt=null,Ea=null;function ia(e){const t=zt;return zt=e,Ea=e&&e.type.__scopeId||null,t}function oO(e){Ea=e}function nO(){Ea=null}function Xe(e,t=zt,r){if(!t||e._n)return e;const o=(...n)=>{o._d&&yd(-1);const i=ia(t),a=e(...n);return ia(i),o._d&&yd(1),a};return o._n=!0,o._c=!0,o._d=!0,o}function al(e){const{type:t,vnode:r,proxy:o,withProxy:n,props:i,propsOptions:[a],slots:l,attrs:s,emit:d,render:c,renderCache:u,data:f,setupState:h,ctx:p,inheritAttrs:b}=e;let g,v;const w=ia(e);try{if(r.shapeFlag&4){const x=n||o;g=pr(c.call(x,x,u,i,h,f,p)),v=s}else{const x=t;g=pr(x.length>1?x(i,{attrs:s,slots:l,emit:d}):x(i,null)),v=t.props?s:n0(s)}}catch(x){qn.length=0,ka(x,e,1),g=ge(Lt)}let $=g;if(v&&b!==!1){const x=Object.keys(v),{shapeFlag:S}=$;x.length&&S&7&&(a&&x.some(Is)&&(v=i0(v,a)),$=lr($,v))}return r.dirs&&($.dirs=$.dirs?$.dirs.concat(r.dirs):r.dirs),r.transition&&($.transition=r.transition),g=$,ia(w),g}const n0=e=>{let t;for(const r in e)(r==="class"||r==="style"||wa(r))&&((t||(t={}))[r]=e[r]);return t},i0=(e,t)=>{const r={};for(const o in e)(!Is(o)||!(o.slice(9)in t))&&(r[o]=e[o]);return r};function a0(e,t,r){const{props:o,children:n,component:i}=e,{props:a,children:l,patchFlag:s}=t,d=i.emitsOptions;if(t.dirs||t.transition)return!0;if(r&&s>=0){if(s&1024)return!0;if(s&16)return o?cd(o,a,d):!!a;if(s&8){const c=t.dynamicProps;for(let u=0;ue.__isSuspense;function c0(e,t){t&&t.pendingBranch?Pe(e)?t.effects.push(...e):t.effects.push(e):r0(e)}function je(e,t){if(yt){let r=yt.provides;const o=yt.parent&&yt.parent.provides;o===r&&(r=yt.provides=Object.create(o)),r[e]=t}}function be(e,t,r=!1){const o=yt||zt;if(o){const n=o.parent==null?o.vnode.appContext&&o.vnode.appContext.provides:o.parent.provides;if(n&&e in n)return n[e];if(arguments.length>1)return r&&Ie(t)?t.call(o.proxy):t}}function xr(e,t){return qs(e,null,t)}const dd={};function qe(e,t,r){return qs(e,t,r)}function qs(e,t,{immediate:r,deep:o,flush:n,onTrack:i,onTrigger:a}=tt){const l=yt;let s,d=!1,c=!1;if(wt(e)?(s=()=>e.value,d=Kf(e)):rn(e)?(s=()=>e,o=!0):Pe(e)?(c=!0,d=e.some(rn),s=()=>e.map(v=>{if(wt(v))return v.value;if(rn(v))return po(v);if(Ie(v))return Wr(v,l,2)})):Ie(e)?t?s=()=>Wr(e,l,2):s=()=>{if(!(l&&l.isUnmounted))return u&&u(),Jt(e,l,3,[f])}:s=ir,t&&o){const v=s;s=()=>po(v())}let u,f=v=>{u=g.onStop=()=>{Wr(v,l,4)}};if(ai)return f=ir,t?r&&Jt(t,l,3,[s(),c?[]:void 0,f]):s(),ir;let h=c?[]:dd;const p=()=>{if(!!g.active)if(t){const v=g.run();(o||d||(c?v.some((w,$)=>ei(w,h[$])):ei(v,h)))&&(u&&u(),Jt(t,l,3,[v,h===dd?void 0:h,f]),h=v)}else g.run()};p.allowRecurse=!!t;let b;n==="sync"?b=p:n==="post"?b=()=>kt(p,l&&l.suspense):b=()=>{!l||l.isMounted?t0(p):p()};const g=new Fs(s,b);return t?r?p():h=g.run():n==="post"?kt(g.run.bind(g),l&&l.suspense):g.run(),()=>{g.stop(),l&&l.scope&&Ms(l.scope.effects,g)}}function d0(e,t,r){const o=this.proxy,n=ft(e)?e.includes(".")?nh(o,e):()=>o[e]:e.bind(o,o);let i;Ie(t)?i=t:(i=t.handler,r=t);const a=yt;ln(this);const l=qs(n,i.bind(o),r);return a?ln(a):wo(),l}function nh(e,t){const r=t.split(".");return()=>{let o=e;for(let n=0;n{po(r,t)});else if(If(e))for(const r in e)po(e[r],t);return e}function ih(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return Ot(()=>{e.isMounted=!0}),It(()=>{e.isUnmounting=!0}),e}const Gt=[Function,Array],u0={name:"BaseTransition",props:{mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Gt,onEnter:Gt,onAfterEnter:Gt,onEnterCancelled:Gt,onBeforeLeave:Gt,onLeave:Gt,onAfterLeave:Gt,onLeaveCancelled:Gt,onBeforeAppear:Gt,onAppear:Gt,onAfterAppear:Gt,onAppearCancelled:Gt},setup(e,{slots:t}){const r=Zr(),o=ih();let n;return()=>{const i=t.default&&Gs(t.default(),!0);if(!i||!i.length)return;let a=i[0];if(i.length>1){for(const b of i)if(b.type!==Lt){a=b;break}}const l=Ge(e),{mode:s}=l;if(o.isLeaving)return ll(a);const d=ud(a);if(!d)return ll(a);const c=ni(d,l,o,r);nn(d,c);const u=r.subTree,f=u&&ud(u);let h=!1;const{getTransitionKey:p}=d.type;if(p){const b=p();n===void 0?n=b:b!==n&&(n=b,h=!0)}if(f&&f.type!==Lt&&(!fo(d,f)||h)){const b=ni(f,l,o,r);if(nn(f,b),s==="out-in")return o.isLeaving=!0,b.afterLeave=()=>{o.isLeaving=!1,r.update()},ll(a);s==="in-out"&&d.type!==Lt&&(b.delayLeave=(g,v,w)=>{const $=lh(o,f);$[String(f.key)]=f,g._leaveCb=()=>{v(),g._leaveCb=void 0,delete c.delayedLeave},c.delayedLeave=w})}return a}}},ah=u0;function lh(e,t){const{leavingVNodes:r}=e;let o=r.get(t.type);return o||(o=Object.create(null),r.set(t.type,o)),o}function ni(e,t,r,o){const{appear:n,mode:i,persisted:a=!1,onBeforeEnter:l,onEnter:s,onAfterEnter:d,onEnterCancelled:c,onBeforeLeave:u,onLeave:f,onAfterLeave:h,onLeaveCancelled:p,onBeforeAppear:b,onAppear:g,onAfterAppear:v,onAppearCancelled:w}=t,$=String(e.key),x=lh(r,e),S=(y,_)=>{y&&Jt(y,o,9,_)},E={mode:i,persisted:a,beforeEnter(y){let _=l;if(!r.isMounted)if(n)_=b||l;else return;y._leaveCb&&y._leaveCb(!0);const R=x[$];R&&fo(e,R)&&R.el._leaveCb&&R.el._leaveCb(),S(_,[y])},enter(y){let _=s,R=d,P=c;if(!r.isMounted)if(n)_=g||s,R=v||d,P=w||c;else return;let j=!1;const T=y._enterCb=N=>{j||(j=!0,N?S(P,[y]):S(R,[y]),E.delayedLeave&&E.delayedLeave(),y._enterCb=void 0)};_?(_(y,T),_.length<=1&&T()):T()},leave(y,_){const R=String(e.key);if(y._enterCb&&y._enterCb(!0),r.isUnmounting)return _();S(u,[y]);let P=!1;const j=y._leaveCb=T=>{P||(P=!0,_(),T?S(p,[y]):S(h,[y]),y._leaveCb=void 0,x[R]===e&&delete x[R])};x[R]=e,f?(f(y,j),f.length<=1&&j()):j()},clone(y){return ni(y,t,r,o)}};return E}function ll(e){if(Ra(e))return e=lr(e),e.children=null,e}function ud(e){return Ra(e)?e.children?e.children[0]:void 0:e}function nn(e,t){e.shapeFlag&6&&e.component?nn(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Gs(e,t=!1,r){let o=[],n=0;for(let i=0;i1)for(let i=0;i!!e.type.__asyncLoader,Ra=e=>e.type.__isKeepAlive,f0={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(e,{slots:t}){const r=Zr(),o=r.ctx;if(!o.renderer)return t.default;const n=new Map,i=new Set;let a=null;const l=r.suspense,{renderer:{p:s,m:d,um:c,o:{createElement:u}}}=o,f=u("div");o.activate=(w,$,x,S,E)=>{const y=w.component;d(w,$,x,0,l),s(y.vnode,w,$,x,y,l,S,w.slotScopeIds,E),kt(()=>{y.isDeactivated=!1,y.a&&tn(y.a);const _=w.props&&w.props.onVnodeMounted;_&&Zt(_,y.parent,w)},l)},o.deactivate=w=>{const $=w.component;d(w,f,null,1,l),kt(()=>{$.da&&tn($.da);const x=w.props&&w.props.onVnodeUnmounted;x&&Zt(x,$.parent,w),$.isDeactivated=!0},l)};function h(w){sl(w),c(w,r,l,!0)}function p(w){n.forEach(($,x)=>{const S=Zl($.type);S&&(!w||!w(S))&&b(x)})}function b(w){const $=n.get(w);!a||$.type!==a.type?h($):a&&sl(a),n.delete(w),i.delete(w)}qe(()=>[e.include,e.exclude],([w,$])=>{w&&p(x=>Fn(w,x)),$&&p(x=>!Fn($,x))},{flush:"post",deep:!0});let g=null;const v=()=>{g!=null&&n.set(g,cl(r.subTree))};return Ot(v),Ys(v),It(()=>{n.forEach(w=>{const{subTree:$,suspense:x}=r,S=cl($);if(w.type===S.type){sl(S);const E=S.component.da;E&&kt(E,x);return}h(w)})}),()=>{if(g=null,!t.default)return null;const w=t.default(),$=w[0];if(w.length>1)return a=null,w;if(!an($)||!($.shapeFlag&4)&&!($.shapeFlag&128))return a=null,$;let x=cl($);const S=x.type,E=Zl(ii(x)?x.type.__asyncResolved||{}:S),{include:y,exclude:_,max:R}=e;if(y&&(!E||!Fn(y,E))||_&&E&&Fn(_,E))return a=x,$;const P=x.key==null?S:x.key,j=n.get(P);return x.el&&(x=lr(x),$.shapeFlag&128&&($.ssContent=x)),g=P,j?(x.el=j.el,x.component=j.component,x.transition&&nn(x,x.transition),x.shapeFlag|=512,i.delete(P),i.add(P)):(i.add(P),R&&i.size>parseInt(R,10)&&b(i.values().next().value)),x.shapeFlag|=256,a=x,$}}},h0=f0;function Fn(e,t){return Pe(e)?e.some(r=>Fn(r,t)):ft(e)?e.split(",").includes(t):e.test?e.test(t):!1}function p0(e,t){sh(e,"a",t)}function m0(e,t){sh(e,"da",t)}function sh(e,t,r=yt){const o=e.__wdc||(e.__wdc=()=>{let n=r;for(;n;){if(n.isDeactivated)return;n=n.parent}return e()});if(za(t,o,r),r){let n=r.parent;for(;n&&n.parent;)Ra(n.parent.vnode)&&v0(o,t,r,n),n=n.parent}}function v0(e,t,r,o){const n=za(t,e,o,!0);Xs(()=>{Ms(o[t],n)},r)}function sl(e){let t=e.shapeFlag;t&256&&(t-=256),t&512&&(t-=512),e.shapeFlag=t}function cl(e){return e.shapeFlag&128?e.ssContent:e}function za(e,t,r=yt,o=!1){if(r){const n=r[e]||(r[e]=[]),i=t.__weh||(t.__weh=(...a)=>{if(r.isUnmounted)return;bn(),ln(r);const l=Jt(t,r,e,a);return wo(),xn(),l});return o?n.unshift(i):n.push(i),i}}const Er=e=>(t,r=yt)=>(!ai||e==="sp")&&za(e,t,r),Yr=Er("bm"),Ot=Er("m"),g0=Er("bu"),Ys=Er("u"),It=Er("bum"),Xs=Er("um"),b0=Er("sp"),x0=Er("rtg"),C0=Er("rtc");function y0(e,t=yt){za("ec",e,t)}let Vl=!0;function w0(e){const t=dh(e),r=e.proxy,o=e.ctx;Vl=!1,t.beforeCreate&&fd(t.beforeCreate,e,"bc");const{data:n,computed:i,methods:a,watch:l,provide:s,inject:d,created:c,beforeMount:u,mounted:f,beforeUpdate:h,updated:p,activated:b,deactivated:g,beforeDestroy:v,beforeUnmount:w,destroyed:$,unmounted:x,render:S,renderTracked:E,renderTriggered:y,errorCaptured:_,serverPrefetch:R,expose:P,inheritAttrs:j,components:T,directives:N,filters:B}=t;if(d&&S0(d,o,null,e.appContext.config.unwrapInjectedRef),a)for(const te in a){const se=a[te];Ie(se)&&(o[te]=se.bind(r))}if(n){const te=n.call(r,r);pt(te)&&(e.data=ar(te))}if(Vl=!0,i)for(const te in i){const se=i[te],_e=Ie(se)?se.bind(r,r):Ie(se.get)?se.get.bind(r,r):ir,Ae=!Ie(se)&&Ie(se.set)?se.set.bind(r):ir,Re=L({get:_e,set:Ae});Object.defineProperty(o,te,{enumerable:!0,configurable:!0,get:()=>Re.value,set:Ee=>Re.value=Ee})}if(l)for(const te in l)ch(l[te],o,r,te);if(s){const te=Ie(s)?s.call(r):s;Reflect.ownKeys(te).forEach(se=>{je(se,te[se])})}c&&fd(c,e,"c");function A(te,se){Pe(se)?se.forEach(_e=>te(_e.bind(r))):se&&te(se.bind(r))}if(A(Yr,u),A(Ot,f),A(g0,h),A(Ys,p),A(p0,b),A(m0,g),A(y0,_),A(C0,E),A(x0,y),A(It,w),A(Xs,x),A(b0,R),Pe(P))if(P.length){const te=e.exposed||(e.exposed={});P.forEach(se=>{Object.defineProperty(te,se,{get:()=>r[se],set:_e=>r[se]=_e})})}else e.exposed||(e.exposed={});S&&e.render===ir&&(e.render=S),j!=null&&(e.inheritAttrs=j),T&&(e.components=T),N&&(e.directives=N)}function S0(e,t,r=ir,o=!1){Pe(e)&&(e=Kl(e));for(const n in e){const i=e[n];let a;pt(i)?"default"in i?a=be(i.from||n,i.default,!0):a=be(i.from||n):a=be(i),wt(a)&&o?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>a.value,set:l=>a.value=l}):t[n]=a}}function fd(e,t,r){Jt(Pe(e)?e.map(o=>o.bind(t.proxy)):e.bind(t.proxy),t,r)}function ch(e,t,r,o){const n=o.includes(".")?nh(r,o):()=>r[o];if(ft(e)){const i=t[e];Ie(i)&&qe(n,i)}else if(Ie(e))qe(n,e.bind(r));else if(pt(e))if(Pe(e))e.forEach(i=>ch(i,t,r,o));else{const i=Ie(e.handler)?e.handler.bind(r):t[e.handler];Ie(i)&&qe(n,i,e)}}function dh(e){const t=e.type,{mixins:r,extends:o}=t,{mixins:n,optionsCache:i,config:{optionMergeStrategies:a}}=e.appContext,l=i.get(t);let s;return l?s=l:!n.length&&!r&&!o?s=t:(s={},n.length&&n.forEach(d=>aa(s,d,a,!0)),aa(s,t,a)),i.set(t,s),s}function aa(e,t,r,o=!1){const{mixins:n,extends:i}=t;i&&aa(e,i,r,!0),n&&n.forEach(a=>aa(e,a,r,!0));for(const a in t)if(!(o&&a==="expose")){const l=_0[a]||r&&r[a];e[a]=l?l(e[a],t[a]):t[a]}return e}const _0={data:hd,props:lo,emits:lo,methods:lo,computed:lo,beforeCreate:Mt,created:Mt,beforeMount:Mt,mounted:Mt,beforeUpdate:Mt,updated:Mt,beforeDestroy:Mt,beforeUnmount:Mt,destroyed:Mt,unmounted:Mt,activated:Mt,deactivated:Mt,errorCaptured:Mt,serverPrefetch:Mt,components:lo,directives:lo,watch:P0,provide:hd,inject:$0};function hd(e,t){return t?e?function(){return St(Ie(e)?e.call(this,this):e,Ie(t)?t.call(this,this):t)}:t:e}function $0(e,t){return lo(Kl(e),Kl(t))}function Kl(e){if(Pe(e)){const t={};for(let r=0;r0)&&!(a&16)){if(a&8){const c=e.vnode.dynamicProps;for(let u=0;u{s=!0;const[f,h]=fh(u,t,!0);St(a,f),h&&l.push(...h)};!r&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}if(!i&&!s)return o.set(e,Qo),Qo;if(Pe(i))for(let c=0;c-1,h[1]=b<0||p-1||Ve(h,"default"))&&l.push(u)}}}const d=[a,l];return o.set(e,d),d}function pd(e){return e[0]!=="$"}function md(e){const t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:e===null?"null":""}function vd(e,t){return md(e)===md(t)}function gd(e,t){return Pe(t)?t.findIndex(r=>vd(r,e)):Ie(t)&&vd(t,e)?0:-1}const hh=e=>e[0]==="_"||e==="$stable",Zs=e=>Pe(e)?e.map(pr):[pr(e)],E0=(e,t,r)=>{const o=Xe((...n)=>Zs(t(...n)),r);return o._c=!1,o},ph=(e,t,r)=>{const o=e._ctx;for(const n in e){if(hh(n))continue;const i=e[n];if(Ie(i))t[n]=E0(n,i,o);else if(i!=null){const a=Zs(i);t[n]=()=>a}}},mh=(e,t)=>{const r=Zs(t);e.slots.default=()=>r},R0=(e,t)=>{if(e.vnode.shapeFlag&32){const r=t._;r?(e.slots=Ge(t),ta(t,"_",r)):ph(t,e.slots={})}else e.slots={},t&&mh(e,t);ta(e.slots,Aa,1)},z0=(e,t,r)=>{const{vnode:o,slots:n}=e;let i=!0,a=tt;if(o.shapeFlag&32){const l=t._;l?r&&l===1?i=!1:(St(n,t),!r&&l===1&&delete n._):(i=!t.$stable,ph(t,n)),a=t}else t&&(mh(e,t),a={default:1});if(i)for(const l in n)!hh(l)&&!(l in a)&&delete n[l]};function Cr(e,t){const r=zt;if(r===null)return e;const o=Oa(r)||r.proxy,n=e.dirs||(e.dirs=[]);for(let i=0;iql(f,t&&(Pe(t)?t[h]:t),r,o,n));return}if(ii(o)&&!n)return;const i=o.shapeFlag&4?Oa(o.component)||o.component.proxy:o.el,a=n?null:i,{i:l,r:s}=e,d=t&&t.r,c=l.refs===tt?l.refs={}:l.refs,u=l.setupState;if(d!=null&&d!==s&&(ft(d)?(c[d]=null,Ve(u,d)&&(u[d]=null)):wt(d)&&(d.value=null)),Ie(s))Wr(s,l,12,[a,c]);else{const f=ft(s),h=wt(s);if(f||h){const p=()=>{if(e.f){const b=f?c[s]:s.value;n?Pe(b)&&Ms(b,i):Pe(b)?b.includes(i)||b.push(i):f?(c[s]=[i],Ve(u,s)&&(u[s]=c[s])):(s.value=[i],e.k&&(c[e.k]=s.value))}else f?(c[s]=a,Ve(u,s)&&(u[s]=a)):wt(s)&&(s.value=a,e.k&&(c[e.k]=a))};a?(p.id=-1,kt(p,r)):p()}}}const kt=c0;function I0(e){return M0(e)}function M0(e,t){const r=gb();r.__VUE__=!0;const{insert:o,remove:n,patchProp:i,createElement:a,createText:l,createComment:s,setText:d,setElementText:c,parentNode:u,nextSibling:f,setScopeId:h=ir,cloneNode:p,insertStaticContent:b}=e,g=(C,k,H,U=null,X=null,ne=null,le=!1,Y=null,J=!!k.dynamicChildren)=>{if(C===k)return;C&&!fo(C,k)&&(U=ce(C),$e(C,X,ne,!0),C=null),k.patchFlag===-2&&(J=!1,k.dynamicChildren=null);const{type:Q,ref:ve,shapeFlag:pe}=k;switch(Q){case ec:v(C,k,H,U);break;case Lt:w(C,k,H,U);break;case Xi:C==null&&$(k,H,U,le);break;case ot:N(C,k,H,U,X,ne,le,Y,J);break;default:pe&1?E(C,k,H,U,X,ne,le,Y,J):pe&6?B(C,k,H,U,X,ne,le,Y,J):(pe&64||pe&128)&&Q.process(C,k,H,U,X,ne,le,Y,J,xe)}ve!=null&&X&&ql(ve,C&&C.ref,ne,k||C,!k)},v=(C,k,H,U)=>{if(C==null)o(k.el=l(k.children),H,U);else{const X=k.el=C.el;k.children!==C.children&&d(X,k.children)}},w=(C,k,H,U)=>{C==null?o(k.el=s(k.children||""),H,U):k.el=C.el},$=(C,k,H,U)=>{[C.el,C.anchor]=b(C.children,k,H,U,C.el,C.anchor)},x=({el:C,anchor:k},H,U)=>{let X;for(;C&&C!==k;)X=f(C),o(C,H,U),C=X;o(k,H,U)},S=({el:C,anchor:k})=>{let H;for(;C&&C!==k;)H=f(C),n(C),C=H;n(k)},E=(C,k,H,U,X,ne,le,Y,J)=>{le=le||k.type==="svg",C==null?y(k,H,U,X,ne,le,Y,J):P(C,k,X,ne,le,Y,J)},y=(C,k,H,U,X,ne,le,Y)=>{let J,Q;const{type:ve,props:pe,shapeFlag:me,transition:we,patchFlag:De,dirs:Ye}=C;if(C.el&&p!==void 0&&De===-1)J=C.el=p(C.el);else{if(J=C.el=a(C.type,ne,pe&&pe.is,pe),me&8?c(J,C.children):me&16&&R(C.children,J,null,U,X,ne&&ve!=="foreignObject",le,Y),Ye&&oo(C,null,U,"created"),pe){for(const Je in pe)Je!=="value"&&!Yi(Je)&&i(J,Je,null,pe[Je],ne,C.children,U,X,D);"value"in pe&&i(J,"value",null,pe.value),(Q=pe.onVnodeBeforeMount)&&Zt(Q,U,C)}_(J,C,C.scopeId,le,U)}Ye&&oo(C,null,U,"beforeMount");const Fe=(!X||X&&!X.pendingBranch)&&we&&!we.persisted;Fe&&we.beforeEnter(J),o(J,k,H),((Q=pe&&pe.onVnodeMounted)||Fe||Ye)&&kt(()=>{Q&&Zt(Q,U,C),Fe&&we.enter(J),Ye&&oo(C,null,U,"mounted")},X)},_=(C,k,H,U,X)=>{if(H&&h(C,H),U)for(let ne=0;ne{for(let Q=J;Q{const Y=k.el=C.el;let{patchFlag:J,dynamicChildren:Q,dirs:ve}=k;J|=C.patchFlag&16;const pe=C.props||tt,me=k.props||tt;let we;H&&no(H,!1),(we=me.onVnodeBeforeUpdate)&&Zt(we,H,k,C),ve&&oo(k,C,H,"beforeUpdate"),H&&no(H,!0);const De=X&&k.type!=="foreignObject";if(Q?j(C.dynamicChildren,Q,Y,H,U,De,ne):le||_e(C,k,Y,null,H,U,De,ne,!1),J>0){if(J&16)T(Y,k,pe,me,H,U,X);else if(J&2&&pe.class!==me.class&&i(Y,"class",null,me.class,X),J&4&&i(Y,"style",pe.style,me.style,X),J&8){const Ye=k.dynamicProps;for(let Fe=0;Fe{we&&Zt(we,H,k,C),ve&&oo(k,C,H,"updated")},U)},j=(C,k,H,U,X,ne,le)=>{for(let Y=0;Y{if(H!==U){for(const Y in U){if(Yi(Y))continue;const J=U[Y],Q=H[Y];J!==Q&&Y!=="value"&&i(C,Y,Q,J,le,k.children,X,ne,D)}if(H!==tt)for(const Y in H)!Yi(Y)&&!(Y in U)&&i(C,Y,H[Y],null,le,k.children,X,ne,D);"value"in U&&i(C,"value",H.value,U.value)}},N=(C,k,H,U,X,ne,le,Y,J)=>{const Q=k.el=C?C.el:l(""),ve=k.anchor=C?C.anchor:l("");let{patchFlag:pe,dynamicChildren:me,slotScopeIds:we}=k;we&&(Y=Y?Y.concat(we):we),C==null?(o(Q,H,U),o(ve,H,U),R(k.children,H,ve,X,ne,le,Y,J)):pe>0&&pe&64&&me&&C.dynamicChildren?(j(C.dynamicChildren,me,H,X,ne,le,Y),(k.key!=null||X&&k===X.subTree)&&Js(C,k,!0)):_e(C,k,H,ve,X,ne,le,Y,J)},B=(C,k,H,U,X,ne,le,Y,J)=>{k.slotScopeIds=Y,C==null?k.shapeFlag&512?X.ctx.activate(k,H,U,le,J):q(k,H,U,X,ne,le,J):A(C,k,J)},q=(C,k,H,U,X,ne,le)=>{const Y=C.component=G0(C,U,X);if(Ra(C)&&(Y.ctx.renderer=xe),Y0(Y),Y.asyncDep){if(X&&X.registerDep(Y,te),!C.el){const J=Y.subTree=ge(Lt);w(null,J,k,H)}return}te(Y,C,k,H,X,ne,le)},A=(C,k,H)=>{const U=k.component=C.component;if(a0(C,k,H))if(U.asyncDep&&!U.asyncResolved){se(U,k,H);return}else U.next=k,e0(U.update),U.update();else k.component=C.component,k.el=C.el,U.vnode=k},te=(C,k,H,U,X,ne,le)=>{const Y=()=>{if(C.isMounted){let{next:ve,bu:pe,u:me,parent:we,vnode:De}=C,Ye=ve,Fe;no(C,!1),ve?(ve.el=De.el,se(C,ve,le)):ve=De,pe&&tn(pe),(Fe=ve.props&&ve.props.onVnodeBeforeUpdate)&&Zt(Fe,we,ve,De),no(C,!0);const Je=al(C),re=C.subTree;C.subTree=Je,g(re,Je,u(re.el),ce(re),C,X,ne),ve.el=Je.el,Ye===null&&l0(C,Je.el),me&&kt(me,X),(Fe=ve.props&&ve.props.onVnodeUpdated)&&kt(()=>Zt(Fe,we,ve,De),X)}else{let ve;const{el:pe,props:me}=k,{bm:we,m:De,parent:Ye}=C,Fe=ii(k);if(no(C,!1),we&&tn(we),!Fe&&(ve=me&&me.onVnodeBeforeMount)&&Zt(ve,Ye,k),no(C,!0),pe&&Z){const Je=()=>{C.subTree=al(C),Z(pe,C.subTree,C,X,null)};Fe?k.type.__asyncLoader().then(()=>!C.isUnmounted&&Je()):Je()}else{const Je=C.subTree=al(C);g(null,Je,H,U,C,X,ne),k.el=Je.el}if(De&&kt(De,X),!Fe&&(ve=me&&me.onVnodeMounted)){const Je=k;kt(()=>Zt(ve,Ye,Je),X)}k.shapeFlag&256&&C.a&&kt(C.a,X),C.isMounted=!0,k=H=U=null}},J=C.effect=new Fs(Y,()=>Jf(C.update),C.scope),Q=C.update=J.run.bind(J);Q.id=C.uid,no(C,!0),Q()},se=(C,k,H)=>{k.component=C;const U=C.vnode.props;C.vnode=k,C.next=null,T0(C,k.props,U,H),z0(C,k.children,H),bn(),Us(void 0,C.update),xn()},_e=(C,k,H,U,X,ne,le,Y,J=!1)=>{const Q=C&&C.children,ve=C?C.shapeFlag:0,pe=k.children,{patchFlag:me,shapeFlag:we}=k;if(me>0){if(me&128){Re(Q,pe,H,U,X,ne,le,Y,J);return}else if(me&256){Ae(Q,pe,H,U,X,ne,le,Y,J);return}}we&8?(ve&16&&D(Q,X,ne),pe!==Q&&c(H,pe)):ve&16?we&16?Re(Q,pe,H,U,X,ne,le,Y,J):D(Q,X,ne,!0):(ve&8&&c(H,""),we&16&&R(pe,H,U,X,ne,le,Y,J))},Ae=(C,k,H,U,X,ne,le,Y,J)=>{C=C||Qo,k=k||Qo;const Q=C.length,ve=k.length,pe=Math.min(Q,ve);let me;for(me=0;meve?D(C,X,ne,!0,!1,pe):R(k,H,U,X,ne,le,Y,J,pe)},Re=(C,k,H,U,X,ne,le,Y,J)=>{let Q=0;const ve=k.length;let pe=C.length-1,me=ve-1;for(;Q<=pe&&Q<=me;){const we=C[Q],De=k[Q]=J?Hr(k[Q]):pr(k[Q]);if(fo(we,De))g(we,De,H,null,X,ne,le,Y,J);else break;Q++}for(;Q<=pe&&Q<=me;){const we=C[pe],De=k[me]=J?Hr(k[me]):pr(k[me]);if(fo(we,De))g(we,De,H,null,X,ne,le,Y,J);else break;pe--,me--}if(Q>pe){if(Q<=me){const we=me+1,De=weme)for(;Q<=pe;)$e(C[Q],X,ne,!0),Q++;else{const we=Q,De=Q,Ye=new Map;for(Q=De;Q<=me;Q++){const Ue=k[Q]=J?Hr(k[Q]):pr(k[Q]);Ue.key!=null&&Ye.set(Ue.key,Q)}let Fe,Je=0;const re=me-De+1;let he=!1,Se=0;const Ne=new Array(re);for(Q=0;Q=re){$e(Ue,X,ne,!0);continue}let dt;if(Ue.key!=null)dt=Ye.get(Ue.key);else for(Fe=De;Fe<=me;Fe++)if(Ne[Fe-De]===0&&fo(Ue,k[Fe])){dt=Fe;break}dt===void 0?$e(Ue,X,ne,!0):(Ne[dt-De]=Q+1,dt>=Se?Se=dt:he=!0,g(Ue,k[dt],H,null,X,ne,le,Y,J),Je++)}const rt=he?B0(Ne):Qo;for(Fe=rt.length-1,Q=re-1;Q>=0;Q--){const Ue=De+Q,dt=k[Ue],Qe=Ue+1{const{el:ne,type:le,transition:Y,children:J,shapeFlag:Q}=C;if(Q&6){Ee(C.component.subTree,k,H,U);return}if(Q&128){C.suspense.move(k,H,U);return}if(Q&64){le.move(C,k,H,xe);return}if(le===ot){o(ne,k,H);for(let pe=0;peY.enter(ne),X);else{const{leave:pe,delayLeave:me,afterLeave:we}=Y,De=()=>o(ne,k,H),Ye=()=>{pe(ne,()=>{De(),we&&we()})};me?me(ne,De,Ye):Ye()}else o(ne,k,H)},$e=(C,k,H,U=!1,X=!1)=>{const{type:ne,props:le,ref:Y,children:J,dynamicChildren:Q,shapeFlag:ve,patchFlag:pe,dirs:me}=C;if(Y!=null&&ql(Y,null,H,C,!0),ve&256){k.ctx.deactivate(C);return}const we=ve&1&&me,De=!ii(C);let Ye;if(De&&(Ye=le&&le.onVnodeBeforeUnmount)&&Zt(Ye,k,C),ve&6)V(C.component,H,U);else{if(ve&128){C.suspense.unmount(H,U);return}we&&oo(C,null,k,"beforeUnmount"),ve&64?C.type.remove(C,k,H,X,xe,U):Q&&(ne!==ot||pe>0&&pe&64)?D(Q,k,H,!1,!0):(ne===ot&&pe&384||!X&&ve&16)&&D(J,k,H),U&&it(C)}(De&&(Ye=le&&le.onVnodeUnmounted)||we)&&kt(()=>{Ye&&Zt(Ye,k,C),we&&oo(C,null,k,"unmounted")},H)},it=C=>{const{type:k,el:H,anchor:U,transition:X}=C;if(k===ot){O(H,U);return}if(k===Xi){S(C);return}const ne=()=>{n(H),X&&!X.persisted&&X.afterLeave&&X.afterLeave()};if(C.shapeFlag&1&&X&&!X.persisted){const{leave:le,delayLeave:Y}=X,J=()=>le(H,ne);Y?Y(C.el,ne,J):J()}else ne()},O=(C,k)=>{let H;for(;C!==k;)H=f(C),n(C),C=H;n(k)},V=(C,k,H)=>{const{bum:U,scope:X,update:ne,subTree:le,um:Y}=C;U&&tn(U),X.stop(),ne&&(ne.active=!1,$e(le,C,k,H)),Y&&kt(Y,k),kt(()=>{C.isUnmounted=!0},k),k&&k.pendingBranch&&!k.isUnmounted&&C.asyncDep&&!C.asyncResolved&&C.suspenseId===k.pendingId&&(k.deps--,k.deps===0&&k.resolve())},D=(C,k,H,U=!1,X=!1,ne=0)=>{for(let le=ne;leC.shapeFlag&6?ce(C.component.subTree):C.shapeFlag&128?C.suspense.next():f(C.anchor||C.el),ue=(C,k,H)=>{C==null?k._vnode&&$e(k._vnode,null,null,!0):g(k._vnode||null,C,k,null,null,null,H),th(),k._vnode=C},xe={p:g,um:$e,m:Ee,r:it,mt:q,mc:R,pc:_e,pbc:j,n:ce,o:e};let G,Z;return t&&([G,Z]=t(xe)),{render:ue,hydrate:G,createApp:O0(ue,G)}}function no({effect:e,update:t},r){e.allowRecurse=t.allowRecurse=r}function Js(e,t,r=!1){const o=e.children,n=t.children;if(Pe(o)&&Pe(n))for(let i=0;i>1,e[r[l]]0&&(t[o]=r[i-1]),r[i]=o)}}for(i=r.length,a=r[i-1];i-- >0;)r[i]=a,a=t[a];return r}const L0=e=>e.__isTeleport,Un=e=>e&&(e.disabled||e.disabled===""),bd=e=>typeof SVGElement!="undefined"&&e instanceof SVGElement,Gl=(e,t)=>{const r=e&&e.to;return ft(r)?t?t(r):null:r},D0={__isTeleport:!0,process(e,t,r,o,n,i,a,l,s,d){const{mc:c,pc:u,pbc:f,o:{insert:h,querySelector:p,createText:b,createComment:g}}=d,v=Un(t.props);let{shapeFlag:w,children:$,dynamicChildren:x}=t;if(e==null){const S=t.el=b(""),E=t.anchor=b("");h(S,r,o),h(E,r,o);const y=t.target=Gl(t.props,p),_=t.targetAnchor=b("");y&&(h(_,y),a=a||bd(y));const R=(P,j)=>{w&16&&c($,P,j,n,i,a,l,s)};v?R(r,E):y&&R(y,_)}else{t.el=e.el;const S=t.anchor=e.anchor,E=t.target=e.target,y=t.targetAnchor=e.targetAnchor,_=Un(e.props),R=_?r:E,P=_?S:y;if(a=a||bd(E),x?(f(e.dynamicChildren,x,R,n,i,a,l),Js(e,t,!0)):s||u(e,t,R,P,n,i,a,l,!1),v)_||Li(t,r,S,d,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const j=t.target=Gl(t.props,p);j&&Li(t,j,null,d,0)}else _&&Li(t,E,y,d,1)}},remove(e,t,r,o,{um:n,o:{remove:i}},a){const{shapeFlag:l,children:s,anchor:d,targetAnchor:c,target:u,props:f}=e;if(u&&i(c),(a||!Un(f))&&(i(d),l&16))for(let h=0;h0?yo||Qo:null,H0(),la>0&&yo&&yo.push(e),e}function Et(e,t,r,o,n,i){return yh(Le(e,t,r,o,n,i,!0))}function mo(e,t,r,o,n){return yh(ge(e,t,r,o,n,!0))}function an(e){return e?e.__v_isVNode===!0:!1}function fo(e,t){return e.type===t.type&&e.key===t.key}const Aa="__vInternal",wh=({key:e})=>e!=null?e:null,Zi=({ref:e,ref_key:t,ref_for:r})=>e!=null?ft(e)||wt(e)||Ie(e)?{i:zt,r:e,k:t,f:!!r}:e:null;function Le(e,t=null,r=null,o=0,n=null,i=e===ot?0:1,a=!1,l=!1){const s={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&wh(t),ref:t&&Zi(t),scopeId:Ea,slotScopeIds:null,children:r,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:o,dynamicProps:n,dynamicChildren:null,appContext:null};return l?(tc(s,r),i&128&&e.normalize(s)):r&&(s.shapeFlag|=ft(r)?8:16),la>0&&!a&&yo&&(s.patchFlag>0||i&6)&&s.patchFlag!==32&&yo.push(s),s}const ge=j0;function j0(e,t=null,r=null,o=0,n=null,i=!1){if((!e||e===xh)&&(e=Lt),an(e)){const l=lr(e,t,!0);return r&&tc(l,r),l}if(Q0(e)&&(e=e.__vccOpts),t){t=N0(t);let{class:l,style:s}=t;l&&!ft(l)&&(t.class=ya(l)),pt(s)&&(Uf(s)&&!Pe(s)&&(s=St({},s)),t.style=Os(s))}const a=ft(e)?1:s0(e)?128:L0(e)?64:pt(e)?4:Ie(e)?2:0;return Le(e,t,r,o,n,a,i,!0)}function N0(e){return e?Uf(e)||Aa in e?St({},e):e:null}function lr(e,t,r=!1){const{props:o,ref:n,patchFlag:i,children:a}=e,l=t?Xr(o||{},t):o;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&wh(l),ref:t&&t.ref?r&&n?Pe(n)?n.concat(Zi(t)):[n,Zi(t)]:Zi(t):n,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:a,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ot?i===-1?16:i|16:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&lr(e.ssContent),ssFallback:e.ssFallback&&lr(e.ssFallback),el:e.el,anchor:e.anchor}}function sr(e=" ",t=0){return ge(ec,null,e,t)}function Sh(e,t){const r=ge(Xi,null,e);return r.staticCount=t,r}function Yl(e="",t=!1){return t?(st(),mo(Lt,null,e)):ge(Lt,null,e)}function pr(e){return e==null||typeof e=="boolean"?ge(Lt):Pe(e)?ge(ot,null,e.slice()):typeof e=="object"?Hr(e):ge(ec,null,String(e))}function Hr(e){return e.el===null||e.memo?e:lr(e)}function tc(e,t){let r=0;const{shapeFlag:o}=e;if(t==null)t=null;else if(Pe(t))r=16;else if(typeof t=="object")if(o&65){const n=t.default;n&&(n._c&&(n._d=!1),tc(e,n()),n._c&&(n._d=!0));return}else{r=32;const n=t._;!n&&!(Aa in t)?t._ctx=zt:n===3&&zt&&(zt.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else Ie(t)?(t={default:t,_ctx:zt},r=32):(t=String(t),o&64?(r=16,t=[sr(t)]):r=8);e.children=t,e.shapeFlag|=r}function Xr(...e){const t={};for(let r=0;rt(a,l,void 0,i&&i[l]));else{const a=Object.keys(e);n=new Array(a.length);for(let l=0,s=a.length;lan(t)?!(t.type===Lt||t.type===ot&&!_h(t.children)):!0)?e:null}const Xl=e=>e?$h(e)?Oa(e)||e.proxy:Xl(e.parent):null,sa=St(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Xl(e.parent),$root:e=>Xl(e.root),$emit:e=>e.emit,$options:e=>dh(e),$forceUpdate:e=>()=>Jf(e.update),$nextTick:e=>br.bind(e.proxy),$watch:e=>d0.bind(e)}),K0={get({_:e},t){const{ctx:r,setupState:o,data:n,props:i,accessCache:a,type:l,appContext:s}=e;let d;if(t[0]!=="$"){const h=a[t];if(h!==void 0)switch(h){case 1:return o[t];case 2:return n[t];case 4:return r[t];case 3:return i[t]}else{if(o!==tt&&Ve(o,t))return a[t]=1,o[t];if(n!==tt&&Ve(n,t))return a[t]=2,n[t];if((d=e.propsOptions[0])&&Ve(d,t))return a[t]=3,i[t];if(r!==tt&&Ve(r,t))return a[t]=4,r[t];Vl&&(a[t]=0)}}const c=sa[t];let u,f;if(c)return t==="$attrs"&&Kt(e,"get",t),c(e);if((u=l.__cssModules)&&(u=u[t]))return u;if(r!==tt&&Ve(r,t))return a[t]=4,r[t];if(f=s.config.globalProperties,Ve(f,t))return f[t]},set({_:e},t,r){const{data:o,setupState:n,ctx:i}=e;return n!==tt&&Ve(n,t)?(n[t]=r,!0):o!==tt&&Ve(o,t)?(o[t]=r,!0):Ve(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=r,!0)},has({_:{data:e,setupState:t,accessCache:r,ctx:o,appContext:n,propsOptions:i}},a){let l;return!!r[a]||e!==tt&&Ve(e,a)||t!==tt&&Ve(t,a)||(l=i[0])&&Ve(l,a)||Ve(o,a)||Ve(sa,a)||Ve(n.config.globalProperties,a)},defineProperty(e,t,r){return r.get!=null?e._.accessCache[t]=0:Ve(r,"value")&&this.set(e,t,r.value,null),Reflect.defineProperty(e,t,r)}},U0=vh();let q0=0;function G0(e,t,r){const o=e.type,n=(t?t.appContext:e.appContext)||U0,i={uid:q0++,vnode:e,type:o,parent:t,appContext:n,root:null,next:null,subTree:null,effect:null,update:null,scope:new bb(!0),render:null,proxy:null,exposed:null,exposeProxy:null,withProxy:null,provides:t?t.provides:Object.create(n.provides),accessCache:null,renderCache:[],components:null,directives:null,propsOptions:fh(o,n),emitsOptions:oh(o,n),emit:null,emitted:null,propsDefaults:tt,inheritAttrs:o.inheritAttrs,ctx:tt,data:tt,props:tt,attrs:tt,slots:tt,refs:tt,setupState:tt,setupContext:null,suspense:r,suspenseId:r?r.pendingId:0,asyncDep:null,asyncResolved:!1,isMounted:!1,isUnmounted:!1,isDeactivated:!1,bc:null,c:null,bm:null,m:null,bu:null,u:null,um:null,bum:null,da:null,a:null,rtg:null,rtc:null,ec:null,sp:null};return i.ctx={_:i},i.root=t?t.root:i,i.emit=o0.bind(null,i),e.ce&&e.ce(i),i}let yt=null;const Zr=()=>yt||zt,ln=e=>{yt=e,e.scope.on()},wo=()=>{yt&&yt.scope.off(),yt=null};function $h(e){return e.vnode.shapeFlag&4}let ai=!1;function Y0(e,t=!1){ai=t;const{props:r,children:o}=e.vnode,n=$h(e);k0(e,r,n,t),R0(e,o);const i=n?X0(e,t):void 0;return ai=!1,i}function X0(e,t){const r=e.type;e.accessCache=Object.create(null),e.proxy=oa(new Proxy(e.ctx,K0));const{setup:o}=r;if(o){const n=e.setupContext=o.length>1?J0(e):null;ln(e),bn();const i=Wr(o,e,0,[e.props,n]);if(xn(),wo(),Af(i)){if(i.then(wo,wo),t)return i.then(a=>{wd(e,a,t)}).catch(a=>{ka(a,e,0)});e.asyncDep=i}else wd(e,i,t)}else Ph(e,t)}function wd(e,t,r){Ie(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:pt(t)&&(e.setupState=Xf(t)),Ph(e,r)}let Sd;function Ph(e,t,r){const o=e.type;if(!e.render){if(!t&&Sd&&!o.render){const n=o.template;if(n){const{isCustomElement:i,compilerOptions:a}=e.appContext.config,{delimiters:l,compilerOptions:s}=o,d=St(St({isCustomElement:i,delimiters:l},a),s);o.render=Sd(n,d)}}e.render=o.render||ir}ln(e),bn(),w0(e),xn(),wo()}function Z0(e){return new Proxy(e.attrs,{get(t,r){return Kt(e,"get","$attrs"),t[r]}})}function J0(e){const t=o=>{e.exposed=o||{}};let r;return{get attrs(){return r||(r=Z0(e))},slots:e.slots,emit:e.emit,expose:t}}function Oa(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Xf(oa(e.exposed)),{get(t,r){if(r in t)return t[r];if(r in sa)return sa[r](e)}}))}function Zl(e){return Ie(e)&&e.displayName||e.name}function Q0(e){return Ie(e)&&"__vccOpts"in e}const L=(e,t)=>Zb(e,t,ai);function m(e,t,r){const o=arguments.length;return o===2?pt(t)&&!Pe(t)?an(t)?ge(e,null,[t]):ge(e,t):ge(e,null,t):(o>3?r=Array.prototype.slice.call(arguments,2):o===3&&an(r)&&(r=[r]),ge(e,t,r))}const e1="3.2.33",t1="http://www.w3.org/2000/svg",ho=typeof document!="undefined"?document:null,_d=ho&&ho.createElement("template"),r1={insert:(e,t,r)=>{t.insertBefore(e,r||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,r,o)=>{const n=t?ho.createElementNS(t1,e):ho.createElement(e,r?{is:r}:void 0);return e==="select"&&o&&o.multiple!=null&&n.setAttribute("multiple",o.multiple),n},createText:e=>ho.createTextNode(e),createComment:e=>ho.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>ho.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},cloneNode(e){const t=e.cloneNode(!0);return"_value"in e&&(t._value=e._value),t},insertStaticContent(e,t,r,o,n,i){const a=r?r.previousSibling:t.lastChild;if(n&&(n===i||n.nextSibling))for(;t.insertBefore(n.cloneNode(!0),r),!(n===i||!(n=n.nextSibling)););else{_d.innerHTML=o?`${e}`:e;const l=_d.content;if(o){const s=l.firstChild;for(;s.firstChild;)l.appendChild(s.firstChild);l.removeChild(s)}t.insertBefore(l,r)}return[a?a.nextSibling:t.firstChild,r?r.previousSibling:t.lastChild]}};function o1(e,t,r){const o=e._vtc;o&&(t=(t?[t,...o]:[...o]).join(" ")),t==null?e.removeAttribute("class"):r?e.setAttribute("class",t):e.className=t}function n1(e,t,r){const o=e.style,n=ft(r);if(r&&!n){for(const i in r)Jl(o,i,r[i]);if(t&&!ft(t))for(const i in t)r[i]==null&&Jl(o,i,"")}else{const i=o.display;n?t!==r&&(o.cssText=r):t&&e.removeAttribute("style"),"_vod"in e&&(o.display=i)}}const $d=/\s*!important$/;function Jl(e,t,r){if(Pe(r))r.forEach(o=>Jl(e,t,o));else if(r==null&&(r=""),t.startsWith("--"))e.setProperty(t,r);else{const o=i1(e,t);$d.test(r)?e.setProperty(Po(o),r.replace($d,""),"important"):e[o]=r}}const Pd=["Webkit","Moz","ms"],dl={};function i1(e,t){const r=dl[t];if(r)return r;let o=vr(t);if(o!=="filter"&&o in e)return dl[t]=o;o=$a(o);for(let n=0;n{let e=Date.now,t=!1;if(typeof window!="undefined"){Date.now()>document.createEvent("Event").timeStamp&&(e=()=>performance.now());const r=navigator.userAgent.match(/firefox\/(\d+)/i);t=!!(r&&Number(r[1])<=53)}return[e,t]})();let Ql=0;const c1=Promise.resolve(),d1=()=>{Ql=0},u1=()=>Ql||(c1.then(d1),Ql=kh());function qo(e,t,r,o){e.addEventListener(t,r,o)}function f1(e,t,r,o){e.removeEventListener(t,r,o)}function h1(e,t,r,o,n=null){const i=e._vei||(e._vei={}),a=i[t];if(o&&a)a.value=o;else{const[l,s]=p1(t);if(o){const d=i[t]=m1(o,n);qo(e,l,d,s)}else a&&(f1(e,l,a,s),i[t]=void 0)}}const Td=/(?:Once|Passive|Capture)$/;function p1(e){let t;if(Td.test(e)){t={};let r;for(;r=e.match(Td);)e=e.slice(0,e.length-r[0].length),t[r[0].toLowerCase()]=!0}return[Po(e.slice(2)),t]}function m1(e,t){const r=o=>{const n=o.timeStamp||kh();(s1||n>=r.attached-1)&&Jt(v1(o,r.value),t,5,[o])};return r.value=e,r.attached=u1(),r}function v1(e,t){if(Pe(t)){const r=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{r.call(e),e._stopped=!0},t.map(o=>n=>!n._stopped&&o&&o(n))}else return t}const Ed=/^on[a-z]/,g1=(e,t,r,o,n=!1,i,a,l,s)=>{t==="class"?o1(e,o,n):t==="style"?n1(e,r,o):wa(t)?Is(t)||h1(e,t,r,o,a):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):b1(e,t,o,n))?l1(e,t,o,i,a,l,s):(t==="true-value"?e._trueValue=o:t==="false-value"&&(e._falseValue=o),a1(e,t,o,n))};function b1(e,t,r,o){return o?!!(t==="innerHTML"||t==="textContent"||t in e&&Ed.test(t)&&Ie(r)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||Ed.test(t)&&ft(r)?!1:t in e}const Ir="transition",En="animation",At=(e,{slots:t})=>m(ah,Eh(e),t);At.displayName="Transition";const Th={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},x1=At.props=St({},ah.props,Th),io=(e,t=[])=>{Pe(e)?e.forEach(r=>r(...t)):e&&e(...t)},Rd=e=>e?Pe(e)?e.some(t=>t.length>1):e.length>1:!1;function Eh(e){const t={};for(const T in e)T in Th||(t[T]=e[T]);if(e.css===!1)return t;const{name:r="v",type:o,duration:n,enterFromClass:i=`${r}-enter-from`,enterActiveClass:a=`${r}-enter-active`,enterToClass:l=`${r}-enter-to`,appearFromClass:s=i,appearActiveClass:d=a,appearToClass:c=l,leaveFromClass:u=`${r}-leave-from`,leaveActiveClass:f=`${r}-leave-active`,leaveToClass:h=`${r}-leave-to`}=e,p=C1(n),b=p&&p[0],g=p&&p[1],{onBeforeEnter:v,onEnter:w,onEnterCancelled:$,onLeave:x,onLeaveCancelled:S,onBeforeAppear:E=v,onAppear:y=w,onAppearCancelled:_=$}=t,R=(T,N,B)=>{so(T,N?c:l),so(T,N?d:a),B&&B()},P=(T,N)=>{so(T,h),so(T,f),N&&N()},j=T=>(N,B)=>{const q=T?y:w,A=()=>R(N,T,B);io(q,[N,A]),zd(()=>{so(N,T?s:i),$r(N,T?c:l),Rd(q)||Ad(N,o,b,A)})};return St(t,{onBeforeEnter(T){io(v,[T]),$r(T,i),$r(T,a)},onBeforeAppear(T){io(E,[T]),$r(T,s),$r(T,d)},onEnter:j(!1),onAppear:j(!0),onLeave(T,N){const B=()=>P(T,N);$r(T,u),zh(),$r(T,f),zd(()=>{so(T,u),$r(T,h),Rd(x)||Ad(T,o,g,B)}),io(x,[T,B])},onEnterCancelled(T){R(T,!1),io($,[T])},onAppearCancelled(T){R(T,!0),io(_,[T])},onLeaveCancelled(T){P(T),io(S,[T])}})}function C1(e){if(e==null)return null;if(pt(e))return[ul(e.enter),ul(e.leave)];{const t=ul(e);return[t,t]}}function ul(e){return ra(e)}function $r(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.add(r)),(e._vtc||(e._vtc=new Set)).add(t)}function so(e,t){t.split(/\s+/).forEach(o=>o&&e.classList.remove(o));const{_vtc:r}=e;r&&(r.delete(t),r.size||(e._vtc=void 0))}function zd(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let y1=0;function Ad(e,t,r,o){const n=e._endId=++y1,i=()=>{n===e._endId&&o()};if(r)return setTimeout(i,r);const{type:a,timeout:l,propCount:s}=Rh(e,t);if(!a)return o();const d=a+"end";let c=0;const u=()=>{e.removeEventListener(d,f),i()},f=h=>{h.target===e&&++c>=s&&u()};setTimeout(()=>{c(r[p]||"").split(", "),n=o(Ir+"Delay"),i=o(Ir+"Duration"),a=Od(n,i),l=o(En+"Delay"),s=o(En+"Duration"),d=Od(l,s);let c=null,u=0,f=0;t===Ir?a>0&&(c=Ir,u=a,f=i.length):t===En?d>0&&(c=En,u=d,f=s.length):(u=Math.max(a,d),c=u>0?a>d?Ir:En:null,f=c?c===Ir?i.length:s.length:0);const h=c===Ir&&/\b(transform|all)(,|$)/.test(r[Ir+"Property"]);return{type:c,timeout:u,propCount:f,hasTransform:h}}function Od(e,t){for(;e.lengthId(r)+Id(e[o])))}function Id(e){return Number(e.slice(0,-1).replace(",","."))*1e3}function zh(){return document.body.offsetHeight}const Ah=new WeakMap,Oh=new WeakMap,w1={name:"TransitionGroup",props:St({},x1,{tag:String,moveClass:String}),setup(e,{slots:t}){const r=Zr(),o=ih();let n,i;return Ys(()=>{if(!n.length)return;const a=e.moveClass||`${e.name||"v"}-move`;if(!P1(n[0].el,r.vnode.el,a))return;n.forEach(S1),n.forEach(_1);const l=n.filter($1);zh(),l.forEach(s=>{const d=s.el,c=d.style;$r(d,a),c.transform=c.webkitTransform=c.transitionDuration="";const u=d._moveCb=f=>{f&&f.target!==d||(!f||/transform$/.test(f.propertyName))&&(d.removeEventListener("transitionend",u),d._moveCb=null,so(d,a))};d.addEventListener("transitionend",u)})}),()=>{const a=Ge(e),l=Eh(a);let s=a.tag||ot;n=i,i=t.default?Gs(t.default()):[];for(let d=0;d{a.split(/\s+/).forEach(l=>l&&o.classList.remove(l))}),r.split(/\s+/).forEach(a=>a&&o.classList.add(a)),o.style.display="none";const n=t.nodeType===1?t:t.parentNode;n.appendChild(o);const{hasTransform:i}=Rh(o);return n.removeChild(o),i}const Md=e=>{const t=e.props["onUpdate:modelValue"];return Pe(t)?r=>tn(t,r):t};function k1(e){e.target.composing=!0}function Bd(e){const t=e.target;t.composing&&(t.composing=!1,T1(t,"input"))}function T1(e,t){const r=document.createEvent("HTMLEvents");r.initEvent(t,!0,!0),e.dispatchEvent(r)}const aO={created(e,{modifiers:{lazy:t,trim:r,number:o}},n){e._assign=Md(n);const i=o||n.props&&n.props.type==="number";qo(e,t?"change":"input",a=>{if(a.target.composing)return;let l=e.value;r?l=l.trim():i&&(l=ra(l)),e._assign(l)}),r&&qo(e,"change",()=>{e.value=e.value.trim()}),t||(qo(e,"compositionstart",k1),qo(e,"compositionend",Bd),qo(e,"change",Bd))},mounted(e,{value:t}){e.value=t==null?"":t},beforeUpdate(e,{value:t,modifiers:{lazy:r,trim:o,number:n}},i){if(e._assign=Md(i),e.composing||document.activeElement===e&&(r||o&&e.value.trim()===t||(n||e.type==="number")&&ra(e.value)===t))return;const a=t==null?"":t;e.value!==a&&(e.value=a)}},E1=["ctrl","shift","alt","meta"],R1={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>E1.some(r=>e[`${r}Key`]&&!t.includes(r))},Hn=(e,t)=>(r,...o)=>{for(let n=0;nr=>{if(!("key"in r))return;const o=Po(r.key);if(t.some(n=>n===o||z1[n]===o))return e(r)},li={beforeMount(e,{value:t},{transition:r}){e._vod=e.style.display==="none"?"":e.style.display,r&&t?r.beforeEnter(e):Rn(e,t)},mounted(e,{value:t},{transition:r}){r&&t&&r.enter(e)},updated(e,{value:t,oldValue:r},{transition:o}){!t!=!r&&(o?t?(o.beforeEnter(e),Rn(e,!0),o.enter(e)):o.leave(e,()=>{Rn(e,!1)}):Rn(e,t))},beforeUnmount(e,{value:t}){Rn(e,t)}};function Rn(e,t){e.style.display=t?e._vod:"none"}const A1=St({patchProp:g1},r1);let Ld;function O1(){return Ld||(Ld=I0(A1))}const I1=(...e)=>{const t=O1().createApp(...e),{mount:r}=t;return t.mount=o=>{const n=M1(o);if(!n)return;const i=t._component;!Ie(i)&&!i.render&&!i.template&&(i.template=n.innerHTML),n.innerHTML="";const a=r(n,!1,n instanceof SVGElement);return n instanceof Element&&(n.removeAttribute("v-cloak"),n.setAttribute("data-v-app","")),a},t};function M1(e){return ft(e)?document.querySelector(e):e}const B1="modulepreload",Dd={},L1="/",Yt=function(t,r){return!r||r.length===0?t():Promise.all(r.map(o=>{if(o=`${L1}${o}`,o in Dd)return;Dd[o]=!0;const n=o.endsWith(".css"),i=n?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${i}`))return;const a=document.createElement("link");if(a.rel=n?"stylesheet":B1,n||(a.as="script",a.crossOrigin=""),a.href=o,document.head.appendChild(a),n)return new Promise((l,s)=>{a.addEventListener("load",l),a.addEventListener("error",()=>s(new Error(`Unable to preload CSS for ${o}`)))})})).then(()=>t())};function D1(){return Ih().__VUE_DEVTOOLS_GLOBAL_HOOK__}function Ih(){return typeof navigator!="undefined"&&typeof window!="undefined"?window:typeof global!="undefined"?global:{}}const F1=typeof Proxy=="function",H1="devtools-plugin:setup",j1="plugin:settings:set";let Oo,es;function N1(){var e;return Oo!==void 0||(typeof window!="undefined"&&window.performance?(Oo=!0,es=window.performance):typeof global!="undefined"&&((e=global.perf_hooks)===null||e===void 0?void 0:e.performance)?(Oo=!0,es=global.perf_hooks.performance):Oo=!1),Oo}function W1(){return N1()?es.now():Date.now()}class V1{constructor(t,r){this.target=null,this.targetQueue=[],this.onQueue=[],this.plugin=t,this.hook=r;const o={};if(t.settings)for(const a in t.settings){const l=t.settings[a];o[a]=l.defaultValue}const n=`__vue-devtools-plugin-settings__${t.id}`;let i=Object.assign({},o);try{const a=localStorage.getItem(n),l=JSON.parse(a);Object.assign(i,l)}catch{}this.fallbacks={getSettings(){return i},setSettings(a){try{localStorage.setItem(n,JSON.stringify(a))}catch{}i=a},now(){return W1()}},r&&r.on(j1,(a,l)=>{a===this.plugin.id&&this.fallbacks.setSettings(l)}),this.proxiedOn=new Proxy({},{get:(a,l)=>this.target?this.target.on[l]:(...s)=>{this.onQueue.push({method:l,args:s})}}),this.proxiedTarget=new Proxy({},{get:(a,l)=>this.target?this.target[l]:l==="on"?this.proxiedOn:Object.keys(this.fallbacks).includes(l)?(...s)=>(this.targetQueue.push({method:l,args:s,resolve:()=>{}}),this.fallbacks[l](...s)):(...s)=>new Promise(d=>{this.targetQueue.push({method:l,args:s,resolve:d})})})}async setRealTarget(t){this.target=t;for(const r of this.onQueue)this.target.on[r.method](...r.args);for(const r of this.targetQueue)r.resolve(await this.target[r.method](...r.args))}}function K1(e,t){const r=e,o=Ih(),n=D1(),i=F1&&r.enableEarlyProxy;if(n&&(o.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__||!i))n.emit(H1,e,t);else{const a=i?new V1(r,n):null;(o.__VUE_DEVTOOLS_PLUGINS__=o.__VUE_DEVTOOLS_PLUGINS__||[]).push({pluginDescriptor:r,setupFn:t,proxy:a}),a&&t(a.proxiedTarget)}}/*! - * vue-router v4.0.14 - * (c) 2022 Eduardo San Martin Morote - * @license MIT - */const Mh=typeof Symbol=="function"&&typeof Symbol.toStringTag=="symbol",Cn=e=>Mh?Symbol(e):"_vr_"+e,U1=Cn("rvlm"),Fd=Cn("rvd"),Ia=Cn("r"),oc=Cn("rl"),ts=Cn("rvl"),Go=typeof window!="undefined";function q1(e){return e.__esModule||Mh&&e[Symbol.toStringTag]==="Module"}const et=Object.assign;function fl(e,t){const r={};for(const o in t){const n=t[o];r[o]=Array.isArray(n)?n.map(e):e(n)}return r}const Gn=()=>{},G1=/\/$/,Y1=e=>e.replace(G1,"");function hl(e,t,r="/"){let o,n={},i="",a="";const l=t.indexOf("?"),s=t.indexOf("#",l>-1?l:0);return l>-1&&(o=t.slice(0,l),i=t.slice(l+1,s>-1?s:t.length),n=e(i)),s>-1&&(o=o||t.slice(0,s),a=t.slice(s,t.length)),o=Q1(o!=null?o:t,r),{fullPath:o+(i&&"?")+i+a,path:o,query:n,hash:a}}function X1(e,t){const r=t.query?e(t.query):"";return t.path+(r&&"?")+r+(t.hash||"")}function Hd(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Z1(e,t,r){const o=t.matched.length-1,n=r.matched.length-1;return o>-1&&o===n&&sn(t.matched[o],r.matched[n])&&Bh(t.params,r.params)&&e(t.query)===e(r.query)&&t.hash===r.hash}function sn(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function Bh(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const r in e)if(!J1(e[r],t[r]))return!1;return!0}function J1(e,t){return Array.isArray(e)?jd(e,t):Array.isArray(t)?jd(t,e):e===t}function jd(e,t){return Array.isArray(t)?e.length===t.length&&e.every((r,o)=>r===t[o]):e.length===1&&e[0]===t}function Q1(e,t){if(e.startsWith("/"))return e;if(!e)return t;const r=t.split("/"),o=e.split("/");let n=r.length-1,i,a;for(i=0;i({left:window.pageXOffset,top:window.pageYOffset});function nx(e){let t;if("el"in e){const r=e.el,o=typeof r=="string"&&r.startsWith("#"),n=typeof r=="string"?o?document.getElementById(r.slice(1)):document.querySelector(r):r;if(!n)return;t=ox(n,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.pageXOffset,t.top!=null?t.top:window.pageYOffset)}function Nd(e,t){return(history.state?history.state.position-t:-1)+e}const rs=new Map;function ix(e,t){rs.set(e,t)}function ax(e){const t=rs.get(e);return rs.delete(e),t}let lx=()=>location.protocol+"//"+location.host;function Lh(e,t){const{pathname:r,search:o,hash:n}=t,i=e.indexOf("#");if(i>-1){let l=n.includes(e.slice(i))?e.slice(i).length:1,s=n.slice(l);return s[0]!=="/"&&(s="/"+s),Hd(s,"")}return Hd(r,e)+o+n}function sx(e,t,r,o){let n=[],i=[],a=null;const l=({state:f})=>{const h=Lh(e,location),p=r.value,b=t.value;let g=0;if(f){if(r.value=h,t.value=f,a&&a===p){a=null;return}g=b?f.position-b.position:0}else o(h);n.forEach(v=>{v(r.value,p,{delta:g,type:si.pop,direction:g?g>0?Yn.forward:Yn.back:Yn.unknown})})};function s(){a=r.value}function d(f){n.push(f);const h=()=>{const p=n.indexOf(f);p>-1&&n.splice(p,1)};return i.push(h),h}function c(){const{history:f}=window;!f.state||f.replaceState(et({},f.state,{scroll:Ma()}),"")}function u(){for(const f of i)f();i=[],window.removeEventListener("popstate",l),window.removeEventListener("beforeunload",c)}return window.addEventListener("popstate",l),window.addEventListener("beforeunload",c),{pauseListeners:s,listen:d,destroy:u}}function Wd(e,t,r,o=!1,n=!1){return{back:e,current:t,forward:r,replaced:o,position:window.history.length,scroll:n?Ma():null}}function cx(e){const{history:t,location:r}=window,o={value:Lh(e,r)},n={value:t.state};n.value||i(o.value,{back:null,current:o.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(s,d,c){const u=e.indexOf("#"),f=u>-1?(r.host&&document.querySelector("base")?e:e.slice(u))+s:lx()+e+s;try{t[c?"replaceState":"pushState"](d,"",f),n.value=d}catch(h){console.error(h),r[c?"replace":"assign"](f)}}function a(s,d){const c=et({},t.state,Wd(n.value.back,s,n.value.forward,!0),d,{position:n.value.position});i(s,c,!0),o.value=s}function l(s,d){const c=et({},n.value,t.state,{forward:s,scroll:Ma()});i(c.current,c,!0);const u=et({},Wd(o.value,s,null),{position:c.position+1},d);i(s,u,!1),o.value=s}return{location:o,state:n,push:l,replace:a}}function dx(e){e=ex(e);const t=cx(e),r=sx(e,t.state,t.location,t.replace);function o(i,a=!0){a||r.pauseListeners(),history.go(i)}const n=et({location:"",base:e,go:o,createHref:rx.bind(null,e)},t,r);return Object.defineProperty(n,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(n,"state",{enumerable:!0,get:()=>t.state.value}),n}function ux(e){return e=location.host?e||location.pathname+location.search:"",e.includes("#")||(e+="#"),dx(e)}function fx(e){return typeof e=="string"||e&&typeof e=="object"}function Dh(e){return typeof e=="string"||typeof e=="symbol"}const Mr={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},Fh=Cn("nf");var Vd;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(Vd||(Vd={}));function cn(e,t){return et(new Error,{type:e,[Fh]:!0},t)}function Br(e,t){return e instanceof Error&&Fh in e&&(t==null||!!(e.type&t))}const Kd="[^/]+?",hx={sensitive:!1,strict:!1,start:!0,end:!0},px=/[.+*?^${}()[\]/\\]/g;function mx(e,t){const r=et({},hx,t),o=[];let n=r.start?"^":"";const i=[];for(const d of e){const c=d.length?[]:[90];r.strict&&!d.length&&(n+="/");for(let u=0;ut.length?t.length===1&&t[0]===40+40?1:-1:0}function gx(e,t){let r=0;const o=e.score,n=t.score;for(;r1&&(s==="*"||s==="+")&&t(`A repeatable param (${d}) must be alone in its segment. eg: '/:ids+.`),i.push({type:1,value:d,regexp:c,repeatable:s==="*"||s==="+",optional:s==="*"||s==="?"})):t("Invalid state to consume buffer"),d="")}function f(){d+=s}for(;l{a(w)}:Gn}function a(c){if(Dh(c)){const u=o.get(c);u&&(o.delete(c),r.splice(r.indexOf(u),1),u.children.forEach(a),u.alias.forEach(a))}else{const u=r.indexOf(c);u>-1&&(r.splice(u,1),c.record.name&&o.delete(c.record.name),c.children.forEach(a),c.alias.forEach(a))}}function l(){return r}function s(c){let u=0;for(;u=0&&(c.record.path!==r[u].record.path||!Hh(c,r[u]));)u++;r.splice(u,0,c),c.record.name&&!Ud(c)&&o.set(c.record.name,c)}function d(c,u){let f,h={},p,b;if("name"in c&&c.name){if(f=o.get(c.name),!f)throw cn(1,{location:c});b=f.record.name,h=et(Sx(u.params,f.keys.filter(w=>!w.optional).map(w=>w.name)),c.params),p=f.stringify(h)}else if("path"in c)p=c.path,f=r.find(w=>w.re.test(p)),f&&(h=f.parse(p),b=f.record.name);else{if(f=u.name?o.get(u.name):r.find(w=>w.re.test(u.path)),!f)throw cn(1,{location:c,currentLocation:u});b=f.record.name,h=et({},u.params,c.params),p=f.stringify(h)}const g=[];let v=f;for(;v;)g.unshift(v.record),v=v.parent;return{name:b,path:p,params:h,matched:g,meta:Px(g)}}return e.forEach(c=>i(c)),{addRoute:i,resolve:d,removeRoute:a,getRoutes:l,getRecordMatcher:n}}function Sx(e,t){const r={};for(const o of t)o in e&&(r[o]=e[o]);return r}function _x(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:$x(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||{}:{default:e.component}}}function $x(e){const t={},r=e.props||!1;if("component"in e)t.default=r;else for(const o in e.components)t[o]=typeof r=="boolean"?r:r[o];return t}function Ud(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function Px(e){return e.reduce((t,r)=>et(t,r.meta),{})}function qd(e,t){const r={};for(const o in e)r[o]=o in t?t[o]:e[o];return r}function Hh(e,t){return t.children.some(r=>r===e||Hh(e,r))}const jh=/#/g,kx=/&/g,Tx=/\//g,Ex=/=/g,Rx=/\?/g,Nh=/\+/g,zx=/%5B/g,Ax=/%5D/g,Wh=/%5E/g,Ox=/%60/g,Vh=/%7B/g,Ix=/%7C/g,Kh=/%7D/g,Mx=/%20/g;function nc(e){return encodeURI(""+e).replace(Ix,"|").replace(zx,"[").replace(Ax,"]")}function Bx(e){return nc(e).replace(Vh,"{").replace(Kh,"}").replace(Wh,"^")}function os(e){return nc(e).replace(Nh,"%2B").replace(Mx,"+").replace(jh,"%23").replace(kx,"%26").replace(Ox,"`").replace(Vh,"{").replace(Kh,"}").replace(Wh,"^")}function Lx(e){return os(e).replace(Ex,"%3D")}function Dx(e){return nc(e).replace(jh,"%23").replace(Rx,"%3F")}function Fx(e){return e==null?"":Dx(e).replace(Tx,"%2F")}function ca(e){try{return decodeURIComponent(""+e)}catch{}return""+e}function Hx(e){const t={};if(e===""||e==="?")return t;const o=(e[0]==="?"?e.slice(1):e).split("&");for(let n=0;ni&&os(i)):[o&&os(o)]).forEach(i=>{i!==void 0&&(t+=(t.length?"&":"")+r,i!=null&&(t+="="+i))})}return t}function jx(e){const t={};for(const r in e){const o=e[r];o!==void 0&&(t[r]=Array.isArray(o)?o.map(n=>n==null?null:""+n):o==null?o:""+o)}return t}function zn(){let e=[];function t(o){return e.push(o),()=>{const n=e.indexOf(o);n>-1&&e.splice(n,1)}}function r(){e=[]}return{add:t,list:()=>e,reset:r}}function jr(e,t,r,o,n){const i=o&&(o.enterCallbacks[n]=o.enterCallbacks[n]||[]);return()=>new Promise((a,l)=>{const s=u=>{u===!1?l(cn(4,{from:r,to:t})):u instanceof Error?l(u):fx(u)?l(cn(2,{from:t,to:u})):(i&&o.enterCallbacks[n]===i&&typeof u=="function"&&i.push(u),a())},d=e.call(o&&o.instances[n],t,r,s);let c=Promise.resolve(d);e.length<3&&(c=c.then(s)),c.catch(u=>l(u))})}function pl(e,t,r,o){const n=[];for(const i of e)for(const a in i.components){let l=i.components[a];if(!(t!=="beforeRouteEnter"&&!i.instances[a]))if(Nx(l)){const d=(l.__vccOpts||l)[t];d&&n.push(jr(d,r,o,i,a))}else{let s=l();n.push(()=>s.then(d=>{if(!d)return Promise.reject(new Error(`Couldn't resolve component "${a}" at "${i.path}"`));const c=q1(d)?d.default:d;i.components[a]=c;const f=(c.__vccOpts||c)[t];return f&&jr(f,r,o,i,a)()}))}}return n}function Nx(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function Yd(e){const t=be(Ia),r=be(oc),o=L(()=>t.resolve(Me(e.to))),n=L(()=>{const{matched:s}=o.value,{length:d}=s,c=s[d-1],u=r.matched;if(!c||!u.length)return-1;const f=u.findIndex(sn.bind(null,c));if(f>-1)return f;const h=Xd(s[d-2]);return d>1&&Xd(c)===h&&u[u.length-1].path!==h?u.findIndex(sn.bind(null,s[d-2])):f}),i=L(()=>n.value>-1&&Ux(r.params,o.value.params)),a=L(()=>n.value>-1&&n.value===r.matched.length-1&&Bh(r.params,o.value.params));function l(s={}){return Kx(s)?t[Me(e.replace)?"replace":"push"](Me(e.to)).catch(Gn):Promise.resolve()}return{route:o,href:L(()=>o.value.href),isActive:i,isExactActive:a,navigate:l}}const Wx=oe({name:"RouterLink",props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:Yd,setup(e,{slots:t}){const r=ar(Yd(e)),{options:o}=be(Ia),n=L(()=>({[Zd(e.activeClass,o.linkActiveClass,"router-link-active")]:r.isActive,[Zd(e.exactActiveClass,o.linkExactActiveClass,"router-link-exact-active")]:r.isExactActive}));return()=>{const i=t.default&&t.default(r);return e.custom?i:m("a",{"aria-current":r.isExactActive?e.ariaCurrentValue:null,href:r.href,onClick:r.navigate,class:n.value},i)}}}),Vx=Wx;function Kx(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function Ux(e,t){for(const r in t){const o=t[r],n=e[r];if(typeof o=="string"){if(o!==n)return!1}else if(!Array.isArray(n)||n.length!==o.length||o.some((i,a)=>i!==n[a]))return!1}return!0}function Xd(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Zd=(e,t,r)=>e!=null?e:t!=null?t:r,qx=oe({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},setup(e,{attrs:t,slots:r}){const o=be(ts),n=L(()=>e.route||o.value),i=be(Fd,0),a=L(()=>n.value.matched[i]);je(Fd,i+1),je(U1,a),je(ts,n);const l=W();return qe(()=>[l.value,a.value,e.name],([s,d,c],[u,f,h])=>{d&&(d.instances[c]=s,f&&f!==d&&s&&s===u&&(d.leaveGuards.size||(d.leaveGuards=f.leaveGuards),d.updateGuards.size||(d.updateGuards=f.updateGuards))),s&&d&&(!f||!sn(d,f)||!u)&&(d.enterCallbacks[c]||[]).forEach(p=>p(s))},{flush:"post"}),()=>{const s=n.value,d=a.value,c=d&&d.components[e.name],u=e.name;if(!c)return Jd(r.default,{Component:c,route:s});const f=d.props[e.name],h=f?f===!0?s.params:typeof f=="function"?f(s):f:null,b=m(c,et({},h,t,{onVnodeUnmounted:g=>{g.component.isUnmounted&&(d.instances[u]=null)},ref:l}));return Jd(r.default,{Component:b,route:s})||b}}});function Jd(e,t){if(!e)return null;const r=e(t);return r.length===1?r[0]:r}const Gx=qx;function Yx(e){const t=wx(e.routes,e),r=e.parseQuery||Hx,o=e.stringifyQuery||Gd,n=e.history,i=zn(),a=zn(),l=zn(),s=Ub(Mr);let d=Mr;Go&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const c=fl.bind(null,O=>""+O),u=fl.bind(null,Fx),f=fl.bind(null,ca);function h(O,V){let D,ce;return Dh(O)?(D=t.getRecordMatcher(O),ce=V):ce=O,t.addRoute(ce,D)}function p(O){const V=t.getRecordMatcher(O);V&&t.removeRoute(V)}function b(){return t.getRoutes().map(O=>O.record)}function g(O){return!!t.getRecordMatcher(O)}function v(O,V){if(V=et({},V||s.value),typeof O=="string"){const Z=hl(r,O,V.path),C=t.resolve({path:Z.path},V),k=n.createHref(Z.fullPath);return et(Z,C,{params:f(C.params),hash:ca(Z.hash),redirectedFrom:void 0,href:k})}let D;if("path"in O)D=et({},O,{path:hl(r,O.path,V.path).path});else{const Z=et({},O.params);for(const C in Z)Z[C]==null&&delete Z[C];D=et({},O,{params:u(O.params)}),V.params=u(V.params)}const ce=t.resolve(D,V),ue=O.hash||"";ce.params=c(f(ce.params));const xe=X1(o,et({},O,{hash:Bx(ue),path:ce.path})),G=n.createHref(xe);return et({fullPath:xe,hash:ue,query:o===Gd?jx(O.query):O.query||{}},ce,{redirectedFrom:void 0,href:G})}function w(O){return typeof O=="string"?hl(r,O,s.value.path):et({},O)}function $(O,V){if(d!==O)return cn(8,{from:V,to:O})}function x(O){return y(O)}function S(O){return x(et(w(O),{replace:!0}))}function E(O){const V=O.matched[O.matched.length-1];if(V&&V.redirect){const{redirect:D}=V;let ce=typeof D=="function"?D(O):D;return typeof ce=="string"&&(ce=ce.includes("?")||ce.includes("#")?ce=w(ce):{path:ce},ce.params={}),et({query:O.query,hash:O.hash,params:O.params},ce)}}function y(O,V){const D=d=v(O),ce=s.value,ue=O.state,xe=O.force,G=O.replace===!0,Z=E(D);if(Z)return y(et(w(Z),{state:ue,force:xe,replace:G}),V||D);const C=D;C.redirectedFrom=V;let k;return!xe&&Z1(o,ce,D)&&(k=cn(16,{to:C,from:ce}),Ae(ce,ce,!0,!1)),(k?Promise.resolve(k):R(C,ce)).catch(H=>Br(H)?Br(H,2)?H:_e(H):te(H,C,ce)).then(H=>{if(H){if(Br(H,2))return y(et(w(H.to),{state:ue,force:xe,replace:G}),V||C)}else H=j(C,ce,!0,G,ue);return P(C,ce,H),H})}function _(O,V){const D=$(O,V);return D?Promise.reject(D):Promise.resolve()}function R(O,V){let D;const[ce,ue,xe]=Xx(O,V);D=pl(ce.reverse(),"beforeRouteLeave",O,V);for(const Z of ce)Z.leaveGuards.forEach(C=>{D.push(jr(C,O,V))});const G=_.bind(null,O,V);return D.push(G),Io(D).then(()=>{D=[];for(const Z of i.list())D.push(jr(Z,O,V));return D.push(G),Io(D)}).then(()=>{D=pl(ue,"beforeRouteUpdate",O,V);for(const Z of ue)Z.updateGuards.forEach(C=>{D.push(jr(C,O,V))});return D.push(G),Io(D)}).then(()=>{D=[];for(const Z of O.matched)if(Z.beforeEnter&&!V.matched.includes(Z))if(Array.isArray(Z.beforeEnter))for(const C of Z.beforeEnter)D.push(jr(C,O,V));else D.push(jr(Z.beforeEnter,O,V));return D.push(G),Io(D)}).then(()=>(O.matched.forEach(Z=>Z.enterCallbacks={}),D=pl(xe,"beforeRouteEnter",O,V),D.push(G),Io(D))).then(()=>{D=[];for(const Z of a.list())D.push(jr(Z,O,V));return D.push(G),Io(D)}).catch(Z=>Br(Z,8)?Z:Promise.reject(Z))}function P(O,V,D){for(const ce of l.list())ce(O,V,D)}function j(O,V,D,ce,ue){const xe=$(O,V);if(xe)return xe;const G=V===Mr,Z=Go?history.state:{};D&&(ce||G?n.replace(O.fullPath,et({scroll:G&&Z&&Z.scroll},ue)):n.push(O.fullPath,ue)),s.value=O,Ae(O,V,D,G),_e()}let T;function N(){T=n.listen((O,V,D)=>{const ce=v(O),ue=E(ce);if(ue){y(et(ue,{replace:!0}),ce).catch(Gn);return}d=ce;const xe=s.value;Go&&ix(Nd(xe.fullPath,D.delta),Ma()),R(ce,xe).catch(G=>Br(G,12)?G:Br(G,2)?(y(G.to,ce).then(Z=>{Br(Z,20)&&!D.delta&&D.type===si.pop&&n.go(-1,!1)}).catch(Gn),Promise.reject()):(D.delta&&n.go(-D.delta,!1),te(G,ce,xe))).then(G=>{G=G||j(ce,xe,!1),G&&(D.delta?n.go(-D.delta,!1):D.type===si.pop&&Br(G,20)&&n.go(-1,!1)),P(ce,xe,G)}).catch(Gn)})}let B=zn(),q=zn(),A;function te(O,V,D){_e(O);const ce=q.list();return ce.length?ce.forEach(ue=>ue(O,V,D)):console.error(O),Promise.reject(O)}function se(){return A&&s.value!==Mr?Promise.resolve():new Promise((O,V)=>{B.add([O,V])})}function _e(O){return A||(A=!O,N(),B.list().forEach(([V,D])=>O?D(O):V()),B.reset()),O}function Ae(O,V,D,ce){const{scrollBehavior:ue}=e;if(!Go||!ue)return Promise.resolve();const xe=!D&&ax(Nd(O.fullPath,0))||(ce||!D)&&history.state&&history.state.scroll||null;return br().then(()=>ue(O,V,xe)).then(G=>G&&nx(G)).catch(G=>te(G,O,V))}const Re=O=>n.go(O);let Ee;const $e=new Set;return{currentRoute:s,addRoute:h,removeRoute:p,hasRoute:g,getRoutes:b,resolve:v,options:e,push:x,replace:S,go:Re,back:()=>Re(-1),forward:()=>Re(1),beforeEach:i.add,beforeResolve:a.add,afterEach:l.add,onError:q.add,isReady:se,install(O){const V=this;O.component("RouterLink",Vx),O.component("RouterView",Gx),O.config.globalProperties.$router=V,Object.defineProperty(O.config.globalProperties,"$route",{enumerable:!0,get:()=>Me(s)}),Go&&!Ee&&s.value===Mr&&(Ee=!0,x(n.location).catch(ue=>{}));const D={};for(const ue in Mr)D[ue]=L(()=>s.value[ue]);O.provide(Ia,V),O.provide(oc,ar(D)),O.provide(ts,s);const ce=O.unmount;$e.add(O),O.unmount=function(){$e.delete(O),$e.size<1&&(d=Mr,T&&T(),s.value=Mr,Ee=!1,A=!1),ce()}}}}function Io(e){return e.reduce((t,r)=>t.then(()=>r()),Promise.resolve())}function Xx(e,t){const r=[],o=[],n=[],i=Math.max(t.matched.length,e.matched.length);for(let a=0;asn(d,l))?o.push(l):r.push(l));const s=e.matched[a];s&&(t.matched.find(d=>sn(d,s))||n.push(s))}return[r,o,n]}function Uh(){return be(Ia)}function Zx(){return be(oc)}const Jx=[{path:"/",name:"home",meta:{title:"\u5E7F\u573A",keepAlive:!0},component:()=>Yt(()=>import("./Home.d188c936.js"),["assets/Home.d188c936.js","assets/Home.07e73aab.css","assets/post-item.03452002.js","assets/post-item.766f3250.css","assets/content.ef1e095a.js","assets/content.ef781517.css","assets/formatTime.02109bf5.js","assets/Thing.eef6b133.js","assets/post-skeleton.39a35f5b.js","assets/post-skeleton.328dfb67.css","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/IEnum.bfd96c78.js","assets/Upload.efe3adfd.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/Pagination.1263479e.js"])},{path:"/post",name:"post",meta:{title:"\u8BDD\u9898\u8BE6\u60C5"},component:()=>Yt(()=>import("./Post.db4b62c9.js"),["assets/Post.db4b62c9.js","assets/Post.de11af43.css","assets/InputGroup.f69c4956.js","assets/formatTime.02109bf5.js","assets/content.ef1e095a.js","assets/content.ef781517.css","assets/Thing.eef6b133.js","assets/post-skeleton.39a35f5b.js","assets/post-skeleton.328dfb67.css","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/IEnum.bfd96c78.js","assets/Upload.efe3adfd.js","assets/MoreHorizFilled.80db5156.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css"])},{path:"/topic",name:"topic",meta:{title:"\u8BDD\u9898"},component:()=>Yt(()=>import("./Topic.c6bdf01d.js"),["assets/Topic.c6bdf01d.js","assets/Topic.9a2ef7f9.css","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/List.49bcdf81.js"])},{path:"/anouncement",name:"anouncement",meta:{title:"\u516C\u544A"},component:()=>Yt(()=>import("./Anouncement.98ee5b6f.js"),["assets/Anouncement.98ee5b6f.js","assets/Anouncement.5f84f68f.css","assets/post-skeleton.39a35f5b.js","assets/post-skeleton.328dfb67.css","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/formatTime.02109bf5.js","assets/Pagination.1263479e.js"])},{path:"/profile",name:"profile",meta:{title:"\u4E3B\u9875"},component:()=>Yt(()=>import("./Profile.75de1930.js"),["assets/Profile.75de1930.js","assets/Profile.df0a7049.css","assets/post-item.03452002.js","assets/post-item.766f3250.css","assets/content.ef1e095a.js","assets/content.ef781517.css","assets/formatTime.02109bf5.js","assets/Thing.eef6b133.js","assets/post-skeleton.39a35f5b.js","assets/post-skeleton.328dfb67.css","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/Pagination.1263479e.js"])},{path:"/user",name:"user",meta:{title:"\u7528\u6237\u8BE6\u60C5"},component:()=>Yt(()=>import("./User.695fa64f.js"),["assets/User.695fa64f.js","assets/User.7b771241.css","assets/post-item.03452002.js","assets/post-item.766f3250.css","assets/content.ef1e095a.js","assets/content.ef781517.css","assets/formatTime.02109bf5.js","assets/Thing.eef6b133.js","assets/post-skeleton.39a35f5b.js","assets/post-skeleton.328dfb67.css","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/Alert.a854329b.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/MoreHorizFilled.80db5156.js","assets/Pagination.1263479e.js"])},{path:"/messages",name:"messages",meta:{title:"\u6D88\u606F"},component:()=>Yt(()=>import("./Messages.c822d4d1.js"),["assets/Messages.c822d4d1.js","assets/Messages.db382f03.css","assets/formatTime.02109bf5.js","assets/Alert.a854329b.js","assets/Thing.eef6b133.js","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/Pagination.1263479e.js"])},{path:"/collection",name:"collection",meta:{title:"\u6536\u85CF"},component:()=>Yt(()=>import("./Collection.02f600ee.js"),["assets/Collection.02f600ee.js","assets/Collection.d63a34f0.css","assets/post-item.03452002.js","assets/post-item.766f3250.css","assets/content.ef1e095a.js","assets/content.ef781517.css","assets/formatTime.02109bf5.js","assets/Thing.eef6b133.js","assets/post-skeleton.39a35f5b.js","assets/post-skeleton.328dfb67.css","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/Pagination.1263479e.js"])},{path:"/contacts",name:"contacts",meta:{title:"\u597D\u53CB"},component:()=>Yt(()=>import("./Contacts.a6b6de0d.js"),["assets/Contacts.a6b6de0d.js","assets/Contacts.e16015c7.css","assets/post-skeleton.39a35f5b.js","assets/post-skeleton.328dfb67.css","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/Pagination.1263479e.js"])},{path:"/wallet",name:"wallet",meta:{title:"\u94B1\u5305"},component:()=>Yt(()=>import("./Wallet.b8e2b626.js"),["assets/Wallet.b8e2b626.js","assets/Wallet.e5757b5e.css","assets/post-skeleton.39a35f5b.js","assets/post-skeleton.328dfb67.css","assets/Skeleton.57e98fe3.js","assets/List.49bcdf81.js","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/formatTime.02109bf5.js","assets/Pagination.1263479e.js"])},{path:"/setting",name:"setting",meta:{title:"\u8BBE\u7F6E"},component:()=>Yt(()=>import("./Setting.837d491b.js"),["assets/Setting.837d491b.js","assets/Setting.a66de7b5.css","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/Upload.efe3adfd.js","assets/Alert.a854329b.js","assets/InputGroup.f69c4956.js"])},{path:"/404",name:"404",meta:{title:"404"},component:()=>Yt(()=>import("./404.15b4dcd0.js"),["assets/404.15b4dcd0.js","assets/404.9c166a4c.css","assets/main-nav.9110259b.js","assets/main-nav.b4a45e8a.css","assets/List.49bcdf81.js"])},{path:"/:pathMatch(.*)",redirect:"/404"}],qh=Yx({history:ux(),routes:Jx});qh.beforeEach((e,t,r)=>{document.title=`${e.meta.title} | \u6CE1\u6CE1 - \u4E00\u4E2A\u6E05\u65B0\u6587\u827A\u7684\u5FAE\u793E\u533A`,r()});/*! - * vuex v4.0.2 - * (c) 2021 Evan You - * @license MIT - */var Gh="store";function Ba(e){return e===void 0&&(e=null),be(e!==null?e:Gh)}function yn(e,t){Object.keys(e).forEach(function(r){return t(e[r],r)})}function Qx(e){return e!==null&&typeof e=="object"}function eC(e){return e&&typeof e.then=="function"}function tC(e,t){return function(){return e(t)}}function Yh(e,t,r){return t.indexOf(e)<0&&(r&&r.prepend?t.unshift(e):t.push(e)),function(){var o=t.indexOf(e);o>-1&&t.splice(o,1)}}function Xh(e,t){e._actions=Object.create(null),e._mutations=Object.create(null),e._wrappedGetters=Object.create(null),e._modulesNamespaceMap=Object.create(null);var r=e.state;La(e,r,[],e._modules.root,!0),ic(e,r,t)}function ic(e,t,r){var o=e._state;e.getters={},e._makeLocalGettersCache=Object.create(null);var n=e._wrappedGetters,i={};yn(n,function(a,l){i[l]=tC(a,e),Object.defineProperty(e.getters,l,{get:function(){return i[l]()},enumerable:!0})}),e._state=ar({data:t}),e.strict&&aC(e),o&&r&&e._withCommit(function(){o.data=null})}function La(e,t,r,o,n){var i=!r.length,a=e._modules.getNamespace(r);if(o.namespaced&&(e._modulesNamespaceMap[a],e._modulesNamespaceMap[a]=o),!i&&!n){var l=ac(t,r.slice(0,-1)),s=r[r.length-1];e._withCommit(function(){l[s]=o.state})}var d=o.context=rC(e,a,r);o.forEachMutation(function(c,u){var f=a+u;oC(e,f,c,d)}),o.forEachAction(function(c,u){var f=c.root?u:a+u,h=c.handler||c;nC(e,f,h,d)}),o.forEachGetter(function(c,u){var f=a+u;iC(e,f,c,d)}),o.forEachChild(function(c,u){La(e,t,r.concat(u),c,n)})}function rC(e,t,r){var o=t==="",n={dispatch:o?e.dispatch:function(i,a,l){var s=da(i,a,l),d=s.payload,c=s.options,u=s.type;return(!c||!c.root)&&(u=t+u),e.dispatch(u,d)},commit:o?e.commit:function(i,a,l){var s=da(i,a,l),d=s.payload,c=s.options,u=s.type;(!c||!c.root)&&(u=t+u),e.commit(u,d,c)}};return Object.defineProperties(n,{getters:{get:o?function(){return e.getters}:function(){return Zh(e,t)}},state:{get:function(){return ac(e.state,r)}}}),n}function Zh(e,t){if(!e._makeLocalGettersCache[t]){var r={},o=t.length;Object.keys(e.getters).forEach(function(n){if(n.slice(0,o)===t){var i=n.slice(o);Object.defineProperty(r,i,{get:function(){return e.getters[n]},enumerable:!0})}}),e._makeLocalGettersCache[t]=r}return e._makeLocalGettersCache[t]}function oC(e,t,r,o){var n=e._mutations[t]||(e._mutations[t]=[]);n.push(function(a){r.call(e,o.state,a)})}function nC(e,t,r,o){var n=e._actions[t]||(e._actions[t]=[]);n.push(function(a){var l=r.call(e,{dispatch:o.dispatch,commit:o.commit,getters:o.getters,state:o.state,rootGetters:e.getters,rootState:e.state},a);return eC(l)||(l=Promise.resolve(l)),e._devtoolHook?l.catch(function(s){throw e._devtoolHook.emit("vuex:error",s),s}):l})}function iC(e,t,r,o){e._wrappedGetters[t]||(e._wrappedGetters[t]=function(i){return r(o.state,o.getters,i.state,i.getters)})}function aC(e){qe(function(){return e._state.data},function(){},{deep:!0,flush:"sync"})}function ac(e,t){return t.reduce(function(r,o){return r[o]},e)}function da(e,t,r){return Qx(e)&&e.type&&(r=t,t=e,e=e.type),{type:e,payload:t,options:r}}var lC="vuex bindings",Qd="vuex:mutations",ml="vuex:actions",Mo="vuex",sC=0;function cC(e,t){K1({id:"org.vuejs.vuex",app:e,label:"Vuex",homepage:"https://next.vuex.vuejs.org/",logo:"https://vuejs.org/images/icons/favicon-96x96.png",packageName:"vuex",componentStateTypes:[lC]},function(r){r.addTimelineLayer({id:Qd,label:"Vuex Mutations",color:eu}),r.addTimelineLayer({id:ml,label:"Vuex Actions",color:eu}),r.addInspector({id:Mo,label:"Vuex",icon:"storage",treeFilterPlaceholder:"Filter stores..."}),r.on.getInspectorTree(function(o){if(o.app===e&&o.inspectorId===Mo)if(o.filter){var n=[];tp(n,t._modules.root,o.filter,""),o.rootNodes=n}else o.rootNodes=[ep(t._modules.root,"")]}),r.on.getInspectorState(function(o){if(o.app===e&&o.inspectorId===Mo){var n=o.nodeId;Zh(t,n),o.state=fC(pC(t._modules,n),n==="root"?t.getters:t._makeLocalGettersCache,n)}}),r.on.editInspectorState(function(o){if(o.app===e&&o.inspectorId===Mo){var n=o.nodeId,i=o.path;n!=="root"&&(i=n.split("/").filter(Boolean).concat(i)),t._withCommit(function(){o.set(t._state.data,i,o.state.value)})}}),t.subscribe(function(o,n){var i={};o.payload&&(i.payload=o.payload),i.state=n,r.notifyComponentUpdate(),r.sendInspectorTree(Mo),r.sendInspectorState(Mo),r.addTimelineEvent({layerId:Qd,event:{time:Date.now(),title:o.type,data:i}})}),t.subscribeAction({before:function(o,n){var i={};o.payload&&(i.payload=o.payload),o._id=sC++,o._time=Date.now(),i.state=n,r.addTimelineEvent({layerId:ml,event:{time:o._time,title:o.type,groupId:o._id,subtitle:"start",data:i}})},after:function(o,n){var i={},a=Date.now()-o._time;i.duration={_custom:{type:"duration",display:a+"ms",tooltip:"Action duration",value:a}},o.payload&&(i.payload=o.payload),i.state=n,r.addTimelineEvent({layerId:ml,event:{time:Date.now(),title:o.type,groupId:o._id,subtitle:"end",data:i}})}})})}var eu=8702998,dC=6710886,uC=16777215,Jh={label:"namespaced",textColor:uC,backgroundColor:dC};function Qh(e){return e&&e!=="root"?e.split("/").slice(-2,-1)[0]:"Root"}function ep(e,t){return{id:t||"root",label:Qh(t),tags:e.namespaced?[Jh]:[],children:Object.keys(e._children).map(function(r){return ep(e._children[r],t+r+"/")})}}function tp(e,t,r,o){o.includes(r)&&e.push({id:o||"root",label:o.endsWith("/")?o.slice(0,o.length-1):o||"Root",tags:t.namespaced?[Jh]:[]}),Object.keys(t._children).forEach(function(n){tp(e,t._children[n],r,o+n+"/")})}function fC(e,t,r){t=r==="root"?t:t[r];var o=Object.keys(t),n={state:Object.keys(e.state).map(function(a){return{key:a,editable:!0,value:e.state[a]}})};if(o.length){var i=hC(t);n.getters=Object.keys(i).map(function(a){return{key:a.endsWith("/")?Qh(a):a,editable:!1,value:ns(function(){return i[a]})}})}return n}function hC(e){var t={};return Object.keys(e).forEach(function(r){var o=r.split("/");if(o.length>1){var n=t,i=o.pop();o.forEach(function(a){n[a]||(n[a]={_custom:{value:{},display:a,tooltip:"Module",abstract:!0}}),n=n[a]._custom.value}),n[i]=ns(function(){return e[r]})}else t[r]=ns(function(){return e[r]})}),t}function pC(e,t){var r=t.split("/").filter(function(o){return o});return r.reduce(function(o,n,i){var a=o[n];if(!a)throw new Error('Missing module "'+n+'" for path "'+t+'".');return i===r.length-1?a:a._children},t==="root"?e:e.root._children)}function ns(e){try{return e()}catch(t){return t}}var cr=function(t,r){this.runtime=r,this._children=Object.create(null),this._rawModule=t;var o=t.state;this.state=(typeof o=="function"?o():o)||{}},rp={namespaced:{configurable:!0}};rp.namespaced.get=function(){return!!this._rawModule.namespaced};cr.prototype.addChild=function(t,r){this._children[t]=r};cr.prototype.removeChild=function(t){delete this._children[t]};cr.prototype.getChild=function(t){return this._children[t]};cr.prototype.hasChild=function(t){return t in this._children};cr.prototype.update=function(t){this._rawModule.namespaced=t.namespaced,t.actions&&(this._rawModule.actions=t.actions),t.mutations&&(this._rawModule.mutations=t.mutations),t.getters&&(this._rawModule.getters=t.getters)};cr.prototype.forEachChild=function(t){yn(this._children,t)};cr.prototype.forEachGetter=function(t){this._rawModule.getters&&yn(this._rawModule.getters,t)};cr.prototype.forEachAction=function(t){this._rawModule.actions&&yn(this._rawModule.actions,t)};cr.prototype.forEachMutation=function(t){this._rawModule.mutations&&yn(this._rawModule.mutations,t)};Object.defineProperties(cr.prototype,rp);var ko=function(t){this.register([],t,!1)};ko.prototype.get=function(t){return t.reduce(function(r,o){return r.getChild(o)},this.root)};ko.prototype.getNamespace=function(t){var r=this.root;return t.reduce(function(o,n){return r=r.getChild(n),o+(r.namespaced?n+"/":"")},"")};ko.prototype.update=function(t){op([],this.root,t)};ko.prototype.register=function(t,r,o){var n=this;o===void 0&&(o=!0);var i=new cr(r,o);if(t.length===0)this.root=i;else{var a=this.get(t.slice(0,-1));a.addChild(t[t.length-1],i)}r.modules&&yn(r.modules,function(l,s){n.register(t.concat(s),l,o)})};ko.prototype.unregister=function(t){var r=this.get(t.slice(0,-1)),o=t[t.length-1],n=r.getChild(o);!n||!n.runtime||r.removeChild(o)};ko.prototype.isRegistered=function(t){var r=this.get(t.slice(0,-1)),o=t[t.length-1];return r?r.hasChild(o):!1};function op(e,t,r){if(t.update(r),r.modules)for(var o in r.modules){if(!t.getChild(o))return;op(e.concat(o),t.getChild(o),r.modules[o])}}function mC(e){return new Ft(e)}var Ft=function(t){var r=this;t===void 0&&(t={});var o=t.plugins;o===void 0&&(o=[]);var n=t.strict;n===void 0&&(n=!1);var i=t.devtools;this._committing=!1,this._actions=Object.create(null),this._actionSubscribers=[],this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._modules=new ko(t),this._modulesNamespaceMap=Object.create(null),this._subscribers=[],this._makeLocalGettersCache=Object.create(null),this._devtools=i;var a=this,l=this,s=l.dispatch,d=l.commit;this.dispatch=function(f,h){return s.call(a,f,h)},this.commit=function(f,h,p){return d.call(a,f,h,p)},this.strict=n;var c=this._modules.root.state;La(this,c,[],this._modules.root),ic(this,c),o.forEach(function(u){return u(r)})},lc={state:{configurable:!0}};Ft.prototype.install=function(t,r){t.provide(r||Gh,this),t.config.globalProperties.$store=this;var o=this._devtools!==void 0?this._devtools:!1;o&&cC(t,this)};lc.state.get=function(){return this._state.data};lc.state.set=function(e){};Ft.prototype.commit=function(t,r,o){var n=this,i=da(t,r,o),a=i.type,l=i.payload,s={type:a,payload:l},d=this._mutations[a];!d||(this._withCommit(function(){d.forEach(function(u){u(l)})}),this._subscribers.slice().forEach(function(c){return c(s,n.state)}))};Ft.prototype.dispatch=function(t,r){var o=this,n=da(t,r),i=n.type,a=n.payload,l={type:i,payload:a},s=this._actions[i];if(!!s){try{this._actionSubscribers.slice().filter(function(c){return c.before}).forEach(function(c){return c.before(l,o.state)})}catch{}var d=s.length>1?Promise.all(s.map(function(c){return c(a)})):s[0](a);return new Promise(function(c,u){d.then(function(f){try{o._actionSubscribers.filter(function(h){return h.after}).forEach(function(h){return h.after(l,o.state)})}catch{}c(f)},function(f){try{o._actionSubscribers.filter(function(h){return h.error}).forEach(function(h){return h.error(l,o.state,f)})}catch{}u(f)})})}};Ft.prototype.subscribe=function(t,r){return Yh(t,this._subscribers,r)};Ft.prototype.subscribeAction=function(t,r){var o=typeof t=="function"?{before:t}:t;return Yh(o,this._actionSubscribers,r)};Ft.prototype.watch=function(t,r,o){var n=this;return qe(function(){return t(n.state,n.getters)},r,Object.assign({},o))};Ft.prototype.replaceState=function(t){var r=this;this._withCommit(function(){r._state.data=t})};Ft.prototype.registerModule=function(t,r,o){o===void 0&&(o={}),typeof t=="string"&&(t=[t]),this._modules.register(t,r),La(this,this.state,t,this._modules.get(t),o.preserveState),ic(this,this.state)};Ft.prototype.unregisterModule=function(t){var r=this;typeof t=="string"&&(t=[t]),this._modules.unregister(t),this._withCommit(function(){var o=ac(r.state,t.slice(0,-1));delete o[t[t.length-1]]}),Xh(this)};Ft.prototype.hasModule=function(t){return typeof t=="string"&&(t=[t]),this._modules.isRegistered(t)};Ft.prototype.hotUpdate=function(t){this._modules.update(t),Xh(this,!0)};Ft.prototype._withCommit=function(t){var r=this._committing;this._committing=!0,t(),this._committing=r};Object.defineProperties(Ft.prototype,lc);var vC=mC({state:{refresh:Date.now(),theme:localStorage.getItem("PAOPAO_THEME"),collapsedLeft:document.body.clientWidth<=821,collapsedRight:document.body.clientWidth<=821,authModalShow:!1,authModelTab:"signin",userInfo:{id:0,username:"",nickname:""}},mutations:{refresh(e,t){e.refresh=t||Date.now()},triggerTheme(e,t){e.theme=t},triggerAuth(e,t){e.authModalShow=t},triggerAuthKey(e,t){e.authModelTab=t},triggerCollapsedLeft(e,t){e.collapsedLeft=t},triggerCollapsedRight(e,t){e.collapsedRight=t},updateUserinfo(e,t){e.userInfo=t},userLogout(e){localStorage.removeItem("PAOPAO_TOKEN"),e.userInfo={id:0,nickname:"",username:""}}},actions:{},modules:{}});let ua=[];const np=new WeakMap;function gC(){ua.forEach(e=>e(...np.get(e))),ua=[]}function ip(e,...t){np.set(e,t),!ua.includes(e)&&ua.push(e)===1&&requestAnimationFrame(gC)}function bC(e,t){let{target:r}=e;for(;r;){if(r.dataset&&r.dataset[t]!==void 0)return!0;r=r.parentElement}return!1}function tu(e){return typeof e=="string"?e.endsWith("px")?Number(e.slice(0,e.length-2)):Number(e):e}function xC(e){if(e!=null)return typeof e=="number"?`${e}px`:e.endsWith("px")?e:`${e}px`}function ap(e,t){const r=e.trim().split(/\s+/g),o={top:r[0]};switch(r.length){case 1:o.right=r[0],o.bottom=r[0],o.left=r[0];break;case 2:o.right=r[1],o.left=r[1],o.bottom=r[0];break;case 3:o.right=r[1],o.bottom=r[2],o.left=r[1];break;case 4:o.right=r[1],o.bottom=r[2],o.left=r[3];break;default:throw new Error("[seemly/getMargin]:"+e+" is not a valid value.")}return t===void 0?o:o[t]}function CC(e,t){const[r,o]=e.split(" ");return t?t==="row"?r:o:{row:r,col:o||r}}var ru={black:"#000",silver:"#C0C0C0",gray:"#808080",white:"#FFF",maroon:"#800000",red:"#F00",purple:"#800080",fuchsia:"#F0F",green:"#008000",lime:"#0F0",olive:"#808000",yellow:"#FF0",navy:"#000080",blue:"#00F",teal:"#008080",aqua:"#0FF",transparent:"#0000"};const wn="^\\s*",Sn="\\s*$",vo="\\s*((\\.\\d+)|(\\d+(\\.\\d*)?))\\s*",go="([0-9A-Fa-f])",bo="([0-9A-Fa-f]{2})",yC=new RegExp(`${wn}rgb\\s*\\(${vo},${vo},${vo}\\)${Sn}`),wC=new RegExp(`${wn}rgba\\s*\\(${vo},${vo},${vo},${vo}\\)${Sn}`),SC=new RegExp(`${wn}#${go}${go}${go}${Sn}`),_C=new RegExp(`${wn}#${bo}${bo}${bo}${Sn}`),$C=new RegExp(`${wn}#${go}${go}${go}${go}${Sn}`),PC=new RegExp(`${wn}#${bo}${bo}${bo}${bo}${Sn}`);function Dt(e){return parseInt(e,16)}function Tr(e){try{let t;if(t=_C.exec(e))return[Dt(t[1]),Dt(t[2]),Dt(t[3]),1];if(t=yC.exec(e))return[Rt(t[1]),Rt(t[5]),Rt(t[9]),1];if(t=wC.exec(e))return[Rt(t[1]),Rt(t[5]),Rt(t[9]),Xn(t[13])];if(t=SC.exec(e))return[Dt(t[1]+t[1]),Dt(t[2]+t[2]),Dt(t[3]+t[3]),1];if(t=PC.exec(e))return[Dt(t[1]),Dt(t[2]),Dt(t[3]),Xn(Dt(t[4])/255)];if(t=$C.exec(e))return[Dt(t[1]+t[1]),Dt(t[2]+t[2]),Dt(t[3]+t[3]),Xn(Dt(t[4]+t[4])/255)];if(e in ru)return Tr(ru[e]);throw new Error(`[seemly/rgba]: Invalid color value ${e}.`)}catch(t){throw t}}function kC(e){return e>1?1:e<0?0:e}function is(e,t,r,o){return`rgba(${Rt(e)}, ${Rt(t)}, ${Rt(r)}, ${kC(o)})`}function vl(e,t,r,o,n){return Rt((e*t*(1-o)+r*o)/n)}function ye(e,t){Array.isArray(e)||(e=Tr(e)),Array.isArray(t)||(t=Tr(t));const r=e[3],o=t[3],n=Xn(r+o-r*o);return is(vl(e[0],r,t[0],o,n),vl(e[1],r,t[1],o,n),vl(e[2],r,t[2],o,n),n)}function ee(e,t){const[r,o,n,i=1]=Array.isArray(e)?e:Tr(e);return t.alpha?is(r,o,n,t.alpha):is(r,o,n,i)}function Yo(e,t){const[r,o,n,i=1]=Array.isArray(e)?e:Tr(e),{lightness:a=1,alpha:l=1}=t;return TC([r*a,o*a,n*a,i*l])}function Xn(e){const t=Math.round(Number(e)*100)/100;return t>1?1:t<0?0:t}function Rt(e){const t=Math.round(Number(e));return t>255?255:t<0?0:t}function TC(e){const[t,r,o]=e;return 3 in e?`rgba(${Rt(t)}, ${Rt(r)}, ${Rt(o)}, ${Xn(e[3])})`:`rgba(${Rt(t)}, ${Rt(r)}, ${Rt(o)}, 1)`}globalThis&&globalThis.__awaiter;function dn(e=8){return Math.random().toString(16).slice(2,2+e)}function EC(e,t="default",r=[]){const n=e.$slots[t];return n===void 0?r:n()}function Vt(e,t=[],r){const o={};return t.forEach(n=>{o[n]=e[n]}),Object.assign(o,r)}function sc(e,t=[],r){const o={};return Object.getOwnPropertyNames(e).forEach(i=>{t.includes(i)||(o[i]=e[i])}),Object.assign(o,r)}function So(e,t=!0,r=[]){return e.forEach(o=>{if(o!==null){if(typeof o!="object"){(typeof o=="string"||typeof o=="number")&&r.push(sr(String(o)));return}if(Array.isArray(o)){So(o,t,r);return}if(o.type===ot){if(o.children===null)return;Array.isArray(o.children)&&So(o.children,t,r)}else o.type!==Lt&&r.push(o)}}),r}function Be(e,...t){if(Array.isArray(e))e.forEach(r=>Be(r,...t));else return e(...t)}function er(e){return Object.keys(e)}const Ct=(e,...t)=>typeof e=="function"?e(...t):typeof e=="string"?sr(e):typeof e=="number"?sr(String(e)):null;function Kr(e,t){console.error(`[naive/${e}]: ${t}`)}function Da(e,t){throw new Error(`[naive/${e}]: ${t}`)}function RC(e){switch(typeof e){case"string":return e||void 0;case"number":return String(e);default:return}}function as(e,t="default",r=void 0){const o=e[t];if(!o)return Kr("getFirstSlotVNode",`slot[${t}] is empty`),null;const n=So(o(r));return n.length===1?n[0]:(Kr("getFirstSlotVNode",`slot[${t}] should have exactly one child`),null)}function zC(e){return t=>{t?e.value=t.$el:e.value=null}}function lO(e){return e}function bi(e){return e.some(t=>an(t)?!(t.type===Lt||t.type===ot&&!bi(t.children)):!0)?e:null}function _o(e,t){return e&&bi(e())||t()}function AC(e,t,r){return e&&bi(e(t))||r(t)}function bt(e,t){const r=e&&bi(e());return t(r||null)}function cc(e){return!(e&&bi(e()))}const OC=/^(\d|\.)+$/,ou=/(\d|\.)+/;function Qt(e,{c:t=1,offset:r=0,attachPx:o=!0}={}){if(typeof e=="number"){const n=(e+r)*t;return n===0?"0":`${n}px`}else if(typeof e=="string")if(OC.test(e)){const n=(Number(e)+r)*t;return o?n===0?"0":`${n}px`:`${n}`}else{const n=ou.exec(e);return n?e.replace(ou,String((Number(n[0])+r)*t)):e}return e}function un(e){return e.replace(/#|\(|\)|,|\s/g,"_")}function IC(e){let t=0;for(let r=0;r{let n=IC(o);if(n){if(n===1){e.forEach(a=>{r.push(o.replace("&",a))});return}}else{e.forEach(a=>{r.push((a&&a+" ")+o)});return}let i=[o];for(;n--;){const a=[];i.forEach(l=>{e.forEach(s=>{a.push(l.replace("&",s))})}),i=a}i.forEach(a=>r.push(a))}),r}function LC(e,t){const r=[];return t.split(lp).forEach(o=>{e.forEach(n=>{r.push((n&&n+" ")+o)})}),r}function DC(e){let t=[""];return e.forEach(r=>{r=r&&r.trim(),r&&(r.includes("&")?t=BC(t,r):t=LC(t,r))}),t.join(", ").replace(MC," ")}function nu(e){if(!e)return;const t=e.parentElement;t&&t.removeChild(e)}function Fa(e){return document.querySelector(`style[cssr-id="${e}"]`)}function FC(e){const t=document.createElement("style");return t.setAttribute("cssr-id",e),t}function Di(e){return e?/^\s*@(s|m)/.test(e):!1}const HC=/[A-Z]/g;function sp(e){return e.replace(HC,t=>"-"+t.toLowerCase())}function jC(e,t=" "){return typeof e=="object"&&e!==null?` { -`+Object.entries(e).map(r=>t+` ${sp(r[0])}: ${r[1]};`).join(` -`)+` -`+t+"}":`: ${e};`}function NC(e,t,r){return typeof e=="function"?e({context:t.context,props:r}):e}function iu(e,t,r,o){if(!t)return"";const n=NC(t,r,o);if(!n)return"";if(typeof n=="string")return`${e} { -${n} -}`;const i=Object.keys(n);if(i.length===0)return r.config.keepEmptyBlock?e+` { -}`:"";const a=e?[e+" {"]:[];return i.forEach(l=>{const s=n[l];if(l==="raw"){a.push(` -`+s+` -`);return}l=sp(l),s!=null&&a.push(` ${l}${jC(s)}`)}),e&&a.push("}"),a.join(` -`)}function ls(e,t,r){!e||e.forEach(o=>{if(Array.isArray(o))ls(o,t,r);else if(typeof o=="function"){const n=o(t);Array.isArray(n)?ls(n,t,r):n&&r(n)}else o&&r(o)})}function cp(e,t,r,o,n,i){const a=e.$;let l="";if(!a||typeof a=="string")Di(a)?l=a:t.push(a);else if(typeof a=="function"){const c=a({context:o.context,props:n});Di(c)?l=c:t.push(c)}else if(a.before&&a.before(o.context),!a.$||typeof a.$=="string")Di(a.$)?l=a.$:t.push(a.$);else if(a.$){const c=a.$({context:o.context,props:n});Di(c)?l=c:t.push(c)}const s=DC(t),d=iu(s,e.props,o,n);l?(r.push(`${l} {`),i&&d&&i.insertRule(`${l} { -${d} -} -`)):(i&&d&&i.insertRule(d),!i&&d.length&&r.push(d)),e.children&&ls(e.children,{context:o.context,props:n},c=>{if(typeof c=="string"){const u=iu(s,{raw:c},o,n);i?i.insertRule(u):r.push(u)}else cp(c,t,r,o,n,i)}),t.pop(),l&&r.push("}"),a&&a.after&&a.after(o.context)}function dp(e,t,r,o=!1){const n=[];return cp(e,[],n,t,r,o?e.instance.__styleSheet:void 0),o?"":n.join(` - -`)}function ci(e){for(var t=0,r,o=0,n=e.length;n>=4;++o,n-=4)r=e.charCodeAt(o)&255|(e.charCodeAt(++o)&255)<<8|(e.charCodeAt(++o)&255)<<16|(e.charCodeAt(++o)&255)<<24,r=(r&65535)*1540483477+((r>>>16)*59797<<16),r^=r>>>24,t=(r&65535)*1540483477+((r>>>16)*59797<<16)^(t&65535)*1540483477+((t>>>16)*59797<<16);switch(n){case 3:t^=(e.charCodeAt(o+2)&255)<<16;case 2:t^=(e.charCodeAt(o+1)&255)<<8;case 1:t^=e.charCodeAt(o)&255,t=(t&65535)*1540483477+((t>>>16)*59797<<16)}return t^=t>>>13,t=(t&65535)*1540483477+((t>>>16)*59797<<16),((t^t>>>15)>>>0).toString(36)}typeof window!="undefined"&&(window.__cssrContext={});function WC(e,t,r){const{els:o}=t;if(r===void 0)o.forEach(nu),t.els=[];else{const n=Fa(r);n&&o.includes(n)&&(nu(n),t.els=o.filter(i=>i!==n))}}function au(e,t){e.push(t)}function VC(e,t,r,o,n,i,a,l,s){if(i&&!s){if(r===void 0){console.error("[css-render/mount]: `id` is required in `silent` mode.");return}const f=window.__cssrContext;f[r]||(f[r]=!0,dp(t,e,o,i));return}let d;if(r===void 0&&(d=t.render(o),r=ci(d)),s){s.adapter(r,d!=null?d:t.render(o));return}const c=Fa(r);if(c!==null&&!a)return c;const u=c!=null?c:FC(r);if(d===void 0&&(d=t.render(o)),u.textContent=d,c!==null)return c;if(l){const f=document.head.querySelector(`meta[name="${l}"]`);if(f)return document.head.insertBefore(u,f),au(t.els,u),u}return n?document.head.insertBefore(u,document.head.querySelector("style, link")):document.head.appendChild(u),au(t.els,u),u}function KC(e){return dp(this,this.instance,e)}function UC(e={}){const{id:t,ssr:r,props:o,head:n=!1,silent:i=!1,force:a=!1,anchorMetaName:l}=e;return VC(this.instance,this,t,o,n,i,a,l,r)}function qC(e={}){const{id:t}=e;WC(this.instance,this,t)}const Fi=function(e,t,r,o){return{instance:e,$:t,props:r,children:o,els:[],render:KC,mount:UC,unmount:qC}},GC=function(e,t,r,o){return Array.isArray(t)?Fi(e,{$:null},null,t):Array.isArray(r)?Fi(e,t,null,r):Array.isArray(o)?Fi(e,t,r,o):Fi(e,t,r,null)};function up(e={}){let t=null;const r={c:(...o)=>GC(r,...o),use:(o,...n)=>o.install(r,...n),find:Fa,context:{},config:e,get __styleSheet(){if(!t){const o=document.createElement("style");return document.head.appendChild(o),t=document.styleSheets[document.styleSheets.length-1],t}return t}};return r}function YC(e,t){if(e===void 0)return!1;if(t){const{context:{ids:r}}=t;return r.has(e)}return Fa(e)!==null}function XC(e){let t=".",r="__",o="--",n;if(e){let p=e.blockPrefix;p&&(t=p),p=e.elementPrefix,p&&(r=p),p=e.modifierPrefix,p&&(o=p)}const i={install(p){n=p.c;const b=p.context;b.bem={},b.bem.b=null,b.bem.els=null}};function a(p){let b,g;return{before(v){b=v.bem.b,g=v.bem.els,v.bem.els=null},after(v){v.bem.b=b,v.bem.els=g},$({context:v,props:w}){return p=typeof p=="string"?p:p({context:v,props:w}),v.bem.b=p,`${(w==null?void 0:w.bPrefix)||t}${v.bem.b}`}}}function l(p){let b;return{before(g){b=g.bem.els},after(g){g.bem.els=b},$({context:g,props:v}){return p=typeof p=="string"?p:p({context:g,props:v}),g.bem.els=p.split(",").map(w=>w.trim()),g.bem.els.map(w=>`${(v==null?void 0:v.bPrefix)||t}${g.bem.b}${r}${w}`).join(", ")}}}function s(p){return{$({context:b,props:g}){p=typeof p=="string"?p:p({context:b,props:g});const v=p.split(",").map(x=>x.trim());function w(x){return v.map(S=>`&${(g==null?void 0:g.bPrefix)||t}${b.bem.b}${x!==void 0?`${r}${x}`:""}${o}${S}`).join(", ")}const $=b.bem.els;return $!==null?w($[0]):w()}}}function d(p){return{$({context:b,props:g}){p=typeof p=="string"?p:p({context:b,props:g});const v=b.bem.els;return`&:not(${(g==null?void 0:g.bPrefix)||t}${b.bem.b}${v!==null&&v.length>0?`${r}${v[0]}`:""}${o}${p})`}}}return Object.assign(i,{cB:(...p)=>n(a(p[0]),p[1],p[2]),cE:(...p)=>n(l(p[0]),p[1],p[2]),cM:(...p)=>n(s(p[0]),p[1],p[2]),cNotM:(...p)=>n(d(p[0]),p[1],p[2])}),i}function ae(e,t){return e+(t==="default"?"":t.replace(/^[a-z]/,r=>r.toUpperCase()))}ae("abc","def");const ZC="n",fn=`.${ZC}-`,JC="__",QC="--",fp=up(),hp=XC({blockPrefix:fn,elementPrefix:JC,modifierPrefix:QC});fp.use(hp);const{c:z,find:sO}=fp,{cB:M,cE:F,cM:K,cNotM:ut}=hp;function dc(e){return z(({props:{bPrefix:t}})=>`${t||fn}modal, ${t||fn}drawer`,[e])}function pp(e){return z(({props:{bPrefix:t}})=>`${t||fn}popover:not(${t||fn}tooltip)`,[e])}function mp(e){return z(({props:{bPrefix:t}})=>`&${t||fn}modal`,e)}const ey=(...e)=>z(">",[M(...e)]);function ty(e){const t=W(!!e.value);if(t.value)return gr(t);const r=qe(e,o=>{o&&(t.value=!0,r())});return gr(t)}function ht(e){const t=L(e),r=W(t.value);return qe(t,o=>{r.value=o}),typeof e=="function"?r:{__v_isRef:!0,get value(){return r.value},set value(o){e.set(o)}}}function uc(){return Zr()!==null}const fc=typeof window!="undefined";let on,Zn;const ry=()=>{var e,t;on=fc?(t=(e=document)===null||e===void 0?void 0:e.fonts)===null||t===void 0?void 0:t.ready:void 0,Zn=!1,on!==void 0?on.then(()=>{Zn=!0}):Zn=!0};ry();function vp(e){if(Zn)return;let t=!1;Ot(()=>{Zn||on==null||on.then(()=>{t||e()})}),It(()=>{t=!0})}const oy={mousemoveoutside:new WeakMap,clickoutside:new WeakMap};function ny(e,t,r){if(e==="mousemoveoutside"){const o=n=>{t.contains(n.target)||r(n)};return{mousemove:o,touchstart:o}}else if(e==="clickoutside"){let o=!1;const n=a=>{o=!t.contains(a.target)},i=a=>{!o||t.contains(a.target)||r(a)};return{mousedown:n,mouseup:i,touchstart:n,touchend:i}}return console.error(`[evtd/create-trap-handler]: name \`${e}\` is invalid. This could be a bug of evtd.`),{}}function gp(e,t,r){const o=oy[e];let n=o.get(t);n===void 0&&o.set(t,n=new WeakMap);let i=n.get(r);return i===void 0&&n.set(r,i=ny(e,t,r)),i}function iy(e,t,r,o){if(e==="mousemoveoutside"||e==="clickoutside"){const n=gp(e,t,r);return Object.keys(n).forEach(i=>{nt(i,document,n[i],o)}),!0}return!1}function ay(e,t,r,o){if(e==="mousemoveoutside"||e==="clickoutside"){const n=gp(e,t,r);return Object.keys(n).forEach(i=>{Ze(i,document,n[i],o)}),!0}return!1}function ly(){if(typeof window=="undefined")return{on:()=>{},off:()=>{}};const e=new WeakMap,t=new WeakMap;function r(){e.set(this,!0)}function o(){e.set(this,!0),t.set(this,!0)}function n(y,_,R){const P=y[_];return y[_]=function(){return R.apply(y,arguments),P.apply(y,arguments)},y}function i(y,_){y[_]=Event.prototype[_]}const a=new WeakMap,l=Object.getOwnPropertyDescriptor(Event.prototype,"currentTarget");function s(){var y;return(y=a.get(this))!==null&&y!==void 0?y:null}function d(y,_){l!==void 0&&Object.defineProperty(y,"currentTarget",{configurable:!0,enumerable:!0,get:_!=null?_:l.get})}const c={bubble:{},capture:{}},u={};function f(){const y=function(_){const{type:R,eventPhase:P,target:j,bubbles:T}=_;if(P===2)return;const N=P===1?"capture":"bubble";let B=j;const q=[];for(;B===null&&(B=window),q.push(B),B!==window;)B=B.parentNode||null;const A=c.capture[R],te=c.bubble[R];if(n(_,"stopPropagation",r),n(_,"stopImmediatePropagation",o),d(_,s),N==="capture"){if(A===void 0)return;for(let se=q.length-1;se>=0&&!e.has(_);--se){const _e=q[se],Ae=A.get(_e);if(Ae!==void 0){a.set(_,_e);for(const Re of Ae){if(t.has(_))break;Re(_)}}if(se===0&&!T&&te!==void 0){const Re=te.get(_e);if(Re!==void 0)for(const Ee of Re){if(t.has(_))break;Ee(_)}}}}else if(N==="bubble"){if(te===void 0)return;for(let se=0;seT(_))};return y.displayName="evtdUnifiedWindowEventHandler",y}const p=f(),b=h();function g(y,_){const R=c[y];return R[_]===void 0&&(R[_]=new Map,window.addEventListener(_,p,y==="capture")),R[_]}function v(y){return u[y]===void 0&&(u[y]=new Set,window.addEventListener(y,b)),u[y]}function w(y,_){let R=y.get(_);return R===void 0&&y.set(_,R=new Set),R}function $(y,_,R,P){const j=c[_][R];if(j!==void 0){const T=j.get(y);if(T!==void 0&&T.has(P))return!0}return!1}function x(y,_){const R=u[y];return!!(R!==void 0&&R.has(_))}function S(y,_,R,P){let j;if(typeof P=="object"&&P.once===!0?j=A=>{E(y,_,j,P),R(A)}:j=R,iy(y,_,j,P))return;const N=P===!0||typeof P=="object"&&P.capture===!0?"capture":"bubble",B=g(N,y),q=w(B,_);if(q.has(j)||q.add(j),_===window){const A=v(y);A.has(j)||A.add(j)}}function E(y,_,R,P){if(ay(y,_,R,P))return;const T=P===!0||typeof P=="object"&&P.capture===!0,N=T?"capture":"bubble",B=g(N,y),q=w(B,_);if(_===window&&!$(_,T?"bubble":"capture",y,R)&&x(y,R)){const te=u[y];te.delete(R),te.size===0&&(window.removeEventListener(y,b),u[y]=void 0)}q.has(R)&&q.delete(R),q.size===0&&B.delete(_),B.size===0&&(window.removeEventListener(y,p,N==="capture"),c[N][y]=void 0)}return{on:S,off:E}}const{on:nt,off:Ze}=ly(),Nn=W(null);function lu(e){if(e.clientX>0||e.clientY>0)Nn.value={x:e.clientX,y:e.clientY};else{const{target:t}=e;if(t instanceof Element){const{left:r,top:o,width:n,height:i}=t.getBoundingClientRect();r>0||o>0?Nn.value={x:r+n/2,y:o+i/2}:Nn.value={x:0,y:0}}else Nn.value=null}}let Hi=0,su=!0;function bp(){if(!fc)return gr(W(null));Hi===0&&nt("click",document,lu,!0);const e=()=>{Hi+=1};return su&&(su=uc())?(Yr(e),It(()=>{Hi-=1,Hi===0&&Ze("click",document,lu,!0)})):e(),gr(Nn)}const sy=W(void 0);let ji=0;function cu(){sy.value=Date.now()}let du=!0;function xp(e){if(!fc)return gr(W(!1));const t=W(!1);let r=null;function o(){r!==null&&window.clearTimeout(r)}function n(){o(),t.value=!0,r=window.setTimeout(()=>{t.value=!1},e)}ji===0&&nt("click",window,cu,!0);const i=()=>{ji+=1,nt("click",window,n,!0)};return du&&(du=uc())?(Yr(i),It(()=>{ji-=1,ji===0&&Ze("click",window,cu,!0),Ze("click",window,n,!0),o()})):i(),gr(t)}function hn(e,t){return qe(e,r=>{r!==void 0&&(t.value=r)}),L(()=>e.value===void 0?t.value:e.value)}function xi(){const e=W(!1);return Ot(()=>{e.value=!0}),gr(e)}function di(e,t){return L(()=>{for(const r of t)if(e[r]!==void 0)return e[r];return e[t[t.length-1]]})}const cy=(typeof window=="undefined"?!1:/iPad|iPhone|iPod/.test(navigator.platform)||navigator.platform==="MacIntel"&&navigator.maxTouchPoints>1)&&!window.MSStream;function dy(){return cy}function uy(e={},t){const r=ar({ctrl:!1,command:!1,win:!1,shift:!1,tab:!1}),{keydown:o,keyup:n}=e,i=s=>{switch(s.key){case"Control":r.ctrl=!0;break;case"Meta":r.command=!0,r.win=!0;break;case"Shift":r.shift=!0;break;case"Tab":r.tab=!0;break}o!==void 0&&Object.keys(o).forEach(d=>{if(d!==s.key)return;const c=o[d];if(typeof c=="function")c(s);else{const{stop:u=!1,prevent:f=!1}=c;u&&s.stopPropagation(),f&&s.preventDefault(),c.handler(s)}})},a=s=>{switch(s.key){case"Control":r.ctrl=!1;break;case"Meta":r.command=!1,r.win=!1;break;case"Shift":r.shift=!1;break;case"Tab":r.tab=!1;break}n!==void 0&&Object.keys(n).forEach(d=>{if(d!==s.key)return;const c=n[d];if(typeof c=="function")c(s);else{const{stop:u=!1,prevent:f=!1}=c;u&&s.stopPropagation(),f&&s.preventDefault(),c.handler(s)}})},l=()=>{(t===void 0||t.value)&&(nt("keydown",document,i),nt("keyup",document,a)),t!==void 0&&qe(t,s=>{s?(nt("keydown",document,i),nt("keyup",document,a)):(Ze("keydown",document,i),Ze("keyup",document,a))})};return uc()?(Yr(l),It(()=>{(t===void 0||t.value)&&(Ze("keydown",document,i),Ze("keyup",document,a))})):l(),gr(r)}const hc="n-modal-body",Cp="n-modal",pc="n-drawer-body",mc="n-popover-body",cO="n-internal-select-menu",fy="n-internal-select-menu-body",yp="__disabled__";function pn(e){const t=be(hc,null),r=be(pc,null),o=be(mc,null),n=be(fy,null);return ht(()=>{var i;const{to:a}=e;return a!==void 0?a===!1?yp:a===!0?"body":a:t!=null&&t.value?(i=t.value.$el)!==null&&i!==void 0?i:t.value:r!=null&&r.value?r.value:o!=null&&o.value?o.value:n!=null&&n.value?n.value:a!=null?a:"body"})}pn.tdkey=yp;pn.propTo={type:[String,Object,Boolean],default:void 0};function hy(e,t,r){var o;const n=be(e,null);if(n===null)return;const i=(o=Zr())===null||o===void 0?void 0:o.proxy;qe(r,a),a(r.value),It(()=>{a(void 0,r.value)});function a(d,c){const u=n[t];c!==void 0&&l(u,c),d!==void 0&&s(u,d)}function l(d,c){d[c]||(d[c]=[]),d[c].splice(d[c].findIndex(u=>u===i),1)}function s(d,c){d[c]||(d[c]=[]),~d[c].findIndex(u=>u===i)||d[c].push(i)}}function py(e,t,r){if(!t)return e;const o=W(e.value);let n=null;return qe(e,i=>{n!==null&&window.clearTimeout(n),i===!0?r&&!r.value?o.value=!0:n=window.setTimeout(()=>{o.value=!0},t):o.value=!1}),o}const ss="n-form-item";function wp(e,{defaultSize:t="medium",mergedSize:r,mergedDisabled:o}={}){const n=be(ss,null);je(ss,null);const i=L(r?()=>r(n):()=>{const{size:s}=e;if(s)return s;if(n){const{mergedSize:d}=n;if(d.value!==void 0)return d.value}return t}),a=L(o?()=>o(n):()=>{const{disabled:s}=e;return s!==void 0?s:n?n.disabled.value:!1}),l=L(()=>{const{status:s}=e;return s||(n==null?void 0:n.mergedValidationStatus.value)});return It(()=>{n&&n.restoreValidation()}),{mergedSizeRef:i,mergedDisabledRef:a,mergedStatusRef:l,nTriggerFormBlur(){n&&n.handleContentBlur()},nTriggerFormChange(){n&&n.handleContentChange()},nTriggerFormFocus(){n&&n.handleContentFocus()},nTriggerFormInput(){n&&n.handleContentInput()}}}var my=typeof global=="object"&&global&&global.Object===Object&&global,Sp=my,vy=typeof self=="object"&&self&&self.Object===Object&&self,gy=Sp||vy||Function("return this")(),dr=gy,by=dr.Symbol,Ur=by,_p=Object.prototype,xy=_p.hasOwnProperty,Cy=_p.toString,An=Ur?Ur.toStringTag:void 0;function yy(e){var t=xy.call(e,An),r=e[An];try{e[An]=void 0;var o=!0}catch{}var n=Cy.call(e);return o&&(t?e[An]=r:delete e[An]),n}var wy=Object.prototype,Sy=wy.toString;function _y(e){return Sy.call(e)}var $y="[object Null]",Py="[object Undefined]",uu=Ur?Ur.toStringTag:void 0;function To(e){return e==null?e===void 0?Py:$y:uu&&uu in Object(e)?yy(e):_y(e)}function qr(e){return e!=null&&typeof e=="object"}var ky="[object Symbol]";function Ha(e){return typeof e=="symbol"||qr(e)&&To(e)==ky}function $p(e,t){for(var r=-1,o=e==null?0:e.length,n=Array(o);++r0){if(++t>=aw)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}function dw(e){return function(){return e}}var uw=function(){try{var e=Ro(Object,"defineProperty");return e({},"",{}),e}catch{}}(),fa=uw,fw=fa?function(e,t){return fa(e,"toString",{configurable:!0,enumerable:!1,value:dw(t),writable:!0})}:vc,hw=fw,pw=cw(hw),mw=pw,vw=9007199254740991,gw=/^(?:0|[1-9]\d*)$/;function bc(e,t){var r=typeof e;return t=t==null?vw:t,!!t&&(r=="number"||r!="symbol"&&gw.test(e))&&e>-1&&e%1==0&&e-1&&e%1==0&&e<=_w}function _n(e){return e!=null&&Cc(e.length)&&!gc(e)}function $w(e,t,r){if(!rr(r))return!1;var o=typeof t;return(o=="number"?_n(r)&&bc(t,r.length):o=="string"&&t in r)?Ci(r[t],e):!1}function Pw(e){return Sw(function(t,r){var o=-1,n=r.length,i=n>1?r[n-1]:void 0,a=n>2?r[2]:void 0;for(i=e.length>3&&typeof i=="function"?(n--,i):void 0,a&&$w(r[0],r[1],a)&&(i=n<3?void 0:i,n=1),t=Object(t);++o-1}function WS(e,t){var r=this.__data__,o=ja(r,e);return o<0?(++this.size,r.push([e,t])):r[o][1]=t,this}function Rr(e){var t=-1,r=e==null?0:e.length;for(this.clear();++tn?0:n+t),r=r>n?n:r,r<0&&(r+=n),n=t>r?0:r-t>>>0,t>>>=0;for(var i=Array(n);++o=o?e:h2(e,t,r)}var m2="\\ud800-\\udfff",v2="\\u0300-\\u036f",g2="\\ufe20-\\ufe2f",b2="\\u20d0-\\u20ff",x2=v2+g2+b2,C2="\\ufe0e\\ufe0f",y2="\\u200d",w2=RegExp("["+y2+m2+x2+C2+"]");function Dp(e){return w2.test(e)}function S2(e){return e.split("")}var Fp="\\ud800-\\udfff",_2="\\u0300-\\u036f",$2="\\ufe20-\\ufe2f",P2="\\u20d0-\\u20ff",k2=_2+$2+P2,T2="\\ufe0e\\ufe0f",E2="["+Fp+"]",ds="["+k2+"]",us="\\ud83c[\\udffb-\\udfff]",R2="(?:"+ds+"|"+us+")",Hp="[^"+Fp+"]",jp="(?:\\ud83c[\\udde6-\\uddff]){2}",Np="[\\ud800-\\udbff][\\udc00-\\udfff]",z2="\\u200d",Wp=R2+"?",Vp="["+T2+"]?",A2="(?:"+z2+"(?:"+[Hp,jp,Np].join("|")+")"+Vp+Wp+")*",O2=Vp+Wp+A2,I2="(?:"+[Hp+ds+"?",ds,jp,Np,E2].join("|")+")",M2=RegExp(us+"(?="+us+")|"+I2+O2,"g");function B2(e){return e.match(M2)||[]}function L2(e){return Dp(e)?B2(e):S2(e)}function D2(e){return function(t){t=Op(t);var r=Dp(t)?L2(t):void 0,o=r?r[0]:t.charAt(0),n=r?p2(r,1).join(""):t.slice(1);return o[e]()+n}}var F2=D2("toUpperCase"),H2=F2;function j2(){this.__data__=new Rr,this.size=0}function N2(e){var t=this.__data__,r=t.delete(e);return this.size=t.size,r}function W2(e){return this.__data__.get(e)}function V2(e){return this.__data__.has(e)}var K2=200;function U2(e,t){var r=this.__data__;if(r instanceof Rr){var o=r.__data__;if(!fi||o.lengthl))return!1;var d=i.get(e),c=i.get(t);if(d&&c)return d==t&&c==e;var u=-1,f=!0,h=r&y_?new va:void 0;for(i.set(e,t),i.set(t,e);++u=t||y<0||u&&_>=i}function v(){var E=Cl();if(g(E))return w(E);l=setTimeout(v,b(E))}function w(E){return l=void 0,f&&o?h(E):(o=n=void 0,a)}function $(){l!==void 0&&clearTimeout(l),d=0,o=s=n=l=void 0}function x(){return l===void 0?a:w(Cl())}function S(){var E=Cl(),y=g(E);if(o=arguments,n=this,s=E,y){if(l===void 0)return p(s);if(u)return clearTimeout(l),l=setTimeout(v,t),h(s)}return l===void 0&&(l=setTimeout(v,t)),a}return S.cancel=$,S.flush=x,S}function ms(e,t,r){(r!==void 0&&!Ci(e[t],r)||r===void 0&&!(t in e))&&xc(e,t,r)}function g5(e){return qr(e)&&_n(e)}function vs(e,t){if(!(t==="constructor"&&typeof e[t]=="function")&&t!="__proto__")return e[t]}function b5(e){return yw(e,Ap(e))}function x5(e,t,r,o,n,i,a){var l=vs(e,r),s=vs(t,r),d=a.get(s);if(d){ms(e,r,d);return}var c=i?i(l,s,r+"",e,t,a):void 0,u=c===void 0;if(u){var f=tr(s),h=!f&&pa(s),p=!f&&!h&&wc(s);c=s,f||h||p?tr(l)?c=l:g5(l)?c=iw(l):h?(u=!1,c=G2(s,!0)):p?(u=!1,c=h_(s,!0)):c=[]:f2(s)||ha(s)?(c=l,ha(l)?c=b5(l):(!rr(l)||gc(l))&&(c=p_(s))):u=!1}u&&(a.set(s,c),n(c,s,o,i,a),a.delete(s)),ms(e,r,c)}function Xp(e,t,r,o,n){e!==t&&Yp(t,function(i,a){if(n||(n=new mr),rr(i))x5(e,t,a,r,Xp,o,n);else{var l=o?o(vs(e,a),i,a+"",e,t,n):void 0;l===void 0&&(l=i),ms(e,a,l)}},Ap)}function C5(e,t){var r=-1,o=_n(e)?Array(e.length):[];return u5(e,function(n,i,a){o[++r]=t(n,i,a)}),o}function y5(e,t){var r=tr(e)?$p:C5;return r(e,i5(t))}var w5=Pw(function(e,t,r){Xp(e,t,r)}),Xo=w5,S5="Expected a function";function yl(e,t,r){var o=!0,n=!0;if(typeof e!="function")throw new TypeError(S5);return rr(r)&&(o="leading"in r?!!r.leading:o,n="trailing"in r?!!r.trailing:n),v5(e,t,{leading:o,maxWait:t,trailing:n})}const Zp=Symbol("@css-render/vue3-ssr");function _5(e,t){return``}function $5(e,t){const r=be(Zp,null);if(r===null){console.error("[css-render/vue3-ssr]: no ssr context found.");return}const{styles:o,ids:n}=r;n.has(e)||o!==null&&(n.add(e),o.push(_5(e,t)))}function $n(){const e=be(Zp,null);if(e!==null)return{adapter:$5,context:e}}var yr={fontFamily:'v-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',fontFamilyMono:"v-mono, SFMono-Regular, Menlo, Consolas, Courier, monospace",fontWeight:"400",fontWeightStrong:"500",cubicBezierEaseInOut:"cubic-bezier(.4, 0, .2, 1)",cubicBezierEaseOut:"cubic-bezier(0, 0, .2, 1)",cubicBezierEaseIn:"cubic-bezier(.4, 0, 1, 1)",borderRadius:"3px",borderRadiusSmall:"2px",fontSize:"14px",fontSizeTiny:"12px",fontSizeSmall:"14px",fontSizeMedium:"14px",fontSizeLarge:"15px",fontSizeHuge:"16px",lineHeight:"1.6",heightTiny:"22px",heightSmall:"28px",heightMedium:"34px",heightLarge:"40px",heightHuge:"46px"};const{fontSize:P5,fontFamily:k5,lineHeight:T5}=yr;var Jp=z("body",` - margin: 0; - font-size: ${P5}; - font-family: ${k5}; - line-height: ${T5}; - -webkit-text-size-adjust: 100%; - -webkit-tap-highlight-color: transparent; -`,[z("input",` - font-family: inherit; - font-size: inherit; - `)]);const Gr="n-config-provider",hi="naive-ui-style";function dO(e){return e}function ze(e,t,r,o,n,i){const a=$n();if(r){const d=()=>{const c=i==null?void 0:i.value;r.mount({id:c===void 0?t:c+t,head:!0,props:{bPrefix:c?`.${c}-`:void 0},anchorMetaName:hi,ssr:a}),Jp.mount({id:"n-global",head:!0,anchorMetaName:hi,ssr:a})};a?d():Yr(d)}const l=be(Gr,null);return L(()=>{var d;const{theme:{common:c,self:u,peers:f={}}={},themeOverrides:h={},builtinThemeOverrides:p={}}=n,{common:b,peers:g}=h,{common:v=void 0,[e]:{common:w=void 0,self:$=void 0,peers:x={}}={}}=(l==null?void 0:l.mergedThemeRef.value)||{},{common:S=void 0,[e]:E={}}=(l==null?void 0:l.mergedThemeOverridesRef.value)||{},{common:y,peers:_={}}=E,R=Xo({},c||w||v||o.common,S,y,b),P=Xo((d=u||$||o.self)===null||d===void 0?void 0:d(R),p,E,h);return{common:R,self:P,peers:Xo({},o.peers,x,f),peerOverrides:Xo({},_,g)}})}ze.props={theme:Object,themeOverrides:Object,builtinThemeOverrides:Object};const Qp="n";function lt(e={},t={defaultBordered:!0}){const r=be(Gr,null);return{inlineThemeDisabled:r==null?void 0:r.inlineThemeDisabled,mergedRtlRef:r==null?void 0:r.mergedRtlRef,mergedComponentPropsRef:r==null?void 0:r.mergedComponentPropsRef,mergedBreakpointsRef:r==null?void 0:r.mergedBreakpointsRef,mergedBorderedRef:L(()=>{var o,n;const{bordered:i}=e;return i!==void 0?i:(n=(o=r==null?void 0:r.mergedBorderedRef.value)!==null&&o!==void 0?o:t.defaultBordered)!==null&&n!==void 0?n:!0}),mergedClsPrefixRef:L(()=>(r==null?void 0:r.mergedClsPrefixRef.value)||Qp),namespaceRef:L(()=>r==null?void 0:r.mergedNamespaceRef.value)}}const E5={name:"en-US",global:{undo:"Undo",redo:"Redo",confirm:"Confirm"},Popconfirm:{positiveText:"Confirm",negativeText:"Cancel"},Cascader:{placeholder:"Please Select",loading:"Loading",loadingRequiredMessage:e=>`Please load all ${e}'s descendants before checking it.`},Time:{dateFormat:"yyyy-MM-dd",dateTimeFormat:"yyyy-MM-dd HH:mm:ss"},DatePicker:{yearFormat:"yyyy",monthFormat:"MMM",dayFormat:"eeeeee",yearTypeFormat:"yyyy",monthTypeFormat:"yyyy-MM",dateFormat:"yyyy-MM-dd",dateTimeFormat:"yyyy-MM-dd HH:mm:ss",quarterFormat:"yyyy-qqq",clear:"Clear",now:"Now",confirm:"Confirm",selectTime:"Select Time",selectDate:"Select Date",datePlaceholder:"Select Date",datetimePlaceholder:"Select Date and Time",monthPlaceholder:"Select Month",yearPlaceholder:"Select Year",quarterPlaceholder:"Select Quarter",startDatePlaceholder:"Start Date",endDatePlaceholder:"End Date",startDatetimePlaceholder:"Start Date and Time",endDatetimePlaceholder:"End Date and Time",monthBeforeYear:!0,firstDayOfWeek:6,today:"Today"},DataTable:{checkTableAll:"Select all in the table",uncheckTableAll:"Unselect all in the table",confirm:"Confirm",clear:"Clear"},Transfer:{sourceTitle:"Source",targetTitle:"Target"},Empty:{description:"No Data"},Select:{placeholder:"Please Select"},TimePicker:{placeholder:"Select Time",positiveText:"OK",negativeText:"Cancel",now:"Now"},Pagination:{goto:"Goto",selectionSuffix:"page"},DynamicTags:{add:"Add"},Log:{loading:"Loading"},Input:{placeholder:"Please Input"},InputNumber:{placeholder:"Please Input"},DynamicInput:{create:"Create"},ThemeEditor:{title:"Theme Editor",clearAllVars:"Clear All Variables",clearSearch:"Clear Search",filterCompName:"Filter Component Name",filterVarName:"Filter Variable Name",import:"Import",export:"Export",restore:"Reset to Default"},Image:{tipPrevious:"Previous picture (\u2190)",tipNext:"Next picture (\u2192)",tipCounterclockwise:"Counterclockwise",tipClockwise:"Clockwise",tipZoomOut:"Zoom out",tipZoomIn:"Zoom in",tipClose:"Close (Esc)"}};var R5=E5;function wl(e){return function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},r=t.width?String(t.width):e.defaultWidth,o=e.formats[r]||e.formats[e.defaultWidth];return o}}function On(e){return function(t,r){var o=r||{},n=o.context?String(o.context):"standalone",i;if(n==="formatting"&&e.formattingValues){var a=e.defaultFormattingWidth||e.defaultWidth,l=o.width?String(o.width):a;i=e.formattingValues[l]||e.formattingValues[a]}else{var s=e.defaultWidth,d=o.width?String(o.width):e.defaultWidth;i=e.values[d]||e.values[s]}var c=e.argumentCallback?e.argumentCallback(t):t;return i[c]}}function z5(e){return function(t){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},o=t.match(e.matchPattern);if(!o)return null;var n=o[0],i=t.match(e.parsePattern);if(!i)return null;var a=e.valueCallback?e.valueCallback(i[0]):i[0];a=r.valueCallback?r.valueCallback(a):a;var l=t.slice(n.length);return{value:a,rest:l}}}function In(e){return function(t){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},o=r.width,n=o&&e.matchPatterns[o]||e.matchPatterns[e.defaultMatchWidth],i=t.match(n);if(!i)return null;var a=i[0],l=o&&e.parsePatterns[o]||e.parsePatterns[e.defaultParseWidth],s=Array.isArray(l)?O5(l,function(u){return u.test(a)}):A5(l,function(u){return u.test(a)}),d;d=e.valueCallback?e.valueCallback(s):s,d=r.valueCallback?r.valueCallback(d):d;var c=t.slice(a.length);return{value:d,rest:c}}}function A5(e,t){for(var r in e)if(e.hasOwnProperty(r)&&t(e[r]))return r}function O5(e,t){for(var r=0;r0?"in "+o:o+" ago":o},B5=M5,L5={full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},D5={full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},F5={full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},H5={date:wl({formats:L5,defaultWidth:"full"}),time:wl({formats:D5,defaultWidth:"full"}),dateTime:wl({formats:F5,defaultWidth:"full"})},j5=H5,N5={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"},W5=function(e,t,r,o){return N5[e]},V5=W5,K5={narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},U5={narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},q5={narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},G5={narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},Y5={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},X5={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},Z5=function(e,t){var r=Number(e),o=r%100;if(o>20||o<10)switch(o%10){case 1:return r+"st";case 2:return r+"nd";case 3:return r+"rd"}return r+"th"},J5={ordinalNumber:Z5,era:On({values:K5,defaultWidth:"wide"}),quarter:On({values:U5,defaultWidth:"wide",argumentCallback:function(e){return e-1}}),month:On({values:q5,defaultWidth:"wide"}),day:On({values:G5,defaultWidth:"wide"}),dayPeriod:On({values:Y5,defaultWidth:"wide",formattingValues:X5,defaultFormattingWidth:"wide"})},Q5=J5,e$=/^(\d+)(th|st|nd|rd)?/i,t$=/\d+/i,r$={narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},o$={any:[/^b/i,/^(a|c)/i]},n$={narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},i$={any:[/1/i,/2/i,/3/i,/4/i]},a$={narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},l$={narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},s$={narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},c$={narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},d$={narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},u$={any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},f$={ordinalNumber:z5({matchPattern:e$,parsePattern:t$,valueCallback:function(e){return parseInt(e,10)}}),era:In({matchPatterns:r$,defaultMatchWidth:"wide",parsePatterns:o$,defaultParseWidth:"any"}),quarter:In({matchPatterns:n$,defaultMatchWidth:"wide",parsePatterns:i$,defaultParseWidth:"any",valueCallback:function(e){return e+1}}),month:In({matchPatterns:a$,defaultMatchWidth:"wide",parsePatterns:l$,defaultParseWidth:"any"}),day:In({matchPatterns:s$,defaultMatchWidth:"wide",parsePatterns:c$,defaultParseWidth:"any"}),dayPeriod:In({matchPatterns:d$,defaultMatchWidth:"any",parsePatterns:u$,defaultParseWidth:"any"})},h$=f$,p$={code:"en-US",formatDistance:B5,formatLong:j5,formatRelative:V5,localize:Q5,match:h$,options:{weekStartsOn:0,firstWeekContainsDate:1}},m$=p$;const v$={name:"en-US",locale:m$};var g$=v$;function em(e){const{mergedLocaleRef:t,mergedDateLocaleRef:r}=be(Gr,null)||{},o=L(()=>{var i,a;return(a=(i=t==null?void 0:t.value)===null||i===void 0?void 0:i[e])!==null&&a!==void 0?a:R5[e]});return{dateLocaleRef:L(()=>{var i;return(i=r==null?void 0:r.value)!==null&&i!==void 0?i:g$}),localeRef:o}}function Jr(e,t,r){if(!t)return;const o=$n(),n=()=>{const i=r==null?void 0:r.value;t.mount({id:i===void 0?e:i+e,head:!0,anchorMetaName:hi,props:{bPrefix:i?`.${i}-`:void 0},ssr:o}),Jp.mount({id:"n-global",head:!0,anchorMetaName:hi,ssr:o})};o?n():Yr(n)}function _t(e,t,r,o){var n;r||Da("useThemeClass","cssVarsRef is not passed");const i=(n=be(Gr,null))===null||n===void 0?void 0:n.mergedThemeHashRef,a=W(""),l=$n();let s;const d=`__${e}`,c=()=>{let u=d;const f=t?t.value:void 0,h=i==null?void 0:i.value;h&&(u+="-"+h),f&&(u+="-"+f);const{themeOverrides:p,builtinThemeOverrides:b}=o;p&&(u+="-"+ci(JSON.stringify(p))),b&&(u+="-"+ci(JSON.stringify(b))),a.value=u,s=()=>{const g=r.value;let v="";for(const w in g)v+=`${w}: ${g[w]};`;z(`.${u}`,v).mount({id:u,ssr:l}),s=void 0}};return xr(()=>{c()}),{themeClass:a,onRender:()=>{s==null||s()}}}var b$=oe({name:"Add",render(){return m("svg",{width:"512",height:"512",viewBox:"0 0 512 512",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M256 112V400M400 256H112",stroke:"currentColor","stroke-width":"32","stroke-linecap":"round","stroke-linejoin":"round"}))}});function wr(e,t){return oe({name:H2(e),setup(){var r;const o=(r=be(Gr,null))===null||r===void 0?void 0:r.mergedIconsRef;return()=>{var n;const i=(n=o==null?void 0:o.value)===null||n===void 0?void 0:n[e];return i?i():t}}})}var x$=oe({name:"ChevronRight",render(){return m("svg",{viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z",fill:"currentColor"}))}}),C$=wr("close",m("svg",{viewBox:"0 0 12 12",version:"1.1",xmlns:"http://www.w3.org/2000/svg","aria-hidden":!0},m("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},m("g",{fill:"currentColor","fill-rule":"nonzero"},m("path",{d:"M2.08859116,2.2156945 L2.14644661,2.14644661 C2.32001296,1.97288026 2.58943736,1.95359511 2.7843055,2.08859116 L2.85355339,2.14644661 L6,5.293 L9.14644661,2.14644661 C9.34170876,1.95118446 9.65829124,1.95118446 9.85355339,2.14644661 C10.0488155,2.34170876 10.0488155,2.65829124 9.85355339,2.85355339 L6.707,6 L9.85355339,9.14644661 C10.0271197,9.32001296 10.0464049,9.58943736 9.91140884,9.7843055 L9.85355339,9.85355339 C9.67998704,10.0271197 9.41056264,10.0464049 9.2156945,9.91140884 L9.14644661,9.85355339 L6,6.707 L2.85355339,9.85355339 C2.65829124,10.0488155 2.34170876,10.0488155 2.14644661,9.85355339 C1.95118446,9.65829124 1.95118446,9.34170876 2.14644661,9.14644661 L5.293,6 L2.14644661,2.85355339 C1.97288026,2.67998704 1.95359511,2.41056264 2.08859116,2.2156945 L2.14644661,2.14644661 L2.08859116,2.2156945 Z"}))))),y$=oe({name:"Eye",render(){return m("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},m("path",{d:"M255.66 112c-77.94 0-157.89 45.11-220.83 135.33a16 16 0 0 0-.27 17.77C82.92 340.8 161.8 400 255.66 400c92.84 0 173.34-59.38 221.79-135.25a16.14 16.14 0 0 0 0-17.47C428.89 172.28 347.8 112 255.66 112z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"}),m("circle",{cx:"256",cy:"256",r:"80",fill:"none",stroke:"currentColor","stroke-miterlimit":"10","stroke-width":"32"}))}}),w$=oe({name:"EyeOff",render(){return m("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512"},m("path",{d:"M432 448a15.92 15.92 0 0 1-11.31-4.69l-352-352a16 16 0 0 1 22.62-22.62l352 352A16 16 0 0 1 432 448z",fill:"currentColor"}),m("path",{d:"M255.66 384c-41.49 0-81.5-12.28-118.92-36.5c-34.07-22-64.74-53.51-88.7-91v-.08c19.94-28.57 41.78-52.73 65.24-72.21a2 2 0 0 0 .14-2.94L93.5 161.38a2 2 0 0 0-2.71-.12c-24.92 21-48.05 46.76-69.08 76.92a31.92 31.92 0 0 0-.64 35.54c26.41 41.33 60.4 76.14 98.28 100.65C162 402 207.9 416 255.66 416a239.13 239.13 0 0 0 75.8-12.58a2 2 0 0 0 .77-3.31l-21.58-21.58a4 4 0 0 0-3.83-1a204.8 204.8 0 0 1-51.16 6.47z",fill:"currentColor"}),m("path",{d:"M490.84 238.6c-26.46-40.92-60.79-75.68-99.27-100.53C349 110.55 302 96 255.66 96a227.34 227.34 0 0 0-74.89 12.83a2 2 0 0 0-.75 3.31l21.55 21.55a4 4 0 0 0 3.88 1a192.82 192.82 0 0 1 50.21-6.69c40.69 0 80.58 12.43 118.55 37c34.71 22.4 65.74 53.88 89.76 91a.13.13 0 0 1 0 .16a310.72 310.72 0 0 1-64.12 72.73a2 2 0 0 0-.15 2.95l19.9 19.89a2 2 0 0 0 2.7.13a343.49 343.49 0 0 0 68.64-78.48a32.2 32.2 0 0 0-.1-34.78z",fill:"currentColor"}),m("path",{d:"M256 160a95.88 95.88 0 0 0-21.37 2.4a2 2 0 0 0-1 3.38l112.59 112.56a2 2 0 0 0 3.38-1A96 96 0 0 0 256 160z",fill:"currentColor"}),m("path",{d:"M165.78 233.66a2 2 0 0 0-3.38 1a96 96 0 0 0 115 115a2 2 0 0 0 1-3.38z",fill:"currentColor"}))}}),tm=wr("error",m("svg",{viewBox:"0 0 48 48",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},m("g",{stroke:"none","stroke-width":"1","fill-rule":"evenodd"},m("g",{"fill-rule":"nonzero"},m("path",{d:"M24,4 C35.045695,4 44,12.954305 44,24 C44,35.045695 35.045695,44 24,44 C12.954305,44 4,35.045695 4,24 C4,12.954305 12.954305,4 24,4 Z M17.8838835,16.1161165 L17.7823881,16.0249942 C17.3266086,15.6583353 16.6733914,15.6583353 16.2176119,16.0249942 L16.1161165,16.1161165 L16.0249942,16.2176119 C15.6583353,16.6733914 15.6583353,17.3266086 16.0249942,17.7823881 L16.1161165,17.8838835 L22.233,24 L16.1161165,30.1161165 L16.0249942,30.2176119 C15.6583353,30.6733914 15.6583353,31.3266086 16.0249942,31.7823881 L16.1161165,31.8838835 L16.2176119,31.9750058 C16.6733914,32.3416647 17.3266086,32.3416647 17.7823881,31.9750058 L17.8838835,31.8838835 L24,25.767 L30.1161165,31.8838835 L30.2176119,31.9750058 C30.6733914,32.3416647 31.3266086,32.3416647 31.7823881,31.9750058 L31.8838835,31.8838835 L31.9750058,31.7823881 C32.3416647,31.3266086 32.3416647,30.6733914 31.9750058,30.2176119 L31.8838835,30.1161165 L25.767,24 L31.8838835,17.8838835 L31.9750058,17.7823881 C32.3416647,17.3266086 32.3416647,16.6733914 31.9750058,16.2176119 L31.8838835,16.1161165 L31.7823881,16.0249942 C31.3266086,15.6583353 30.6733914,15.6583353 30.2176119,16.0249942 L30.1161165,16.1161165 L24,22.233 L17.8838835,16.1161165 L17.7823881,16.0249942 L17.8838835,16.1161165 Z"}))))),rm=wr("info",m("svg",{viewBox:"0 0 28 28",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},m("g",{stroke:"none","stroke-width":"1","fill-rule":"evenodd"},m("g",{"fill-rule":"nonzero"},m("path",{d:"M14,2 C20.6274,2 26,7.37258 26,14 C26,20.6274 20.6274,26 14,26 C7.37258,26 2,20.6274 2,14 C2,7.37258 7.37258,2 14,2 Z M14,11 C13.4477,11 13,11.4477 13,12 L13,12 L13,20 C13,20.5523 13.4477,21 14,21 C14.5523,21 15,20.5523 15,20 L15,20 L15,12 C15,11.4477 14.5523,11 14,11 Z M14,6.75 C13.3096,6.75 12.75,7.30964 12.75,8 C12.75,8.69036 13.3096,9.25 14,9.25 C14.6904,9.25 15.25,8.69036 15.25,8 C15.25,7.30964 14.6904,6.75 14,6.75 Z"}))))),om=wr("success",m("svg",{viewBox:"0 0 48 48",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},m("g",{stroke:"none","stroke-width":"1","fill-rule":"evenodd"},m("g",{"fill-rule":"nonzero"},m("path",{d:"M24,4 C35.045695,4 44,12.954305 44,24 C44,35.045695 35.045695,44 24,44 C12.954305,44 4,35.045695 4,24 C4,12.954305 12.954305,4 24,4 Z M32.6338835,17.6161165 C32.1782718,17.1605048 31.4584514,17.1301307 30.9676119,17.5249942 L30.8661165,17.6161165 L20.75,27.732233 L17.1338835,24.1161165 C16.6457281,23.6279612 15.8542719,23.6279612 15.3661165,24.1161165 C14.9105048,24.5717282 14.8801307,25.2915486 15.2749942,25.7823881 L15.3661165,25.8838835 L19.8661165,30.3838835 C20.3217282,30.8394952 21.0415486,30.8698693 21.5323881,30.4750058 L21.6338835,30.3838835 L32.6338835,19.3838835 C33.1220388,18.8957281 33.1220388,18.1042719 32.6338835,17.6161165 Z"}))))),nm=wr("warning",m("svg",{viewBox:"0 0 24 24",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},m("g",{stroke:"none","stroke-width":"1","fill-rule":"evenodd"},m("g",{"fill-rule":"nonzero"},m("path",{d:"M12,2 C17.523,2 22,6.478 22,12 C22,17.522 17.523,22 12,22 C6.477,22 2,17.522 2,12 C2,6.478 6.477,2 12,2 Z M12.0018002,15.0037242 C11.450254,15.0037242 11.0031376,15.4508407 11.0031376,16.0023869 C11.0031376,16.553933 11.450254,17.0010495 12.0018002,17.0010495 C12.5533463,17.0010495 13.0004628,16.553933 13.0004628,16.0023869 C13.0004628,15.4508407 12.5533463,15.0037242 12.0018002,15.0037242 Z M11.99964,7 C11.4868042,7.00018474 11.0642719,7.38637706 11.0066858,7.8837365 L11,8.00036004 L11.0018003,13.0012393 L11.00857,13.117858 C11.0665141,13.6151758 11.4893244,14.0010638 12.0021602,14.0008793 C12.514996,14.0006946 12.9375283,13.6145023 12.9951144,13.1171428 L13.0018002,13.0005193 L13,7.99964009 L12.9932303,7.8830214 C12.9352861,7.38570354 12.5124758,6.99981552 11.99964,7 Z"}))))),S$=oe({name:"ChevronDown",render(){return m("svg",{viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M3.14645 5.64645C3.34171 5.45118 3.65829 5.45118 3.85355 5.64645L8 9.79289L12.1464 5.64645C12.3417 5.45118 12.6583 5.45118 12.8536 5.64645C13.0488 5.84171 13.0488 6.15829 12.8536 6.35355L8.35355 10.8536C8.15829 11.0488 7.84171 11.0488 7.64645 10.8536L3.14645 6.35355C2.95118 6.15829 2.95118 5.84171 3.14645 5.64645Z",fill:"currentColor"}))}}),_$=wr("clear",m("svg",{viewBox:"0 0 16 16",version:"1.1",xmlns:"http://www.w3.org/2000/svg"},m("g",{stroke:"none","stroke-width":"1",fill:"none","fill-rule":"evenodd"},m("g",{fill:"currentColor","fill-rule":"nonzero"},m("path",{d:"M8,2 C11.3137085,2 14,4.6862915 14,8 C14,11.3137085 11.3137085,14 8,14 C4.6862915,14 2,11.3137085 2,8 C2,4.6862915 4.6862915,2 8,2 Z M6.5343055,5.83859116 C6.33943736,5.70359511 6.07001296,5.72288026 5.89644661,5.89644661 L5.89644661,5.89644661 L5.83859116,5.9656945 C5.70359511,6.16056264 5.72288026,6.42998704 5.89644661,6.60355339 L5.89644661,6.60355339 L7.293,8 L5.89644661,9.39644661 L5.83859116,9.4656945 C5.70359511,9.66056264 5.72288026,9.92998704 5.89644661,10.1035534 L5.89644661,10.1035534 L5.9656945,10.1614088 C6.16056264,10.2964049 6.42998704,10.2771197 6.60355339,10.1035534 L6.60355339,10.1035534 L8,8.707 L9.39644661,10.1035534 L9.4656945,10.1614088 C9.66056264,10.2964049 9.92998704,10.2771197 10.1035534,10.1035534 L10.1035534,10.1035534 L10.1614088,10.0343055 C10.2964049,9.83943736 10.2771197,9.57001296 10.1035534,9.39644661 L10.1035534,9.39644661 L8.707,8 L10.1035534,6.60355339 L10.1614088,6.5343055 C10.2964049,6.33943736 10.2771197,6.07001296 10.1035534,5.89644661 L10.1035534,5.89644661 L10.0343055,5.83859116 C9.83943736,5.70359511 9.57001296,5.72288026 9.39644661,5.89644661 L9.39644661,5.89644661 L8,7.293 L6.60355339,5.89644661 Z"}))))),$$=oe({name:"ChevronDownFilled",render(){return m("svg",{viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M3.20041 5.73966C3.48226 5.43613 3.95681 5.41856 4.26034 5.70041L8 9.22652L11.7397 5.70041C12.0432 5.41856 12.5177 5.43613 12.7996 5.73966C13.0815 6.0432 13.0639 6.51775 12.7603 6.7996L8.51034 10.7996C8.22258 11.0668 7.77743 11.0668 7.48967 10.7996L3.23966 6.7996C2.93613 6.51775 2.91856 6.0432 3.20041 5.73966Z",fill:"currentColor"}))}}),P$=wr("rotateClockwise",m("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10C17 12.7916 15.3658 15.2026 13 16.3265V14.5C13 14.2239 12.7761 14 12.5 14C12.2239 14 12 14.2239 12 14.5V17.5C12 17.7761 12.2239 18 12.5 18H15.5C15.7761 18 16 17.7761 16 17.5C16 17.2239 15.7761 17 15.5 17H13.8758C16.3346 15.6357 18 13.0128 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 10.2761 2.22386 10.5 2.5 10.5C2.77614 10.5 3 10.2761 3 10Z",fill:"currentColor"}),m("path",{d:"M10 12C11.1046 12 12 11.1046 12 10C12 8.89543 11.1046 8 10 8C8.89543 8 8 8.89543 8 10C8 11.1046 8.89543 12 10 12ZM10 11C9.44772 11 9 10.5523 9 10C9 9.44772 9.44772 9 10 9C10.5523 9 11 9.44772 11 10C11 10.5523 10.5523 11 10 11Z",fill:"currentColor"}))),k$=wr("rotateClockwise",m("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M17 10C17 6.13401 13.866 3 10 3C6.13401 3 3 6.13401 3 10C3 12.7916 4.63419 15.2026 7 16.3265V14.5C7 14.2239 7.22386 14 7.5 14C7.77614 14 8 14.2239 8 14.5V17.5C8 17.7761 7.77614 18 7.5 18H4.5C4.22386 18 4 17.7761 4 17.5C4 17.2239 4.22386 17 4.5 17H6.12422C3.66539 15.6357 2 13.0128 2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10C18 10.2761 17.7761 10.5 17.5 10.5C17.2239 10.5 17 10.2761 17 10Z",fill:"currentColor"}),m("path",{d:"M10 12C8.89543 12 8 11.1046 8 10C8 8.89543 8.89543 8 10 8C11.1046 8 12 8.89543 12 10C12 11.1046 11.1046 12 10 12ZM10 11C10.5523 11 11 10.5523 11 10C11 9.44772 10.5523 9 10 9C9.44772 9 9 9.44772 9 10C9 10.5523 9.44772 11 10 11Z",fill:"currentColor"}))),T$=wr("zoomIn",m("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M11.5 8.5C11.5 8.22386 11.2761 8 11 8H9V6C9 5.72386 8.77614 5.5 8.5 5.5C8.22386 5.5 8 5.72386 8 6V8H6C5.72386 8 5.5 8.22386 5.5 8.5C5.5 8.77614 5.72386 9 6 9H8V11C8 11.2761 8.22386 11.5 8.5 11.5C8.77614 11.5 9 11.2761 9 11V9H11C11.2761 9 11.5 8.77614 11.5 8.5Z",fill:"currentColor"}),m("path",{d:"M8.5 3C11.5376 3 14 5.46243 14 8.5C14 9.83879 13.5217 11.0659 12.7266 12.0196L16.8536 16.1464C17.0488 16.3417 17.0488 16.6583 16.8536 16.8536C16.68 17.0271 16.4106 17.0464 16.2157 16.9114L16.1464 16.8536L12.0196 12.7266C11.0659 13.5217 9.83879 14 8.5 14C5.46243 14 3 11.5376 3 8.5C3 5.46243 5.46243 3 8.5 3ZM8.5 4C6.01472 4 4 6.01472 4 8.5C4 10.9853 6.01472 13 8.5 13C10.9853 13 13 10.9853 13 8.5C13 6.01472 10.9853 4 8.5 4Z",fill:"currentColor"}))),E$=wr("zoomOut",m("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M11 8C11.2761 8 11.5 8.22386 11.5 8.5C11.5 8.77614 11.2761 9 11 9H6C5.72386 9 5.5 8.77614 5.5 8.5C5.5 8.22386 5.72386 8 6 8H11Z",fill:"currentColor"}),m("path",{d:"M14 8.5C14 5.46243 11.5376 3 8.5 3C5.46243 3 3 5.46243 3 8.5C3 11.5376 5.46243 14 8.5 14C9.83879 14 11.0659 13.5217 12.0196 12.7266L16.1464 16.8536L16.2157 16.9114C16.4106 17.0464 16.68 17.0271 16.8536 16.8536C17.0488 16.6583 17.0488 16.3417 16.8536 16.1464L12.7266 12.0196C13.5217 11.0659 14 9.83879 14 8.5ZM4 8.5C4 6.01472 6.01472 4 8.5 4C10.9853 4 13 6.01472 13 8.5C13 10.9853 10.9853 13 8.5 13C6.01472 13 4 10.9853 4 8.5Z",fill:"currentColor"}))),Va=oe({name:"BaseIconSwitchTransition",setup(e,{slots:t}){const r=xi();return()=>m(At,{name:"icon-switch-transition",appear:r.value},t)}}),Ka=oe({name:"FadeInExpandTransition",props:{appear:Boolean,group:Boolean,mode:String,onLeave:Function,onAfterLeave:Function,onAfterEnter:Function,width:Boolean,reverse:Boolean},setup(e,{slots:t}){function r(l){e.width?l.style.maxWidth=`${l.offsetWidth}px`:l.style.maxHeight=`${l.offsetHeight}px`,l.offsetWidth}function o(l){e.width?l.style.maxWidth="0":l.style.maxHeight="0",l.offsetWidth;const{onLeave:s}=e;s&&s()}function n(l){e.width?l.style.maxWidth="":l.style.maxHeight="";const{onAfterLeave:s}=e;s&&s()}function i(l){if(l.style.transition="none",e.width){const s=l.offsetWidth;l.style.maxWidth="0",l.offsetWidth,l.style.transition="",l.style.maxWidth=`${s}px`}else if(e.reverse)l.style.maxHeight=`${l.offsetHeight}px`,l.offsetHeight,l.style.transition="",l.style.maxHeight="0";else{const s=l.offsetHeight;l.style.maxHeight="0",l.offsetWidth,l.style.transition="",l.style.maxHeight=`${s}px`}l.offsetWidth}function a(l){var s;e.width?l.style.maxWidth="":e.reverse||(l.style.maxHeight=""),(s=e.onAfterEnter)===null||s===void 0||s.call(e)}return()=>{const l=e.group?rc:At;return m(l,{name:e.width?"fade-in-width-expand-transition":"fade-in-height-expand-transition",mode:e.mode,appear:e.appear,onEnter:i,onAfterEnter:a,onBeforeLeave:r,onLeave:o,onAfterLeave:n},t)}}}),R$=M("base-icon",` - height: 1em; - width: 1em; - line-height: 1em; - text-align: center; - display: inline-block; - position: relative; - fill: currentColor; - transform: translateZ(0); -`,[z("svg",{height:"1em",width:"1em"})]),Bt=oe({name:"BaseIcon",props:{role:String,ariaLabel:String,ariaDisabled:{type:Boolean,default:void 0},ariaHidden:{type:Boolean,default:void 0},clsPrefix:{type:String,required:!0},onClick:Function,onMousedown:Function,onMouseup:Function},setup(e){Jr("-base-icon",R$,Oe(e,"clsPrefix"))},render(){return m("i",{class:`${this.clsPrefix}-base-icon`,onClick:this.onClick,onMousedown:this.onMousedown,onMouseup:this.onMouseup,role:this.role,"aria-label":this.ariaLabel,"aria-hidden":this.ariaHidden,"aria-disabled":this.ariaDisabled},this.$slots)}}),z$=M("base-close",` - cursor: pointer; - color: var(--n-close-color); -`,[z("&:hover",{color:"var(--n-close-color-hover)"}),z("&:active",{color:"var(--n-close-color-pressed)"}),K("disabled",{cursor:"not-allowed!important",color:"var(--n-close-color-disabled)"})]),yi=oe({name:"BaseClose",props:{clsPrefix:{type:String,required:!0},disabled:{type:Boolean,default:void 0},onClick:Function},setup(e){return Jr("-base-close",z$,Oe(e,"clsPrefix")),()=>{const{clsPrefix:t,disabled:r}=e;return m(Bt,{role:"button",ariaDisabled:r,ariaLabel:"close",clsPrefix:t,class:[`${t}-base-close`,r&&`${t}-base-close--disabled`],onClick:r?void 0:e.onClick},{default:()=>m(C$,null)})}}});const{cubicBezierEaseInOut:A$}=yr;function pi({originalTransform:e="",left:t=0,top:r=0,transition:o=`all .3s ${A$} !important`}={}){return[z("&.icon-switch-transition-enter-from, &.icon-switch-transition-leave-to",{transform:e+" scale(0.75)",left:t,top:r,opacity:0}),z("&.icon-switch-transition-enter-to, &.icon-switch-transition-leave-from",{transform:`scale(1) ${e}`,left:t,top:r,opacity:1}),z("&.icon-switch-transition-enter-active, &.icon-switch-transition-leave-active",{transformOrigin:"center",position:"absolute",left:t,top:r,transition:o})]}var O$=z([z("@keyframes loading-container-rotate",` - to { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - `),z("@keyframes loading-layer-rotate",` - 12.5% { - -webkit-transform: rotate(135deg); - transform: rotate(135deg); - } - 25% { - -webkit-transform: rotate(270deg); - transform: rotate(270deg); - } - 37.5% { - -webkit-transform: rotate(405deg); - transform: rotate(405deg); - } - 50% { - -webkit-transform: rotate(540deg); - transform: rotate(540deg); - } - 62.5% { - -webkit-transform: rotate(675deg); - transform: rotate(675deg); - } - 75% { - -webkit-transform: rotate(810deg); - transform: rotate(810deg); - } - 87.5% { - -webkit-transform: rotate(945deg); - transform: rotate(945deg); - } - 100% { - -webkit-transform: rotate(1080deg); - transform: rotate(1080deg); - } - `),z("@keyframes loading-left-spin",` - from { - -webkit-transform: rotate(265deg); - transform: rotate(265deg); - } - 50% { - -webkit-transform: rotate(130deg); - transform: rotate(130deg); - } - to { - -webkit-transform: rotate(265deg); - transform: rotate(265deg); - } - `),z("@keyframes loading-right-spin",` - from { - -webkit-transform: rotate(-265deg); - transform: rotate(-265deg); - } - 50% { - -webkit-transform: rotate(-130deg); - transform: rotate(-130deg); - } - to { - -webkit-transform: rotate(-265deg); - transform: rotate(-265deg); - } - `),M("base-loading",` - position: relative; - line-height: 0; - width: 1em; - height: 1em; - `,[F("transition-wrapper",` - position: absolute; - width: 100%; - height: 100%; - `,[pi()]),F("container",` - display: inline-flex; - position: relative; - direction: ltr; - line-height: 0; - animation: loading-container-rotate 1568.2352941176ms linear infinite; - font-size: 0; - letter-spacing: 0; - white-space: nowrap; - opacity: 1; - width: 100%; - height: 100%; - `,[F("svg",` - stroke: var(--n-text-color); - fill: transparent; - position: absolute; - height: 100%; - overflow: hidden; - `),F("container-layer",` - position: absolute; - width: 100%; - height: 100%; - animation: loading-layer-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; - `,[F("container-layer-left",` - display: inline-flex; - position: relative; - width: 50%; - height: 100%; - overflow: hidden; - `,[F("svg",` - animation: loading-left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; - width: 200%; - `)]),F("container-layer-patch",` - position: absolute; - top: 0; - left: 47.5%; - box-sizing: border-box; - width: 5%; - height: 100%; - overflow: hidden; - `,[F("svg",` - left: -900%; - width: 2000%; - transform: rotate(180deg); - `)]),F("container-layer-right",` - display: inline-flex; - position: relative; - width: 50%; - height: 100%; - overflow: hidden; - `,[F("svg",` - animation: loading-right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; - left: -100%; - width: 200%; - `)])])]),F("placeholder",` - position: absolute; - left: 50%; - top: 50%; - transform: translateX(-50%) translateY(-50%); - `,[pi({left:"50%",top:"50%",originalTransform:"translateX(-50%) translateY(-50%)"})])])]),Ua=oe({name:"BaseLoading",props:{clsPrefix:{type:String,required:!0},scale:{type:Number,default:1},radius:{type:Number,default:100},strokeWidth:{type:Number,default:28},stroke:{type:String,default:void 0},show:{type:Boolean,default:!0}},setup(e){Jr("-base-loading",O$,Oe(e,"clsPrefix"))},render(){const{clsPrefix:e,radius:t,strokeWidth:r,stroke:o,scale:n}=this,i=t/n;return m("div",{class:`${e}-base-loading`,role:"img","aria-label":"loading"},m(Va,null,{default:()=>this.show?m("div",{key:"icon",class:`${e}-base-loading__transition-wrapper`},m("div",{class:`${e}-base-loading__container`},m("div",{class:`${e}-base-loading__container-layer`},m("div",{class:`${e}-base-loading__container-layer-left`},m("svg",{class:`${e}-base-loading__svg`,viewBox:`0 0 ${2*i} ${2*i}`,xmlns:"http://www.w3.org/2000/svg",style:{color:o}},m("circle",{fill:"none",stroke:"currentColor","stroke-width":r,"stroke-linecap":"round",cx:i,cy:i,r:t-r/2,"stroke-dasharray":4.91*t,"stroke-dashoffset":2.46*t}))),m("div",{class:`${e}-base-loading__container-layer-patch`},m("svg",{class:`${e}-base-loading__svg`,viewBox:`0 0 ${2*i} ${2*i}`,xmlns:"http://www.w3.org/2000/svg",style:{color:o}},m("circle",{fill:"none",stroke:"currentColor","stroke-width":r,"stroke-linecap":"round",cx:i,cy:i,r:t-r/2,"stroke-dasharray":4.91*t,"stroke-dashoffset":2.46*t}))),m("div",{class:`${e}-base-loading__container-layer-right`},m("svg",{class:`${e}-base-loading__svg`,viewBox:`0 0 ${2*i} ${2*i}`,xmlns:"http://www.w3.org/2000/svg",style:{color:o}},m("circle",{fill:"none",stroke:"currentColor","stroke-width":r,"stroke-linecap":"round",cx:i,cy:i,r:t-r/2,"stroke-dasharray":4.91*t,"stroke-dashoffset":2.46*t})))))):m("div",{key:"placeholder",class:`${e}-base-loading__placeholder`},this.$slots)}))}});function Fu(e){return Array.isArray(e)?e:[e]}const gs={STOP:"STOP"};function im(e,t){const r=t(e);e.children!==void 0&&r!==gs.STOP&&e.children.forEach(o=>im(o,t))}function I$(e,t={}){const{preserveGroup:r=!1}=t,o=[],n=r?a=>{a.isLeaf||(o.push(a.key),i(a.children))}:a=>{a.isLeaf||(a.isGroup||o.push(a.key),i(a.children))};function i(a){a.forEach(n)}return i(e),o}function M$(e,t){const{isLeaf:r}=e;return r!==void 0?r:!t(e)}function B$(e){return e.children}function L$(e){return e.key}function D$(){return!1}function F$(e,t){const{isLeaf:r}=e;return!(r===!1&&!Array.isArray(t(e)))}function H$(e){return e.disabled===!0}function j$(e,t){return e.isLeaf===!1&&!Array.isArray(t(e))}function Sl(e){var t;return e==null?[]:Array.isArray(e)?e:(t=e.checkedKeys)!==null&&t!==void 0?t:[]}function _l(e){var t;return e==null||Array.isArray(e)?[]:(t=e.indeterminateKeys)!==null&&t!==void 0?t:[]}function N$(e,t){const r=new Set(e);return t.forEach(o=>{r.has(o)||r.add(o)}),Array.from(r)}function W$(e,t){const r=new Set(e);return t.forEach(o=>{r.has(o)&&r.delete(o)}),Array.from(r)}function V$(e){return(e==null?void 0:e.type)==="group"}function uO(e){const t=new Map;return e.forEach((r,o)=>{t.set(r.key,o)}),r=>{var o;return(o=t.get(r))!==null&&o!==void 0?o:null}}class K$ extends Error{constructor(){super(),this.message="SubtreeNotLoadedError: checking a subtree whose required nodes are not fully loaded."}}function U$(e,t,r,o){return ga(t.concat(e),r,o,!1)}function q$(e,t){const r=new Set;return e.forEach(o=>{const n=t.treeNodeMap.get(o);if(n!==void 0){let i=n.parent;for(;i!==null&&!(i.disabled||r.has(i.key));)r.add(i.key),i=i.parent}}),r}function G$(e,t,r,o){const n=ga(t,r,o,!1),i=ga(e,r,o,!0),a=q$(e,r),l=[];return n.forEach(s=>{(i.has(s)||a.has(s))&&l.push(s)}),l.forEach(s=>n.delete(s)),n}function $l(e,t){const{checkedKeys:r,keysToCheck:o,keysToUncheck:n,indeterminateKeys:i,cascade:a,leafOnly:l,checkStrategy:s,allowNotLoaded:d}=e;if(!a)return o!==void 0?{checkedKeys:N$(r,o),indeterminateKeys:Array.from(i)}:n!==void 0?{checkedKeys:W$(r,n),indeterminateKeys:Array.from(i)}:{checkedKeys:Array.from(r),indeterminateKeys:Array.from(i)};const{levelTreeNodeMap:c}=t;let u;n!==void 0?u=G$(n,r,t,d):o!==void 0?u=U$(o,r,t,d):u=ga(r,t,d,!1);const f=s==="parent",h=s==="child"||l,p=u,b=new Set,g=Math.max.apply(null,Array.from(c.keys()));for(let v=g;v>=0;v-=1){const w=v===0,$=c.get(v);for(const x of $){if(x.isLeaf)continue;const{key:S,shallowLoaded:E}=x;if(h&&E&&x.children.forEach(P=>{!P.disabled&&!P.isLeaf&&P.shallowLoaded&&p.has(P.key)&&p.delete(P.key)}),x.disabled||!E)continue;let y=!0,_=!1,R=!0;for(const P of x.children){const j=P.key;if(!P.disabled){if(R&&(R=!1),p.has(j))_=!0;else if(b.has(j)){_=!0,y=!1;break}else if(y=!1,_)break}}y&&!R?(f&&x.children.forEach(P=>{!P.disabled&&p.has(P.key)&&p.delete(P.key)}),p.add(S)):_&&b.add(S),w&&h&&p.has(S)&&p.delete(S)}}return{checkedKeys:Array.from(p),indeterminateKeys:Array.from(b)}}function ga(e,t,r,o){const{treeNodeMap:n,getChildren:i}=t,a=new Set,l=new Set(e);return e.forEach(s=>{const d=n.get(s);d!==void 0&&im(d,c=>{if(c.disabled)return gs.STOP;const{key:u}=c;if(!a.has(u)&&(a.add(u),l.add(u),j$(c.rawNode,i))){if(o)return gs.STOP;if(!r)throw new K$}})}),l}function Y$(e,{includeGroup:t=!1,includeSelf:r=!0},o){var n;const i=o.treeNodeMap;let a=e==null?null:(n=i.get(e))!==null&&n!==void 0?n:null;const l={keyPath:[],treeNodePath:[],treeNode:a};if(a!=null&&a.ignored)return l.treeNode=null,l;for(;a;)!a.ignored&&(t||!a.isGroup)&&l.treeNodePath.push(a),a=a.parent;return l.treeNodePath.reverse(),r||l.treeNodePath.pop(),l.keyPath=l.treeNodePath.map(s=>s.key),l}function X$(e){if(e.length===0)return null;const t=e[0];return t.isGroup||t.ignored||t.disabled?t.getNext():t}function Z$(e,t){const r=e.siblings,o=r.length,{index:n}=e;return t?r[(n+1)%o]:n===r.length-1?null:r[n+1]}function Hu(e,t,{loop:r=!1,includeDisabled:o=!1}={}){const n=t==="prev"?J$:Z$,i={reverse:t==="prev"};let a=!1,l=null;function s(d){if(d!==null){if(d===e){if(!a)a=!0;else if(!e.disabled&&!e.isGroup){l=e;return}}else if((!d.disabled||o)&&!d.ignored&&!d.isGroup){l=d;return}if(d.isGroup){const c=Tc(d,i);c!==null?l=c:s(n(d,r))}else{const c=n(d,!1);if(c!==null)s(c);else{const u=Q$(d);u!=null&&u.isGroup?s(n(u,r)):r&&s(n(d,!0))}}}}return s(e),l}function J$(e,t){const r=e.siblings,o=r.length,{index:n}=e;return t?r[(n-1+o)%o]:n===0?null:r[n-1]}function Q$(e){return e.parent}function Tc(e,t={}){const{reverse:r=!1}=t,{children:o}=e;if(o){const{length:n}=o,i=r?n-1:0,a=r?-1:n,l=r?-1:1;for(let s=i;s!==a;s+=l){const d=o[s];if(!d.disabled&&!d.ignored)if(d.isGroup){const c=Tc(d,t);if(c!==null)return c}else return d}}return null}const eP={getChild(){return this.ignored?null:Tc(this)},getParent(){const{parent:e}=this;return e!=null&&e.isGroup?e.getParent():e},getNext(e={}){return Hu(this,"next",e)},getPrev(e={}){return Hu(this,"prev",e)}};function tP(e,t){const r=t?new Set(t):void 0,o=[];function n(i){i.forEach(a=>{o.push(a),!(a.isLeaf||!a.children||a.ignored)&&(a.isGroup||r===void 0||r.has(a.key))&&n(a.children)})}return n(e),o}function rP(e,t){const r=e.key;for(;t;){if(t.key===r)return!0;t=t.parent}return!1}function am(e,t,r,o,n,i=null,a=0){const l=[];return e.forEach((s,d)=>{var c;const u=Object.create(o);if(u.rawNode=s,u.siblings=l,u.level=a,u.index=d,u.isFirstChild=d===0,u.isLastChild=d+1===e.length,u.parent=i,!u.ignored){const f=n(s);Array.isArray(f)&&(u.children=am(f,t,r,o,n,u,a+1))}l.push(u),t.set(u.key,u),r.has(a)||r.set(a,[]),(c=r.get(a))===null||c===void 0||c.push(u)}),l}function lm(e,t={}){var r;const o=new Map,n=new Map,{getDisabled:i=H$,getIgnored:a=D$,getIsGroup:l=V$,getKey:s=L$}=t,d=(r=t.getChildren)!==null&&r!==void 0?r:B$,c=t.ignoreEmptyChildren?x=>{const S=d(x);return Array.isArray(S)?S.length?S:null:S}:d,u=Object.assign({get key(){return s(this.rawNode)},get disabled(){return i(this.rawNode)},get isGroup(){return l(this.rawNode)},get isLeaf(){return M$(this.rawNode,c)},get shallowLoaded(){return F$(this.rawNode,c)},get ignored(){return a(this.rawNode)},contains(x){return rP(this,x)}},eP),f=am(e,o,n,u,c);function h(x){if(x==null)return null;const S=o.get(x);return S&&!S.isGroup&&!S.ignored?S:null}function p(x){if(x==null)return null;const S=o.get(x);return S&&!S.ignored?S:null}function b(x,S){const E=p(x);return E?E.getPrev(S):null}function g(x,S){const E=p(x);return E?E.getNext(S):null}function v(x){const S=p(x);return S?S.getParent():null}function w(x){const S=p(x);return S?S.getChild():null}const $={treeNodes:f,treeNodeMap:o,levelTreeNodeMap:n,maxLevel:Math.max(...n.keys()),getChildren:c,getFlattenedNodes(x){return tP(f,x)},getNode:h,getPrev:b,getNext:g,getParent:v,getChild:w,getFirstAvailableNode(){return X$(f)},getPath(x,S={}){return Y$(x,S,$)},getCheckedKeys(x,S={}){const{cascade:E=!0,leafOnly:y=!1,checkStrategy:_="all",allowNotLoaded:R=!1}=S;return $l({checkedKeys:Sl(x),indeterminateKeys:_l(x),cascade:E,leafOnly:y,checkStrategy:_,allowNotLoaded:R},$)},check(x,S,E={}){const{cascade:y=!0,leafOnly:_=!1,checkStrategy:R="all",allowNotLoaded:P=!1}=E;return $l({checkedKeys:Sl(S),indeterminateKeys:_l(S),keysToCheck:x==null?[]:Fu(x),cascade:y,leafOnly:_,checkStrategy:R,allowNotLoaded:P},$)},uncheck(x,S,E={}){const{cascade:y=!0,leafOnly:_=!1,checkStrategy:R="all",allowNotLoaded:P=!1}=E;return $l({checkedKeys:Sl(S),indeterminateKeys:_l(S),keysToUncheck:x==null?[]:Fu(x),cascade:y,leafOnly:_,checkStrategy:R,allowNotLoaded:P},$)},getNonLeafKeys(x={}){return I$(f,x)}};return $}function bs(e,t,r="default"){const o=t[r];if(o===void 0)throw new Error(`[vueuc/${e}]: slot[${r}] is empty.`);return o()}function xs(e,t=!0,r=[]){return e.forEach(o=>{if(o!==null){if(typeof o!="object"){(typeof o=="string"||typeof o=="number")&&r.push(sr(String(o)));return}if(Array.isArray(o)){xs(o,t,r);return}if(o.type===ot){if(o.children===null)return;Array.isArray(o.children)&&xs(o.children,t,r)}else o.type!==Lt&&r.push(o)}}),r}function ju(e,t,r="default"){const o=t[r];if(o===void 0)throw new Error(`[vueuc/${e}]: slot[${r}] is empty.`);const n=xs(o());if(n.length===1)return n[0];throw new Error(`[vueuc/${e}]: slot[${r}] should have exactly one child.`)}let Lr=null;function sm(){if(Lr===null&&(Lr=document.getElementById("v-binder-view-measurer"),Lr===null)){Lr=document.createElement("div"),Lr.id="v-binder-view-measurer";const{style:e}=Lr;e.position="fixed",e.left="0",e.right="0",e.top="0",e.bottom="0",e.pointerEvents="none",e.visibility="hidden",document.body.appendChild(Lr)}return Lr.getBoundingClientRect()}function oP(e,t){const r=sm();return{top:t,left:e,height:0,width:0,right:r.width-e,bottom:r.height-t}}function Pl(e){const t=e.getBoundingClientRect(),r=sm();return{left:t.left-r.left,top:t.top-r.top,bottom:r.height+r.top-t.bottom,right:r.width+r.left-t.right,width:t.width,height:t.height}}function nP(e){return e.nodeType===9?null:e.parentNode}function cm(e){if(e===null)return null;const t=nP(e);if(t===null)return null;if(t.nodeType===9)return document;if(t.nodeType===1){const{overflow:r,overflowX:o,overflowY:n}=getComputedStyle(t);if(/(auto|scroll|overlay)/.test(r+n+o))return t}return cm(t)}const iP=oe({name:"Binder",props:{syncTargetWithParent:Boolean,syncTarget:{type:Boolean,default:!0}},setup(e){var t;je("VBinder",(t=Zr())===null||t===void 0?void 0:t.proxy);const r=be("VBinder",null),o=W(null),n=v=>{o.value=v,r&&e.syncTargetWithParent&&r.setTargetRef(v)};let i=[];const a=()=>{let v=o.value;for(;v=cm(v),v!==null;)i.push(v);for(const w of i)nt("scroll",w,u,!0)},l=()=>{for(const v of i)Ze("scroll",v,u,!0);i=[]},s=new Set,d=v=>{s.size===0&&a(),s.has(v)||s.add(v)},c=v=>{s.has(v)&&s.delete(v),s.size===0&&l()},u=()=>{ip(f)},f=()=>{s.forEach(v=>v())},h=new Set,p=v=>{h.size===0&&nt("resize",window,g),h.has(v)||h.add(v)},b=v=>{h.has(v)&&h.delete(v),h.size===0&&Ze("resize",window,g)},g=()=>{h.forEach(v=>v())};return It(()=>{Ze("resize",window,g),l()}),{targetRef:o,setTargetRef:n,addScrollListener:d,removeScrollListener:c,addResizeListener:p,removeResizeListener:b}},render(){return bs("binder",this.$slots)}});var dm=iP,um=oe({name:"Target",setup(){const{setTargetRef:e,syncTarget:t}=be("VBinder");return{syncTarget:t,setTargetDirective:{mounted:e,updated:e}}},render(){const{syncTarget:e,setTargetDirective:t}=this;return e?Cr(ju("follower",this.$slots),[[t]]):ju("follower",this.$slots)}});const Bo="@@mmoContext",aP={mounted(e,{value:t}){e[Bo]={handler:void 0},typeof t=="function"&&(e[Bo].handler=t,nt("mousemoveoutside",e,t))},updated(e,{value:t}){const r=e[Bo];typeof t=="function"?r.handler?r.handler!==t&&(Ze("mousemoveoutside",e,r.handler),r.handler=t,nt("mousemoveoutside",e,t)):(e[Bo].handler=t,nt("mousemoveoutside",e,t)):r.handler&&(Ze("mousemoveoutside",e,r.handler),r.handler=void 0)},unmounted(e){const{handler:t}=e[Bo];t&&Ze("mousemoveoutside",e,t),e[Bo].handler=void 0}};var lP=aP;const Lo="@@coContext",sP={mounted(e,{value:t,modifiers:r}){e[Lo]={handler:void 0},typeof t=="function"&&(e[Lo].handler=t,nt("clickoutside",e,t,{capture:r.capture}))},updated(e,{value:t,modifiers:r}){const o=e[Lo];typeof t=="function"?o.handler?o.handler!==t&&(Ze("clickoutside",e,o.handler,{capture:r.capture}),o.handler=t,nt("clickoutside",e,t,{capture:r.capture})):(e[Lo].handler=t,nt("clickoutside",e,t,{capture:r.capture})):o.handler&&(Ze("clickoutside",e,o.handler,{capture:r.capture}),o.handler=void 0)},unmounted(e,{modifiers:t}){const{handler:r}=e[Lo];r&&Ze("clickoutside",e,r,{capture:t.capture}),e[Lo].handler=void 0}};var Cs=sP;function cP(e,t){console.error(`[vdirs/${e}]: ${t}`)}class dP{constructor(){this.elementZIndex=new Map,this.nextZIndex=2e3}get elementCount(){return this.elementZIndex.size}ensureZIndex(t,r){const{elementZIndex:o}=this;if(r!==void 0){t.style.zIndex=`${r}`,o.delete(t);return}const{nextZIndex:n}=this;o.has(t)&&o.get(t)+1===this.nextZIndex||(t.style.zIndex=`${n}`,o.set(t,n),this.nextZIndex=n+1,this.squashState())}unregister(t,r){const{elementZIndex:o}=this;o.has(t)?o.delete(t):r===void 0&&cP("z-index-manager/unregister-element","Element not found when unregistering."),this.squashState()}squashState(){const{elementCount:t}=this;t||(this.nextZIndex=2e3),this.nextZIndex-t>2500&&this.rearrange()}rearrange(){const t=Array.from(this.elementZIndex.entries());t.sort((r,o)=>r[1]-o[1]),this.nextZIndex=2e3,t.forEach(r=>{const o=r[0],n=this.nextZIndex++;`${n}`!==o.style.zIndex&&(o.style.zIndex=`${n}`)})}}var kl=new dP;const Do="@@ziContext",uP={mounted(e,t){const{value:r={}}=t,{zIndex:o,enabled:n}=r;e[Do]={enabled:!!n,initialized:!1},n&&(kl.ensureZIndex(e,o),e[Do].initialized=!0)},updated(e,t){const{value:r={}}=t,{zIndex:o,enabled:n}=r,i=e[Do].enabled;n&&!i&&(kl.ensureZIndex(e,o),e[Do].initialized=!0),e[Do].enabled=!!n},unmounted(e,t){if(!e[Do].initialized)return;const{value:r={}}=t,{zIndex:o}=r;kl.unregister(e,o)}};var qa=uP;function Nu(e,t){console.error(`[vueuc/${e}]: ${t}`)}const{c:Zo}=up(),fm="vueuc-style";function Wu(e){return typeof e=="string"?document.querySelector(e):e()}var Ec=oe({name:"LazyTeleport",props:{to:{type:[String,Object],default:void 0},disabled:Boolean,show:{type:Boolean,required:!0}},setup(e){return{showTeleport:ty(Oe(e,"show")),mergedTo:L(()=>{const{to:t}=e;return t!=null?t:"body"})}},render(){return this.showTeleport?this.disabled?bs("lazy-teleport",this.$slots):m(gh,{disabled:this.disabled,to:this.mergedTo},bs("lazy-teleport",this.$slots)):null}});const Wi={top:"bottom",bottom:"top",left:"right",right:"left"},Vu={start:"end",center:"center",end:"start"},Tl={top:"height",bottom:"height",left:"width",right:"width"},fP={"bottom-start":"top left",bottom:"top center","bottom-end":"top right","top-start":"bottom left",top:"bottom center","top-end":"bottom right","right-start":"top left",right:"center left","right-end":"bottom left","left-start":"top right",left:"center right","left-end":"bottom right"},hP={"bottom-start":"bottom left",bottom:"bottom center","bottom-end":"bottom right","top-start":"top left",top:"top center","top-end":"top right","right-start":"top right",right:"center right","right-end":"bottom right","left-start":"top left",left:"center left","left-end":"bottom left"},pP={"bottom-start":"right","bottom-end":"left","top-start":"right","top-end":"left","right-start":"bottom","right-end":"top","left-start":"bottom","left-end":"top"},Ku={top:!0,bottom:!1,left:!0,right:!1},Uu={top:"end",bottom:"start",left:"end",right:"start"};function mP(e,t,r,o,n,i){if(!n||i)return{placement:e,top:0,left:0};const[a,l]=e.split("-");let s=l!=null?l:"center",d={top:0,left:0};const c=(h,p,b)=>{let g=0,v=0;const w=r[h]-t[p]-t[h];return w>0&&o&&(b?v=Ku[p]?w:-w:g=Ku[p]?w:-w),{left:g,top:v}},u=a==="left"||a==="right";if(s!=="center"){const h=pP[e],p=Wi[h],b=Tl[h];if(r[b]>t[b]){if(t[h]+t[b]t[p]&&(s=Vu[l])}else{const h=a==="bottom"||a==="top"?"left":"top",p=Wi[h],b=Tl[h],g=(r[b]-t[b])/2;(t[h]t[p]?(s=Uu[h],d=c(b,h,u)):(s=Uu[p],d=c(b,p,u)))}let f=a;return t[a] *",{pointerEvents:"all"})])]);var hm=oe({name:"Follower",inheritAttrs:!1,props:{show:Boolean,enabled:{type:Boolean,default:void 0},placement:{type:String,default:"bottom"},syncTrigger:{type:Array,default:["resize","scroll"]},to:[String,Object],flip:{type:Boolean,default:!0},internalShift:Boolean,x:Number,y:Number,width:String,minWidth:String,containerClass:String,teleportDisabled:Boolean,zindexable:{type:Boolean,default:!0},zIndex:Number,overlap:Boolean},setup(e){const t=be("VBinder"),r=ht(()=>e.enabled!==void 0?e.enabled:e.show),o=W(null),n=W(null),i=()=>{const{syncTrigger:f}=e;f.includes("scroll")&&t.addScrollListener(s),f.includes("resize")&&t.addResizeListener(s)},a=()=>{t.removeScrollListener(s),t.removeResizeListener(s)};Ot(()=>{r.value&&(s(),i())});const l=$n();bP.mount({id:"vueuc/binder",head:!0,anchorMetaName:fm,ssr:l}),It(()=>{a()}),vp(()=>{r.value&&s()});const s=()=>{if(!r.value)return;const f=o.value;if(f===null)return;const h=t.targetRef,{x:p,y:b,overlap:g}=e,v=p!==void 0&&b!==void 0?oP(p,b):Pl(h);f.style.setProperty("--v-target-width",`${Math.round(v.width)}px`),f.style.setProperty("--v-target-height",`${Math.round(v.height)}px`);const{width:w,minWidth:$,placement:x,internalShift:S,flip:E}=e;f.setAttribute("v-placement",x),g?f.setAttribute("v-overlap",""):f.removeAttribute("v-overlap");const{style:y}=f;w==="target"?y.width=`${v.width}px`:w!==void 0?y.width=w:y.width="",$==="target"?y.minWidth=`${v.width}px`:$!==void 0?y.minWidth=$:y.minWidth="";const _=Pl(f),R=Pl(n.value),{left:P,top:j,placement:T}=mP(x,v,_,S,E,g),N=vP(T,g),{left:B,top:q,transform:A}=gP(T,R,v,j,P,g);f.setAttribute("v-placement",T),f.style.setProperty("--v-offset-left",`${Math.round(P)}px`),f.style.setProperty("--v-offset-top",`${Math.round(j)}px`),f.style.transform=`translateX(${B}) translateY(${q}) ${A}`,f.style.transformOrigin=N};qe(r,f=>{f?(i(),d()):a()});const d=()=>{br().then(s).catch(f=>console.error(f))};["placement","x","y","internalShift","flip","width","overlap","minWidth"].forEach(f=>{qe(Oe(e,f),s)}),["teleportDisabled"].forEach(f=>{qe(Oe(e,f),d)}),qe(Oe(e,"syncTrigger"),f=>{f.includes("resize")?t.addResizeListener(s):t.removeResizeListener(s),f.includes("scroll")?t.addScrollListener(s):t.removeScrollListener(s)});const c=xi(),u=ht(()=>{const{to:f}=e;if(f!==void 0)return f;c.value});return{VBinder:t,mergedEnabled:r,offsetContainerRef:n,followerRef:o,mergedTo:u,syncPosition:s}},render(){return m(Ec,{show:this.show,to:this.mergedTo,disabled:this.teleportDisabled},{default:()=>{var e,t;const r=m("div",{class:["v-binder-follower-container",this.containerClass],ref:"offsetContainerRef"},[m("div",{class:"v-binder-follower-content",ref:"followerRef"},(t=(e=this.$slots).default)===null||t===void 0?void 0:t.call(e))]);return this.zindexable?Cr(r,[[qa,{enabled:this.mergedEnabled,zIndex:this.zIndex}]]):r}})}}),pm=function(){if(typeof Map!="undefined")return Map;function e(t,r){var o=-1;return t.some(function(n,i){return n[0]===r?(o=i,!0):!1}),o}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var o=e(this.__entries__,r),n=this.__entries__[o];return n&&n[1]},t.prototype.set=function(r,o){var n=e(this.__entries__,r);~n?this.__entries__[n][1]=o:this.__entries__.push([r,o])},t.prototype.delete=function(r){var o=this.__entries__,n=e(o,r);~n&&o.splice(n,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,o){o===void 0&&(o=null);for(var n=0,i=this.__entries__;n0},e.prototype.connect_=function(){!ys||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),_P?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!ys||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,o=r===void 0?"":r,n=SP.some(function(i){return!!~o.indexOf(i)});n&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),mm=function(e,t){for(var r=0,o=Object.keys(t);r0},e}(),gm=typeof WeakMap!="undefined"?new WeakMap:new pm,bm=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=$P.getInstance(),o=new MP(t,r,this);gm.set(this,o)}return e}();["observe","unobserve","disconnect"].forEach(function(e){bm.prototype[e]=function(){var t;return(t=gm.get(this))[e].apply(t,arguments)}});var BP=function(){return typeof ba.ResizeObserver!="undefined"?ba.ResizeObserver:bm}();class LP{constructor(){this.handleResize=this.handleResize.bind(this),this.observer=new BP(this.handleResize),this.elHandlersMap=new Map}handleResize(t){for(const r of t){const o=this.elHandlersMap.get(r.target);o!==void 0&&o(r)}}registerHandler(t,r){this.elHandlersMap.set(t,r),this.observer.observe(t)}unregisterHandler(t){!this.elHandlersMap.has(t)||(this.elHandlersMap.delete(t),this.observer.unobserve(t))}}var Gu=new LP,vn=oe({name:"ResizeObserver",props:{onResize:Function},setup(e){return{registered:!1,handleResize(t){const{onResize:r}=e;r!==void 0&&r(t)}}},mounted(){const e=this.$el;if(e===void 0){Nu("resize-observer","$el does not exist.");return}if(e.nextElementSibling!==e.nextSibling&&e.nodeType===3&&e.nodeValue!==""){Nu("resize-observer","$el can not be observed (it may be a text node).");return}e.nextElementSibling!==null&&(Gu.registerHandler(e.nextElementSibling,this.handleResize),this.registered=!0)},beforeUnmount(){this.registered&&Gu.unregisterHandler(this.$el.nextElementSibling)},render(){return V0(this.$slots,"default")}});const DP=Zo(".v-x-scroll",{overflow:"auto",scrollbarWidth:"none"},[Zo("&::-webkit-scrollbar",{width:0,height:0})]);var FP=oe({name:"XScroll",props:{disabled:Boolean,onScroll:Function},setup(){const e=W(null);function t(n){!(n.currentTarget.offsetWidth=0;t--){const r=e.childNodes[t];if(xm(r)&&(wm(r)||ym(r)))return!0}return!1}function wm(e){if(!HP(e))return!1;try{e.focus()}catch{}return document.activeElement===e}function HP(e){if(e.tabIndex>0||e.tabIndex===0&&e.getAttribute("tabIndex")!==null)return!0;if(e.getAttribute("disabled"))return!1;switch(e.nodeName){case"A":return!!e.href&&e.rel!=="ignore";case"INPUT":return e.type!=="hidden"&&e.type!=="file";case"BUTTON":case"SELECT":case"TEXTAREA":return!0;default:return!1}}let Mn=[];const Sm=oe({name:"FocusTrap",props:{disabled:Boolean,active:Boolean,autoFocus:{type:Boolean,default:!0},onEsc:Function,initialFocusTo:String,finalFocusTo:String,returnFocusOnDeactivated:{type:Boolean,default:!0}},setup(e){const t=dn(),r=W(null),o=W(null);let n=!1,i=!1;const a=document.activeElement;function l(){return Mn[Mn.length-1]===t}function s(g){var v;g.code==="Escape"&&l()&&((v=e.onEsc)===null||v===void 0||v.call(e))}Ot(()=>{qe(()=>e.active,g=>{g?(u(),nt("keydown",document,s)):(Ze("keydown",document,s),n&&f())},{immediate:!0})}),It(()=>{Ze("keydown",document,s),n&&f()});function d(g){if(!i&&l()){const v=c();if(v===null||v.contains(g.target))return;h("first")}}function c(){const g=r.value;if(g===null)return null;let v=g;for(;v=v.nextSibling,!(v===null||v instanceof Element&&v.tagName==="DIV"););return v}function u(){var g;if(!e.disabled){if(Mn.push(t),e.autoFocus){const{initialFocusTo:v}=e;v===void 0?h("first"):(g=Wu(v))===null||g===void 0||g.focus()}n=!0,document.addEventListener("focus",d,!0)}}function f(){var g;if(e.disabled||(document.removeEventListener("focus",d,!0),Mn=Mn.filter(w=>w!==t),l()))return;const{finalFocusTo:v}=e;v!==void 0?(g=Wu(v))===null||g===void 0||g.focus():e.returnFocusOnDeactivated&&a instanceof HTMLElement&&(i=!0,a.focus({preventScroll:!0}),i=!1)}function h(g){if(!!l()&&e.active){const v=r.value,w=o.value;if(v!==null&&w!==null){const $=c();if($==null||$===w){i=!0,v.focus({preventScroll:!0}),i=!1;return}i=!0;const x=g==="first"?Cm($):ym($);i=!1,x||(i=!0,v.focus({preventScroll:!0}),i=!1)}}}function p(g){if(i)return;const v=c();v!==null&&(g.relatedTarget!==null&&v.contains(g.relatedTarget)?h("last"):h("first"))}function b(g){i||(g.relatedTarget!==null&&g.relatedTarget===r.value?h("last"):h("first"))}return{focusableStartRef:r,focusableEndRef:o,focusableStyle:"position: absolute; height: 0; width: 0;",handleStartFocus:p,handleEndFocus:b}},render(){const{default:e}=this.$slots;if(e===void 0)return null;if(this.disabled)return e();const{active:t,focusableStyle:r}=this;return m(ot,null,[m("div",{"aria-hidden":"true",tabindex:t?"0":"-1",ref:"focusableStartRef",style:r,onFocus:this.handleStartFocus}),e(),m("div",{"aria-hidden":"true",style:r,ref:"focusableEndRef",tabindex:t?"0":"-1",onFocus:this.handleEndFocus})])}}),fe={neutralBase:"#000",neutralInvertBase:"#fff",neutralTextBase:"#fff",neutralPopover:"rgb(72, 72, 78)",neutralCard:"rgb(24, 24, 28)",neutralModal:"rgb(44, 44, 50)",neutralBody:"rgb(16, 16, 20)",alpha1:"0.9",alpha2:"0.82",alpha3:"0.52",alpha4:"0.38",alpha5:"0.28",alphaClose:"0.52",alphaDisabled:"0.38",alphaDisabledInput:"0.06",alphaPending:"0.09",alphaTablePending:"0.06",alphaTableStriped:"0.05",alphaPressed:"0.05",alphaAvatar:"0.18",alphaRail:"0.2",alphaProgressRail:"0.12",alphaBorder:"0.24",alphaDivider:"0.09",alphaInput:"0.1",alphaAction:"0.06",alphaTab:"0.04",alphaScrollbar:"0.2",alphaScrollbarHover:"0.3",alphaCode:"0.12",alphaTag:"0",primaryHover:"#7fe7c4",primaryDefault:"#63e2b7",primaryActive:"#5acea7",primarySuppl:"rgb(42, 148, 125)",infoHover:"#8acbec",infoDefault:"#70c0e8",infoActive:"#66afd3",infoSuppl:"rgb(56, 137, 197)",errorHover:"#e98b8b",errorDefault:"#e88080",errorActive:"#e57272",errorSuppl:"rgb(208, 58, 82)",warningHover:"#f5d599",warningDefault:"#f2c97d",warningActive:"#e6c260",warningSuppl:"rgb(240, 138, 0)",successHover:"#7fe7c4",successDefault:"#63e2b7",successActive:"#5acea7",successSuppl:"rgb(42, 148, 125)"},jP=Tr(fe.neutralBase),_m=Tr(fe.neutralInvertBase),NP="rgba("+_m.slice(0,3).join(", ")+", ";function We(e){return NP+String(e)+")"}function WP(e){const t=Array.from(_m);return t[3]=Number(e),ye(jP,t)}const VP=Object.assign(Object.assign({name:"common"},yr),{baseColor:fe.neutralBase,primaryColor:fe.primaryDefault,primaryColorHover:fe.primaryHover,primaryColorPressed:fe.primaryActive,primaryColorSuppl:fe.primarySuppl,infoColor:fe.infoDefault,infoColorHover:fe.infoHover,infoColorPressed:fe.infoActive,infoColorSuppl:fe.infoSuppl,successColor:fe.successDefault,successColorHover:fe.successHover,successColorPressed:fe.successActive,successColorSuppl:fe.successSuppl,warningColor:fe.warningDefault,warningColorHover:fe.warningHover,warningColorPressed:fe.warningActive,warningColorSuppl:fe.warningSuppl,errorColor:fe.errorDefault,errorColorHover:fe.errorHover,errorColorPressed:fe.errorActive,errorColorSuppl:fe.errorSuppl,textColorBase:fe.neutralTextBase,textColor1:We(fe.alpha1),textColor2:We(fe.alpha2),textColor3:We(fe.alpha3),textColorDisabled:We(fe.alpha4),placeholderColor:We(fe.alpha4),placeholderColorDisabled:We(fe.alpha5),iconColor:We(fe.alpha4),iconColorDisabled:We(fe.alpha5),iconColorHover:We(Number(fe.alpha4)*1.25),iconColorPressed:We(Number(fe.alpha4)*.8),opacity1:fe.alpha1,opacity2:fe.alpha2,opacity3:fe.alpha3,opacity4:fe.alpha4,opacity5:fe.alpha5,dividerColor:We(fe.alphaDivider),borderColor:We(fe.alphaBorder),closeColorHover:We(Number(fe.alphaClose)*1.25),closeColor:We(Number(fe.alphaClose)),closeColorPressed:We(Number(fe.alphaClose)*.8),closeColorDisabled:We(fe.alpha4),clearColor:We(fe.alpha4),clearColorHover:Yo(We(fe.alpha4),{alpha:1.25}),clearColorPressed:Yo(We(fe.alpha4),{alpha:.8}),scrollbarColor:We(fe.alphaScrollbar),scrollbarColorHover:We(fe.alphaScrollbarHover),scrollbarWidth:"5px",scrollbarHeight:"5px",scrollbarBorderRadius:"5px",progressRailColor:We(fe.alphaProgressRail),railColor:We(fe.alphaRail),popoverColor:fe.neutralPopover,tableColor:fe.neutralCard,cardColor:fe.neutralCard,modalColor:fe.neutralModal,bodyColor:fe.neutralBody,tagColor:WP(fe.alphaTag),avatarColor:We(fe.alphaAvatar),invertedColor:fe.neutralBase,inputColor:We(fe.alphaInput),codeColor:We(fe.alphaCode),tabColor:We(fe.alphaTab),actionColor:We(fe.alphaAction),tableHeaderColor:We(fe.alphaAction),hoverColor:We(fe.alphaPending),tableColorHover:We(fe.alphaTablePending),tableColorStriped:We(fe.alphaTableStriped),pressedColor:We(fe.alphaPressed),opacityDisabled:fe.alphaDisabled,inputColorDisabled:We(fe.alphaDisabledInput),buttonColor2:"rgba(255, 255, 255, .06)",buttonColor2Hover:"rgba(255, 255, 255, .09)",buttonColor2Pressed:"rgba(255, 255, 255, .05)",boxShadow1:"0 1px 2px -2px rgba(0, 0, 0, .24), 0 3px 6px 0 rgba(0, 0, 0, .18), 0 5px 12px 4px rgba(0, 0, 0, .12)",boxShadow2:"0 3px 6px -4px rgba(0, 0, 0, .24), 0 6px 12px 0 rgba(0, 0, 0, .16), 0 9px 18px 8px rgba(0, 0, 0, .10)",boxShadow3:"0 6px 16px -9px rgba(0, 0, 0, .08), 0 9px 28px 0 rgba(0, 0, 0, .05), 0 12px 48px 16px rgba(0, 0, 0, .03)"});var de=VP;const Ce={neutralBase:"#FFF",neutralInvertBase:"#000",neutralTextBase:"#000",neutralPopover:"#fff",neutralCard:"#fff",neutralModal:"#fff",neutralBody:"#fff",alpha1:"0.82",alpha2:"0.72",alpha3:"0.38",alpha4:"0.24",alpha5:"0.18",alphaClose:"0.52",alphaDisabled:"0.5",alphaDisabledInput:"0.02",alphaPending:"0.05",alphaTablePending:"0.02",alphaPressed:"0.07",alphaAvatar:"0.2",alphaRail:"0.14",alphaProgressRail:".08",alphaBorder:"0.12",alphaDivider:"0.06",alphaInput:"0",alphaAction:"0.02",alphaTab:"0.04",alphaScrollbar:"0.25",alphaScrollbarHover:"0.4",alphaCode:"0.05",alphaTag:"0.02",primaryHover:"#36ad6a",primaryDefault:"#18a058",primaryActive:"#0c7a43",primarySuppl:"#36ad6a",infoHover:"#4098fc",infoDefault:"#2080f0",infoActive:"#1060c9",infoSuppl:"#4098fc",errorHover:"#de576d",errorDefault:"#d03050",errorActive:"#ab1f3f",errorSuppl:"#de576d",warningHover:"#fcb040",warningDefault:"#f0a020",warningActive:"#c97c10",warningSuppl:"#fcb040",successHover:"#36ad6a",successDefault:"#18a058",successActive:"#0c7a43",successSuppl:"#36ad6a"},KP=Tr(Ce.neutralBase),$m=Tr(Ce.neutralInvertBase),UP="rgba("+$m.slice(0,3).join(", ")+", ";function Yu(e){return UP+String(e)+")"}function Pt(e){const t=Array.from($m);return t[3]=Number(e),ye(KP,t)}const qP=Object.assign(Object.assign({name:"common"},yr),{baseColor:Ce.neutralBase,primaryColor:Ce.primaryDefault,primaryColorHover:Ce.primaryHover,primaryColorPressed:Ce.primaryActive,primaryColorSuppl:Ce.primarySuppl,infoColor:Ce.infoDefault,infoColorHover:Ce.infoHover,infoColorPressed:Ce.infoActive,infoColorSuppl:Ce.infoSuppl,successColor:Ce.successDefault,successColorHover:Ce.successHover,successColorPressed:Ce.successActive,successColorSuppl:Ce.successSuppl,warningColor:Ce.warningDefault,warningColorHover:Ce.warningHover,warningColorPressed:Ce.warningActive,warningColorSuppl:Ce.warningSuppl,errorColor:Ce.errorDefault,errorColorHover:Ce.errorHover,errorColorPressed:Ce.errorActive,errorColorSuppl:Ce.errorSuppl,textColorBase:Ce.neutralTextBase,textColor1:"rgb(31, 34, 37)",textColor2:"rgb(51, 54, 57)",textColor3:"rgb(118, 124, 130)",textColorDisabled:Pt(Ce.alpha4),placeholderColor:Pt(Ce.alpha4),placeholderColorDisabled:Pt(Ce.alpha5),iconColor:Pt(Ce.alpha4),iconColorHover:Yo(Pt(Ce.alpha4),{lightness:.75}),iconColorPressed:Yo(Pt(Ce.alpha4),{lightness:.9}),iconColorDisabled:Pt(Ce.alpha5),opacity1:Ce.alpha1,opacity2:Ce.alpha2,opacity3:Ce.alpha3,opacity4:Ce.alpha4,opacity5:Ce.alpha5,dividerColor:"rgb(239, 239, 245)",borderColor:"rgb(224, 224, 230)",closeColor:Pt(Number(Ce.alphaClose)),closeColorHover:Pt(Number(Ce.alphaClose)*1.25),closeColorPressed:Pt(Number(Ce.alphaClose)*.8),closeColorDisabled:Pt(Ce.alpha4),clearColor:Pt(Ce.alpha4),clearColorHover:Yo(Pt(Ce.alpha4),{lightness:.75}),clearColorPressed:Yo(Pt(Ce.alpha4),{lightness:.9}),scrollbarColor:Yu(Ce.alphaScrollbar),scrollbarColorHover:Yu(Ce.alphaScrollbarHover),scrollbarWidth:"5px",scrollbarHeight:"5px",scrollbarBorderRadius:"5px",progressRailColor:Pt(Ce.alphaProgressRail),railColor:"rgb(219, 219, 223)",popoverColor:Ce.neutralPopover,tableColor:Ce.neutralCard,cardColor:Ce.neutralCard,modalColor:Ce.neutralModal,bodyColor:Ce.neutralBody,tagColor:"rgb(250, 250, 252)",avatarColor:Pt(Ce.alphaAvatar),invertedColor:"rgb(0, 20, 40)",inputColor:Pt(Ce.alphaInput),codeColor:"rgb(244, 244, 248)",tabColor:"rgb(247, 247, 250)",actionColor:"rgb(250, 250, 252)",tableHeaderColor:"rgb(250, 250, 252)",hoverColor:"rgb(243, 243, 245)",tableColorHover:"rgba(0, 0, 100, 0.03)",tableColorStriped:"rgba(0, 0, 100, 0.02)",pressedColor:"rgb(237, 237, 239)",opacityDisabled:Ce.alphaDisabled,inputColorDisabled:"rgb(250, 250, 252)",buttonColor2:"rgba(46, 51, 56, .05)",buttonColor2Hover:"rgba(46, 51, 56, .09)",buttonColor2Pressed:"rgba(46, 51, 56, .13)",boxShadow1:"0 1px 2px -2px rgba(0, 0, 0, .08), 0 3px 6px 0 rgba(0, 0, 0, .06), 0 5px 12px 4px rgba(0, 0, 0, .04)",boxShadow2:"0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05)",boxShadow3:"0 6px 16px -9px rgba(0, 0, 0, .08), 0 9px 28px 0 rgba(0, 0, 0, .05), 0 12px 48px 16px rgba(0, 0, 0, .03)"});var Ke=qP,GP={iconSizeSmall:"34px",iconSizeMedium:"40px",iconSizeLarge:"46px",iconSizeHuge:"52px"};const Pm=e=>{const{textColorDisabled:t,iconColor:r,textColor2:o,fontSizeSmall:n,fontSizeMedium:i,fontSizeLarge:a,fontSizeHuge:l}=e;return Object.assign(Object.assign({},GP),{fontSizeSmall:n,fontSizeMedium:i,fontSizeLarge:a,fontSizeHuge:l,textColor:t,iconColor:r,extraTextColor:o})},YP={name:"Empty",common:Ke,self:Pm};var km=YP;const XP={name:"Empty",common:de,self:Pm};var wi=XP;const Tm=e=>{const{scrollbarColor:t,scrollbarColorHover:r}=e;return{color:t,colorHover:r}},ZP={name:"Scrollbar",common:Ke,self:Tm};var Rc=ZP;const JP={name:"Scrollbar",common:de,self:Tm};var Ut=JP;const{cubicBezierEaseInOut:Xu}=yr;function mi({name:e="fade-in",enterDuration:t="0.2s",leaveDuration:r="0.2s",enterCubicBezier:o=Xu,leaveCubicBezier:n=Xu}={}){return[z(`&.${e}-transition-enter-active`,{transition:`all ${t} ${o}!important`}),z(`&.${e}-transition-leave-active`,{transition:`all ${r} ${n}!important`}),z(`&.${e}-transition-enter-from, &.${e}-transition-leave-to`,{opacity:0}),z(`&.${e}-transition-leave-from, &.${e}-transition-enter-to`,{opacity:1})]}var QP=M("scrollbar",` - overflow: hidden; - position: relative; - z-index: auto; - height: 100%; - width: 100%; -`,[z(">",[M("scrollbar-container",` - width: 100%; - overflow: scroll; - height: 100%; - max-height: inherit; - scrollbar-width: none; - `,[z("&::-webkit-scrollbar, &::-webkit-scrollbar-track-piece, &::-webkit-scrollbar-thumb",` - width: 0; - height: 0; - display: none; - `),z(">",[M("scrollbar-content",` - box-sizing: border-box; - min-width: 100%; - `)])]),M("scrollbar-rail",` - position: absolute; - pointer-events: none; - user-select: none; - `,[K("horizontal",` - left: 2px; - right: 2px; - bottom: 4px; - height: var(--n-scrollbar-height); - `,[z(">",[F("scrollbar",` - height: var(--n-scrollbar-height); - border-radius: var(--n-scrollbar-border-radius); - right: 0; - `)])]),K("vertical",` - right: 4px; - top: 2px; - bottom: 2px; - width: var(--n-scrollbar-width); - `,[z(">",[F("scrollbar",` - width: var(--n-scrollbar-width); - border-radius: var(--n-scrollbar-border-radius); - bottom: 0; - `)])]),K("disabled",[z(">",[F("scrollbar",{pointerEvents:"none"})])]),z(">",[F("scrollbar",` - position: absolute; - cursor: pointer; - pointer-events: all; - background-color: var(--n-scrollbar-color); - transition: background-color .2s var(--n-scrollbar-bezier); - `,[mi(),z("&:hover",{backgroundColor:"var(--n-scrollbar-color-hover)"})])])])])]);const e3=Object.assign(Object.assign({},ze.props),{size:{type:Number,default:5},duration:{type:Number,default:0},scrollable:{type:Boolean,default:!0},xScrollable:Boolean,useUnifiedContainer:Boolean,triggerDisplayManually:Boolean,container:Function,content:Function,containerClass:String,containerStyle:[String,Object],contentClass:String,contentStyle:[String,Object],horizontalRailStyle:[String,Object],verticalRailStyle:[String,Object],onScroll:Function,onWheel:Function,onResize:Function,internalOnUpdateScrollLeft:Function}),t3=oe({name:"Scrollbar",props:e3,inheritAttrs:!1,setup(e){const{mergedClsPrefixRef:t,inlineThemeDisabled:r}=lt(e),o=W(null),n=W(null),i=W(null),a=W(null),l=W(null),s=W(null),d=W(null),c=W(null),u=W(null),f=W(null),h=W(null),p=W(0),b=W(0),g=W(!1),v=W(!1);let w=!1,$=!1,x,S,E=0,y=0,_=0,R=0;const P=dy(),j=L(()=>{const{value:re}=c,{value:he}=s,{value:Se}=f;return re===null||he===null||Se===null?0:Math.min(re,Se*re/he+e.size*1.5)}),T=L(()=>`${j.value}px`),N=L(()=>{const{value:re}=u,{value:he}=d,{value:Se}=h;return re===null||he===null||Se===null?0:Se*re/he+e.size*1.5}),B=L(()=>`${N.value}px`),q=L(()=>{const{value:re}=c,{value:he}=p,{value:Se}=s,{value:Ne}=f;if(re===null||Se===null||Ne===null)return 0;{const rt=Se-re;return rt?he/rt*(Ne-j.value):0}}),A=L(()=>`${q.value}px`),te=L(()=>{const{value:re}=u,{value:he}=b,{value:Se}=d,{value:Ne}=h;if(re===null||Se===null||Ne===null)return 0;{const rt=Se-re;return rt?he/rt*(Ne-N.value):0}}),se=L(()=>`${te.value}px`),_e=L(()=>{const{value:re}=c,{value:he}=s;return re!==null&&he!==null&&he>re}),Ae=L(()=>{const{value:re}=u,{value:he}=d;return re!==null&&he!==null&&he>re}),Re=L(()=>{const{container:re}=e;return re?re():n.value}),Ee=L(()=>{const{content:re}=e;return re?re():i.value}),$e=le,it=re=>{const{onResize:he}=e;he&&he(re),le()},O=(re,he)=>{if(!e.scrollable)return;if(typeof re=="number"){D(re,he!=null?he:0,0,!1,"auto");return}const{left:Se,top:Ne,index:rt,elSize:Ue,position:dt,behavior:Qe,el:or,debounce:Ar=!0}=re;(Se!==void 0||Ne!==void 0)&&D(Se!=null?Se:0,Ne!=null?Ne:0,0,!1,Qe),or!==void 0?D(0,or.offsetTop,or.offsetHeight,Ar,Qe):rt!==void 0&&Ue!==void 0?D(0,rt*Ue,Ue,Ar,Qe):dt==="bottom"?D(0,Number.MAX_SAFE_INTEGER,0,!1,Qe):dt==="top"&&D(0,0,0,!1,Qe)},V=(re,he)=>{if(!e.scrollable)return;const{value:Se}=Re;!Se||(typeof re=="object"?Se.scrollBy(re):Se.scrollBy(re,he||0))};function D(re,he,Se,Ne,rt){const{value:Ue}=Re;if(!!Ue){if(Ne){const{scrollTop:dt,offsetHeight:Qe}=Ue;if(he>dt){he+Se<=dt+Qe||Ue.scrollTo({left:re,top:he+Se-Qe,behavior:rt});return}}Ue.scrollTo({left:re,top:he,behavior:rt})}}function ce(){C(),k(),le()}function ue(){xe()}function xe(){G(),Z()}function G(){S!==void 0&&window.clearTimeout(S),S=window.setTimeout(()=>{v.value=!1},e.duration)}function Z(){x!==void 0&&window.clearTimeout(x),x=window.setTimeout(()=>{g.value=!1},e.duration)}function C(){x!==void 0&&window.clearTimeout(x),g.value=!0}function k(){S!==void 0&&window.clearTimeout(S),v.value=!0}function H(re){const{onScroll:he}=e;he&&he(re),U()}function U(){const{value:re}=Re;re&&(p.value=re.scrollTop,b.value=re.scrollLeft)}function X(){const{value:re}=Ee;re&&(s.value=re.offsetHeight,d.value=re.offsetWidth);const{value:he}=Re;he&&(c.value=he.offsetHeight,u.value=he.offsetWidth);const{value:Se}=l,{value:Ne}=a;Se&&(h.value=Se.offsetWidth),Ne&&(f.value=Ne.offsetHeight)}function ne(){const{value:re}=Re;re&&(p.value=re.scrollTop,b.value=re.scrollLeft,c.value=re.offsetHeight,u.value=re.offsetWidth,s.value=re.scrollHeight,d.value=re.scrollWidth);const{value:he}=l,{value:Se}=a;he&&(h.value=he.offsetWidth),Se&&(f.value=Se.offsetHeight)}function le(){!e.scrollable||(e.useUnifiedContainer?ne():(X(),U()))}function Y(re){var he;return!(!((he=o.value)===null||he===void 0)&&he.contains(re.target))}function J(re){re.preventDefault(),re.stopPropagation(),$=!0,nt("mousemove",window,Q,!0),nt("mouseup",window,ve,!0),y=b.value,_=re.clientX}function Q(re){if(!$)return;x!==void 0&&window.clearTimeout(x),S!==void 0&&window.clearTimeout(S);const{value:he}=u,{value:Se}=d,{value:Ne}=N;if(he===null||Se===null)return;const Ue=(re.clientX-_)*(Se-he)/(he-Ne),dt=Se-he;let Qe=y+Ue;Qe=Math.min(dt,Qe),Qe=Math.max(Qe,0);const{value:or}=Re;if(or){or.scrollLeft=Qe;const{internalOnUpdateScrollLeft:Ar}=e;Ar&&Ar(Qe)}}function ve(re){re.preventDefault(),re.stopPropagation(),Ze("mousemove",window,Q,!0),Ze("mouseup",window,ve,!0),$=!1,le(),Y(re)&&xe()}function pe(re){re.preventDefault(),re.stopPropagation(),w=!0,nt("mousemove",window,me,!0),nt("mouseup",window,we,!0),E=p.value,R=re.clientY}function me(re){if(!w)return;x!==void 0&&window.clearTimeout(x),S!==void 0&&window.clearTimeout(S);const{value:he}=c,{value:Se}=s,{value:Ne}=j;if(he===null||Se===null)return;const Ue=(re.clientY-R)*(Se-he)/(he-Ne),dt=Se-he;let Qe=E+Ue;Qe=Math.min(dt,Qe),Qe=Math.max(Qe,0);const{value:or}=Re;or&&(or.scrollTop=Qe)}function we(re){re.preventDefault(),re.stopPropagation(),Ze("mousemove",window,me,!0),Ze("mouseup",window,we,!0),w=!1,le(),Y(re)&&xe()}xr(()=>{const{value:re}=Ae,{value:he}=_e,{value:Se}=t,{value:Ne}=l,{value:rt}=a;Ne&&(re?Ne.classList.remove(`${Se}-scrollbar-rail--disabled`):Ne.classList.add(`${Se}-scrollbar-rail--disabled`)),rt&&(he?rt.classList.remove(`${Se}-scrollbar-rail--disabled`):rt.classList.add(`${Se}-scrollbar-rail--disabled`))}),Ot(()=>{e.container||le()}),It(()=>{x!==void 0&&window.clearTimeout(x),S!==void 0&&window.clearTimeout(S),Ze("mousemove",window,me,!0),Ze("mouseup",window,we,!0)});const De=ze("Scrollbar","-scrollbar",QP,Rc,e,t),Ye=L(()=>{const{common:{cubicBezierEaseInOut:re,scrollbarBorderRadius:he,scrollbarHeight:Se,scrollbarWidth:Ne},self:{color:rt,colorHover:Ue}}=De.value;return{"--n-scrollbar-bezier":re,"--n-scrollbar-color":rt,"--n-scrollbar-color-hover":Ue,"--n-scrollbar-border-radius":he,"--n-scrollbar-width":Ne,"--n-scrollbar-height":Se}}),Fe=r?_t("scrollbar",void 0,Ye,e):void 0;return Object.assign(Object.assign({},{scrollTo:O,scrollBy:V,sync:le,syncUnifiedContainer:ne,handleMouseEnterWrapper:ce,handleMouseLeaveWrapper:ue}),{mergedClsPrefix:t,containerScrollTop:p,wrapperRef:o,containerRef:n,contentRef:i,yRailRef:a,xRailRef:l,needYBar:_e,needXBar:Ae,yBarSizePx:T,xBarSizePx:B,yBarTopPx:A,xBarLeftPx:se,isShowXBar:g,isShowYBar:v,isIos:P,handleScroll:H,handleContentResize:$e,handleContainerResize:it,handleYScrollMouseDown:pe,handleXScrollMouseDown:J,cssVars:r?void 0:Ye,themeClass:Fe==null?void 0:Fe.themeClass,onRender:Fe==null?void 0:Fe.onRender})},render(){var e;const{$slots:t,mergedClsPrefix:r,triggerDisplayManually:o}=this;if(!this.scrollable)return(e=t.default)===null||e===void 0?void 0:e.call(t);const n=()=>{var i,a;return(i=this.onRender)===null||i===void 0||i.call(this),m("div",Xr(this.$attrs,{role:"none",ref:"wrapperRef",class:[`${r}-scrollbar`,this.themeClass],style:this.cssVars,onMouseenter:o?void 0:this.handleMouseEnterWrapper,onMouseleave:o?void 0:this.handleMouseLeaveWrapper}),[this.container?(a=t.default)===null||a===void 0?void 0:a.call(t):m("div",{role:"none",ref:"containerRef",class:[`${r}-scrollbar-container`,this.containerClass],style:this.containerStyle,onScroll:this.handleScroll,onWheel:this.onWheel},m(vn,{onResize:this.handleContentResize},{default:()=>m("div",{ref:"contentRef",role:"none",style:[{width:this.xScrollable?"fit-content":null},this.contentStyle],class:[`${r}-scrollbar-content`,this.contentClass]},t)})),m("div",{ref:"yRailRef",class:`${r}-scrollbar-rail ${r}-scrollbar-rail--vertical`,style:this.horizontalRailStyle,"aria-hidden":!0},m(At,{name:"fade-in-transition"},{default:()=>this.needYBar&&this.isShowYBar&&!this.isIos?m("div",{class:`${r}-scrollbar-rail__scrollbar`,style:{height:this.yBarSizePx,top:this.yBarTopPx},onMousedown:this.handleYScrollMouseDown}):null})),m("div",{ref:"xRailRef",class:`${r}-scrollbar-rail ${r}-scrollbar-rail--horizontal`,style:this.verticalRailStyle,"aria-hidden":!0},m(At,{name:"fade-in-transition"},{default:()=>this.needXBar&&this.isShowXBar&&!this.isIos?m("div",{class:`${r}-scrollbar-rail__scrollbar`,style:{width:this.xBarSizePx,left:this.xBarLeftPx},onMousedown:this.handleXScrollMouseDown}):null}))])};return this.container?n():m(vn,{onResize:this.handleContainerResize},{default:n})}});var Em=t3,r3={height:"calc(var(--n-option-height) * 7.6)",paddingSmall:"4px 0",paddingMedium:"4px 0",paddingLarge:"4px 0",paddingHuge:"4px 0",optionPaddingSmall:"0 12px",optionPaddingMedium:"0 12px",optionPaddingLarge:"0 12px",optionPaddingHuge:"0 12px",loadingSize:"18px"};const Rm=e=>{const{borderRadius:t,popoverColor:r,textColor3:o,dividerColor:n,textColor2:i,primaryColorPressed:a,textColorDisabled:l,primaryColor:s,opacityDisabled:d,hoverColor:c,fontSizeSmall:u,fontSizeMedium:f,fontSizeLarge:h,fontSizeHuge:p,heightSmall:b,heightMedium:g,heightLarge:v,heightHuge:w}=e;return Object.assign(Object.assign({},r3),{optionFontSizeSmall:u,optionFontSizeMedium:f,optionFontSizeLarge:h,optionFontSizeHuge:p,optionHeightSmall:b,optionHeightMedium:g,optionHeightLarge:v,optionHeightHuge:w,borderRadius:t,color:r,groupHeaderTextColor:o,actionDividerColor:n,optionTextColor:i,optionTextColorPressed:a,optionTextColorDisabled:l,optionTextColorActive:s,optionOpacityDisabled:d,optionCheckColor:s,optionColorPending:c,optionColorActive:c,actionTextColor:i,loadingColor:s})},o3={name:"InternalSelectMenu",common:Ke,peers:{Scrollbar:Rc,Empty:km},self:Rm};var n3=o3;const i3={name:"InternalSelectMenu",common:de,peers:{Scrollbar:Ut,Empty:wi},self:Rm};var Si=i3;const{cubicBezierEaseIn:Zu,cubicBezierEaseOut:Ju}=yr;function vi({transformOrigin:e="inherit",duration:t=".2s",enterScale:r=".9",originalTransform:o="",originalTransition:n=""}={}){return[z("&.fade-in-scale-up-transition-leave-active",{transformOrigin:e,transition:`opacity ${t} ${Zu}, transform ${t} ${Zu} ${n&&","+n}`}),z("&.fade-in-scale-up-transition-enter-active",{transformOrigin:e,transition:`opacity ${t} ${Ju}, transform ${t} ${Ju} ${n&&","+n}`}),z("&.fade-in-scale-up-transition-enter-from, &.fade-in-scale-up-transition-leave-to",{opacity:0,transform:`${o} scale(${r})`}),z("&.fade-in-scale-up-transition-leave-from, &.fade-in-scale-up-transition-enter-to",{opacity:1,transform:`${o} scale(1)`})]}var a3=M("base-wave",` - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - border-radius: inherit; -`),zm=oe({name:"BaseWave",props:{clsPrefix:{type:String,required:!0}},setup(e){Jr("-base-wave",a3,Oe(e,"clsPrefix"));const t=W(null),r=W(!1);let o=null;return It(()=>{o!==null&&window.clearTimeout(o)}),{active:r,selfRef:t,play(){o!==null&&(window.clearTimeout(o),r.value=!1,o=null),br(()=>{var n;(n=t.value)===null||n===void 0||n.offsetHeight,r.value=!0,o=window.setTimeout(()=>{r.value=!1,o=null},1e3)})}}},render(){const{clsPrefix:e}=this;return m("div",{ref:"selfRef","aria-hidden":!0,class:[`${e}-base-wave`,this.active&&`${e}-base-wave--active`]})}}),l3={space:"6px",spaceArrow:"10px",arrowOffset:"10px",arrowOffsetVertical:"10px",arrowHeight:"6px",padding:"8px 14px"};const Am=e=>{const{boxShadow2:t,popoverColor:r,textColor2:o,borderRadius:n,fontSize:i,dividerColor:a}=e;return Object.assign(Object.assign({},l3),{fontSize:i,borderRadius:n,color:r,dividerColor:a,textColor:o,boxShadow:t})},s3={name:"Popover",common:Ke,self:Am};var _i=s3;const c3={name:"Popover",common:de,self:Am};var zo=c3;const El={top:"bottom",bottom:"top",left:"right",right:"left"},gt="var(--n-arrow-height) * 1.414";var d3=z([M("popover",` - transition: - box-shadow .3s var(--n-bezier), - background-color .3s var(--n-bezier), - color .3s var(--n-bezier); - transform-origin: inherit; - position: relative; - font-size: var(--n-font-size); - color: var(--n-text-color); - box-shadow: var(--n-box-shadow); - `,[z("&.popover-transition-enter-from, &.popover-transition-leave-to",` - opacity: 0; - transform: scale(.85); - `),z("&.popover-transition-enter-to, &.popover-transition-leave-from",` - transform: scale(1); - opacity: 1; - `),z("&.popover-transition-enter-active",` - transition: - opacity .15s var(--n-bezier-ease-out), - transform .15s var(--n-bezier-ease-out); - `),z("&.popover-transition-leave-active",` - transition: - opacity .15s var(--n-bezier-ease-in), - transform .15s var(--n-bezier-ease-in); - `),ut("raw",` - background-color: var(--n-color); - border-radius: var(--n-border-radius); - `,[ut("show-header","padding: var(--n-padding);")]),F("header",` - padding: var(--n-padding); - border-bottom: 1px solid var(--n-divider-color); - transition: border-color .3s var(--n-bezier); - `),F("content",` - padding: var(--n-padding); - `),M("popover-arrow-wrapper",` - position: absolute; - overflow: hidden; - pointer-events: none; - `,[M("popover-arrow",` - transition: background-color .3s var(--n-bezier); - position: absolute; - display: block; - width: calc(${gt}); - height: calc(${gt}); - box-shadow: 0 0 8px 0 rgba(0, 0, 0, .12); - transform: rotate(45deg); - background-color: var(--n-color); - pointer-events: all; - `)])]),Xt("top-start",` - top: calc(${gt} / -2 + 1px); - left: calc(${_r("top-start")} - var(--v-offset-left)); - `),Xt("top",` - top: calc(${gt} / -2 + 1px); - transform: translateX(calc(${gt} / -2)) rotate(45deg); - left: 50%; - `),Xt("top-end",` - top: calc(${gt} / -2 + 1px); - right: calc(${_r("top-end")} + var(--v-offset-left)); - `),Xt("bottom-start",` - bottom: calc(${gt} / -2 + 1px); - left: calc(${_r("bottom-start")} - var(--v-offset-left)); - `),Xt("bottom",` - bottom: calc(${gt} / -2 + 1px); - transform: translateX(calc(${gt} / -2)) rotate(45deg); - left: 50%; - `),Xt("bottom-end",` - bottom: calc(${gt} / -2 + 1px); - right: calc(${_r("bottom-end")} + var(--v-offset-left)); - `),Xt("left-start",` - left: calc(${gt} / -2 + 1px); - top: calc(${_r("left-start")} - var(--v-offset-top)); - `),Xt("left",` - left: calc(${gt} / -2 + 1px); - transform: translateY(calc(${gt} / -2)) rotate(45deg); - top: 50%; - `),Xt("left-end",` - left: calc(${gt} / -2 + 1px); - bottom: calc(${_r("left-end")} + var(--v-offset-top)); - `),Xt("right-start",` - right: calc(${gt} / -2 + 1px); - top: calc(${_r("right-start")} - var(--v-offset-top)); - `),Xt("right",` - right: calc(${gt} / -2 + 1px); - transform: translateY(calc(${gt} / -2)) rotate(45deg); - top: 50%; - `),Xt("right-end",` - right: calc(${gt} / -2 + 1px); - bottom: calc(${_r("right-end")} + var(--v-offset-top)); - `),...y5({top:["right-start","left-start"],right:["top-end","bottom-end"],bottom:["right-end","left-end"],left:["top-start","bottom-start"]},(e,t)=>{const r=["right","left"].includes(t),o=r?"width":"height";return e.map(n=>{const i=n.split("-")[1]==="end",l=`calc((${`var(--v-target-${o}, 0px)`} - ${gt}) / 2)`,s=_r(n);return z(`[v-placement="${n}"] >`,[M("popover",[K("center-arrow",[M("popover-arrow",`${t}: calc(max(${l}, ${s}) ${i?"+":"-"} var(--v-offset-${r?"left":"top"}));`)])])])})})]);function _r(e){return["top","bottom"].includes(e.split("-")[0])?"var(--n-arrow-offset)":"var(--n-arrow-offset-vertical)"}function Xt(e,t){const r=e.split("-")[0],o=["top","bottom"].includes(r)?"height: var(--n-space-arrow);":"width: var(--n-space-arrow);";return z(`[v-placement="${e}"] >`,[M("popover",[ut("manual-trigger",` - margin-${El[r]}: var(--n-space); - `),K("show-arrow",` - margin-${El[r]}: var(--n-space-arrow); - `),K("overlap",` - margin: 0; - `),ey("popover-arrow-wrapper",` - right: 0; - left: 0; - top: 0; - bottom: 0; - ${r}: calc(100% - 1px); - ${El[r]}: auto; - ${o} - `,[M("popover-arrow",t)])])])}const Om=Object.assign(Object.assign({},ze.props),{to:pn.propTo,show:Boolean,trigger:String,showArrow:Boolean,delay:Number,duration:Number,raw:Boolean,arrowPointToCenter:Boolean,arrowStyle:[String,Object],displayDirective:String,x:Number,y:Number,flip:Boolean,overlap:Boolean,placement:String,width:[Number,String],keepAliveOnHover:Boolean,internalTrapFocus:Boolean,animated:Boolean,onClickoutside:Function,minWidth:Number,maxWidth:Number}),Im=({arrowStyle:e,clsPrefix:t})=>m("div",{key:"__popover-arrow__",class:`${t}-popover-arrow-wrapper`},m("div",{class:`${t}-popover-arrow`,style:e}));var u3=oe({name:"PopoverBody",inheritAttrs:!1,props:Om,setup(e,{slots:t,attrs:r}){const{namespaceRef:o,mergedClsPrefixRef:n,inlineThemeDisabled:i}=lt(e),a=ze("Popover","-popover",d3,_i,e,n),l=W(null),s=be("NPopover"),d=W(null),c=W(e.show),u=L(()=>{const{trigger:E,onClickoutside:y}=e,_=[],{positionManuallyRef:{value:R}}=s;return R||(E==="click"&&!y&&_.push([Cs,$,void 0,{capture:!0}]),E==="hover"&&_.push([lP,w])),y&&_.push([Cs,$,void 0,{capture:!0}]),e.displayDirective==="show"&&_.push([li,e.show]),_}),f=L(()=>[{width:e.width==="trigger"?"":Qt(e.width)},e.maxWidth?{maxWidth:Qt(e.maxWidth)}:{},e.minWidth?{minWidth:Qt(e.minWidth)}:{},i?void 0:h.value]),h=L(()=>{const{common:{cubicBezierEaseInOut:E,cubicBezierEaseIn:y,cubicBezierEaseOut:_},self:{space:R,spaceArrow:P,padding:j,fontSize:T,textColor:N,dividerColor:B,color:q,boxShadow:A,borderRadius:te,arrowHeight:se,arrowOffset:_e,arrowOffsetVertical:Ae}}=a.value;return{"--n-box-shadow":A,"--n-bezier":E,"--n-bezier-ease-in":y,"--n-bezier-ease-out":_,"--n-font-size":T,"--n-text-color":N,"--n-color":q,"--n-divider-color":B,"--n-border-radius":te,"--n-arrow-height":se,"--n-arrow-offset":_e,"--n-arrow-offset-vertical":Ae,"--n-padding":j,"--n-space":R,"--n-space-arrow":P}}),p=i?_t("popover",void 0,h,e):void 0;s.setBodyInstance({syncPosition:b}),It(()=>{s.setBodyInstance(null)}),qe(Oe(e,"show"),E=>{e.animated||(E?c.value=!0:c.value=!1)});function b(){var E;(E=l.value)===null||E===void 0||E.syncPosition()}function g(E){e.trigger==="hover"&&e.keepAliveOnHover&&s.handleMouseEnter(E)}function v(E){e.trigger==="hover"&&e.keepAliveOnHover&&s.handleMouseLeave(E)}function w(E){e.trigger==="hover"&&!x().contains(E.target)&&s.handleMouseMoveOutside(E)}function $(E){(e.trigger==="click"&&!x().contains(E.target)||e.onClickoutside)&&s.handleClickOutside(E)}function x(){return s.getTriggerElement()}je(mc,d),je(pc,null),je(hc,null);function S(){p==null||p.onRender();let E;const{internalRenderBodyRef:{value:y}}=s,{value:_}=n;if(y)E=y([`${_}-popover`,p==null?void 0:p.themeClass.value,e.overlap&&`${_}-popover--overlap`],d,f.value,g,v);else{const{value:R}=s.extraClassRef,{internalTrapFocus:P}=e,j=()=>{var T;return[bt(t.header,N=>N&&[m("div",{class:`${_}-popover__header`},N),m("div",{class:`${_}-popover__content`},t)])||((T=t.default)===null||T===void 0?void 0:T.call(t)),e.showArrow?Im({arrowStyle:e.arrowStyle,clsPrefix:_}):null]};E=m("div",Xr({class:[`${_}-popover`,p==null?void 0:p.themeClass.value,R.map(T=>`${_}-${T}`),{[`${_}-popover--overlap`]:e.overlap,[`${_}-popover--show-arrow`]:e.showArrow,[`${_}-popover--show-header`]:!cc(t.header),[`${_}-popover--raw`]:e.raw,[`${_}-popover--manual-trigger`]:e.trigger==="manual",[`${_}-popover--center-arrow`]:e.arrowPointToCenter}],ref:d,style:f.value,onKeydown:s.handleKeydown,onMouseenter:g,onMouseleave:v},r),P?m(Sm,{active:e.show,autoFocus:!0},{default:j}):j())}return e.displayDirective==="show"||e.show?Cr(E,u.value):null}return{namespace:o,isMounted:s.isMountedRef,zIndex:s.zIndexRef,followerRef:l,adjustedTo:pn(e),followerEnabled:c,renderContentNode:S}},render(){return m(hm,{zIndex:this.zIndex,show:this.show,enabled:this.followerEnabled,to:this.adjustedTo,x:this.x,y:this.y,flip:this.flip,placement:this.placement,containerClass:this.namespace,ref:"followerRef",overlap:this.overlap,width:this.width==="trigger"?"target":void 0,teleportDisabled:this.adjustedTo===pn.tdkey},{default:()=>this.animated?m(At,{name:"popover-transition",appear:this.isMounted,onEnter:()=>{this.followerEnabled=!0},onAfterLeave:()=>{this.followerEnabled=!1}},{default:this.renderContentNode}):this.renderContentNode()})}});const f3=Object.keys(Om),h3={focus:["onFocus","onBlur"],click:["onClick"],hover:["onMouseenter","onMouseleave"],manual:[],nested:["onFocus","onBlur","onMouseenter","onMouseleave","onClick"]};function p3(e,t,r){h3[t].forEach(o=>{e.props?e.props=Object.assign({},e.props):e.props={};const n=e.props[o],i=r[o];n?e.props[o]=(...a)=>{n(...a),i(...a)}:e.props[o]=i})}const m3=sr("").type,Ya={show:{type:Boolean,default:void 0},defaultShow:Boolean,showArrow:{type:Boolean,default:!0},trigger:{type:String,default:"hover"},delay:{type:Number,default:100},duration:{type:Number,default:100},raw:Boolean,placement:{type:String,default:"top"},x:Number,y:Number,arrowPointToCenter:Boolean,disabled:Boolean,getDisabled:Function,displayDirective:{type:String,default:"if"},arrowStyle:[String,Object],flip:{type:Boolean,default:!0},animated:{type:Boolean,default:!0},width:{type:[Number,String],default:void 0},overlap:Boolean,keepAliveOnHover:{type:Boolean,default:!0},onClickoutside:Function,internalExtraClass:{type:Array,default:()=>[]},"onUpdate:show":[Function,Array],onUpdateShow:[Function,Array],zIndex:Number,to:pn.propTo,internalSyncTargetWithParent:Boolean,internalInheritedEventHandlers:{type:Array,default:()=>[]},internalTrapFocus:Boolean,onShow:[Function,Array],onHide:[Function,Array],arrow:{type:Boolean,default:void 0},minWidth:Number,maxWidth:Number},v3=Object.assign(Object.assign(Object.assign({},ze.props),Ya),{internalRenderBody:Function});var Mm=oe({name:"Popover",inheritAttrs:!1,props:v3,__popover__:!0,setup(e){const t=xi(),r=W(null),o=L(()=>e.show),n=W(e.defaultShow),i=hn(o,n),a=ht(()=>e.disabled?!1:i.value),l=()=>{if(e.disabled)return!0;const{getDisabled:B}=e;return!!(B!=null&&B())},s=()=>l()?!1:i.value,d=di(e,["arrow","showArrow"]),c=L(()=>e.overlap?!1:d.value);let u=null;const f=W(null),h=W(null),p=ht(()=>e.x!==void 0&&e.y!==void 0);function b(B){const{"onUpdate:show":q,onUpdateShow:A,onShow:te,onHide:se}=e;n.value=B,q&&Be(q,B),A&&Be(A,B),B&&te&&Be(te,!0),B&&se&&Be(se,!1)}function g(){u&&u.syncPosition()}function v(){const{value:B}=f;B&&(window.clearTimeout(B),f.value=null)}function w(){const{value:B}=h;B&&(window.clearTimeout(B),h.value=null)}function $(){const B=l();if(e.trigger==="focus"&&!B){if(s())return;b(!0)}}function x(){const B=l();if(e.trigger==="focus"&&!B){if(!s())return;b(!1)}}function S(){const B=l();if(e.trigger==="hover"&&!B){if(w(),f.value!==null||s())return;const q=()=>{b(!0),f.value=null},{delay:A}=e;A===0?q():f.value=window.setTimeout(q,A)}}function E(){const B=l();if(e.trigger==="hover"&&!B){if(v(),h.value!==null||!s())return;const q=()=>{b(!1),h.value=null},{duration:A}=e;A===0?q():h.value=window.setTimeout(q,A)}}function y(){E()}function _(B){var q;!s()||(e.trigger==="click"&&(v(),w(),b(!1)),(q=e.onClickoutside)===null||q===void 0||q.call(e,B))}function R(){if(e.trigger==="click"&&!l()){v(),w();const B=!s();b(B)}}function P(B){!e.internalTrapFocus||B.code==="Escape"&&(v(),w(),b(!1))}function j(B){n.value=B}function T(){var B;return(B=r.value)===null||B===void 0?void 0:B.targetRef}function N(B){u=B}return je("NPopover",{getTriggerElement:T,handleKeydown:P,handleMouseEnter:S,handleMouseLeave:E,handleClickOutside:_,handleMouseMoveOutside:y,setBodyInstance:N,positionManuallyRef:p,isMountedRef:t,zIndexRef:Oe(e,"zIndex"),extraClassRef:Oe(e,"internalExtraClass"),internalRenderBodyRef:Oe(e,"internalRenderBody")}),{binderInstRef:r,positionManually:p,mergedShowConsideringDisabledProp:a,uncontrolledShow:n,mergedShowArrow:c,getMergedShow:s,setShow:j,handleClick:R,handleMouseEnter:S,handleMouseLeave:E,handleFocus:$,handleBlur:x,syncPosition:g}},render(){var e;const{positionManually:t,$slots:r}=this;let o,n=!1;if(!t&&(r.activator?o=as(r,"activator"):o=as(r,"trigger"),o)){o=lr(o),o=o.type===m3?m("span",[o]):o;const i={onClick:this.handleClick,onMouseenter:this.handleMouseEnter,onMouseleave:this.handleMouseLeave,onFocus:this.handleFocus,onBlur:this.handleBlur};if(!((e=o.type)===null||e===void 0)&&e.__popover__)n=!0,o.props||(o.props={internalSyncTargetWithParent:!0,internalInheritedEventHandlers:[]}),o.props.internalSyncTargetWithParent=!0,o.props.internalInheritedEventHandlers?o.props.internalInheritedEventHandlers=[i,...o.props.internalInheritedEventHandlers]:o.props.internalInheritedEventHandlers=[i];else{const{internalInheritedEventHandlers:a}=this,l=[i,...a],s={onBlur:d=>{l.forEach(c=>{c.onBlur(d)})},onFocus:d=>{l.forEach(c=>{c.onFocus(d)})},onClick:d=>{l.forEach(c=>{c.onClick(d)})},onMouseenter:d=>{l.forEach(c=>{c.onMouseenter(d)})},onMouseleave:d=>{l.forEach(c=>{c.onMouseleave(d)})}};p3(o,a?"nested":t?"manual":this.trigger,s)}}return m(dm,{ref:"binderInstRef",syncTarget:!n,syncTargetWithParent:this.internalSyncTargetWithParent},{default:()=>{this.mergedShowConsideringDisabledProp;const i=this.getMergedShow();return[this.internalTrapFocus&&i?Cr(m("div",{style:{position:"fixed",inset:0}}),[[qa,{enabled:i,zIndex:this.zIndex}]]):null,t?null:m(um,null,{default:()=>o}),m(u3,Vt(this.$props,f3,Object.assign(Object.assign({},this.$attrs),{showArrow:this.mergedShowArrow,show:i})),{default:()=>{var a,l;return(l=(a=this.$slots).default)===null||l===void 0?void 0:l.call(a)},header:()=>{var a,l;return(l=(a=this.$slots).header)===null||l===void 0?void 0:l.call(a)}})]}})}}),Bm={closeSizeSmall:"14px",closeSizeMedium:"14px",closeSizeLarge:"14px",padding:"0 7px",closeMargin:"0 0 0 3px",closeMarginRtl:"0 3px 0 0"};const g3={name:"Tag",common:de,self(e){const{textColor2:t,primaryColorHover:r,primaryColorPressed:o,primaryColor:n,infoColor:i,successColor:a,warningColor:l,errorColor:s,baseColor:d,borderColor:c,opacityDisabled:u,closeColor:f,closeColorHover:h,closeColorPressed:p,borderRadiusSmall:b,fontSizeTiny:g,fontSizeSmall:v,fontSizeMedium:w,heightTiny:$,heightSmall:x,heightMedium:S}=e;return Object.assign(Object.assign({},Bm),{heightSmall:$,heightMedium:x,heightLarge:S,borderRadius:b,opacityDisabled:u,fontSizeSmall:g,fontSizeMedium:v,fontSizeLarge:w,textColorCheckable:t,textColorHoverCheckable:r,textColorPressedCheckable:o,textColorChecked:d,colorCheckable:"#0000",colorHoverCheckable:"#0000",colorPressedCheckable:"#0000",colorChecked:n,colorCheckedHover:r,colorCheckedPressed:o,border:`1px solid ${c}`,textColor:t,color:"#0000",closeColor:f,closeColorHover:h,closeColorPressed:p,borderPrimary:`1px solid ${ee(n,{alpha:.3})}`,textColorPrimary:n,colorPrimary:"#0000",closeColorPrimary:ee(n,{alpha:.7}),closeColorHoverPrimary:ee(n,{alpha:.85}),closeColorPressedPrimary:ee(n,{alpha:.57}),borderInfo:`1px solid ${ee(i,{alpha:.3})}`,textColorInfo:i,colorInfo:"#0000",closeColorInfo:ee(i,{alpha:.7}),closeColorHoverInfo:ee(i,{alpha:.85}),closeColorPressedInfo:ee(i,{alpha:.57}),borderSuccess:`1px solid ${ee(a,{alpha:.3})}`,textColorSuccess:a,colorSuccess:"#0000",closeColorSuccess:ee(a,{alpha:.7}),closeColorHoverSuccess:ee(a,{alpha:.85}),closeColorPressedSuccess:ee(a,{alpha:.57}),borderWarning:`1px solid ${ee(l,{alpha:.3})}`,textColorWarning:l,colorWarning:"#0000",closeColorWarning:ee(l,{alpha:.7}),closeColorHoverWarning:ee(l,{alpha:.85}),closeColorPressedWarning:ee(l,{alpha:.57}),borderError:`1px solid ${ee(s,{alpha:.3})}`,textColorError:s,colorError:"#0000",closeColorError:ee(s,{alpha:.7}),closeColorHoverError:ee(s,{alpha:.85}),closeColorPressedError:ee(s,{alpha:.57})})}};var Lm=g3;const b3=e=>{const{textColor2:t,primaryColorHover:r,primaryColorPressed:o,primaryColor:n,infoColor:i,successColor:a,warningColor:l,errorColor:s,baseColor:d,borderColor:c,opacityDisabled:u,tagColor:f,closeColor:h,closeColorHover:p,closeColorPressed:b,borderRadiusSmall:g,fontSizeTiny:v,fontSizeSmall:w,fontSizeMedium:$,heightTiny:x,heightSmall:S,heightMedium:E}=e;return Object.assign(Object.assign({},Bm),{heightSmall:x,heightMedium:S,heightLarge:E,borderRadius:g,opacityDisabled:u,fontSizeSmall:v,fontSizeMedium:w,fontSizeLarge:$,textColorCheckable:t,textColorHoverCheckable:r,textColorPressedCheckable:o,textColorChecked:d,colorCheckable:"#0000",colorHoverCheckable:"#0000",colorPressedCheckable:"#0000",colorChecked:n,colorCheckedHover:r,colorCheckedPressed:o,border:`1px solid ${c}`,textColor:t,color:f,closeColor:h,closeColorHover:p,closeColorPressed:b,borderPrimary:`1px solid ${ee(n,{alpha:.3})}`,textColorPrimary:n,colorPrimary:ee(n,{alpha:.1}),closeColorPrimary:ee(n,{alpha:.75}),closeColorHoverPrimary:ee(n,{alpha:.6}),closeColorPressedPrimary:ee(n,{alpha:.9}),borderInfo:`1px solid ${ee(i,{alpha:.3})}`,textColorInfo:i,colorInfo:ee(i,{alpha:.1}),closeColorInfo:ee(i,{alpha:.75}),closeColorHoverInfo:ee(i,{alpha:.6}),closeColorPressedInfo:ee(i,{alpha:.9}),borderSuccess:`1px solid ${ee(a,{alpha:.3})}`,textColorSuccess:a,colorSuccess:ee(a,{alpha:.1}),closeColorSuccess:ee(a,{alpha:.75}),closeColorHoverSuccess:ee(a,{alpha:.6}),closeColorPressedSuccess:ee(a,{alpha:.9}),borderWarning:`1px solid ${ee(l,{alpha:.35})}`,textColorWarning:l,colorWarning:ee(l,{alpha:.12}),closeColorWarning:ee(l,{alpha:.75}),closeColorHoverWarning:ee(l,{alpha:.6}),closeColorPressedWarning:ee(l,{alpha:.9}),borderError:`1px solid ${ee(s,{alpha:.23})}`,textColorError:s,colorError:ee(s,{alpha:.08}),closeColorError:ee(s,{alpha:.65}),closeColorHoverError:ee(s,{alpha:.5}),closeColorPressedError:ee(s,{alpha:.8})})},x3={name:"Tag",common:Ke,self:b3};var C3=x3,y3={color:Object,type:{type:String,default:"default"},round:Boolean,size:{type:String,default:"medium"},closable:Boolean,disabled:{type:Boolean,default:void 0}},w3=M("tag",` - white-space: nowrap; - position: relative; - box-sizing: border-box; - cursor: default; - display: inline-flex; - align-items: center; - flex-wrap: nowrap; - padding: var(--n-padding); - border-radius: var(--n-border-radius); - color: var(--n-text-color); - background-color: var(--n-color); - transition: - border-color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - color .3s var(--n-bezier), - box-shadow .3s var(--n-bezier), - opacity .3s var(--n-bezier); - line-height: 1; - height: var(--n-height); - font-size: var(--n-font-size); -`,[F("border",` - pointer-events: none; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - border-radius: inherit; - border: var(--n-border); - transition: border-color .3s var(--n-bezier); - `),F("avatar",` - display: flex; - margin-right: 6px; - `),F("close",` - font-size: var(--n-close-size); - margin: var(--n-close-margin); - transition: color .3s var(--n-bezier); - cursor: pointer; - `),K("round",` - padding: 0 calc(var(--n-height) / 2); - border-radius: calc(var(--n-height) / 2); - `,[F("avatar",` - margin-left: calc((var(--n-height) - 8px) / -2); - `)]),K("disabled",` - cursor: not-allowed !important; - opacity: var(--n-opacity-disabled); - `),K("checkable",` - cursor: pointer; - box-shadow: none; - color: var(--n-text-color-checkable); - background-color: var(--n-color-checkable); - `,[ut("disabled",[z("&:hover","background-color: var(--n-color-hover-checkable);",[ut("checked","color: var(--n-text-color-hover-checkable);")]),z("&:active","background-color: var(--n-color-pressed-checkable);",[ut("checked","color: var(--n-text-color-pressed-checkable);")])]),K("checked",` - color: var(--n-text-color-checked); - background-color: var(--n-color-checked); - `,[ut("disabled",[z("&:hover","background-color: var(--n-color-checked-hover);"),z("&:active","background-color: var(--n-color-checked-pressed);")])])])]);function Pn(e,t,r){if(!t)return;const o=$n(),n=L(()=>{const{value:a}=t;if(!a)return;const l=a[e];if(!!l)return l}),i=()=>{xr(()=>{const{value:a}=r,l=`${a}${e}Rtl`;if(YC(l,o))return;const{value:s}=n;!s||s.style.mount({id:l,head:!0,anchorMetaName:hi,props:{bPrefix:a?`.${a}-`:void 0},ssr:o})})};return o?i():Yr(i),n}const S3=Object.assign(Object.assign(Object.assign({},ze.props),y3),{bordered:{type:Boolean,default:void 0},checked:Boolean,checkable:Boolean,onClose:[Array,Function],onMouseenter:Function,onMouseleave:Function,"onUpdate:checked":Function,onUpdateChecked:Function,internalStopClickPropagation:Boolean,onCheckedChange:{type:Function,validator:()=>!0,default:void 0}}),Dm="n-tag";var fO=oe({name:"Tag",props:S3,setup(e){const t=W(null),{mergedBorderedRef:r,mergedClsPrefixRef:o,inlineThemeDisabled:n,mergedRtlRef:i}=lt(e),a=ze("Tag","-tag",w3,C3,e,o);je(Dm,{roundRef:Oe(e,"round")});function l(h){if(!e.disabled&&e.checkable){const{checked:p,onCheckedChange:b,onUpdateChecked:g,"onUpdate:checked":v}=e;g&&g(!p),v&&v(!p),b&&b(!p)}}function s(h){if(e.internalStopClickPropagation&&h.stopPropagation(),!e.disabled){const{onClose:p}=e;p&&Be(p,h)}}const d={setTextContent(h){const{value:p}=t;p&&(p.textContent=h)}},c=Pn("Tag",i,o),u=L(()=>{const{type:h,size:p,color:{color:b,textColor:g}={}}=e,{common:{cubicBezierEaseInOut:v},self:{padding:w,closeMargin:$,closeMarginRtl:x,borderRadius:S,opacityDisabled:E,textColorCheckable:y,textColorHoverCheckable:_,textColorPressedCheckable:R,textColorChecked:P,colorCheckable:j,colorHoverCheckable:T,colorPressedCheckable:N,colorChecked:B,colorCheckedHover:q,colorCheckedPressed:A,[ae("closeSize",p)]:te,[ae("fontSize",p)]:se,[ae("height",p)]:_e,[ae("color",h)]:Ae,[ae("textColor",h)]:Re,[ae("border",h)]:Ee,[ae("closeColor",h)]:$e,[ae("closeColorHover",h)]:it,[ae("closeColorPressed",h)]:O}}=a.value;return{"--n-avatar-size-override":`calc(${_e} - 8px)`,"--n-bezier":v,"--n-border-radius":S,"--n-border":Ee,"--n-close-color":$e,"--n-close-color-hover":it,"--n-close-color-pressed":O,"--n-close-color-disabled":$e,"--n-close-margin":$,"--n-close-margin-rtl":x,"--n-close-size":te,"--n-color":b||Ae,"--n-color-checkable":j,"--n-color-checked":B,"--n-color-checked-hover":q,"--n-color-checked-pressed":A,"--n-color-hover-checkable":T,"--n-color-pressed-checkable":N,"--n-font-size":se,"--n-height":_e,"--n-opacity-disabled":E,"--n-padding":w,"--n-text-color":g||Re,"--n-text-color-checkable":y,"--n-text-color-checked":P,"--n-text-color-hover-checkable":_,"--n-text-color-pressed-checkable":R}}),f=n?_t("tag",L(()=>{let h="";const{type:p,size:b,color:{color:g,textColor:v}={}}=e;return h+=p[0],h+=b[0],g&&(h+=`a${un(g)}`),v&&(h+=`b${un(v)}`),h}),u,e):void 0;return Object.assign(Object.assign({},d),{rtlEnabled:c,mergedClsPrefix:o,contentRef:t,mergedBordered:r,handleClick:l,handleCloseClick:s,cssVars:n?void 0:u,themeClass:f==null?void 0:f.themeClass,onRender:f==null?void 0:f.onRender})},render(){var e,t;const{mergedClsPrefix:r,rtlEnabled:o,color:{borderColor:n}={},onRender:i,$slots:a}=this;return i==null||i(),m("div",{class:[`${r}-tag`,this.themeClass,{[`${r}-tag--rtl`]:o,[`${r}-tag--disabled`]:this.disabled,[`${r}-tag--checkable`]:this.checkable,[`${r}-tag--checked`]:this.checkable&&this.checked,[`${r}-tag--round`]:this.round}],style:this.cssVars,onClick:this.handleClick,onMouseenter:this.onMouseenter,onMouseleave:this.onMouseleave},bt(a.avatar,l=>l&&m("div",{class:`${r}-tag__avatar`},l)),m("span",{class:`${r}-tag__content`,ref:"contentRef"},(t=(e=this.$slots).default)===null||t===void 0?void 0:t.call(e)),!this.checkable&&this.closable?m(yi,{clsPrefix:r,class:`${r}-tag__close`,disabled:this.disabled,onClick:this.handleCloseClick}):null,!this.checkable&&this.mergedBordered?m("div",{class:`${r}-tag__border`,style:{borderColor:n}}):null)}}),_3=M("base-clear",` - flex-shrink: 0; - height: 1em; - width: 1em; - position: relative; -`,[z(">",[F("clear",` - font-size: var(--n-clear-size); - cursor: pointer; - color: var(--n-clear-color); - transition: color .3s var(--n-bezier); - `,[z("&:hover",` - color: var(--n-clear-color-hover)!important; - `),z("&:active",` - color: var(--n-clear-color-pressed)!important; - `)]),F("placeholder",` - display: flex; - `),F("clear, placeholder",` - position: absolute; - left: 50%; - top: 50%; - transform: translateX(-50%) translateY(-50%); - `,[pi({originalTransform:"translateX(-50%) translateY(-50%)",left:"50%",top:"50%"})])])]),ws=oe({name:"BaseClear",props:{clsPrefix:{type:String,required:!0},show:Boolean,onClear:Function},setup(e){return Jr("-base-clear",_3,Oe(e,"clsPrefix")),{handleMouseDown(t){t.preventDefault()}}},render(){const{clsPrefix:e}=this;return m("div",{class:`${e}-base-clear`},m(Va,null,{default:()=>{var t,r;return this.show?m(Bt,{clsPrefix:e,key:"dismiss",class:`${e}-base-clear__clear`,onClick:this.onClear,onMousedown:this.handleMouseDown,"data-clear":!0},{default:()=>m(_$,null)}):m("div",{key:"icon",class:`${e}-base-clear__placeholder`},(r=(t=this.$slots).default)===null||r===void 0?void 0:r.call(t))}}))}}),$3=oe({name:"InternalSelectionSuffix",props:{clsPrefix:{type:String,required:!0},showArrow:{type:Boolean,default:void 0},showClear:{type:Boolean,default:void 0},loading:{type:Boolean,default:!1},onClear:Function},setup(e,{slots:t}){return()=>{const{clsPrefix:r}=e;return m(Ua,{clsPrefix:r,class:`${r}-base-suffix`,strokeWidth:24,scale:.85,show:e.loading},{default:()=>e.showArrow?m(ws,{clsPrefix:r,show:e.showClear,onClear:e.onClear},{default:()=>m(Bt,{clsPrefix:r,class:`${r}-base-suffix__arrow`},{default:()=>_o(t.default,()=>[m(S$,null)])})}):null})}}}),Fm={paddingSingle:"0 26px 0 12px",paddingMultiple:"3px 26px 0 12px",clearSize:"16px",arrowSize:"16px"};const P3=e=>{const{borderRadius:t,textColor2:r,textColorDisabled:o,inputColor:n,inputColorDisabled:i,primaryColor:a,primaryColorHover:l,warningColor:s,warningColorHover:d,errorColor:c,errorColorHover:u,borderColor:f,iconColor:h,iconColorDisabled:p,clearColor:b,clearColorHover:g,clearColorPressed:v,placeholderColor:w,placeholderColorDisabled:$,fontSizeTiny:x,fontSizeSmall:S,fontSizeMedium:E,fontSizeLarge:y,heightTiny:_,heightSmall:R,heightMedium:P,heightLarge:j}=e;return Object.assign(Object.assign({},Fm),{fontSizeTiny:x,fontSizeSmall:S,fontSizeMedium:E,fontSizeLarge:y,heightTiny:_,heightSmall:R,heightMedium:P,heightLarge:j,borderRadius:t,textColor:r,textColorDisabled:o,placeholderColor:w,placeholderColorDisabled:$,color:n,colorDisabled:i,colorActive:n,border:`1px solid ${f}`,borderHover:`1px solid ${l}`,borderActive:`1px solid ${a}`,borderFocus:`1px solid ${l}`,boxShadowHover:"none",boxShadowActive:`0 0 0 2px ${ee(a,{alpha:.2})}`,boxShadowFocus:`0 0 0 2px ${ee(a,{alpha:.2})}`,caretColor:a,arrowColor:h,arrowColorDisabled:p,loadingColor:a,borderWarning:`1px solid ${s}`,borderHoverWarning:`1px solid ${d}`,borderActiveWarning:`1px solid ${s}`,borderFocusWarning:`1px solid ${d}`,boxShadowHoverWarning:"none",boxShadowActiveWarning:`0 0 0 2px ${ee(s,{alpha:.2})}`,boxShadowFocusWarning:`0 0 0 2px ${ee(s,{alpha:.2})}`,colorActiveWarning:n,caretColorWarning:s,borderError:`1px solid ${c}`,borderHoverError:`1px solid ${u}`,borderActiveError:`1px solid ${c}`,borderFocusError:`1px solid ${u}`,boxShadowHoverError:"none",boxShadowActiveError:`0 0 0 2px ${ee(c,{alpha:.2})}`,boxShadowFocusError:`0 0 0 2px ${ee(c,{alpha:.2})}`,colorActiveError:n,caretColorError:c,clearColor:b,clearColorHover:g,clearColorPressed:v})},k3={name:"InternalSelection",common:Ke,peers:{Popover:_i},self:P3};var T3=k3;const E3={name:"InternalSelection",common:de,peers:{Popover:zo},self(e){const{borderRadius:t,textColor2:r,textColorDisabled:o,inputColor:n,inputColorDisabled:i,primaryColor:a,primaryColorHover:l,warningColor:s,warningColorHover:d,errorColor:c,errorColorHover:u,iconColor:f,iconColorDisabled:h,clearColor:p,clearColorHover:b,clearColorPressed:g,placeholderColor:v,placeholderColorDisabled:w,fontSizeTiny:$,fontSizeSmall:x,fontSizeMedium:S,fontSizeLarge:E,heightTiny:y,heightSmall:_,heightMedium:R,heightLarge:P}=e;return Object.assign(Object.assign({},Fm),{fontSizeTiny:$,fontSizeSmall:x,fontSizeMedium:S,fontSizeLarge:E,heightTiny:y,heightSmall:_,heightMedium:R,heightLarge:P,borderRadius:t,textColor:r,textColorDisabled:o,placeholderColor:v,placeholderColorDisabled:w,color:n,colorDisabled:i,colorActive:ee(a,{alpha:.1}),border:"1px solid #0000",borderHover:`1px solid ${l}`,borderActive:`1px solid ${a}`,borderFocus:`1px solid ${l}`,boxShadowHover:"none",boxShadowActive:`0 0 8px 0 ${ee(a,{alpha:.4})}`,boxShadowFocus:`0 0 8px 0 ${ee(a,{alpha:.4})}`,caretColor:a,arrowColor:f,arrowColorDisabled:h,loadingColor:a,borderWarning:`1px solid ${s}`,borderHoverWarning:`1px solid ${d}`,borderActiveWarning:`1px solid ${s}`,borderFocusWarning:`1px solid ${d}`,boxShadowHoverWarning:"none",boxShadowActiveWarning:`0 0 8px 0 ${ee(s,{alpha:.4})}`,boxShadowFocusWarning:`0 0 8px 0 ${ee(s,{alpha:.4})}`,colorActiveWarning:ee(s,{alpha:.1}),caretColorWarning:s,borderError:`1px solid ${c}`,borderHoverError:`1px solid ${u}`,borderActiveError:`1px solid ${c}`,borderFocusError:`1px solid ${u}`,boxShadowHoverError:"none",boxShadowActiveError:`0 0 8px 0 ${ee(c,{alpha:.4})}`,boxShadowFocusError:`0 0 8px 0 ${ee(c,{alpha:.4})}`,colorActiveError:ee(c,{alpha:.1}),caretColorError:c,clearColor:p,clearColorHover:b,clearColorPressed:g})}};var zc=E3,Qu=oe({name:"SlotMachineNumber",props:{clsPrefix:{type:String,required:!0},value:{type:[Number,String],required:!0},oldOriginalNumber:{type:Number,default:void 0},newOriginalNumber:{type:Number,default:void 0}},setup(e){const t=W(null),r=W(e.value),o=W(e.value),n=W("up"),i=W(!1),a=L(()=>i.value?`${e.clsPrefix}-base-slot-machine-current-number--${n.value}-scroll`:null),l=L(()=>i.value?`${e.clsPrefix}-base-slot-machine-old-number--${n.value}-scroll`:null);qe(Oe(e,"value"),(c,u)=>{r.value=u,o.value=c,br(s)});function s(){const c=e.newOriginalNumber,u=e.oldOriginalNumber;u===void 0||c===void 0||(c>u?d("up"):u>c&&d("down"))}function d(c){n.value=c,i.value=!1,br(()=>{var u;(u=t.value)===null||u===void 0||u.offsetWidth,i.value=!0})}return()=>{const{clsPrefix:c}=e;return m("span",{ref:t,class:`${c}-base-slot-machine-number`},r.value!==null?m("span",{class:[`${c}-base-slot-machine-old-number ${c}-base-slot-machine-old-number--top`,l.value]},r.value):null,m("span",{class:[`${c}-base-slot-machine-current-number`,a.value]},m("span",{ref:"numberWrapper",class:[`${c}-base-slot-machine-current-number__inner`,typeof e.value!="number"&&`${c}-base-slot-machine-current-number__inner--not-number`]},o.value)),r.value!==null?m("span",{class:[`${c}-base-slot-machine-old-number ${c}-base-slot-machine-old-number--bottom`,l.value]},r.value):null)}}});const{cubicBezierEaseInOut:Dr}=yr;function Hm({duration:e=".2s",delay:t=".1s"}={}){return[z("&.fade-in-width-expand-transition-leave-from, &.fade-in-width-expand-transition-enter-to",{opacity:1}),z("&.fade-in-width-expand-transition-leave-to, &.fade-in-width-expand-transition-enter-from",` - opacity: 0!important; - margin-left: 0!important; - margin-right: 0!important; - `),z("&.fade-in-width-expand-transition-leave-active",` - overflow: hidden; - transition: - opacity ${e} ${Dr}, - max-width ${e} ${Dr} ${t}, - margin-left ${e} ${Dr} ${t}, - margin-right ${e} ${Dr} ${t}; - `),z("&.fade-in-width-expand-transition-enter-active",` - overflow: hidden; - transition: - opacity ${e} ${Dr} ${t}, - max-width ${e} ${Dr}, - margin-left ${e} ${Dr}, - margin-right ${e} ${Dr}; - `)]}const{cubicBezierEaseOut:Fo}=yr;function R3({duration:e=".2s"}={}){return[z("&.fade-up-width-expand-transition-leave-active",{transition:` - opacity ${e} ${Fo}, - max-width ${e} ${Fo}, - transform ${e} ${Fo} - `}),z("&.fade-up-width-expand-transition-enter-active",{transition:` - opacity ${e} ${Fo}, - max-width ${e} ${Fo}, - transform ${e} ${Fo} - `}),z("&.fade-up-width-expand-transition-enter-to",{opacity:1,transform:"translateX(0) translateY(0)"}),z("&.fade-up-width-expand-transition-enter-from",{maxWidth:"0 !important",opacity:0,transform:"translateY(60%)"}),z("&.fade-up-width-expand-transition-leave-from",{opacity:1,transform:"translateY(0)"}),z("&.fade-up-width-expand-transition-leave-to",{maxWidth:"0 !important",opacity:0,transform:"translateY(60%)"})]}var z3=z([z("@keyframes n-base-slot-machine-fade-up-in",` - from { - transform: translateY(60%); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } - `),z("@keyframes n-base-slot-machine-fade-down-in",` - from { - transform: translateY(-60%); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } - `),z("@keyframes n-base-slot-machine-fade-up-out",` - from { - transform: translateY(0%); - opacity: 1; - } - to { - transform: translateY(-60%); - opacity: 0; - } - `),z("@keyframes n-base-slot-machine-fade-down-out",` - from { - transform: translateY(0%); - opacity: 1; - } - to { - transform: translateY(60%); - opacity: 0; - } - `),M("base-slot-machine",` - overflow: hidden; - white-space: nowrap; - display: inline-block; - height: 18px; - line-height: 18px; - `,[M("base-slot-machine-number",` - display: inline-block; - position: relative; - height: 18px; - width: .6em; - max-width: .6em; - `,[R3({duration:".2s"}),Hm({duration:".2s",delay:"0s"}),M("base-slot-machine-old-number",` - display: inline-block; - opacity: 0; - position: absolute; - left: 0; - right: 0; - `,[K("top",{transform:"translateY(-100%)"}),K("bottom",{transform:"translateY(100%)"}),K("down-scroll",{animation:"n-base-slot-machine-fade-down-out .2s cubic-bezier(0, 0, .2, 1)",animationIterationCount:1}),K("up-scroll",{animation:"n-base-slot-machine-fade-up-out .2s cubic-bezier(0, 0, .2, 1)",animationIterationCount:1})]),M("base-slot-machine-current-number",` - display: inline-block; - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; - opacity: 1; - transform: translateY(0); - width: .6em; - `,[K("down-scroll",{animation:"n-base-slot-machine-fade-down-in .2s cubic-bezier(0, 0, .2, 1)",animationIterationCount:1}),K("up-scroll",{animation:"n-base-slot-machine-fade-up-in .2s cubic-bezier(0, 0, .2, 1)",animationIterationCount:1}),F("inner",` - display: inline-block; - position: absolute; - right: 0; - top: 0; - width: .6em; - `,[K("not-number",` - right: unset; - left: 0; - `)])])])])]),A3=oe({name:"BaseSlotMachine",props:{clsPrefix:{type:String,required:!0},value:{type:[Number,String],default:0},max:{type:Number,default:void 0},appeared:{type:Boolean,required:!0}},setup(e){Jr("-base-slot-machine",z3,Oe(e,"clsPrefix"));const t=W(),r=W(),o=L(()=>{if(typeof e.value=="string")return[];if(e.value<1)return[0];const n=[];let i=e.value;for(e.max!==void 0&&(i=Math.min(e.max,i));i>=1;)n.push(i%10),i/=10,i=Math.floor(i);return n.reverse(),n});return qe(Oe(e,"value"),(n,i)=>{typeof n=="string"?(r.value=void 0,t.value=void 0):typeof i=="string"?(r.value=n,t.value=void 0):(r.value=n,t.value=i)}),()=>{const{value:n,clsPrefix:i}=e;return typeof n=="number"?m("span",{class:`${i}-base-slot-machine`},m(rc,{name:"fade-up-width-expand-transition",tag:"span"},{default:()=>o.value.map((a,l)=>m(Qu,{clsPrefix:i,key:o.value.length-l-1,oldOriginalNumber:t.value,newOriginalNumber:r.value,value:a}))}),m(Ka,{key:"+",width:!0},{default:()=>e.max!==void 0&&e.max{const{borderRadius:t,railColor:r,primaryColor:o,primaryColorHover:n,primaryColorPressed:i,textColor2:a}=e;return Object.assign(Object.assign({},D3),{borderRadius:t,railColor:r,railColorActive:o,linkColor:ee(o,{alpha:.15}),linkTextColor:a,linkTextColorHover:n,linkTextColorPressed:i,linkTextColorActive:o})},H3={name:"Anchor",common:de,self:F3};var j3=H3,Nm={paddingTiny:"0 8px",paddingSmall:"0 10px",paddingMedium:"0 12px",paddingLarge:"0 14px",clearSize:"16px"};const N3={name:"Input",common:de,self(e){const{textColor2:t,textColor3:r,textColorDisabled:o,primaryColor:n,primaryColorHover:i,inputColor:a,inputColorDisabled:l,warningColor:s,warningColorHover:d,errorColor:c,errorColorHover:u,borderRadius:f,lineHeight:h,fontSizeTiny:p,fontSizeSmall:b,fontSizeMedium:g,fontSizeLarge:v,heightTiny:w,heightSmall:$,heightMedium:x,heightLarge:S,clearColor:E,clearColorHover:y,clearColorPressed:_,placeholderColor:R,placeholderColorDisabled:P,iconColor:j,iconColorDisabled:T,iconColorHover:N,iconColorPressed:B}=e;return Object.assign(Object.assign({},Nm),{countTextColor:r,heightTiny:w,heightSmall:$,heightMedium:x,heightLarge:S,fontSizeTiny:p,fontSizeSmall:b,fontSizeMedium:g,fontSizeLarge:v,lineHeight:h,lineHeightTextarea:h,borderRadius:f,iconSize:"16px",groupLabelColor:a,textColor:t,textColorDisabled:o,textDecorationColor:t,groupLabelTextColor:t,caretColor:n,placeholderColor:R,placeholderColorDisabled:P,color:a,colorDisabled:l,colorFocus:ee(n,{alpha:.1}),groupLabelBorder:"1px solid #0000",border:"1px solid #0000",borderHover:`1px solid ${i}`,borderDisabled:"1px solid #0000",borderFocus:`1px solid ${i}`,boxShadowFocus:`0 0 8px 0 ${ee(n,{alpha:.3})}`,loadingColor:n,loadingColorWarning:s,borderWarning:`1px solid ${s}`,borderHoverWarning:`1px solid ${d}`,colorFocusWarning:ee(s,{alpha:.1}),borderFocusWarning:`1px solid ${d}`,boxShadowFocusWarning:`0 0 8px 0 ${ee(s,{alpha:.3})}`,caretColorWarning:s,loadingColorError:c,borderError:`1px solid ${c}`,borderHoverError:`1px solid ${u}`,colorFocusError:ee(c,{alpha:.1}),borderFocusError:`1px solid ${u}`,boxShadowFocusError:`0 0 8px 0 ${ee(c,{alpha:.3})}`,caretColorError:c,clearColor:E,clearColorHover:y,clearColorPressed:_,iconColor:j,iconColorDisabled:T,iconColorHover:N,iconColorPressed:B,suffixTextColor:t})}};var ur=N3;const W3=e=>{const{textColor2:t,textColor3:r,textColorDisabled:o,primaryColor:n,primaryColorHover:i,inputColor:a,inputColorDisabled:l,borderColor:s,warningColor:d,warningColorHover:c,errorColor:u,errorColorHover:f,borderRadius:h,lineHeight:p,fontSizeTiny:b,fontSizeSmall:g,fontSizeMedium:v,fontSizeLarge:w,heightTiny:$,heightSmall:x,heightMedium:S,heightLarge:E,actionColor:y,clearColor:_,clearColorHover:R,clearColorPressed:P,placeholderColor:j,placeholderColorDisabled:T,iconColor:N,iconColorDisabled:B,iconColorHover:q,iconColorPressed:A}=e;return Object.assign(Object.assign({},Nm),{countTextColor:r,heightTiny:$,heightSmall:x,heightMedium:S,heightLarge:E,fontSizeTiny:b,fontSizeSmall:g,fontSizeMedium:v,fontSizeLarge:w,lineHeight:p,lineHeightTextarea:p,borderRadius:h,iconSize:"16px",groupLabelColor:y,groupLabelTextColor:t,textColor:t,textColorDisabled:o,textDecorationColor:t,caretColor:n,placeholderColor:j,placeholderColorDisabled:T,color:a,colorDisabled:l,colorFocus:a,groupLabelBorder:`1px solid ${s}`,border:`1px solid ${s}`,borderHover:`1px solid ${i}`,borderDisabled:`1px solid ${s}`,borderFocus:`1px solid ${i}`,boxShadowFocus:`0 0 0 2px ${ee(n,{alpha:.2})}`,loadingColor:n,loadingColorWarning:d,borderWarning:`1px solid ${d}`,borderHoverWarning:`1px solid ${c}`,colorFocusWarning:a,borderFocusWarning:`1px solid ${c}`,boxShadowFocusWarning:`0 0 0 2px ${ee(d,{alpha:.2})}`,caretColorWarning:d,loadingColorError:u,borderError:`1px solid ${u}`,borderHoverError:`1px solid ${f}`,colorFocusError:a,borderFocusError:`1px solid ${f}`,boxShadowFocusError:`0 0 0 2px ${ee(u,{alpha:.2})}`,caretColorError:u,clearColor:_,clearColorHover:R,clearColorPressed:P,iconColor:N,iconColorDisabled:B,iconColorHover:q,iconColorPressed:A,suffixTextColor:t})},V3={name:"Input",common:Ke,self:W3};var Wm=V3;const Vm="n-input";function K3(e){let t=0;for(const r of e)t++;return t}function Vi(e){return["",void 0,null].includes(e)}var ef=oe({name:"InputWordCount",setup(e,{slots:t}){const{mergedValueRef:r,maxlengthRef:o,mergedClsPrefixRef:n}=be(Vm),i=L(()=>{const{value:a}=r;return a===null||Array.isArray(a)?0:K3(a)});return()=>{const{value:a}=o,{value:l}=r;return m("span",{class:`${n.value}-input-word-count`},AC(t.default,{value:l===null||Array.isArray(l)?"":l},()=>[a===void 0?i.value:`${i.value} / ${a}`]))}}}),U3=M("input",` - max-width: 100%; - cursor: text; - line-height: 1.5; - z-index: auto; - outline: none; - box-sizing: border-box; - position: relative; - display: inline-flex; - border-radius: var(--n-border-radius); - background-color: var(--n-color); - transition: background-color .3s var(--n-bezier); - font-size: var(--n-font-size); - --n-padding-vertical: calc((var(--n-height) - 1.5 * var(--n-font-size)) / 2); -`,[F("input, textarea",` - overflow: hidden; - flex-grow: 1; - position: relative; - `),F("input-el, textarea-el, input-mirror, textarea-mirror, separator, placeholder",` - box-sizing: border-box; - font-size: inherit; - line-height: 1.5; - font-family: inherit; - border: none; - outline: none; - background-color: #0000; - text-align: inherit; - transition: - caret-color .3s var(--n-bezier), - color .3s var(--n-bezier), - text-decoration-color .3s var(--n-bezier); - `),F("input-el, textarea-el",` - -webkit-appearance: none; - scrollbar-width: none; - width: 100%; - min-width: 0; - text-decoration-color: var(--n-text-decoration-color); - color: var(--n-text-color); - caret-color: var(--n-caret-color); - background-color: transparent; - `,[z("&::-webkit-scrollbar, &::-webkit-scrollbar-track-piece, &::-webkit-scrollbar-thumb",` - width: 0; - height: 0; - display: none; - `),z("&::placeholder","color: #0000;"),z("&:-webkit-autofill ~",[F("placeholder","display: none;")])]),K("round",[ut("textarea","border-radius: calc(var(--n-height) / 2);")]),F("placeholder",` - pointer-events: none; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - overflow: hidden; - color: var(--n-placeholder-color); - `,[z("span",` - width: 100%; - display: inline-block; - `)]),K("textarea",[F("placeholder","overflow: visible;")]),ut("autosize","width: 100%;"),K("autosize",[F("textarea-el, input-el",` - position: absolute; - top: 0; - left: 0; - height: 100%; - `)]),M("input-wrapper",` - overflow: hidden; - display: inline-flex; - flex-grow: 1; - position: relative; - padding-left: var(--n-padding-left); - padding-right: var(--n-padding-right); - `),F("input-mirror",` - padding: 0; - height: var(--n-height); - overflow: hidden; - visibility: hidden; - position: static; - white-space: nowrap; - pointer-events: none; - `),F("input-el",` - padding: 0; - height: var(--n-height); - line-height: var(--n-height); - `,[z("+",[F("placeholder",` - display: flex; - align-items: center; - `)])]),ut("textarea",[F("placeholder","white-space: nowrap;")]),F("eye",` - transition: color .3s var(--n-bezier); - `),K("textarea","width: 100%;",[M("input-word-count",` - position: absolute; - right: var(--n-padding-right); - bottom: var(--n-padding-vertical); - `),K("resizable",[M("input-wrapper",` - resize: vertical; - min-height: var(--n-height); - `)]),F("textarea",` - position: static; - `),F("textarea-el, textarea-mirror, placeholder",` - height: 100%; - left: var(--n-padding-left); - right: var(--n-padding-right); - padding-left: 0; - padding-right: 0; - padding-top: var(--n-padding-vertical); - padding-bottom: var(--n-padding-vertical); - word-break: break-word; - display: inline-block; - vertical-align: bottom; - box-sizing: border-box; - line-height: var(--n-line-height-textarea); - margin: 0; - resize: none; - white-space: pre-wrap; - `),F("textarea-mirror",` - width: 100%; - pointer-events: none; - overflow: hidden; - visibility: hidden; - position: static; - white-space: pre-wrap; - overflow-wrap: break-word; - `)]),K("pair",[F("input-el, placeholder","text-align: center;"),F("separator",` - display: flex; - align-items: center; - transition: color .3s var(--n-bezier); - color: var(--n-text-color); - `,[M("icon",` - color: var(--n-icon-color); - `),M("base-icon",` - color: var(--n-icon-color); - `)])]),K("disabled",` - cursor: not-allowed; - background-color: var(--n-color-disabled); - `,[F("border","border: var(--n-border-disabled);"),F("input-el, textarea-el",` - cursor: not-allowed; - color: var(--n-text-color-disabled); - text-decoration-color: var(--n-text-color-disabled); - `),F("placeholder","color: var(--n-placeholder-color-disabled);"),F("separator","color: var(--n-text-color-disabled);",[M("icon",` - color: var(--n-icon-color-disabled); - `),M("base-icon",` - color: var(--n-icon-color-disabled); - `)]),F("suffix, prefix","color: var(--n-text-color-disabled);",[M("icon",` - color: var(--n-icon-color-disabled); - `),M("internal-icon",` - color: var(--n-icon-color-disabled); - `)])]),ut("disabled",[F("eye",` - display: flex; - align-items: center; - justify-content: center; - color: var(--n-icon-color); - cursor: pointer; - `,[z("&:hover",` - color: var(--n-icon-color-hover); - `),z("&:active",` - color: var(--n-icon-color-pressed); - `),M("icon",[z("&:hover",` - color: var(--n-icon-color-hover); - `),z("&:active",` - color: var(--n-icon-color-pressed); - `)])]),z("&:hover",[F("state-border","border: var(--n-border-hover);")]),K("focus","background-color: var(--n-color-focus);",[F("state-border",` - border: var(--n-border-focus); - box-shadow: var(--n-box-shadow-focus); - `)])]),F("border, state-border",` - box-sizing: border-box; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - pointer-events: none; - border-radius: inherit; - border: var(--n-border); - transition: - box-shadow .3s var(--n-bezier), - border-color .3s var(--n-bezier); - `),F("state-border",` - border-color: #0000; - z-index: 1; - `),F("prefix","margin-right: 4px;"),F("suffix",` - margin-left: 4px; - `),F("suffix, prefix",` - transition: color .3s var(--n-bezier); - flex-wrap: nowrap; - flex-shrink: 0; - line-height: var(--n-height); - white-space: nowrap; - display: inline-flex; - align-items: center; - justify-content: center; - color: var(--n-suffix-text-color); - `,[M("base-loading",` - font-size: var(--n-icon-size); - margin: 0 2px; - color: var(--n-loading-color); - `),M("base-clear",` - font-size: var(--n-icon-size); - `,[F("placeholder",[M("base-icon",` - transition: color .3s var(--n-bezier); - color: var(--n-icon-color); - font-size: var(--n-icon-size); - `)])]),M("icon",` - transition: color .3s var(--n-bezier); - color: var(--n-icon-color); - font-size: var(--n-icon-size); - `),M("base-icon",` - font-size: var(--n-icon-size); - `)]),M("input-word-count",` - pointer-events: none; - line-height: 1.5; - font-size: .85em; - color: var(--n-count-text-color); - transition: color .3s var(--n-bezier); - margin-left: 4px; - font-variant: tabular-nums; - `),["warning","error"].map(e=>K(`${e}-status`,[ut("disabled",[M("base-loading",` - color: var(--n-loading-color-${e}) - `),F("input-el, textarea-el",` - caret-color: var(--n-caret-color-${e}); - `),F("state-border",` - border: var(--n-border-${e}); - `),z("&:hover",[F("state-border",` - border: var(--n-border-hover-${e}); - `)]),z("&:focus",` - background-color: var(--n-color-focus-${e}); - `,[F("state-border",` - box-shadow: var(--n-box-shadow-focus-${e}); - border: var(--n-border-focus-${e}); - `)]),K("focus",` - background-color: var(--n-color-focus-${e}); - `,[F("state-border",` - box-shadow: var(--n-box-shadow-focus-${e}); - border: var(--n-border-focus-${e}); - `)])])]))]);const q3=Object.assign(Object.assign({},ze.props),{bordered:{type:Boolean,default:void 0},type:{type:String,default:"text"},placeholder:[Array,String],defaultValue:{type:[String,Array],default:null},value:[String,Array],disabled:{type:Boolean,default:void 0},size:String,rows:{type:[Number,String],default:3},round:Boolean,minlength:[String,Number],maxlength:[String,Number],clearable:Boolean,autosize:{type:[Boolean,Object],default:!1},pair:Boolean,separator:String,readonly:{type:[String,Boolean],default:!1},passivelyActivated:Boolean,showPasswordOn:String,stateful:{type:Boolean,default:!0},autofocus:Boolean,inputProps:Object,resizable:{type:Boolean,default:!0},showCount:Boolean,loading:{type:Boolean,default:void 0},onMousedown:Function,onKeydown:Function,onKeyup:Function,onInput:[Function,Array],onFocus:[Function,Array],onBlur:[Function,Array],onClick:[Function,Array],onChange:[Function,Array],onClear:[Function,Array],status:String,"onUpdate:value":[Function,Array],onUpdateValue:[Function,Array],textDecoration:[String,Array],attrSize:{type:Number,default:20},onInputBlur:[Function,Array],onInputFocus:[Function,Array],onDeactivate:[Function,Array],onActivate:[Function,Array],onWrapperFocus:[Function,Array],onWrapperBlur:[Function,Array],internalDeactivateOnEnter:Boolean,internalForceFocus:Boolean,internalLoadingBeforeSuffix:Boolean,showPasswordToggle:Boolean});var Km=oe({name:"Input",props:q3,setup(e){const{mergedClsPrefixRef:t,mergedBorderedRef:r,inlineThemeDisabled:o,mergedRtlRef:n}=lt(e),i=ze("Input","-input",U3,Wm,e,t),a=W(null),l=W(null),s=W(null),d=W(null),c=W(null),u=W(null),f=W(null),{localeRef:h}=em("Input"),p=W(e.defaultValue),b=Oe(e,"value"),g=hn(b,p),v=wp(e),{mergedSizeRef:w,mergedDisabledRef:$,mergedStatusRef:x}=v,S=W(!1),E=W(!1),y=W(!1),_=W(!1);let R=null;const P=L(()=>{const{placeholder:I,pair:ie}=e;return ie?Array.isArray(I)?I:I===void 0?["",""]:[I,I]:I===void 0?[h.value.placeholder]:[I]}),j=L(()=>{const{value:I}=y,{value:ie}=g,{value:Te}=P;return!I&&(Vi(ie)||Array.isArray(ie)&&Vi(ie[0]))&&Te[0]}),T=L(()=>{const{value:I}=y,{value:ie}=g,{value:Te}=P;return!I&&Te[1]&&(Vi(ie)||Array.isArray(ie)&&Vi(ie[1]))}),N=ht(()=>e.internalForceFocus||S.value),B=ht(()=>{if($.value||e.readonly||!e.clearable||!N.value&&!E.value)return!1;const{value:I}=g,{value:ie}=N;return e.pair?!!(Array.isArray(I)&&(I[0]||I[1]))&&(E.value||ie):!!I&&(E.value||ie)}),q=L(()=>{const{showPasswordOn:I}=e;if(I)return I;if(e.showPasswordToggle)return"click"}),A=W(!1),te=L(()=>{const{textDecoration:I}=e;return I?Array.isArray(I)?I.map(ie=>({textDecoration:ie})):[{textDecoration:I}]:["",""]}),se=W(void 0),_e=()=>{var I,ie;if(e.type==="textarea"){const{autosize:Te}=e;if(Te&&(se.value=(ie=(I=f.value)===null||I===void 0?void 0:I.$el)===null||ie===void 0?void 0:ie.offsetWidth),!l.value||typeof Te=="boolean")return;const{paddingTop:mt,paddingBottom:vt,lineHeight:$t}=window.getComputedStyle(l.value),eo=Number(mt.slice(0,-2)),to=Number(vt.slice(0,-2)),ro=Number($t.slice(0,-2)),{value:kn}=s;if(!kn)return;if(Te.minRows){const Tn=Math.max(Te.minRows,1),nl=`${eo+to+ro*Tn}px`;kn.style.minHeight=nl}if(Te.maxRows){const Tn=`${eo+to+ro*Te.maxRows}px`;kn.style.maxHeight=Tn}}},Ae=L(()=>{const{maxlength:I}=e;return I===void 0?void 0:Number(I)});Ot(()=>{const{value:I}=g;Array.isArray(I)||Qe(I)});const Re=Zr().proxy;function Ee(I){const{onUpdateValue:ie,"onUpdate:value":Te,onInput:mt}=e,{nTriggerFormInput:vt}=v;ie&&Be(ie,I),Te&&Be(Te,I),mt&&Be(mt,I),p.value=I,vt()}function $e(I){const{onChange:ie}=e,{nTriggerFormChange:Te}=v;ie&&Be(ie,I),p.value=I,Te()}function it(I){const{onBlur:ie}=e,{nTriggerFormBlur:Te}=v;ie&&Be(ie,I),Te()}function O(I){const{onFocus:ie}=e,{nTriggerFormFocus:Te}=v;ie&&Be(ie,I),Te()}function V(I){const{onClear:ie}=e;ie&&Be(ie,I)}function D(I){const{onInputBlur:ie}=e;ie&&Be(ie,I)}function ce(I){const{onInputFocus:ie}=e;ie&&Be(ie,I)}function ue(){const{onDeactivate:I}=e;I&&Be(I)}function xe(){const{onActivate:I}=e;I&&Be(I)}function G(I){const{onClick:ie}=e;ie&&Be(ie,I)}function Z(I){const{onWrapperFocus:ie}=e;ie&&Be(ie,I)}function C(I){const{onWrapperBlur:ie}=e;ie&&Be(ie,I)}function k(){y.value=!0}function H(I){y.value=!1,I.target===u.value?U(I,1):U(I,0)}function U(I,ie=0,Te="input"){const mt=I.target.value;if(Qe(mt),e.type==="textarea"){const{value:$t}=f;$t&&$t.syncUnifiedContainer()}if(R=mt,y.value)return;const vt=mt;if(!e.pair)Te==="input"?Ee(vt):$e(vt);else{let{value:$t}=g;Array.isArray($t)?$t=[...$t]:$t=["",""],$t[ie]=vt,Te==="input"?Ee($t):$e($t)}Re.$forceUpdate()}function X(I){D(I),I.relatedTarget===a.value&&ue(),I.relatedTarget!==null&&(I.relatedTarget===c.value||I.relatedTarget===u.value||I.relatedTarget===l.value)||(_.value=!1),J(I,"blur")}function ne(I){ce(I),S.value=!0,_.value=!0,xe(),J(I,"focus")}function le(I){e.passivelyActivated&&(C(I),J(I,"blur"))}function Y(I){e.passivelyActivated&&(S.value=!0,Z(I),J(I,"focus"))}function J(I,ie){I.relatedTarget!==null&&(I.relatedTarget===c.value||I.relatedTarget===u.value||I.relatedTarget===l.value||I.relatedTarget===a.value)||(ie==="focus"?(O(I),S.value=!0):ie==="blur"&&(it(I),S.value=!1))}function Q(I,ie){U(I,ie,"change")}function ve(I){G(I)}function pe(I){V(I),e.pair?(Ee(["",""]),$e(["",""])):(Ee(""),$e(""))}function me(I){const{onMousedown:ie}=e;ie&&ie(I);const{tagName:Te}=I.target;if(Te!=="INPUT"&&Te!=="TEXTAREA"){if(e.resizable){const{value:mt}=a;if(mt){const{left:vt,top:$t,width:eo,height:to}=mt.getBoundingClientRect(),ro=14;if(vt+eo-ro{mt.preventDefault(),Ze("mouseup",document,ie)};if(nt("mouseup",document,ie),q.value!=="mousedown")return;A.value=!0;const Te=()=>{A.value=!1,Ze("mouseup",document,Te)};nt("mouseup",document,Te)}function Je(I){var ie;switch((ie=e.onKeydown)===null||ie===void 0||ie.call(e,I),I.code){case"Escape":he();break;case"Enter":case"NumpadEnter":re(I);break}}function re(I){var ie,Te;if(e.passivelyActivated){const{value:mt}=_;if(mt){e.internalDeactivateOnEnter&&he();return}I.preventDefault(),e.type==="textarea"?(ie=l.value)===null||ie===void 0||ie.focus():(Te=c.value)===null||Te===void 0||Te.focus()}}function he(){e.passivelyActivated&&(_.value=!1,br(()=>{var I;(I=a.value)===null||I===void 0||I.focus()}))}function Se(){var I,ie,Te;$.value||(e.passivelyActivated?(I=a.value)===null||I===void 0||I.focus():((ie=l.value)===null||ie===void 0||ie.focus(),(Te=c.value)===null||Te===void 0||Te.focus()))}function Ne(){var I;!((I=a.value)===null||I===void 0)&&I.contains(document.activeElement)&&document.activeElement.blur()}function rt(){var I,ie;(I=l.value)===null||I===void 0||I.select(),(ie=c.value)===null||ie===void 0||ie.select()}function Ue(){$.value||(l.value?l.value.focus():c.value&&c.value.focus())}function dt(){const{value:I}=a;(I==null?void 0:I.contains(document.activeElement))&&I!==document.activeElement&&he()}function Qe(I){const{type:ie,pair:Te,autosize:mt}=e;if(!Te&&mt)if(ie==="textarea"){const{value:vt}=s;vt&&(vt.textContent=(I!=null?I:"")+`\r -`)}else{const{value:vt}=d;vt&&(I?vt.textContent=I:vt.innerHTML=" ")}}function or(){_e()}const Ar=W({top:"0"});function xg(I){var ie;const{scrollTop:Te}=I.target;Ar.value.top=`${-Te}px`,(ie=f.value)===null||ie===void 0||ie.syncUnifiedContainer()}let Ri=null;xr(()=>{const{autosize:I,type:ie}=e;I&&ie==="textarea"?Ri=qe(g,Te=>{!Array.isArray(Te)&&Te!==R&&Qe(Te)}):Ri==null||Ri()});let zi=null;xr(()=>{e.type==="textarea"?zi=qe(g,I=>{var ie;!Array.isArray(I)&&I!==R&&((ie=f.value)===null||ie===void 0||ie.syncUnifiedContainer())}):zi==null||zi()}),je(Vm,{mergedValueRef:g,maxlengthRef:Ae,mergedClsPrefixRef:t});const Cg={wrapperElRef:a,inputElRef:c,textareaElRef:l,isCompositing:y,focus:Se,blur:Ne,select:rt,deactivate:dt,activate:Ue},yg=Pn("Input",n,t),td=L(()=>{const{value:I}=w,{common:{cubicBezierEaseInOut:ie},self:{color:Te,borderRadius:mt,textColor:vt,caretColor:$t,caretColorError:eo,caretColorWarning:to,textDecorationColor:ro,border:kn,borderDisabled:Tn,borderHover:nl,borderFocus:wg,placeholderColor:Sg,placeholderColorDisabled:_g,lineHeightTextarea:$g,colorDisabled:Pg,colorFocus:kg,textColorDisabled:Tg,boxShadowFocus:Eg,iconSize:Rg,colorFocusWarning:zg,boxShadowFocusWarning:Ag,borderWarning:Og,borderFocusWarning:Ig,borderHoverWarning:Mg,colorFocusError:Bg,boxShadowFocusError:Lg,borderError:Dg,borderFocusError:Fg,borderHoverError:Hg,clearSize:jg,clearColor:Ng,clearColorHover:Wg,clearColorPressed:Vg,iconColor:Kg,iconColorDisabled:Ug,suffixTextColor:qg,countTextColor:Gg,iconColorHover:Yg,iconColorPressed:Xg,loadingColor:Zg,loadingColorError:Jg,loadingColorWarning:Qg,[ae("padding",I)]:eb,[ae("fontSize",I)]:tb,[ae("height",I)]:rb}}=i.value,{left:ob,right:nb}=ap(eb);return{"--n-bezier":ie,"--n-count-text-color":Gg,"--n-color":Te,"--n-font-size":tb,"--n-border-radius":mt,"--n-height":rb,"--n-padding-left":ob,"--n-padding-right":nb,"--n-text-color":vt,"--n-caret-color":$t,"--n-text-decoration-color":ro,"--n-border":kn,"--n-border-disabled":Tn,"--n-border-hover":nl,"--n-border-focus":wg,"--n-placeholder-color":Sg,"--n-placeholder-color-disabled":_g,"--n-icon-size":Rg,"--n-line-height-textarea":$g,"--n-color-disabled":Pg,"--n-color-focus":kg,"--n-text-color-disabled":Tg,"--n-box-shadow-focus":Eg,"--n-loading-color":Zg,"--n-caret-color-warning":to,"--n-color-focus-warning":zg,"--n-box-shadow-focus-warning":Ag,"--n-border-warning":Og,"--n-border-focus-warning":Ig,"--n-border-hover-warning":Mg,"--n-loading-color-warning":Qg,"--n-caret-color-error":eo,"--n-color-focus-error":Bg,"--n-box-shadow-focus-error":Lg,"--n-border-error":Dg,"--n-border-focus-error":Fg,"--n-border-hover-error":Hg,"--n-loading-color-error":Jg,"--n-clear-color":Ng,"--n-clear-size":jg,"--n-clear-color-hover":Wg,"--n-clear-color-pressed":Vg,"--n-icon-color":Kg,"--n-icon-color-hover":Yg,"--n-icon-color-pressed":Xg,"--n-icon-color-disabled":Ug,"--n-suffix-text-color":qg}}),Ao=o?_t("input",L(()=>{const{value:I}=w;return I[0]}),td,e):void 0;return Object.assign(Object.assign({},Cg),{wrapperElRef:a,inputElRef:c,inputMirrorElRef:d,inputEl2Ref:u,textareaElRef:l,textareaMirrorElRef:s,textareaScrollbarInstRef:f,rtlEnabled:yg,uncontrolledValue:p,mergedValue:g,passwordVisible:A,mergedPlaceholder:P,showPlaceholder1:j,showPlaceholder2:T,mergedFocus:N,isComposing:y,activated:_,showClearButton:B,mergedSize:w,mergedDisabled:$,textDecorationStyle:te,mergedClsPrefix:t,mergedBordered:r,mergedShowPasswordOn:q,placeholderStyle:Ar,mergedStatus:x,textAreaScrollContainerWidth:se,handleTextAreaScroll:xg,handleCompositionStart:k,handleCompositionEnd:H,handleInput:U,handleInputBlur:X,handleInputFocus:ne,handleWrapperBlur:le,handleWrapperFocus:Y,handleMouseEnter:we,handleMouseLeave:De,handleMouseDown:me,handleChange:Q,handleClick:ve,handleClear:pe,handlePasswordToggleClick:Ye,handlePasswordToggleMousedown:Fe,handleWrapperKeyDown:Je,handleTextAreaMirrorResize:or,getTextareaScrollContainer:()=>l.value,mergedTheme:i,cssVars:o?void 0:td,themeClass:Ao==null?void 0:Ao.themeClass,onRender:Ao==null?void 0:Ao.onRender})},render(){const{mergedClsPrefix:e,mergedStatus:t,themeClass:r,onRender:o,$slots:n}=this;return o==null||o(),m("div",{ref:"wrapperElRef",class:[`${e}-input`,r,t&&`${e}-input--${t}-status`,{[`${e}-input--rtl`]:this.rtlEnabled,[`${e}-input--disabled`]:this.mergedDisabled,[`${e}-input--textarea`]:this.type==="textarea",[`${e}-input--resizable`]:this.resizable&&!this.autosize,[`${e}-input--autosize`]:this.autosize,[`${e}-input--round`]:this.round&&this.type!=="textarea",[`${e}-input--pair`]:this.pair,[`${e}-input--focus`]:this.mergedFocus,[`${e}-input--stateful`]:this.stateful}],style:this.cssVars,tabindex:!this.mergedDisabled&&this.passivelyActivated&&!this.activated?0:void 0,onFocus:this.handleWrapperFocus,onBlur:this.handleWrapperBlur,onClick:this.handleClick,onMousedown:this.handleMouseDown,onMouseenter:this.handleMouseEnter,onMouseleave:this.handleMouseLeave,onCompositionstart:this.handleCompositionStart,onCompositionend:this.handleCompositionEnd,onKeyup:this.onKeyup,onKeydown:this.handleWrapperKeyDown},m("div",{class:`${e}-input-wrapper`},bt(n.prefix,i=>i&&m("div",{class:`${e}-input__prefix`},i)),this.type==="textarea"?m(Em,{ref:"textareaScrollbarInstRef",class:`${e}-input__textarea`,container:this.getTextareaScrollContainer,triggerDisplayManually:!0,useUnifiedContainer:!0},{default:()=>{const{textAreaScrollContainerWidth:i}=this,a={width:this.autosize&&i&&`${i}px`};return m(ot,null,m("textarea",Object.assign({},this.inputProps,{ref:"textareaElRef",class:`${e}-input__textarea-el`,autofocus:this.autofocus,rows:Number(this.rows),placeholder:this.placeholder,value:this.mergedValue,disabled:this.mergedDisabled,maxlength:this.maxlength,minlength:this.minlength,readonly:this.readonly,tabindex:this.passivelyActivated&&!this.activated?-1:void 0,style:[this.textDecorationStyle[0],a],onBlur:this.handleInputBlur,onFocus:this.handleInputFocus,onInput:this.handleInput,onChange:this.handleChange,onScroll:this.handleTextAreaScroll})),this.showPlaceholder1?m("div",{class:`${e}-input__placeholder`,style:[this.placeholderStyle,a],key:"placeholder"},this.mergedPlaceholder[0]):null,this.autosize?m(vn,{onResize:this.handleTextAreaMirrorResize},{default:()=>m("div",{ref:"textareaMirrorElRef",class:`${e}-input__textarea-mirror`,key:"mirror"})}):null)}}):m("div",{class:`${e}-input__input`},m("input",Object.assign({type:this.type==="password"&&this.mergedShowPasswordOn&&this.passwordVisible?"text":this.type},this.inputProps,{ref:"inputElRef",class:`${e}-input__input-el`,style:this.textDecorationStyle[0],tabindex:this.passivelyActivated&&!this.activated?-1:void 0,placeholder:this.mergedPlaceholder[0],disabled:this.mergedDisabled,maxlength:this.maxlength,minlength:this.minlength,value:Array.isArray(this.mergedValue)?this.mergedValue[0]:this.mergedValue,readonly:this.readonly,autofocus:this.autofocus,size:this.attrSize,onBlur:this.handleInputBlur,onFocus:this.handleInputFocus,onInput:i=>this.handleInput(i,0),onChange:i=>this.handleChange(i,0)})),this.showPlaceholder1?m("div",{class:`${e}-input__placeholder`},m("span",null,this.mergedPlaceholder[0])):null,this.autosize?m("div",{class:`${e}-input__input-mirror`,key:"mirror",ref:"inputMirrorElRef"},"\xA0"):null),!this.pair&&bt(n.suffix,i=>i||this.clearable||this.showCount||this.mergedShowPasswordOn||this.loading!==void 0?m("div",{class:`${e}-input__suffix`},[bt(n.clear,a=>(this.clearable||a)&&m(ws,{clsPrefix:e,show:this.showClearButton,onClear:this.handleClear},{default:()=>a})),this.internalLoadingBeforeSuffix?null:i,this.loading!==void 0?m($3,{clsPrefix:e,loading:this.loading,showArrow:!1,showClear:!1,style:this.cssVars}):null,this.internalLoadingBeforeSuffix?i:null,this.showCount&&this.type!=="textarea"?m(ef,null,{default:a=>{var l;return(l=n.count)===null||l===void 0?void 0:l.call(n,a)}}):null,this.mergedShowPasswordOn&&this.type==="password"?m(Bt,{clsPrefix:e,class:`${e}-input__eye`,onMousedown:this.handlePasswordToggleMousedown,onClick:this.handlePasswordToggleClick},{default:()=>this.passwordVisible?_o(n["password-visible-icon"],()=>[m(y$,null)]):_o(n["password-invisible-icon"],()=>[m(w$,null)])}):null]):null)),this.pair?m("span",{class:`${e}-input__separator`},_o(n.separator,()=>[this.separator])):null,this.pair?m("div",{class:`${e}-input-wrapper`},m("div",{class:`${e}-input__input`},m("input",{ref:"inputEl2Ref",type:this.type,class:`${e}-input__input-el`,tabindex:this.passivelyActivated&&!this.activated?-1:void 0,placeholder:this.mergedPlaceholder[1],disabled:this.mergedDisabled,maxlength:this.maxlength,minlength:this.minlength,value:Array.isArray(this.mergedValue)?this.mergedValue[1]:void 0,readonly:this.readonly,style:this.textDecorationStyle[1],onBlur:this.handleInputBlur,onFocus:this.handleInputFocus,onInput:i=>this.handleInput(i,1),onChange:i=>this.handleChange(i,1)}),this.showPlaceholder2?m("div",{class:`${e}-input__placeholder`},m("span",null,this.mergedPlaceholder[1])):null),bt(n.suffix,i=>(this.clearable||i)&&m("div",{class:`${e}-input__suffix`},[this.clearable&&m(ws,{clsPrefix:e,show:this.showClearButton,onClear:this.handleClear},{default:()=>{var a;return(a=n.clear)===null||a===void 0?void 0:a.call(n)}}),i]))):null,this.mergedBordered?m("div",{class:`${e}-input__border`}):null,this.mergedBordered?m("div",{class:`${e}-input__state-border`}):null,this.showCount&&this.type==="textarea"?m(ef,null,{default:i=>{var a;return(a=n.count)===null||a===void 0?void 0:a.call(n,i)}}):null)}});function G3(e){const{boxShadow2:t}=e;return{menuBoxShadow:t}}const Y3={name:"AutoComplete",common:de,peers:{InternalSelectMenu:Si,Input:ur},self:G3};var X3=Y3;const Z3="n-avatar-group",Um=e=>{const{borderRadius:t,avatarColor:r,cardColor:o,fontSize:n,heightTiny:i,heightSmall:a,heightMedium:l,heightLarge:s,heightHuge:d,modalColor:c,popoverColor:u}=e;return{borderRadius:t,fontSize:n,border:`2px solid ${o}`,heightTiny:i,heightSmall:a,heightMedium:l,heightLarge:s,heightHuge:d,color:ye(o,r),colorModal:ye(c,r),colorPopover:ye(u,r)}},J3={name:"Avatar",common:Ke,self:Um};var Q3=J3;const e6={name:"Avatar",common:de,self:Um};var qm=e6,t6=M("avatar",` - width: var(--n-merged-size); - height: var(--n-merged-size); - color: #FFF; - font-size: var(--n-font-size); - display: inline-flex; - position: relative; - overflow: hidden; - text-align: center; - border: var(--n-border); - border-radius: var(--n-border-radius); - --n-merged-color: var(--n-color); - background-color: var(--n-merged-color); - transition: - border-color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - color .3s var(--n-bezier); -`,[dc(z("&","--n-merged-color: var(--n-color-modal);")),pp(z("&","--n-merged-color: var(--n-color-popover);")),z("img",` - width: 100%; - height: 100%; - `),F("text",` - white-space: nowrap; - display: inline-block; - position: absolute; - left: 50%; - top: 50%; - `),M("icon",` - vertical-align: bottom; - font-size: calc(var(--n-merged-size) - 6px); - `),F("text","line-height: 1.25")]);const r6=Object.assign(Object.assign({},ze.props),{size:[String,Number],src:String,circle:{type:Boolean,default:void 0},objectFit:String,round:{type:Boolean,default:void 0},bordered:{type:Boolean,default:void 0},onError:Function,fallbackSrc:String,color:String});var o6=oe({name:"Avatar",props:r6,setup(e){const{mergedClsPrefixRef:t,inlineThemeDisabled:r}=lt(e),o=W(!1);let n=null;const i=W(null),a=W(null),l=()=>{const{value:v}=i;if(v&&(n===null||n!==v.innerHTML)){n=v.innerHTML;const{value:w}=a;if(w){const{offsetWidth:$,offsetHeight:x}=w,{offsetWidth:S,offsetHeight:E}=v,y=.9,_=Math.min($/S*y,x/E*y,1);v.style.transform=`translateX(-50%) translateY(-50%) scale(${_})`}}},s=be(Z3,null),d=L(()=>{const{size:v}=e;if(v)return v;const{size:w}=s||{};return w||"medium"}),c=ze("Avatar","-avatar",t6,Q3,e,t),u=be(Dm,null),f=L(()=>{if(s)return!0;const{round:v,circle:w}=e;return v!==void 0||w!==void 0?v||w:u?u.roundRef.value:!1}),h=L(()=>s?!0:e.bordered||!1),p=v=>{o.value=!0;const{onError:w}=e;w&&w(v)};qe(()=>e.src,()=>o.value=!1);const b=L(()=>{const v=d.value,w=f.value,$=h.value,{color:x}=e,{self:{borderRadius:S,fontSize:E,color:y,border:_,colorModal:R,colorPopover:P},common:{cubicBezierEaseInOut:j}}=c.value;let T;return typeof v=="number"?T=`${v}px`:T=c.value.self[ae("height",v)],{"--n-font-size":E,"--n-border":$?_:"none","--n-border-radius":w?"50%":S,"--n-color":x||y,"--n-color-modal":x||R,"--n-color-popover":x||P,"--n-bezier":j,"--n-merged-size":`var(--n-avatar-size-override, ${T})`}}),g=r?_t("avatar",L(()=>{const v=d.value,w=f.value,$=h.value,{color:x}=e;let S="";return v&&(typeof v=="number"?S+=`a${v}`:S+=v[0]),w&&(S+="b"),$&&(S+="c"),x&&(S+=un(x)),S}),b,e):void 0;return{textRef:i,selfRef:a,mergedRoundRef:f,mergedClsPrefix:t,fitTextTransform:l,cssVars:r?void 0:b,themeClass:g==null?void 0:g.themeClass,onRender:g==null?void 0:g.onRender,hasLoadError:o,handleError:p}},render(){const{$slots:e,src:t,mergedClsPrefix:r,onRender:o}=this;o==null||o();let n;return this.hasLoadError?n=m("img",{src:this.fallbackSrc,style:{objectFit:this.objectFit}}):n=bt(e.default,i=>{if(i)return m(vn,{onResize:this.fitTextTransform},{default:()=>m("span",{ref:"textRef",class:`${r}-avatar__text`},i)});if(t)return m("img",{src:t,onError:this.handleError,style:{objectFit:this.objectFit}})}),m("span",{ref:"selfRef",class:[`${r}-avatar`,this.themeClass],style:this.cssVars},n)}});const n6={name:"AvatarGroup",common:de,peers:{Avatar:qm}};var i6=n6,a6={width:"44px",height:"44px",borderRadius:"22px",iconSize:"26px"};const l6={name:"BackTop",common:de,self(e){const{popoverColor:t,textColor2:r,primaryColorHover:o,primaryColorPressed:n}=e;return Object.assign(Object.assign({},a6),{color:t,textColor:r,iconColor:r,iconColorHover:o,iconColorPressed:n,boxShadow:"0 2px 8px 0px rgba(0, 0, 0, .12)",boxShadowHover:"0 2px 12px 0px rgba(0, 0, 0, .18)",boxShadowPressed:"0 2px 12px 0px rgba(0, 0, 0, .18)"})}};var s6=l6;const c6={name:"Badge",common:de,self(e){const{errorColorSuppl:t,infoColorSuppl:r,successColorSuppl:o,warningColorSuppl:n,fontFamily:i}=e;return{color:t,colorInfo:r,colorSuccess:o,colorError:t,colorWarning:n,fontSize:"12px",fontFamily:i}}};var d6=c6;const u6=e=>{const{errorColor:t,infoColor:r,successColor:o,warningColor:n,fontFamily:i}=e;return{color:t,colorInfo:r,colorSuccess:o,colorError:t,colorWarning:n,fontSize:"12px",fontFamily:i}},f6={name:"Badge",common:Ke,self:u6};var h6=f6,p6=z([z("@keyframes badge-wave-spread",{from:{boxShadow:"0 0 0.5px 0px var(--n-ripple-color)",opacity:.6},to:{boxShadow:"0 0 0.5px 4.5px var(--n-ripple-color)",opacity:0}}),M("badge",` - display: inline-flex; - position: relative; - vertical-align: middle; - color: var(--n-color); - font-family: var(--n-font-family); - `,[K("as-is",[M("badge-sup",{position:"static",transform:"translateX(0)"},[vi({transformOrigin:"left bottom",originalTransform:"translateX(0)"})])]),K("dot",[M("badge-sup",` - height: 8px; - width: 8px; - padding: 0; - min-width: 8px; - left: 100%; - bottom: calc(100% - 4px); - `,[z("::before","border-radius: 4px;")])]),M("badge-sup",` - background: var(--n-color); - transition: - background-color .3s var(--n-bezier), - color .3s var(--n-bezier); - color: #FFF; - position: absolute; - height: 18px; - line-height: 18px; - border-radius: 9px; - padding: 0 6px; - text-align: center; - font-size: var(--n-font-size); - transform: translateX(-50%); - left: 100%; - bottom: calc(100% - 9px); - font-variant-numeric: tabular-nums; - z-index: 1; - display: flex; - align-items: center; - `,[vi({transformOrigin:"left bottom",originalTransform:"translateX(-50%)"}),M("base-wave",{zIndex:1,animationDuration:"2s",animationIterationCount:"infinite",animationDelay:"1s",animationTimingFunction:"var(--n-ripple-bezier)",animationName:"badge-wave-spread"}),z("&::before",` - opacity: 0; - transform: scale(1); - border-radius: 9px; - content: ""; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - `)])])]);const m6=Object.assign(Object.assign({},ze.props),{value:[String,Number],max:Number,dot:Boolean,type:{type:String,default:"default"},show:{type:Boolean,default:!0},showZero:Boolean,processing:Boolean,color:String});var v6=oe({name:"Badge",props:m6,setup(e,{slots:t}){const{mergedClsPrefixRef:r,inlineThemeDisabled:o,mergedRtlRef:n}=lt(e),i=ze("Badge","-badge",p6,h6,e,r),a=W(!1),l=()=>{a.value=!0},s=()=>{a.value=!1},d=L(()=>e.show&&(e.dot||e.value!==void 0&&!(!e.showZero&&e.value<=0)||!cc(t.value)));Ot(()=>{d.value&&(a.value=!0)});const c=Pn("Badge",n,r),u=L(()=>{const{type:h,color:p}=e,{common:{cubicBezierEaseInOut:b,cubicBezierEaseOut:g},self:{[ae("color",h)]:v,fontFamily:w,fontSize:$}}=i.value;return{"--n-font-size":$,"--n-font-family":w,"--n-color":p||v,"--n-ripple-color":p||v,"--n-bezier":b,"--n-ripple-bezier":g}}),f=o?_t("badge",L(()=>{let h="";const{type:p,color:b}=e;return p&&(h+=p[0]),b&&(h+=un(b)),h}),u,e):void 0;return{rtlEnabled:c,mergedClsPrefix:r,appeared:a,showBadge:d,handleAfterEnter:l,handleAfterLeave:s,cssVars:o?void 0:u,themeClass:f==null?void 0:f.themeClass,onRender:f==null?void 0:f.onRender}},render(){var e;const{mergedClsPrefix:t,onRender:r,themeClass:o,$slots:n}=this;r==null||r();const i=(e=n.default)===null||e===void 0?void 0:e.call(n);return m("div",{class:[`${t}-badge`,this.rtlEnabled&&`${t}-badge--rtl`,o,{[`${t}-badge--dot`]:this.dot,[`${t}-badge--as-is`]:!i}],style:this.cssVars},i,m(At,{name:"fade-in-scale-up-transition",onAfterEnter:this.handleAfterEnter,onAfterLeave:this.handleAfterLeave},{default:()=>this.showBadge?m("sup",{class:`${t}-badge-sup`,title:RC(this.value)},_o(n.value,()=>[this.dot?null:m(A3,{clsPrefix:t,appeared:this.appeared,max:this.max,value:this.value})]),this.processing?m(zm,{clsPrefix:t}):null):null}))}}),g6={fontWeightActive:"400"};const b6=e=>{const{fontSize:t,textColor3:r,primaryColorHover:o,primaryColorPressed:n,textColor2:i}=e;return Object.assign(Object.assign({},g6),{fontSize:t,itemTextColor:r,itemTextColorHover:o,itemTextColorPressed:n,itemTextColorActive:i,separatorColor:r})},x6={name:"Breadcrumb",common:de,self:b6};var C6=x6;function ao(e){return ye(e,[255,255,255,.16])}function Ki(e){return ye(e,[0,0,0,.12])}var y6={paddingTiny:"0 6px",paddingSmall:"0 10px",paddingMedium:"0 14px",paddingLarge:"0 18px",paddingRoundTiny:"0 10px",paddingRoundSmall:"0 14px",paddingRoundMedium:"0 18px",paddingRoundLarge:"0 22px",iconMarginTiny:"6px",iconMarginSmall:"6px",iconMarginMedium:"6px",iconMarginLarge:"6px",iconSizeTiny:"14px",iconSizeSmall:"18px",iconSizeMedium:"18px",iconSizeLarge:"20px",rippleDuration:".6s"};const Gm=e=>{const{heightTiny:t,heightSmall:r,heightMedium:o,heightLarge:n,borderRadius:i,fontSizeTiny:a,fontSizeSmall:l,fontSizeMedium:s,fontSizeLarge:d,opacityDisabled:c,textColor2:u,textColor3:f,primaryColorHover:h,primaryColorPressed:p,borderColor:b,primaryColor:g,baseColor:v,infoColor:w,infoColorHover:$,infoColorPressed:x,successColor:S,successColorHover:E,successColorPressed:y,warningColor:_,warningColorHover:R,warningColorPressed:P,errorColor:j,errorColorHover:T,errorColorPressed:N,fontWeight:B,buttonColor2:q,buttonColor2Hover:A,buttonColor2Pressed:te,fontWeightStrong:se}=e;return Object.assign(Object.assign({},y6),{heightTiny:t,heightSmall:r,heightMedium:o,heightLarge:n,borderRadiusTiny:i,borderRadiusSmall:i,borderRadiusMedium:i,borderRadiusLarge:i,fontSizeTiny:a,fontSizeSmall:l,fontSizeMedium:s,fontSizeLarge:d,opacityDisabled:c,colorOpacitySecondary:"0.16",colorOpacitySecondaryHover:"0.22",colorOpacitySecondaryPressed:"0.28",colorSecondary:q,colorSecondaryHover:A,colorSecondaryPressed:te,colorTertiary:q,colorTertiaryHover:A,colorTertiaryPressed:te,colorQuaternary:"#0000",colorQuaternaryHover:A,colorQuaternaryPressed:te,color:"#0000",colorHover:"#0000",colorPressed:"#0000",colorFocus:"#0000",colorDisabled:"#0000",textColor:u,textColorTertiary:f,textColorHover:h,textColorPressed:p,textColorFocus:h,textColorDisabled:u,textColorText:u,textColorTextHover:h,textColorTextPressed:p,textColorTextFocus:h,textColorTextDisabled:u,textColorGhost:u,textColorGhostHover:h,textColorGhostPressed:p,textColorGhostFocus:h,textColorGhostDisabled:u,border:`1px solid ${b}`,borderHover:`1px solid ${h}`,borderPressed:`1px solid ${p}`,borderFocus:`1px solid ${h}`,borderDisabled:`1px solid ${b}`,rippleColor:g,colorPrimary:g,colorHoverPrimary:h,colorPressedPrimary:p,colorFocusPrimary:h,colorDisabledPrimary:g,textColorPrimary:v,textColorHoverPrimary:v,textColorPressedPrimary:v,textColorFocusPrimary:v,textColorDisabledPrimary:v,textColorTextPrimary:g,textColorTextHoverPrimary:h,textColorTextPressedPrimary:p,textColorTextFocusPrimary:h,textColorTextDisabledPrimary:u,textColorGhostPrimary:g,textColorGhostHoverPrimary:h,textColorGhostPressedPrimary:p,textColorGhostFocusPrimary:h,textColorGhostDisabledPrimary:g,borderPrimary:`1px solid ${g}`,borderHoverPrimary:`1px solid ${h}`,borderPressedPrimary:`1px solid ${p}`,borderFocusPrimary:`1px solid ${h}`,borderDisabledPrimary:`1px solid ${g}`,rippleColorPrimary:g,colorInfo:w,colorHoverInfo:$,colorPressedInfo:x,colorFocusInfo:$,colorDisabledInfo:w,textColorInfo:v,textColorHoverInfo:v,textColorPressedInfo:v,textColorFocusInfo:v,textColorDisabledInfo:v,textColorTextInfo:w,textColorTextHoverInfo:$,textColorTextPressedInfo:x,textColorTextFocusInfo:$,textColorTextDisabledInfo:u,textColorGhostInfo:w,textColorGhostHoverInfo:$,textColorGhostPressedInfo:x,textColorGhostFocusInfo:$,textColorGhostDisabledInfo:w,borderInfo:`1px solid ${w}`,borderHoverInfo:`1px solid ${$}`,borderPressedInfo:`1px solid ${x}`,borderFocusInfo:`1px solid ${$}`,borderDisabledInfo:`1px solid ${w}`,rippleColorInfo:w,colorSuccess:S,colorHoverSuccess:E,colorPressedSuccess:y,colorFocusSuccess:E,colorDisabledSuccess:S,textColorSuccess:v,textColorHoverSuccess:v,textColorPressedSuccess:v,textColorFocusSuccess:v,textColorDisabledSuccess:v,textColorTextSuccess:S,textColorTextHoverSuccess:E,textColorTextPressedSuccess:y,textColorTextFocusSuccess:E,textColorTextDisabledSuccess:u,textColorGhostSuccess:S,textColorGhostHoverSuccess:E,textColorGhostPressedSuccess:y,textColorGhostFocusSuccess:E,textColorGhostDisabledSuccess:S,borderSuccess:`1px solid ${S}`,borderHoverSuccess:`1px solid ${E}`,borderPressedSuccess:`1px solid ${y}`,borderFocusSuccess:`1px solid ${E}`,borderDisabledSuccess:`1px solid ${S}`,rippleColorSuccess:S,colorWarning:_,colorHoverWarning:R,colorPressedWarning:P,colorFocusWarning:R,colorDisabledWarning:_,textColorWarning:v,textColorHoverWarning:v,textColorPressedWarning:v,textColorFocusWarning:v,textColorDisabledWarning:v,textColorTextWarning:_,textColorTextHoverWarning:R,textColorTextPressedWarning:P,textColorTextFocusWarning:R,textColorTextDisabledWarning:u,textColorGhostWarning:_,textColorGhostHoverWarning:R,textColorGhostPressedWarning:P,textColorGhostFocusWarning:R,textColorGhostDisabledWarning:_,borderWarning:`1px solid ${_}`,borderHoverWarning:`1px solid ${R}`,borderPressedWarning:`1px solid ${P}`,borderFocusWarning:`1px solid ${R}`,borderDisabledWarning:`1px solid ${_}`,rippleColorWarning:_,colorError:j,colorHoverError:T,colorPressedError:N,colorFocusError:T,colorDisabledError:j,textColorError:v,textColorHoverError:v,textColorPressedError:v,textColorFocusError:v,textColorDisabledError:v,textColorTextError:j,textColorTextHoverError:T,textColorTextPressedError:N,textColorTextFocusError:T,textColorTextDisabledError:u,textColorGhostError:j,textColorGhostHoverError:T,textColorGhostPressedError:N,textColorGhostFocusError:T,textColorGhostDisabledError:j,borderError:`1px solid ${j}`,borderHoverError:`1px solid ${T}`,borderPressedError:`1px solid ${N}`,borderFocusError:`1px solid ${T}`,borderDisabledError:`1px solid ${j}`,rippleColorError:j,waveOpacity:"0.6",fontWeight:B,fontWeightStrong:se})},w6={name:"Button",common:Ke,self:Gm};var Xa=w6;const S6={name:"Button",common:de,self(e){const t=Gm(e);return t.waveOpacity="0.8",t.colorOpacitySecondary="0.16",t.colorOpacitySecondaryHover="0.2",t.colorOpacitySecondaryPressed="0.12",t}};var qt=S6;const ct="0!important",Ym="-1px!important";function Ho(e){return K(e+"-type",[z("& +",[M("button",{},[K(e+"-type",[F("border",{borderLeftWidth:ct}),F("state-border",{left:Ym})])])])])}function jo(e){return K(e+"-type",[z("& +",[M("button",[K(e+"-type",[F("border",{borderTopWidth:ct}),F("state-border",{top:Ym})])])])])}var _6=M("button-group",` - flex-wrap: nowrap; - display: inline-flex; - position: relative; -`,[ut("vertical",{flexDirection:"row"},[M("button",[z("&:first-child:not(:last-child)",` - margin-right: ${ct}; - border-top-right-radius: ${ct}; - border-bottom-right-radius: ${ct}; - `),z("&:last-child:not(:first-child)",` - margin-left: ${ct}; - border-top-left-radius: ${ct}; - border-bottom-left-radius: ${ct}; - `),z("&:not(:first-child):not(:last-child)",` - margin-left: ${ct}; - margin-right: ${ct}; - border-radius: ${ct}; - `),Ho("default"),K("ghost",[Ho("primary"),Ho("info"),Ho("success"),Ho("warning"),Ho("error")])])]),K("vertical",{flexDirection:"column"},[M("button",[z("&:first-child:not(:last-child)",` - margin-bottom: ${ct}; - margin-left: ${ct}; - margin-right: ${ct}; - border-bottom-left-radius: ${ct}; - border-bottom-right-radius: ${ct}; - `),z("&:last-child:not(:first-child)",` - margin-top: ${ct}; - margin-left: ${ct}; - margin-right: ${ct}; - border-top-left-radius: ${ct}; - border-top-right-radius: ${ct}; - `),z("&:not(:first-child):not(:last-child)",` - margin: ${ct}; - border-radius: ${ct}; - `),jo("default"),K("ghost",[jo("primary"),jo("info"),jo("success"),jo("warning"),jo("error")])])])]);const Xm="n-button-group",$6={size:{type:String,default:void 0},vertical:Boolean};var hO=oe({name:"ButtonGroup",props:$6,setup(e){const{mergedClsPrefixRef:t}=lt(e);return Jr("-button-group",_6,t),je(Xm,e),{mergedClsPrefix:t}},render(){const{mergedClsPrefix:e}=this;return m("div",{class:[`${e}-button-group`,this.vertical&&`${e}-button-group--vertical`],role:"group"},this.$slots)}}),P6=z([M("button",` - margin: 0; - font-weight: var(--n-font-weight); - line-height: 1; - font-family: inherit; - padding: var(--n-padding); - height: var(--n-height); - font-size: var(--n-font-size); - border-radius: var(--n-border-radius); - color: var(--n-text-color); - background-color: var(--n-color); - width: var(--n-width); - white-space: nowrap; - outline: none; - position: relative; - z-index: auto; - border: none; - display: inline-flex; - flex-wrap: nowrap; - flex-shrink: 0; - align-items: center; - justify-content: center; - user-select: none; - text-align: center; - cursor: pointer; - text-decoration: none; - transition: - color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - opacity .3s var(--n-bezier), - border-color .3s var(--n-bezier); - `,[K("color",[F("border",{borderColor:"var(--n-border-color)"}),K("disabled",[F("border",{borderColor:"var(--n-border-color-disabled)"})]),ut("disabled",[z("&:focus",[F("state-border",{borderColor:"var(--n-border-color-focus)"})]),z("&:hover",[F("state-border",{borderColor:"var(--n-border-color-hover)"})]),z("&:active",[F("state-border",{borderColor:"var(--n-border-color-pressed)"})]),K("pressed",[F("state-border",{borderColor:"var(--n-border-color-pressed)"})])])]),K("disabled",{backgroundColor:"var(--n-color-disabled)",color:"var(--n-text-color-disabled)"},[F("border",{border:"var(--n-border-disabled)"})]),ut("disabled",[z("&:focus",{backgroundColor:"var(--n-color-focus)",color:"var(--n-text-color-focus)"},[F("state-border",{border:"var(--n-border-focus)"})]),z("&:hover",{backgroundColor:"var(--n-color-hover)",color:"var(--n-text-color-hover)"},[F("state-border",{border:"var(--n-border-hover)"})]),z("&:active",{backgroundColor:"var(--n-color-pressed)",color:"var(--n-text-color-pressed)"},[F("state-border",{border:"var(--n-border-pressed)"})]),K("pressed",{backgroundColor:"var(--n-color-pressed)",color:"var(--n-text-color-pressed)"},[F("state-border",{border:"var(--n-border-pressed)"})])]),K("loading",{"pointer-events":"none"}),M("base-wave",` - pointer-events: none; - top: 0; - right: 0; - bottom: 0; - left: 0; - animation-iteration-count: 1; - animation-duration: var(--n-ripple-duration); - animation-timing-function: var(--n-bezier-ease-out), var(--n-bezier-ease-out); - `,[K("active",{zIndex:1,animationName:"button-wave-spread, button-wave-opacity"})]),typeof window!="undefined"&&"MozBoxSizing"in document.createElement("div").style?z("&::moz-focus-inner",{border:0}):null,F("border, state-border",` - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - border-radius: inherit; - transition: border-color .3s var(--n-bezier); - pointer-events: none; - `),F("border",{border:"var(--n-border)"}),F("state-border",{border:"var(--n-border)",borderColor:"#0000",zIndex:1}),F("icon",` - margin: var(--n-icon-margin); - margin-left: 0; - height: var(--n-icon-size); - width: var(--n-icon-size); - max-width: var(--n-icon-size); - font-size: var(--n-icon-size); - position: relative; - flex-shrink: 0; - `,[M("icon-slot",` - height: var(--n-icon-size); - width: var(--n-icon-size); - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - display: flex; - `,[pi({top:"50%",originalTransform:"translateY(-50%)"})]),Hm()]),F("content",` - display: flex; - align-items: center; - flex-wrap: nowrap; - `,[z("~",[F("icon",{margin:"var(--n-icon-margin)",marginRight:0})])]),K("block",` - display: flex; - width: 100%; - `),K("dashed",[F("border, state-border",{borderStyle:"dashed !important"})]),K("disabled",{cursor:"not-allowed",opacity:"var(--n-opacity-disabled)"})]),z("@keyframes button-wave-spread",{from:{boxShadow:"0 0 0.5px 0 var(--n-ripple-color)"},to:{boxShadow:"0 0 0.5px 4.5px var(--n-ripple-color)"}}),z("@keyframes button-wave-opacity",{from:{opacity:"var(--n-wave-opacity)"},to:{opacity:0}})]);const k6=Object.assign(Object.assign({},ze.props),{color:String,textColor:String,text:Boolean,block:Boolean,loading:Boolean,disabled:Boolean,circle:Boolean,size:String,ghost:Boolean,round:Boolean,secondary:Boolean,tertiary:Boolean,quaternary:Boolean,strong:Boolean,focusable:{type:Boolean,default:!0},keyboard:{type:Boolean,default:!0},tag:{type:String,default:"button"},type:{type:String,default:"default"},dashed:Boolean,iconPlacement:{type:String,default:"left"},attrType:{type:String,default:"button"},bordered:{type:Boolean,default:!0},onClick:[Function,Array],internalAutoFocus:Boolean}),Zm=oe({name:"Button",props:k6,setup(e){const t=W(null),r=W(null),o=W(!1);Ot(()=>{const{value:x}=t;x&&!e.disabled&&e.focusable&&e.internalAutoFocus&&x.focus({preventScroll:!0})});const n=ht(()=>!e.quaternary&&!e.tertiary&&!e.secondary&&!e.text&&(!e.color||e.ghost||e.dashed)&&e.bordered),i=be(Xm,{}),{mergedSizeRef:a}=wp({},{defaultSize:"medium",mergedSize:x=>{const{size:S}=e;if(S)return S;const{size:E}=i;if(E)return E;const{mergedSize:y}=x||{};return y?y.value:"medium"}}),l=L(()=>e.focusable&&!e.disabled),s=x=>{var S;x.preventDefault(),!e.disabled&&l.value&&((S=t.value)===null||S===void 0||S.focus({preventScroll:!0}))},d=x=>{var S;if(!e.disabled&&!e.loading){const{onClick:E}=e;E&&Be(E,x),e.text||(S=r.value)===null||S===void 0||S.play()}},c=x=>{switch(x.code){case"Enter":case"NumpadEnter":if(!e.keyboard)return;o.value=!1}},u=x=>{switch(x.code){case"Enter":case"NumpadEnter":if(!e.keyboard||e.loading){x.preventDefault();return}o.value=!0}},f=()=>{o.value=!1},{inlineThemeDisabled:h,mergedClsPrefixRef:p,mergedRtlRef:b}=lt(e),g=ze("Button","-button",P6,Xa,e,p),v=Pn("Button",b,p),w=L(()=>{const x=g.value,{common:{cubicBezierEaseInOut:S,cubicBezierEaseOut:E},self:y}=x,{rippleDuration:_,opacityDisabled:R,fontWeight:P,fontWeightStrong:j}=y,T=a.value,{dashed:N,type:B,ghost:q,text:A,color:te,round:se,circle:_e,textColor:Ae,secondary:Re,tertiary:Ee,quaternary:$e,strong:it}=e,O={"font-weight":it?j:P};let V={"--n-color":"initial","--n-color-hover":"initial","--n-color-pressed":"initial","--n-color-focus":"initial","--n-color-disabled":"initial","--n-ripple-color":"initial","--n-text-color":"initial","--n-text-color-hover":"initial","--n-text-color-pressed":"initial","--n-text-color-focus":"initial","--n-text-color-disabled":"initial"};const D=B==="tertiary",ce=B==="default",ue=D?"default":B;if(A){const Y=Ae||te,J=Y||y[ae("textColorText",ue)];V={"--n-color":"#0000","--n-color-hover":"#0000","--n-color-pressed":"#0000","--n-color-focus":"#0000","--n-color-disabled":"#0000","--n-ripple-color":"#0000","--n-text-color":J,"--n-text-color-hover":Y?ao(Y):y[ae("textColorTextHover",ue)],"--n-text-color-pressed":Y?Ki(Y):y[ae("textColorTextPressed",ue)],"--n-text-color-focus":Y?ao(Y):y[ae("textColorTextHover",ue)],"--n-text-color-disabled":Y||y[ae("textColorTextDisabled",ue)]}}else if(q||N){const Y=Ae||te;V={"--n-color":"#0000","--n-color-hover":"#0000","--n-color-pressed":"#0000","--n-color-focus":"#0000","--n-color-disabled":"#0000","--n-ripple-color":te||y[ae("rippleColor",ue)],"--n-text-color":Y||y[ae("textColorGhost",ue)],"--n-text-color-hover":Y?ao(Y):y[ae("textColorGhostHover",ue)],"--n-text-color-pressed":Y?Ki(Y):y[ae("textColorGhostPressed",ue)],"--n-text-color-focus":Y?ao(Y):y[ae("textColorGhostHover",ue)],"--n-text-color-disabled":Y||y[ae("textColorGhostDisabled",ue)]}}else if(Re){const Y=ce?y.textColor:D?y.textColorTertiary:y[ae("color",ue)],J=te||Y,Q=B!=="default"&&B!=="tertiary";V={"--n-color":Q?ee(J,{alpha:Number(y.colorOpacitySecondary)}):y.colorSecondary,"--n-color-hover":Q?ee(J,{alpha:Number(y.colorOpacitySecondaryHover)}):y.colorSecondaryHover,"--n-color-pressed":Q?ee(J,{alpha:Number(y.colorOpacitySecondaryPressed)}):y.colorSecondaryPressed,"--n-color-focus":Q?ee(J,{alpha:Number(y.colorOpacitySecondaryHover)}):y.colorSecondaryHover,"--n-color-disabled":y.colorSecondary,"--n-ripple-color":"#0000","--n-text-color":J,"--n-text-color-hover":J,"--n-text-color-pressed":J,"--n-text-color-focus":J,"--n-text-color-disabled":J}}else if(Ee||$e){const Y=ce?y.textColor:D?y.textColorTertiary:y[ae("color",ue)],J=te||Y;Ee?(V["--n-color"]=y.colorTertiary,V["--n-color-hover"]=y.colorTertiaryHover,V["--n-color-pressed"]=y.colorTertiaryPressed,V["--n-color-focus"]=y.colorSecondaryHover,V["--n-color-disabled"]=y.colorTertiary):(V["--n-color"]=y.colorQuaternary,V["--n-color-hover"]=y.colorQuaternaryHover,V["--n-color-pressed"]=y.colorQuaternaryPressed,V["--n-color-focus"]=y.colorQuaternaryHover,V["--n-color-disabled"]=y.colorQuaternary),V["--n-ripple-color"]="#0000",V["--n-text-color"]=J,V["--n-text-color-hover"]=J,V["--n-text-color-pressed"]=J,V["--n-text-color-focus"]=J,V["--n-text-color-disabled"]=J}else V={"--n-color":te||y[ae("color",ue)],"--n-color-hover":te?ao(te):y[ae("colorHover",ue)],"--n-color-pressed":te?Ki(te):y[ae("colorPressed",ue)],"--n-color-focus":te?ao(te):y[ae("colorFocus",ue)],"--n-color-disabled":te||y[ae("colorDisabled",ue)],"--n-ripple-color":te||y[ae("rippleColor",ue)],"--n-text-color":Ae||(te?y.textColorPrimary:D?y.textColorTertiary:y[ae("textColor",ue)]),"--n-text-color-hover":Ae||(te?y.textColorHoverPrimary:y[ae("textColorHover",ue)]),"--n-text-color-pressed":Ae||(te?y.textColorPressedPrimary:y[ae("textColorPressed",ue)]),"--n-text-color-focus":Ae||(te?y.textColorFocusPrimary:y[ae("textColorFocus",ue)]),"--n-text-color-disabled":Ae||(te?y.textColorDisabledPrimary:y[ae("textColorDisabled",ue)])};let xe={"--n-border":"initial","--n-border-hover":"initial","--n-border-pressed":"initial","--n-border-focus":"initial","--n-border-disabled":"initial"};A?xe={"--n-border":"none","--n-border-hover":"none","--n-border-pressed":"none","--n-border-focus":"none","--n-border-disabled":"none"}:xe={"--n-border":y[ae("border",ue)],"--n-border-hover":y[ae("borderHover",ue)],"--n-border-pressed":y[ae("borderPressed",ue)],"--n-border-focus":y[ae("borderFocus",ue)],"--n-border-disabled":y[ae("borderDisabled",ue)]};const{[ae("height",T)]:G,[ae("fontSize",T)]:Z,[ae("padding",T)]:C,[ae("paddingRound",T)]:k,[ae("iconSize",T)]:H,[ae("borderRadius",T)]:U,[ae("iconMargin",T)]:X,waveOpacity:ne}=y,le={"--n-width":_e&&!A?G:"initial","--n-height":A?"initial":G,"--n-font-size":Z,"--n-padding":_e||A?"initial":se?k:C,"--n-icon-size":H,"--n-icon-margin":X,"--n-border-radius":A?"initial":_e||se?G:U};return Object.assign(Object.assign(Object.assign(Object.assign({"--n-bezier":S,"--n-bezier-ease-out":E,"--n-ripple-duration":_,"--n-opacity-disabled":R,"--n-wave-opacity":ne},O),V),xe),le)}),$=h?_t("button",L(()=>{let x="";const{dashed:S,type:E,ghost:y,text:_,color:R,round:P,circle:j,textColor:T,secondary:N,tertiary:B,quaternary:q,strong:A}=e;S&&(x+="a"),y&&(x+="b"),_&&(x+="c"),P&&(x+="d"),j&&(x+="e"),N&&(x+="f"),B&&(x+="g"),q&&(x+="h"),A&&(x+="i"),R&&(x+="j"+un(R)),T&&(x+="k"+un(T));const{value:te}=a;return x+="l"+te[0],x+="m"+E[0],x}),w,e):void 0;return{selfElRef:t,waveElRef:r,mergedClsPrefix:p,mergedFocusable:l,mergedSize:a,showBorder:n,enterPressed:o,rtlEnabled:v,handleMousedown:s,handleKeydown:u,handleBlur:f,handleKeyup:c,handleClick:d,customColorCssVars:L(()=>{const{color:x}=e;if(!x)return null;const S=ao(x);return{"--n-border-color":x,"--n-border-color-hover":S,"--n-border-color-pressed":Ki(x),"--n-border-color-focus":S,"--n-border-color-disabled":x}}),cssVars:h?void 0:w,themeClass:$==null?void 0:$.themeClass,onRender:$==null?void 0:$.onRender}},render(){const{mergedClsPrefix:e,tag:t,onRender:r}=this;r==null||r();const o=bt(this.$slots.default,n=>n&&m("span",{class:`${e}-button__content`},n));return m(t,{ref:"selfElRef",class:[this.themeClass,`${e}-button`,`${e}-button--${this.type}-type`,`${e}-button--${this.mergedSize}-type`,this.rtlEnabled&&`${e}-button--rtl`,this.disabled&&`${e}-button--disabled`,this.block&&`${e}-button--block`,this.enterPressed&&`${e}-button--pressed`,!this.text&&this.dashed&&`${e}-button--dashed`,this.color&&`${e}-button--color`,this.secondary&&`${e}-button--secondary`,this.loading&&`${e}-button--loading`,this.ghost&&`${e}-button--ghost`],tabindex:this.mergedFocusable?0:-1,type:this.attrType,style:this.cssVars,disabled:this.disabled,onClick:this.handleClick,onBlur:this.handleBlur,onMousedown:this.handleMousedown,onKeyup:this.handleKeyup,onKeydown:this.handleKeydown},this.iconPlacement==="right"&&o,m(Ka,{width:!0},{default:()=>bt(this.$slots.icon,n=>(this.loading||n)&&m("span",{class:`${e}-button__icon`,style:{margin:cc(this.$slots.default)?"0":""}},m(Va,null,{default:()=>this.loading?m(Ua,{clsPrefix:e,key:"loading",class:`${e}-icon-slot`,strokeWidth:20}):m("div",{key:"icon",class:`${e}-icon-slot`,role:"none"},n)})))}),this.iconPlacement==="left"&&o,this.text?null:m(zm,{ref:"waveElRef",clsPrefix:e}),this.showBorder?m("div",{"aria-hidden":!0,class:`${e}-button__border`,style:this.customColorCssVars}):null,this.showBorder?m("div",{"aria-hidden":!0,class:`${e}-button__state-border`,style:this.customColorCssVars}):null)}});var Ca=Zm;const pO=Zm;var T6={titleFontSize:"22px"};const E6=e=>{const{borderRadius:t,fontSize:r,lineHeight:o,textColor2:n,textColor1:i,textColorDisabled:a,dividerColor:l,fontWeightStrong:s,primaryColor:d,baseColor:c,hoverColor:u,cardColor:f,modalColor:h,popoverColor:p}=e;return Object.assign(Object.assign({},T6),{borderRadius:t,borderColor:ye(f,l),borderColorModal:ye(h,l),borderColorPopover:ye(p,l),textColor:n,titleFontWeight:s,titleTextColor:i,dayTextColor:a,fontSize:r,lineHeight:o,dateColorCurrent:d,dateTextColorCurrent:c,cellColorHover:ye(f,u),cellColorHoverModal:ye(h,u),cellColorHoverPopover:ye(p,u),cellColor:f,cellColorModal:h,cellColorPopover:p,barColor:d})},R6={name:"Calendar",common:de,peers:{Button:qt},self:E6};var z6=R6;const A6=e=>{const{fontSize:t,boxShadow2:r,popoverColor:o,textColor2:n,borderRadius:i,borderColor:a,heightSmall:l,heightMedium:s,heightLarge:d,fontSizeSmall:c,fontSizeMedium:u,fontSizeLarge:f,dividerColor:h}=e;return{panelFontSize:t,boxShadow:r,color:o,textColor:n,borderRadius:i,border:`1px solid ${a}`,heightSmall:l,heightMedium:s,heightLarge:d,fontSizeSmall:c,fontSizeMedium:u,fontSizeLarge:f,dividerColor:h}},O6={name:"ColorPicker",common:de,peers:{Input:ur,Button:qt},self:A6};var I6=O6,M6={paddingSmall:"12px 16px 12px",paddingMedium:"19px 24px 20px",paddingLarge:"23px 32px 24px",paddingHuge:"27px 40px 28px",titleFontSizeSmall:"16px",titleFontSizeMedium:"18px",titleFontSizeLarge:"18px",titleFontSizeHuge:"18px",closeSize:"18px"};const Jm=e=>{const{primaryColor:t,borderRadius:r,lineHeight:o,fontSize:n,cardColor:i,textColor2:a,textColor1:l,dividerColor:s,fontWeightStrong:d,closeColor:c,closeColorHover:u,closeColorPressed:f,modalColor:h,boxShadow1:p,popoverColor:b,actionColor:g}=e;return Object.assign(Object.assign({},M6),{lineHeight:o,color:i,colorModal:h,colorPopover:b,colorTarget:t,colorEmbedded:g,textColor:a,titleTextColor:l,borderColor:s,actionColor:g,titleFontWeight:d,closeColor:c,closeColorHover:u,closeColorPressed:f,fontSizeSmall:n,fontSizeMedium:n,fontSizeLarge:n,fontSizeHuge:n,boxShadow:p,borderRadius:r})},B6={name:"Card",common:Ke,self:Jm};var Qm=B6;const L6={name:"Card",common:de,self(e){const t=Jm(e),{cardColor:r}=e;return t.colorEmbedded=r,t}};var ev=L6,D6=z([M("card",` - font-size: var(--n-font-size); - line-height: var(--n-line-height); - display: flex; - flex-direction: column; - width: 100%; - box-sizing: border-box; - position: relative; - border-radius: var(--n-border-radius); - background-color: var(--n-color); - color: var(--n-text-color); - transition: - color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - box-shadow .3s var(--n-bezier), - border-color .3s var(--n-bezier); - `,[K("hoverable",[z("&:hover","box-shadow: var(--n-box-shadow);")]),K("content-segmented",[z(">",[F("content",{paddingTop:"var(--n-padding-bottom)"})])]),K("content-soft-segmented",[z(">",[F("content",` - margin: 0 var(--n-padding-left); - padding: var(--n-padding-bottom) 0; - `)])]),K("footer-segmented",[z(">",[F("footer",{paddingTop:"var(--n-padding-bottom)"})])]),K("footer-soft-segmented",[z(">",[F("footer",` - padding: var(--n-padding-bottom) 0; - margin: 0 var(--n-padding-left); - `)])]),z(">",[M("card-header",` - box-sizing: border-box; - display: flex; - align-items: center; - font-size: var(--n-title-font-size); - padding: - var(--n-padding-top) - var(--n-padding-left) - var(--n-padding-bottom) - var(--n-padding-left); - `,[F("main",` - font-weight: var(--n-title-font-weight); - transition: color .3s var(--n-bezier); - flex: 1; - color: var(--n-title-text-color); - `),F("extra",` - display: flex; - align-items: center; - font-size: var(--n-font-size); - font-weight: 400; - transition: color .3s var(--n-bezier); - color: var(--n-text-color); - `),F("close",` - font-size: var(--n-close-size); - transition: color .3s var(--n-bezier); - `)]),F("action",` - box-sizing: border-box; - transition: - background-color .3s var(--n-bezier), - border-color .3s var(--n-bezier); - background-clip: padding-box; - background-color: var(--n-action-color); - `),F("content","flex: 1;"),F("content, footer",` - box-sizing: border-box; - padding: 0 var(--n-padding-left) var(--n-padding-bottom) var(--n-padding-left); - font-size: var(--n-font-size); - `,[z("&:first-child",{paddingTop:"var(--n-padding-bottom)"})]),F("action",` - background-color: var(--n-action-color); - padding: var(--n-padding-bottom) var(--n-padding-left); - border-bottom-left-radius: var(--n-border-radius); - border-bottom-right-radius: var(--n-border-radius); - `)]),M("card-cover",` - overflow: hidden; - width: 100%; - border-radius: var(--n-border-radius) var(--n-border-radius) 0 0; - `,[z("img",` - display: block; - width: 100%; - `)]),K("bordered",` - border: 1px solid var(--n-border-color); - `,[z("&:target","border-color: var(--n-color-target);")]),K("action-segmented",[z(">",[F("action",[z("&:not(:first-child)",{borderTop:"1px solid var(--n-border-color)"})])])]),K("content-segmented, content-soft-segmented",[z(">",[F("content",{transition:"border-color 0.3s var(--n-bezier)"},[z("&:not(:first-child)",{borderTop:"1px solid var(--n-border-color)"})])])]),K("footer-segmented, footer-soft-segmented",[z(">",[F("footer",{transition:"border-color 0.3s var(--n-bezier)"},[z("&:not(:first-child)",{borderTop:"1px solid var(--n-border-color)"})])])])]),dc(M("card",{background:"var(--n-color-modal)"})),pp(M("card",{background:"var(--n-color-popover)"})),M("card",[mp({background:"var(--n-color-modal)"})])]);const Ac={title:String,contentStyle:[Object,String],headerStyle:[Object,String],headerExtraStyle:[Object,String],footerStyle:[Object,String],embedded:Boolean,segmented:{type:[Boolean,Object],default:!1},size:{type:String,default:"medium"},bordered:{type:Boolean,default:!0},closable:{type:Boolean,default:!1},hoverable:Boolean,role:String,onClose:[Function,Array]},F6=er(Ac),H6=Object.assign(Object.assign({},ze.props),Ac);var Oc=oe({name:"Card",props:H6,setup(e){const t=()=>{const{onClose:d}=e;d&&Be(d)},{inlineThemeDisabled:r,mergedClsPrefixRef:o,mergedRtlRef:n}=lt(e),i=ze("Card","-card",D6,Qm,e,o),a=Pn("Card",n,o),l=L(()=>{const{size:d}=e,{self:{color:c,colorModal:u,colorTarget:f,textColor:h,titleTextColor:p,titleFontWeight:b,borderColor:g,actionColor:v,borderRadius:w,closeColor:$,closeColorHover:x,closeColorPressed:S,lineHeight:E,closeSize:y,boxShadow:_,colorPopover:R,colorEmbedded:P,[ae("padding",d)]:j,[ae("fontSize",d)]:T,[ae("titleFontSize",d)]:N},common:{cubicBezierEaseInOut:B}}=i.value,{top:q,left:A,bottom:te}=ap(j);return{"--n-bezier":B,"--n-border-radius":w,"--n-color":e.embedded?P:c,"--n-color-modal":u,"--n-color-popover":R,"--n-color-target":f,"--n-text-color":h,"--n-line-height":E,"--n-action-color":v,"--n-title-text-color":p,"--n-title-font-weight":b,"--n-close-color":$,"--n-close-color-hover":x,"--n-close-color-pressed":S,"--n-border-color":g,"--n-box-shadow":_,"--n-padding-top":q,"--n-padding-bottom":te,"--n-padding-left":A,"--n-font-size":T,"--n-title-font-size":N,"--n-close-size":y}}),s=r?_t("card",L(()=>e.size[0]),l,e):void 0;return{rtlEnabled:a,mergedClsPrefix:o,mergedTheme:i,handleCloseClick:t,cssVars:r?void 0:l,themeClass:s==null?void 0:s.themeClass,onRender:s==null?void 0:s.onRender}},render(){const{segmented:e,bordered:t,hoverable:r,mergedClsPrefix:o,rtlEnabled:n,onRender:i,$slots:a}=this;return i==null||i(),m("div",{class:[`${o}-card`,this.themeClass,{[`${o}-card--rtl`]:n,[`${o}-card--content${typeof e!="boolean"&&e.content==="soft"?"-soft":""}-segmented`]:e===!0||e!==!1&&e.content,[`${o}-card--footer${typeof e!="boolean"&&e.footer==="soft"?"-soft":""}-segmented`]:e===!0||e!==!1&&e.footer,[`${o}-card--action-segmented`]:e===!0||e!==!1&&e.action,[`${o}-card--bordered`]:t,[`${o}-card--hoverable`]:r}],style:this.cssVars,role:this.role},bt(a.cover,l=>l&&m("div",{class:`${o}-card-cover`,role:"none"},l)),bt(a.header,l=>l||this.title||this.closable?m("div",{class:`${o}-card-header`,style:this.headerStyle},m("div",{class:`${o}-card-header__main`,role:"heading"},l||[this.title]),bt(a["header-extra"],s=>s&&m("div",{class:`${o}-card-header__extra`,style:this.headerExtraStyle},s)),this.closable?m(yi,{clsPrefix:o,class:`${o}-card-header__close`,onClick:this.handleCloseClick}):null):null),bt(a.default,l=>l&&m("div",{class:`${o}-card__content`,style:this.contentStyle,role:"none"},l)),bt(a.footer,l=>l&&[m("div",{class:`${o}-card__footer`,style:this.footerStyle,role:"none"},l)]),bt(a.action,l=>l&&m("div",{class:`${o}-card__action`,role:"none"},l)))}});const j6=e=>({dotSize:"8px",dotColor:"rgba(255, 255, 255, .3)",dotColorActive:"rgba(255, 255, 255, 1)",dotColorFocus:"rgba(255, 255, 255, .5)",dotLineWidth:"16px",dotLineWidthActive:"24px",arrowColor:"#eee"}),N6={name:"Carousel",common:de,self:j6};var W6=N6,V6={sizeSmall:"14px",sizeMedium:"16px",sizeLarge:"18px",labelPadding:"0 8px"};const K6=e=>{const{baseColor:t,inputColorDisabled:r,cardColor:o,modalColor:n,popoverColor:i,textColorDisabled:a,borderColor:l,primaryColor:s,textColor2:d,fontSizeSmall:c,fontSizeMedium:u,fontSizeLarge:f,borderRadiusSmall:h,lineHeight:p}=e;return Object.assign(Object.assign({},V6),{labelLineHeight:p,fontSizeSmall:c,fontSizeMedium:u,fontSizeLarge:f,borderRadius:h,color:t,colorChecked:s,colorDisabled:r,colorDisabledChecked:r,colorTableHeader:o,colorTableHeaderModal:n,colorTableHeaderPopover:i,checkMarkColor:t,checkMarkColorDisabled:a,checkMarkColorDisabledChecked:a,border:`1px solid ${l}`,borderDisabled:`1px solid ${l}`,borderDisabledChecked:`1px solid ${l}`,borderChecked:`1px solid ${s}`,borderFocus:`1px solid ${s}`,boxShadowFocus:`0 0 0 2px ${ee(s,{alpha:.3})}`,textColor:d,textColorDisabled:a})},U6={name:"Checkbox",common:de,self(e){const{cardColor:t}=e,r=K6(e);return r.color="#0000",r.checkMarkColor=t,r}};var $i=U6;const q6=e=>{const{borderRadius:t,boxShadow2:r,popoverColor:o,textColor2:n,textColor3:i,primaryColor:a,textColorDisabled:l,dividerColor:s,hoverColor:d,fontSizeMedium:c,heightMedium:u}=e;return{menuBorderRadius:t,menuColor:o,menuBoxShadow:r,menuDividerColor:s,menuHeight:"calc(var(--n-option-height) * 6.6)",optionArrowColor:i,optionHeight:u,optionFontSize:c,optionColorHover:d,optionTextColor:n,optionTextColorActive:a,optionTextColorDisabled:l,optionCheckMarkColor:a,loadingColor:a,columnWidth:"180px"}},G6={name:"Cascader",common:de,peers:{InternalSelectMenu:Si,InternalSelection:zc,Scrollbar:Ut,Checkbox:$i,Empty:km},self:q6};var Y6=G6;const X6={name:"Code",common:de,self(e){const{textColor2:t,fontSize:r,fontWeightStrong:o}=e;return{textColor:t,fontSize:r,fontWeightStrong:o,"mono-3":"#5c6370","hue-1":"#56b6c2","hue-2":"#61aeee","hue-3":"#c678dd","hue-4":"#98c379","hue-5":"#e06c75","hue-5-2":"#be5046","hue-6":"#d19a66","hue-6-2":"#e6c07b"}}};var tv=X6;const Z6=e=>{const{fontWeight:t,textColor1:r,textColor2:o,dividerColor:n,fontSize:i}=e;return{titleFontSize:i,titleFontWeight:t,dividerColor:n,titleTextColor:r,fontSize:i,textColor:o,arrowColor:o}},J6={name:"Collapse",common:de,self:Z6};var Q6=J6;const e4=e=>{const{cubicBezierEaseInOut:t}=e;return{bezier:t}},t4={name:"CollapseTransition",common:de,self:e4};var r4=t4;const o4={abstract:Boolean,bordered:{type:Boolean,default:void 0},clsPrefix:String,locale:Object,dateLocale:Object,namespace:String,rtl:Array,tag:{type:String,default:"div"},hljs:Object,theme:Object,themeOverrides:Object,componentOptions:Object,icons:Object,breakpoints:Object,inlineThemeDisabled:{type:Boolean,default:void 0},as:{type:String,validator:()=>(Kr("config-provider","`as` is deprecated, please use `tag` instead."),!0),default:void 0}};var n4=oe({name:"ConfigProvider",alias:["App"],props:o4,setup(e){const t=be(Gr,null),r=L(()=>{const{theme:h}=e;if(h===null)return;const p=t==null?void 0:t.mergedThemeRef.value;return h===void 0?p:p===void 0?h:Object.assign({},p,h)}),o=L(()=>{const{themeOverrides:h}=e;if(h!==null){if(h===void 0)return t==null?void 0:t.mergedThemeOverridesRef.value;{const p=t==null?void 0:t.mergedThemeOverridesRef.value;return p===void 0?h:Xo({},p,h)}}}),n=ht(()=>{const{namespace:h}=e;return h===void 0?t==null?void 0:t.mergedNamespaceRef.value:h}),i=ht(()=>{const{bordered:h}=e;return h===void 0?t==null?void 0:t.mergedBorderedRef.value:h}),a=L(()=>{const{icons:h}=e;return h===void 0?t==null?void 0:t.mergedIconsRef.value:h}),l=L(()=>{const{componentOptions:h}=e;return h!==void 0?h:t==null?void 0:t.mergedComponentPropsRef.value}),s=L(()=>{const{clsPrefix:h}=e;return h!==void 0?h:t==null?void 0:t.mergedClsPrefixRef.value}),d=L(()=>{var h;const{rtl:p}=e;if(p===void 0)return t==null?void 0:t.mergedRtlRef.value;const b={};for(const g of p)b[g.name]=oa(g),(h=g.peers)===null||h===void 0||h.forEach(v=>{v.name in b||(b[v.name]=oa(v))});return b}),c=L(()=>e.breakpoints||(t==null?void 0:t.mergedBreakpointsRef.value)),u=e.inlineThemeDisabled||(t==null?void 0:t.inlineThemeDisabled),f=L(()=>{const{value:h}=r,{value:p}=o,b=p&&Object.keys(p).length!==0,g=h==null?void 0:h.name;return g?b?`${g}-${ci(JSON.stringify(o.value))}`:g:b?ci(JSON.stringify(o.value)):""});return je(Gr,{mergedThemeHashRef:f,mergedBreakpointsRef:c,mergedRtlRef:d,mergedIconsRef:a,mergedComponentPropsRef:l,mergedBorderedRef:i,mergedNamespaceRef:n,mergedClsPrefixRef:s,mergedLocaleRef:L(()=>{const{locale:h}=e;if(h!==null)return h===void 0?t==null?void 0:t.mergedLocaleRef.value:h}),mergedDateLocaleRef:L(()=>{const{dateLocale:h}=e;if(h!==null)return h===void 0?t==null?void 0:t.mergedDateLocaleRef.value:h}),mergedHljsRef:L(()=>{const{hljs:h}=e;return h===void 0?t==null?void 0:t.mergedHljsRef.value:h}),mergedThemeRef:r,mergedThemeOverridesRef:o,inlineThemeDisabled:u||!1}),{mergedClsPrefix:s,mergedBordered:i,mergedNamespace:n,mergedTheme:r,mergedThemeOverrides:o}},render(){var e,t,r,o;return this.abstract?(o=(r=this.$slots).default)===null||o===void 0?void 0:o.call(r):m(this.as||this.tag,{class:`${this.mergedClsPrefix||Qp}-config-provider`},(t=(e=this.$slots).default)===null||t===void 0?void 0:t.call(e))}});function rv(e){const{boxShadow2:t}=e;return{menuBoxShadow:t}}const i4={name:"Select",common:Ke,peers:{InternalSelection:T3,InternalSelectMenu:n3},self:rv};var a4=i4;const l4={name:"Select",common:de,peers:{InternalSelection:zc,InternalSelectMenu:Si},self:rv};var ov=l4,s4={itemSize:"28px",itemPadding:"0 4px",itemMargin:"0 0 0 8px",itemMarginRtl:"0 8px 0 0",buttonIconSize:"16px",inputWidth:"60px",selectWidth:"unset",inputMargin:"0 0 0 8px",inputMarginRtl:"0 8px 0 0",selectMargin:"0 0 0 8px",prefixMargin:"0 8px 0 0",suffixMargin:"0 0 0 8px",jumperFontSize:"14px"};const nv=e=>{const{textColor2:t,primaryColor:r,primaryColorHover:o,primaryColorPressed:n,inputColorDisabled:i,textColorDisabled:a,borderColor:l,borderRadius:s,fontSize:d}=e;return Object.assign(Object.assign({},s4),{buttonColor:"#0000",buttonColorHover:"#0000",buttonColorPressed:"#0000",buttonBorder:`1px solid ${l}`,buttonBorderHover:`1px solid ${l}`,buttonBorderPressed:`1px solid ${l}`,buttonIconColor:t,buttonIconColorHover:t,buttonIconColorPressed:t,itemTextColor:t,itemTextColorHover:o,itemTextColorPressed:n,itemTextColorActive:r,itemTextColorDisabled:a,itemColor:"#0000",itemColorHover:"#0000",itemColorPressed:"#0000",itemColorActive:"#0000",itemColorActiveHover:"#0000",itemColorDisabled:i,itemBorder:"1px solid #0000",itemBorderHover:"1px solid #0000",itemBorderPressed:"1px solid #0000",itemBorderActive:`1px solid ${r}`,itemBorderDisabled:`1px solid ${l}`,itemBorderRadius:s,itemFontSize:d,jumperTextColor:t,jumperTextColorDisabled:a})},c4={name:"Pagination",common:Ke,peers:{Select:a4,Input:Wm},self:nv};var mO=c4;const d4={name:"Pagination",common:de,peers:{Select:ov,Input:ur},self(e){const{primaryColor:t,opacity3:r}=e,o=ee(t,{alpha:Number(r)}),n=nv(e);return n.itemBorderActive=`1px solid ${o}`,n.itemBorderDisabled="1px solid #0000",n}};var iv=d4,av={padding:"8px 14px"};const u4={name:"Tooltip",common:de,peers:{Popover:zo},self(e){const{borderRadius:t,boxShadow2:r,popoverColor:o,textColor2:n}=e;return Object.assign(Object.assign({},av),{borderRadius:t,boxShadow:r,color:o,textColor:n})}};var Za=u4;const f4=e=>{const{borderRadius:t,boxShadow2:r,baseColor:o}=e;return Object.assign(Object.assign({},av),{borderRadius:t,boxShadow:r,color:ye(o,"rgba(0, 0, 0, .85)"),textColor:o})},h4={name:"Tooltip",common:Ke,peers:{Popover:_i},self:f4};var Ic=h4;const p4={name:"Ellipsis",common:de,peers:{Tooltip:Za}};var lv=p4,m4={radioSizeSmall:"14px",radioSizeMedium:"16px",radioSizeLarge:"18px",labelPadding:"0 8px"};const v4={name:"Radio",common:de,self(e){const{borderColor:t,primaryColor:r,baseColor:o,textColorDisabled:n,inputColorDisabled:i,textColor2:a,opacityDisabled:l,borderRadius:s,fontSizeSmall:d,fontSizeMedium:c,fontSizeLarge:u,heightSmall:f,heightMedium:h,heightLarge:p,lineHeight:b}=e;return Object.assign(Object.assign({},m4),{labelLineHeight:b,buttonHeightSmall:f,buttonHeightMedium:h,buttonHeightLarge:p,fontSizeSmall:d,fontSizeMedium:c,fontSizeLarge:u,boxShadow:`inset 0 0 0 1px ${t}`,boxShadowActive:`inset 0 0 0 1px ${r}`,boxShadowFocus:`inset 0 0 0 1px ${r}, 0 0 0 2px ${ee(r,{alpha:.3})}`,boxShadowHover:`inset 0 0 0 1px ${r}`,boxShadowDisabled:`inset 0 0 0 1px ${t}`,color:"#0000",colorDisabled:i,textColor:a,textColorDisabled:n,dotColorActive:r,dotColorDisabled:t,buttonBorderColor:t,buttonBorderColorActive:r,buttonBorderColorHover:r,buttonColor:"#0000",buttonColorActive:r,buttonTextColor:a,buttonTextColorActive:o,buttonTextColorHover:r,opacityDisabled:l,buttonBoxShadowFocus:`inset 0 0 0 1px ${r}, 0 0 0 2px ${ee(r,{alpha:.3})}`,buttonBoxShadowHover:`inset 0 0 0 1px ${r}`,buttonBoxShadow:"inset 0 0 0 1px #0000",buttonBorderRadius:s})}};var sv=v4,g4={thPaddingSmall:"8px",thPaddingMedium:"12px",thPaddingLarge:"12px",tdPaddingSmall:"8px",tdPaddingMedium:"12px",tdPaddingLarge:"12px",sorterSize:"15px",filterSize:"15px",paginationMargin:"12px 0 0 0",emptyPadding:"48px 0",actionPadding:"8px 12px",actionButtonMargin:"0 8px 0 0"};const b4=e=>{const{cardColor:t,modalColor:r,popoverColor:o,textColor2:n,textColor1:i,tableHeaderColor:a,tableColorHover:l,iconColor:s,primaryColor:d,fontWeightStrong:c,borderRadius:u,lineHeight:f,fontSizeSmall:h,fontSizeMedium:p,fontSizeLarge:b,dividerColor:g,heightSmall:v,opacityDisabled:w,tableColorStriped:$}=e;return Object.assign(Object.assign({},g4),{actionDividerColor:g,lineHeight:f,borderRadius:u,fontSizeSmall:h,fontSizeMedium:p,fontSizeLarge:b,borderColor:ye(t,g),tdColorHover:ye(t,l),tdColorStriped:ye(t,$),thColor:ye(t,a),thColorHover:ye(ye(t,a),l),tdColor:t,tdTextColor:n,thTextColor:i,thFontWeight:c,thButtonColorHover:l,thIconColor:s,thIconColorActive:d,borderColorModal:ye(r,g),tdColorHoverModal:ye(r,l),tdColorStripedModal:ye(r,$),thColorModal:ye(r,a),thColorHoverModal:ye(ye(r,a),l),tdColorModal:r,borderColorPopover:ye(o,g),tdColorHoverPopover:ye(o,l),tdColorStripedPopover:ye(o,$),thColorPopover:ye(o,a),thColorHoverPopover:ye(ye(o,a),l),tdColorPopover:o,boxShadowBefore:"inset -12px 0 8px -12px rgba(0, 0, 0, .18)",boxShadowAfter:"inset 12px 0 8px -12px rgba(0, 0, 0, .18)",loadingColor:d,loadingSize:v,opacityLoading:w})},x4={name:"DataTable",common:de,peers:{Button:qt,Checkbox:$i,Radio:sv,Pagination:iv,Scrollbar:Ut,Empty:wi,Popover:zo,Ellipsis:lv},self(e){const t=b4(e);return t.boxShadowAfter="inset 12px 0 8px -12px rgba(0, 0, 0, .36)",t.boxShadowBefore="inset -12px 0 8px -12px rgba(0, 0, 0, .36)",t}};var C4=x4;const y4=Object.assign(Object.assign({},Ya),ze.props);var cv=oe({name:"Tooltip",props:y4,__popover__:!0,setup(e){const t=ze("Tooltip","-tooltip",void 0,Ic,e),r=W(null);return Object.assign(Object.assign({},{syncPosition(){r.value.syncPosition()},setShow(n){r.value.setShow(n)}}),{popoverRef:r,mergedTheme:t,popoverThemeOverrides:L(()=>t.value.self)})},render(){const{mergedTheme:e,internalExtraClass:t}=this;return m(Mm,Object.assign(Object.assign({},this.$props),{theme:e.peers.Popover,themeOverrides:e.peerOverrides.Popover,builtinThemeOverrides:this.popoverThemeOverrides,internalExtraClass:t.concat("tooltip"),ref:"popoverRef"}),this.$slots)}}),w4={padding:"4px 0",optionIconSizeSmall:"14px",optionIconSizeMedium:"16px",optionIconSizeLarge:"16px",optionIconSizeHuge:"18px",optionSuffixWidthSmall:"14px",optionSuffixWidthMedium:"14px",optionSuffixWidthLarge:"16px",optionSuffixWidthHuge:"16px",optionIconSuffixWidthSmall:"32px",optionIconSuffixWidthMedium:"32px",optionIconSuffixWidthLarge:"36px",optionIconSuffixWidthHuge:"36px",optionPrefixWidthSmall:"14px",optionPrefixWidthMedium:"14px",optionPrefixWidthLarge:"16px",optionPrefixWidthHuge:"16px",optionIconPrefixWidthSmall:"36px",optionIconPrefixWidthMedium:"36px",optionIconPrefixWidthLarge:"40px",optionIconPrefixWidthHuge:"40px"};const dv=e=>{const{primaryColor:t,textColor2:r,dividerColor:o,hoverColor:n,popoverColor:i,invertedColor:a,borderRadius:l,fontSizeSmall:s,fontSizeMedium:d,fontSizeLarge:c,fontSizeHuge:u,heightSmall:f,heightMedium:h,heightLarge:p,heightHuge:b,textColor3:g,opacityDisabled:v}=e;return Object.assign(Object.assign({},w4),{optionHeightSmall:f,optionHeightMedium:h,optionHeightLarge:p,optionHeightHuge:b,borderRadius:l,fontSizeSmall:s,fontSizeMedium:d,fontSizeLarge:c,fontSizeHuge:u,optionTextColor:r,optionTextColorHover:r,optionTextColorActive:t,optionTextColorChildActive:t,color:i,dividerColor:o,suffixColor:r,prefixColor:r,optionColorHover:n,optionColorActive:ee(t,{alpha:.1}),groupHeaderTextColor:g,optionTextColorInverted:"#BBB",optionTextColorHoverInverted:"#FFF",optionTextColorActiveInverted:"#FFF",optionTextColorChildActiveInverted:"#FFF",colorInverted:a,dividerColorInverted:"#BBB",suffixColorInverted:"#BBB",prefixColorInverted:"#BBB",optionColorHoverInverted:t,optionColorActiveInverted:t,groupHeaderTextColorInverted:"#AAA",optionOpacityDisabled:v})},S4={name:"Dropdown",common:Ke,peers:{Popover:_i},self:dv};var uv=S4;const _4={name:"Dropdown",common:de,peers:{Popover:zo},self(e){const{primaryColorSuppl:t,primaryColor:r,popoverColor:o}=e,n=dv(e);return n.colorInverted=o,n.optionColorActive=ee(r,{alpha:.15}),n.optionColorActiveInverted=t,n.optionColorHoverInverted=t,n}};var fv=_4,hv=oe({name:"DropdownDivider",props:{clsPrefix:{type:String,required:!0}},render(){return m("div",{class:`${this.clsPrefix}-dropdown-divider`})}});const pv=e=>{const{textColorBase:t,opacity1:r,opacity2:o,opacity3:n,opacity4:i,opacity5:a}=e;return{color:t,opacity1Depth:r,opacity2Depth:o,opacity3Depth:n,opacity4Depth:i,opacity5Depth:a}},$4={name:"Icon",common:Ke,self:pv};var P4=$4;const k4={name:"Icon",common:de,self:pv};var T4=k4,E4=M("icon",` - height: 1em; - width: 1em; - line-height: 1em; - text-align: center; - display: inline-block; - position: relative; - fill: currentColor; - transform: translateZ(0); -`,[K("color-transition",{transition:"color .3s var(--n-bezier)"}),K("depth",{color:"var(--n-color)"},[z("svg",{opacity:"var(--n-opacity)",transition:"opacity .3s var(--n-bezier)"})]),z("svg",{height:"1em",width:"1em"})]);const Jo=oe({_n_icon__:!0,name:"Icon",inheritAttrs:!1,props:Object.assign(Object.assign({},ze.props),{depth:[String,Number],size:[Number,String],color:String,component:Object}),setup(e){const{mergedClsPrefixRef:t,inlineThemeDisabled:r}=lt(e),o=ze("Icon","-icon",E4,P4,e,t),n=L(()=>{const{depth:a}=e,{common:{cubicBezierEaseInOut:l},self:s}=o.value;if(a!==void 0){const{color:d,[`opacity${a}Depth`]:c}=s;return{"--n-bezier":l,"--n-color":d,"--n-opacity":c}}return{"--n-bezier":l,"--n-color":"","--n-opacity":""}}),i=r?_t("icon",L(()=>`${e.depth||"d"}`),n,e):void 0;return{mergedClsPrefix:t,mergedStyle:L(()=>{const{size:a,color:l}=e;return{fontSize:Qt(a),color:l}}),cssVars:r?void 0:n,themeClass:i==null?void 0:i.themeClass,onRender:i==null?void 0:i.onRender}},render(){var e;const{$parent:t,depth:r,mergedClsPrefix:o,component:n,onRender:i,themeClass:a}=this;return!((e=t==null?void 0:t.$options)===null||e===void 0)&&e._n_icon__&&Kr("icon","don't wrap `n-icon` inside `n-icon`"),i==null||i(),m("i",Xr(this.$attrs,{role:"img",class:[`${o}-icon`,a,{[`${o}-icon--depth`]:r,[`${o}-icon--color-transition`]:r!==void 0}],style:[this.cssVars,this.mergedStyle]}),n?m(n):this.$slots)}}),Mc="n-dropdown-menu",Ja="n-dropdown",tf="n-dropdown-option";function Ss(e,t){return e.type==="submenu"||e.type===void 0&&e[t]!==void 0}function R4(e){return e.type==="group"}function mv(e){return e.type==="divider"}function z4(e){return e.type==="render"}var vv=oe({name:"DropdownOption",props:{clsPrefix:{type:String,required:!0},tmNode:{type:Object,required:!0},parentKey:{type:[String,Number],default:null},placement:{type:String,default:"right-start"},props:Object},setup(e){const t=be(Ja),{hoverKeyRef:r,keyboardKeyRef:o,lastToggledSubmenuKeyRef:n,pendingKeyPathRef:i,activeKeyPathRef:a,animatedRef:l,mergedShowRef:s,renderLabelRef:d,renderIconRef:c,labelFieldRef:u,childrenFieldRef:f}=t,h=be(tf,null),p=be(Mc),b=L(()=>e.tmNode.rawNode),g=L(()=>{const{value:N}=f;return Ss(e.tmNode.rawNode,N)}),v=L(()=>{const{disabled:N}=e.tmNode;return N}),w=L(()=>{if(!g.value)return!1;const{key:N,disabled:B}=e.tmNode;if(B)return!1;const{value:q}=r,{value:A}=o,{value:te}=n,{value:se}=i;return q!==null?se.includes(N):A!==null?se.includes(N)&&se[se.length-1]!==N:te!==null?se.includes(N):!1}),$=L(()=>o.value===null&&!l.value),x=py(w,300,$),S=L(()=>!!(h!=null&&h.enteringSubmenuRef.value)),E=W(!1);je(tf,{enteringSubmenuRef:E});function y(){E.value=!0}function _(){E.value=!1}function R(){const{parentKey:N,tmNode:B}=e;!s.value||(n.value=N,o.value=null,r.value=B.key)}function P(){const{tmNode:N}=e;!s.value||r.value!==N.key&&R()}function j(N){if(!s.value)return;const{relatedTarget:B}=N;B&&!bC({target:B},"dropdownOption")&&(r.value=null)}function T(){const{value:N}=g,{tmNode:B}=e;!s.value||!N&&!B.disabled&&(t.doSelect(B.key,B.rawNode),t.doUpdateShow(!1))}return{labelField:u,renderLabel:d,renderIcon:c,siblingHasIcon:p.showIconRef,siblingHasSubmenu:p.hasSubmenuRef,animated:l,mergedShowSubmenu:L(()=>x.value&&!S.value),rawNode:b,hasSubmenu:g,pending:ht(()=>{const{value:N}=i,{key:B}=e.tmNode;return N.includes(B)}),childActive:ht(()=>{const{value:N}=a,{key:B}=e.tmNode,q=N.findIndex(A=>B===A);return q===-1?!1:q{const{value:N}=a,{key:B}=e.tmNode,q=N.findIndex(A=>B===A);return q===-1?!1:q===N.length-1}),mergedDisabled:v,handleClick:T,handleMouseMove:P,handleMouseEnter:R,handleMouseLeave:j,handleSubmenuBeforeEnter:y,handleSubmenuAfterEnter:_}},render(){var e;const{animated:t,rawNode:r,mergedShowSubmenu:o,clsPrefix:n,siblingHasIcon:i,siblingHasSubmenu:a,renderLabel:l,renderIcon:s,props:d}=this,c=o?m(gv,{clsPrefix:n,tmNodes:this.tmNode.children,parentKey:this.tmNode.key}):null,u={class:[`${n}-dropdown-option-body`,this.pending&&`${n}-dropdown-option-body--pending`,this.active&&`${n}-dropdown-option-body--active`,this.childActive&&`${n}-dropdown-option-body--child-active`,this.mergedDisabled&&`${n}-dropdown-option-body--disabled`],onMousemove:this.handleMouseMove,onMouseenter:this.handleMouseEnter,onMouseleave:this.handleMouseLeave,onClick:this.handleClick};return m("div",{class:`${n}-dropdown-option`},m("div",Xr(u,d),[m("div",{"data-dropdown-option":!0,class:[`${n}-dropdown-option-body__prefix`,i&&`${n}-dropdown-option-body__prefix--show-icon`]},[s?s(r):Ct(r.icon)]),m("div",{"data-dropdown-option":!0,class:`${n}-dropdown-option-body__label`},l?l(r):Ct((e=r[this.labelField])!==null&&e!==void 0?e:r.title)),m("div",{"data-dropdown-option":!0,class:[`${n}-dropdown-option-body__suffix`,a&&`${n}-dropdown-option-body__suffix--has-submenu`]},this.hasSubmenu?m(Jo,null,{default:()=>m(x$,null)}):null)]),this.hasSubmenu?m(dm,null,{default:()=>[m(um,null,{default:()=>m("div",{class:`${n}-dropdown-offset-container`},m(hm,{show:this.mergedShowSubmenu,placement:this.placement,teleportDisabled:!0},{default:()=>m("div",{class:`${n}-dropdown-menu-wrapper`},t?m(At,{onBeforeEnter:this.handleSubmenuBeforeEnter,onAfterEnter:this.handleSubmenuAfterEnter,name:"fade-in-scale-up-transition",appear:!0},{default:()=>c}):c)}))})]}):null)}}),A4=oe({name:"DropdownGroupHeader",props:{clsPrefix:{type:String,required:!0},tmNode:{type:Object,required:!0}},setup(){const{showIconRef:e,hasSubmenuRef:t}=be(Mc),{renderLabelRef:r,labelFieldRef:o}=be(Ja);return{labelField:o,showIcon:e,hasSubmenu:t,renderLabel:r}},render(){var e;const{clsPrefix:t,hasSubmenu:r,showIcon:o,renderLabel:n}=this,{rawNode:i}=this.tmNode;return m("div",{class:`${t}-dropdown-option`},m("div",{class:`${t}-dropdown-option-body ${t}-dropdown-option-body--group`},m("div",{"data-dropdown-option":!0,class:[`${t}-dropdown-option-body__prefix`,o&&`${t}-dropdown-option-body__prefix--show-icon`]},Ct(i.icon)),m("div",{class:`${t}-dropdown-option-body__label`,"data-dropdown-option":!0},n?n(i):Ct((e=i.title)!==null&&e!==void 0?e:i[this.labelField])),m("div",{class:[`${t}-dropdown-option-body__suffix`,r&&`${t}-dropdown-option-body__suffix--has-submenu`],"data-dropdown-option":!0})))}}),O4=oe({name:"NDropdownGroup",props:{clsPrefix:{type:String,required:!0},tmNode:{type:Object,required:!0},parentKey:{type:[String,Number],default:null}},render(){const{tmNode:e,parentKey:t,clsPrefix:r}=this,{children:o}=e;return m(ot,null,m(A4,{clsPrefix:r,tmNode:e,key:e.key}),o==null?void 0:o.map(n=>mv(n.rawNode)?m(hv,{clsPrefix:r,key:n.key}):n.isGroup?(Kr("dropdown","`group` node is not allowed to be put in `group` node."),null):m(vv,{clsPrefix:r,tmNode:n,parentKey:t,key:n.key})))}}),I4=oe({name:"DropdownRenderOption",props:{tmNode:{type:Object,required:!0}},render(){const{rawNode:{render:e,props:t}}=this.tmNode;return m("div",t,[e==null?void 0:e()])}}),gv=oe({name:"DropdownMenu",props:{showArrow:Boolean,arrowStyle:[String,Object],clsPrefix:{type:String,required:!0},tmNodes:{type:Array,default:()=>[]},parentKey:{type:[String,Number],default:null}},setup(e){const{renderIconRef:t,childrenFieldRef:r}=be(Ja);je(Mc,{showIconRef:L(()=>{const o=t.value;return e.tmNodes.some(n=>{var i;if(n.isGroup)return(i=n.children)===null||i===void 0?void 0:i.some(({rawNode:l})=>o?o(l):l.icon);const{rawNode:a}=n;return o?o(a):a.icon})}),hasSubmenuRef:L(()=>{const{value:o}=r;return e.tmNodes.some(n=>{var i;if(n.isGroup)return(i=n.children)===null||i===void 0?void 0:i.some(({rawNode:l})=>Ss(l,o));const{rawNode:a}=n;return Ss(a,o)})})})},render(){const{parentKey:e,clsPrefix:t}=this;return m("div",{class:`${t}-dropdown-menu`},this.tmNodes.map(r=>{const{rawNode:o}=r;return z4(o)?m(I4,{tmNode:r,key:r.key}):mv(o)?m(hv,{clsPrefix:t,key:r.key}):R4(o)?m(O4,{clsPrefix:t,tmNode:r,parentKey:e,key:r.key}):m(vv,{clsPrefix:t,tmNode:r,parentKey:e,key:r.key,props:o.props})}),this.showArrow?Im({clsPrefix:t,arrowStyle:this.arrowStyle}):null)}}),M4=M("dropdown-menu",` - transform-origin: inherit; - padding: var(--n-padding); - background-color: var(--n-color); - border-radius: var(--n-border-radius); - box-shadow: var(--n-box-shadow); - transition: - background-color .3s var(--n-bezier), - box-shadow .3s var(--n-bezier); -`,[vi(),M("dropdown-option",` - position: relative; - `,[z("a",` - text-decoration: none; - color: inherit; - `,[z("&::before",` - content: ""; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - `)]),M("dropdown-option-body",` - display: flex; - cursor: pointer; - height: var(--n-option-height); - line-height: var(--n-option-height); - font-size: var(--n-font-size); - color: var(--n-option-text-color); - transition: - background-color .3s var(--n-bezier), - color .3s var(--n-bezier); - `,[K("pending",[ut("disabled",{color:"var(--n-option-text-color-hover)",backgroundColor:"var(--n-option-color-hover)"}),F("prefix, suffix",{color:"var(--n-option-text-color-hover)"})]),K("active",[ut("disabled",{color:"var(--n-option-text-color-active)",backgroundColor:"var(--n-option-color-active)"}),F("prefix, suffix",{color:"var(--n-option-text-color-active)"})]),K("disabled",{cursor:"not-allowed",opacity:"var(--n-option-opacity-disabled)"}),K("child-active",{color:"var(--n-option-text-color-child-active)"},[F("prefix, suffix",{color:"var(--n-option-text-color-child-active)"})]),K("group",{fontSize:"calc(var(--n-font-size) - 1px)",color:"var(--n-group-header-text-color)"},[F("prefix",{width:"calc(var(--n-option-prefix-width) / 2)"},[K("show-icon",{width:"calc(var(--n-option-icon-prefix-width) / 2)"})])]),F("prefix",` - width: var(--n-option-prefix-width); - display: flex; - justify-content: center; - align-items: center; - color: var(--n-prefix-color); - transition: color .3s var(--n-bezier); - `,[K("show-icon",{width:"var(--n-option-icon-prefix-width)"}),M("icon",{fontSize:"var(--n-option-icon-size)"})]),F("label",{whiteSpace:"nowrap",flex:1}),F("suffix",` - box-sizing: border-box; - flex-grow: 0; - flex-shrink: 0; - display: flex; - justify-content: flex-end; - align-items: center; - min-width: var(--n-option-suffix-width); - padding: 0 8px; - transition: color .3s var(--n-bezier); - color: var(--n-suffix-color); - `,[K("has-submenu",{width:"var(--n-option-icon-suffix-width)"}),M("icon",{fontSize:"var(--n-option-icon-size)"})]),M("dropdown-menu",{pointerEvents:"all"})]),M("dropdown-offset-container",` - pointer-events: none; - position: absolute; - left: 0; - right: 0; - top: -4px; - bottom: -4px; - `)]),M("dropdown-divider",` - transition: background-color .3s var(--n-bezier); - background-color: var(--n-divider-color); - height: 1px; - margin: 4px 0; - `),M("dropdown-menu-wrapper",` - transform-origin: inherit; - width: fit-content; - `)]);const B4={animated:{type:Boolean,default:!0},keyboard:{type:Boolean,default:!0},size:{type:String,default:"medium"},inverted:Boolean,placement:{type:String,default:"bottom"},onSelect:[Function,Array],options:{type:Array,default:()=>[]},showArrow:Boolean,renderLabel:Function,renderIcon:Function,labelField:{type:String,default:"label"},keyField:{type:String,default:"key"},childrenField:{type:String,default:"children"},value:[String,Number]},L4=Object.keys(Ya),D4=Object.assign(Object.assign(Object.assign({},Ya),B4),ze.props);var F4=oe({name:"Dropdown",inheritAttrs:!1,props:D4,setup(e){const t=W(!1),r=hn(Oe(e,"show"),t),o=L(()=>{const{keyField:T,childrenField:N}=e;return lm(e.options,{getKey(B){return B[T]},getDisabled(B){return B.disabled===!0},getIgnored(B){return B.type==="divider"||B.type==="render"},getChildren(B){return B[N]}})}),n=L(()=>o.value.treeNodes),i=W(null),a=W(null),l=W(null),s=L(()=>{var T,N,B;return(B=(N=(T=i.value)!==null&&T!==void 0?T:a.value)!==null&&N!==void 0?N:l.value)!==null&&B!==void 0?B:null}),d=L(()=>o.value.getPath(s.value).keyPath),c=L(()=>o.value.getPath(e.value).keyPath),u=ht(()=>e.keyboard&&r.value);uy({keydown:{ArrowUp:{prevent:!0,handler:S},ArrowRight:{prevent:!0,handler:x},ArrowDown:{prevent:!0,handler:E},ArrowLeft:{prevent:!0,handler:$},Escape:w},keyup:{Enter:y}},u);const{mergedClsPrefixRef:f,inlineThemeDisabled:h}=lt(e),p=ze("Dropdown","-dropdown",M4,uv,e,f);je(Ja,{labelFieldRef:Oe(e,"labelField"),childrenFieldRef:Oe(e,"childrenField"),renderLabelRef:Oe(e,"renderLabel"),renderIconRef:Oe(e,"renderIcon"),hoverKeyRef:i,keyboardKeyRef:a,lastToggledSubmenuKeyRef:l,pendingKeyPathRef:d,activeKeyPathRef:c,animatedRef:Oe(e,"animated"),mergedShowRef:r,doSelect:b,doUpdateShow:g}),qe(r,T=>{T||v()});function b(T,N){const{onSelect:B}=e;B&&Be(B,T,N)}function g(T){const{"onUpdate:show":N,onUpdateShow:B}=e;N&&Be(N,T),B&&Be(B,T),t.value=T}function v(){i.value=null,a.value=null,l.value=null}function w(){g(!1)}function $(){R("left")}function x(){R("right")}function S(){R("up")}function E(){R("down")}function y(){const T=_();T!=null&&T.isLeaf&&(b(T.key,T.rawNode),g(!1))}function _(){var T;const{value:N}=o,{value:B}=s;return!N||B===null?null:(T=N.getNode(B))!==null&&T!==void 0?T:null}function R(T){const{value:N}=s,{value:{getFirstAvailableNode:B}}=o;let q=null;if(N===null){const A=B();A!==null&&(q=A.key)}else{const A=_();if(A){let te;switch(T){case"down":te=A.getNext();break;case"up":te=A.getPrev();break;case"right":te=A.getChild();break;case"left":te=A.getParent();break}te&&(q=te.key)}}q!==null&&(i.value=null,a.value=q)}const P=L(()=>{const{size:T,inverted:N}=e,{common:{cubicBezierEaseInOut:B},self:q}=p.value,{padding:A,dividerColor:te,borderRadius:se,optionOpacityDisabled:_e,[ae("optionIconSuffixWidth",T)]:Ae,[ae("optionSuffixWidth",T)]:Re,[ae("optionIconPrefixWidth",T)]:Ee,[ae("optionPrefixWidth",T)]:$e,[ae("fontSize",T)]:it,[ae("optionHeight",T)]:O,[ae("optionIconSize",T)]:V}=q,D={"--n-bezier":B,"--n-font-size":it,"--n-padding":A,"--n-border-radius":se,"--n-option-height":O,"--n-option-prefix-width":$e,"--n-option-icon-prefix-width":Ee,"--n-option-suffix-width":Re,"--n-option-icon-suffix-width":Ae,"--n-option-icon-size":V,"--n-divider-color":te,"--n-option-opacity-disabled":_e};return N?(D["--n-color"]=q.colorInverted,D["--n-option-color-hover"]=q.optionColorHoverInverted,D["--n-option-color-active"]=q.optionColorActiveInverted,D["--n-option-text-color"]=q.optionTextColorInverted,D["--n-option-text-color-hover"]=q.optionTextColorHoverInverted,D["--n-option-text-color-active"]=q.optionTextColorActiveInverted,D["--n-option-text-color-child-active"]=q.optionTextColorChildActiveInverted,D["--n-prefix-color"]=q.prefixColorInverted,D["--n-suffix-color"]=q.suffixColorInverted,D["--n-group-header-text-color"]=q.groupHeaderTextColorInverted):(D["--n-color"]=q.color,D["--n-option-color-hover"]=q.optionColorHover,D["--n-option-color-active"]=q.optionColorActive,D["--n-option-text-color"]=q.optionTextColor,D["--n-option-text-color-hover"]=q.optionTextColorHover,D["--n-option-text-color-active"]=q.optionTextColorActive,D["--n-option-text-color-child-active"]=q.optionTextColorChildActive,D["--n-prefix-color"]=q.prefixColor,D["--n-suffix-color"]=q.suffixColor,D["--n-group-header-text-color"]=q.groupHeaderTextColor),D}),j=h?_t("dropdown",L(()=>`${e.size[0]}${e.inverted?"i":""}`),P,e):void 0;return{mergedClsPrefix:f,mergedTheme:p,tmNodes:n,mergedShow:r,doUpdateShow:g,cssVars:h?void 0:P,themeClass:j==null?void 0:j.themeClass,onRender:j==null?void 0:j.onRender}},render(){const e=(o,n,i,a,l)=>{var s;const{mergedClsPrefix:d}=this;(s=this.onRender)===null||s===void 0||s.call(this);const c={ref:zC(n),class:[o,`${d}-dropdown`,this.themeClass,this.trigger==="manual"&&`${d}-popover--manual-trigger`,this.showArrow&&`${d}-popover--show-arrow`],clsPrefix:d,tmNodes:this.tmNodes,style:[i,this.cssVars],showArrow:this.showArrow,arrowStyle:this.arrowStyle,onMouseenter:a,onMouseleave:l};return m(gv,Xr(this.$attrs,c))},{mergedTheme:t}=this,r={show:this.mergedShow,theme:t.peers.Popover,themeOverrides:t.peerOverrides.Popover,internalRenderBody:e,onUpdateShow:this.doUpdateShow};return m(Mm,Object.assign({},Vt(this.$props,L4),r),{trigger:()=>{var o,n;return(n=(o=this.$slots).default)===null||n===void 0?void 0:n.call(o)}})}}),H4={itemFontSize:"12px",itemHeight:"36px",itemWidth:"52px",panelActionPadding:"8px 0"};const j4=e=>{const{popoverColor:t,textColor2:r,primaryColor:o,hoverColor:n,dividerColor:i,opacityDisabled:a,boxShadow2:l,borderRadius:s,iconColor:d,iconColorDisabled:c}=e;return Object.assign(Object.assign({},H4),{panelColor:t,panelBoxShadow:l,panelDividerColor:i,itemTextColor:r,itemTextColorActive:o,itemColorHover:n,itemOpacityDisabled:a,itemBorderRadius:s,borderRadius:s,iconColor:d,iconColorDisabled:c})},N4={name:"TimePicker",common:de,peers:{Scrollbar:Ut,Button:qt,Input:ur},self:j4};var bv=N4,W4={itemSize:"24px",itemCellWidth:"38px",itemCellHeight:"32px",scrollItemWidth:"80px",scrollItemHeight:"40px",panelExtraFooterPadding:"8px 12px",panelActionPadding:"8px 12px",calendarTitlePadding:"0",calendarTitleHeight:"28px",arrowSize:"14px",panelHeaderPadding:"8px 12px",calendarDaysHeight:"32px",calendarTitleGridTempateColumns:"28px 28px 1fr 28px 28px",calendarLeftPaddingDate:"6px 12px 4px 12px",calendarLeftPaddingDatetime:"4px 12px",calendarLeftPaddingDaterange:"6px 12px 4px 12px",calendarLeftPaddingDatetimerange:"4px 12px",calendarLeftPaddingMonth:"0",calendarLeftPaddingYear:"0",calendarLeftPaddingQuarter:"0",calendarRightPaddingDate:"6px 12px 4px 12px",calendarRightPaddingDatetime:"4px 12px",calendarRightPaddingDaterange:"6px 12px 4px 12px",calendarRightPaddingDatetimerange:"4px 12px",calendarRightPaddingMonth:"0",calendarRightPaddingYear:"0",calendarRightPaddingQuarter:"0"};const V4=e=>{const{hoverColor:t,fontSize:r,textColor2:o,textColorDisabled:n,popoverColor:i,primaryColor:a,borderRadiusSmall:l,iconColor:s,iconColorDisabled:d,textColor1:c,dividerColor:u,boxShadow2:f,borderRadius:h,fontWeightStrong:p}=e;return Object.assign(Object.assign({},W4),{itemFontSize:r,calendarDaysFontSize:r,calendarTitleFontSize:r,itemTextColor:o,itemTextColorDisabled:n,itemTextColorActive:i,itemTextColorCurrent:a,itemColorIncluded:ee(a,{alpha:.1}),itemColorHover:t,itemColorDisabled:t,itemColorActive:a,itemBorderRadius:l,panelColor:i,panelTextColor:o,arrowColor:s,calendarTitleTextColor:c,calendarTitleColorHover:t,calendarDaysTextColor:o,panelHeaderDividerColor:u,calendarDaysDividerColor:u,calendarDividerColor:u,panelActionDividerColor:u,panelBoxShadow:f,panelBorderRadius:h,calendarTitleFontWeight:p,scrollItemBorderRadius:h,iconColor:s,iconColorDisabled:d})},K4={name:"DatePicker",common:de,peers:{Input:ur,Button:qt,TimePicker:bv,Scrollbar:Ut},self(e){const{popoverColor:t,hoverColor:r,primaryColor:o}=e,n=V4(e);return n.itemColorDisabled=ye(t,r),n.itemColorIncluded=ee(o,{alpha:.15}),n.itemColorHover=ye(t,r),n}};var U4=K4,q4={thPaddingBorderedSmall:"8px 12px",thPaddingBorderedMedium:"12px 16px",thPaddingBorderedLarge:"16px 24px",thPaddingSmall:"0",thPaddingMedium:"0",thPaddingLarge:"0",tdPaddingBorderedSmall:"8px 12px",tdPaddingBorderedMedium:"12px 16px",tdPaddingBorderedLarge:"16px 24px",tdPaddingSmall:"0 0 8px 0",tdPaddingMedium:"0 0 12px 0",tdPaddingLarge:"0 0 16px 0"};const G4=e=>{const{tableHeaderColor:t,textColor2:r,textColor1:o,cardColor:n,modalColor:i,popoverColor:a,dividerColor:l,borderRadius:s,fontWeightStrong:d,lineHeight:c,fontSizeSmall:u,fontSizeMedium:f,fontSizeLarge:h}=e;return Object.assign(Object.assign({},q4),{lineHeight:c,fontSizeSmall:u,fontSizeMedium:f,fontSizeLarge:h,titleTextColor:o,thColor:ye(n,t),thColorModal:ye(i,t),thColorPopover:ye(a,t),thTextColor:o,thFontWeight:d,tdTextColor:r,tdColor:n,tdColorModal:i,tdColorPopover:a,borderColor:ye(n,l),borderColorModal:ye(i,l),borderColorPopover:ye(a,l),borderRadius:s})},Y4={name:"Descriptions",common:de,self:G4};var X4=Y4,Z4={titleFontSize:"18px",padding:"16px 28px 20px 28px",iconSize:"28px",actionSpace:"12px",contentMargin:"8px 0 16px 0",iconMargin:"0 4px 0 0",iconMarginIconTop:"4px 0 8px 0",closeSize:"18px",closeMargin:"22px 28px 0 0",closeMarginIconTop:"12px 18px 0 0"};const xv=e=>{const{textColor1:t,textColor2:r,modalColor:o,closeColor:n,closeColorHover:i,closeColorPressed:a,infoColor:l,successColor:s,warningColor:d,errorColor:c,primaryColor:u,dividerColor:f,borderRadius:h,fontWeightStrong:p,lineHeight:b,fontSize:g}=e;return Object.assign(Object.assign({},Z4),{fontSize:g,lineHeight:b,border:`1px solid ${f}`,titleTextColor:t,textColor:r,color:o,closeColor:n,closeColorHover:i,closeColorPressed:a,iconColor:u,iconColorInfo:l,iconColorSuccess:s,iconColorWarning:d,iconColorError:c,borderRadius:h,titleFontWeight:p})},J4={name:"Dialog",common:Ke,peers:{Button:Xa},self:xv};var Cv=J4;const Q4={name:"Dialog",common:de,peers:{Button:qt},self:xv};var yv=Q4;const Qa={icon:Function,type:{type:String,default:"default"},title:[String,Function],closable:{type:Boolean,default:!0},negativeText:String,positiveText:String,positiveButtonProps:Object,negativeButtonProps:Object,content:[String,Function],action:Function,showIcon:{type:Boolean,default:!0},loading:Boolean,bordered:Boolean,iconPlacement:String,onPositiveClick:Function,onNegativeClick:Function,onClose:Function},wv=er(Qa);var ek=z([M("dialog",` - line-height: var(--n-line-height); - position: relative; - background: var(--n-color); - color: var(--n-text-color); - box-sizing: border-box; - margin: auto; - border-radius: var(--n-border-radius); - padding: var(--n-padding); - transition: - border-color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - color .3s var(--n-bezier); - `,[F("icon",{color:"var(--n-icon-color)"}),K("bordered",{border:"var(--n-border)"}),K("icon-top",[F("close",{margin:"var(--n-close-margin)"}),F("icon",{margin:"var(--n-icon-margin)"}),F("content",{textAlign:"center"}),F("title",{justifyContent:"center"}),F("action",{justifyContent:"center"})]),K("icon-left",[F("icon",{margin:"var(--n-icon-margin)"})]),F("close",` - font-size: var(--n-close-size); - position: absolute; - right: 0; - top: 0; - margin: var(--n-close-margin); - transition: .3s color var(--n-bezier); - z-index: 1; - `),F("content",` - font-size: var(--n-font-size); - margin: var(--n-content-margin); - position: relative; - word-break: break-word; - `,[K("last","margin-bottom: 0;")]),F("action",` - display: flex; - justify-content: flex-end; - `,[z("> *:not(:last-child)",{marginRight:"var(--n-action-space)"})]),F("icon",{fontSize:"var(--n-icon-size)",transition:"color .3s var(--n-bezier)"}),F("title",` - transition: color .3s var(--n-bezier); - display: flex; - align-items: center; - font-size: var(--n-title-font-size); - font-weight: var(--n-title-font-weight); - color: var(--n-title-text-color); - `),M("dialog-icon-container",{display:"flex",justifyContent:"center"})]),dc(M("dialog",` - width: 446px; - max-width: calc(100vw - 32px); - `)),M("dialog",[mp(` - width: 446px; - max-width: calc(100vw - 32px); - `)])]);const rf=m(rm,null),tk={default:rf,info:rf,success:m(om,null),warning:m(nm,null),error:m(tm,null)},Sv=oe({name:"Dialog",alias:["NimbusConfirmCard","Confirm"],props:Object.assign(Object.assign({},ze.props),Qa),setup(e){const{mergedComponentPropsRef:t,mergedClsPrefixRef:r,inlineThemeDisabled:o}=lt(e),n=L(()=>{var u,f;const{iconPlacement:h}=e;return h||((f=(u=t==null?void 0:t.value)===null||u===void 0?void 0:u.Dialog)===null||f===void 0?void 0:f.iconPlacement)||"left"});function i(u){const{onPositiveClick:f}=e;f&&f(u)}function a(u){const{onNegativeClick:f}=e;f&&f(u)}function l(){const{onClose:u}=e;u&&u()}const s=ze("Dialog","-dialog",ek,Cv,e,r),d=L(()=>{const{type:u}=e,f=n.value,{common:{cubicBezierEaseInOut:h},self:{fontSize:p,lineHeight:b,border:g,titleTextColor:v,textColor:w,color:$,closeColor:x,closeColorHover:S,closeColorPressed:E,borderRadius:y,titleFontWeight:_,titleFontSize:R,padding:P,iconSize:j,actionSpace:T,contentMargin:N,closeSize:B,[f==="top"?"iconMarginIconTop":"iconMargin"]:q,[f==="top"?"closeMarginIconTop":"closeMargin"]:A,[ae("iconColor",u)]:te}}=s.value;return{"--n-font-size":p,"--n-icon-color":te,"--n-bezier":h,"--n-close-margin":A,"--n-icon-margin":q,"--n-icon-size":j,"--n-close-size":B,"--n-close-color":x,"--n-close-color-hover":S,"--n-close-color-pressed":E,"--n-color":$,"--n-text-color":w,"--n-border-radius":y,"--n-padding":P,"--n-line-height":b,"--n-border":g,"--n-content-margin":N,"--n-title-font-size":R,"--n-title-font-weight":_,"--n-title-text-color":v,"--n-action-space":T}}),c=o?_t("dialog",L(()=>`${e.type[0]}${n.value[0]}`),d,e):void 0;return{mergedClsPrefix:r,mergedIconPlacement:n,mergedTheme:s,handlePositiveClick:i,handleNegativeClick:a,handleCloseClick:l,cssVars:o?void 0:d,themeClass:c==null?void 0:c.themeClass,onRender:c==null?void 0:c.onRender}},render(){var e;const{bordered:t,mergedIconPlacement:r,cssVars:o,closable:n,showIcon:i,title:a,content:l,action:s,negativeText:d,positiveText:c,positiveButtonProps:u,negativeButtonProps:f,handlePositiveClick:h,handleNegativeClick:p,mergedTheme:b,loading:g,type:v,mergedClsPrefix:w}=this;(e=this.onRender)===null||e===void 0||e.call(this);const $=i?m(Bt,{clsPrefix:w,class:`${w}-dialog__icon`},{default:()=>bt(this.$slots.icon,S=>S||(this.icon?Ct(this.icon):tk[this.type]))}):null,x=bt(this.$slots.action,S=>S||c||d||s?m("div",{class:`${w}-dialog__action`},S||(s?[Ct(s)]:[this.negativeText&&m(Ca,Object.assign({theme:b.peers.Button,themeOverrides:b.peerOverrides.Button,ghost:!0,size:"small",onClick:p},f),{default:()=>Ct(this.negativeText)}),this.positiveText&&m(Ca,Object.assign({theme:b.peers.Button,themeOverrides:b.peerOverrides.Button,size:"small",type:v==="default"?"primary":v,disabled:g,loading:g,onClick:h},u),{default:()=>Ct(this.positiveText)})])):null);return m("div",{class:[`${w}-dialog`,this.themeClass,`${w}-dialog--icon-${r}`,t&&`${w}-dialog--bordered`],style:o,role:"dialog"},n?m(yi,{clsPrefix:w,class:`${w}-dialog__close`,onClick:this.handleCloseClick}):null,i&&r==="top"?m("div",{class:`${w}-dialog-icon-container`},$):null,m("div",{class:`${w}-dialog__title`},i&&r==="left"?$:null,_o(this.$slots.header,()=>[Ct(a)])),m("div",{class:[`${w}-dialog__content`,x?"":`${w}-dialog__content--last`]},_o(this.$slots.default,()=>[Ct(l)])),x)}}),_v="n-dialog-provider",rk="n-dialog-api",$v=e=>{const{modalColor:t,textColor2:r,boxShadow3:o}=e;return{color:t,textColor:r,boxShadow:o}},ok={name:"Modal",common:Ke,peers:{Scrollbar:Rc,Dialog:Cv,Card:Qm},self:$v};var nk=ok;const ik={name:"Modal",common:de,peers:{Scrollbar:Ut,Dialog:yv,Card:ev},self:$v};var ak=ik;const Bc=Object.assign(Object.assign({},Ac),Qa),lk=er(Bc);var sk=oe({name:"ModalBody",inheritAttrs:!1,props:Object.assign(Object.assign({show:{type:Boolean,required:!0},preset:String,displayDirective:{type:String,required:!0},trapFocus:{type:Boolean,default:!0},autoFocus:{type:Boolean,default:!0}},Bc),{onClickoutside:{type:Function,required:!0},onBeforeLeave:{type:Function,required:!0},onAfterLeave:{type:Function,required:!0},onPositiveClick:{type:Function,required:!0},onNegativeClick:{type:Function,required:!0},onClose:{type:Function,required:!0},onAfterEnter:Function,onEsc:Function}),setup(e){const t=W(null),r=W(null),o=W(e.show),n=W(null),i=W(null);qe(Oe(e,"show"),v=>{v&&(o.value=!0)});const a=be(Cp);function l(){if(a.transformOriginRef.value==="center")return"";const{value:v}=n,{value:w}=i;if(v===null||w===null)return"";if(r.value){const $=r.value.containerScrollTop;return`${v}px ${w+$}px`}return""}function s(v){if(a.transformOriginRef.value==="center")return;const w=a.getMousePosition();if(!w||!r.value)return;const $=r.value.containerScrollTop,{offsetLeft:x,offsetTop:S}=v;if(w){const E=w.y,y=w.x;n.value=-(x-y),i.value=-(S-E-$)}v.style.transformOrigin=l()}function d(v){br(()=>{s(v)})}function c(v){v.style.transformOrigin=l(),e.onBeforeLeave()}function u(){o.value=!1,n.value=null,i.value=null,e.onAfterLeave()}function f(){const{onClose:v}=e;v&&v()}function h(){e.onNegativeClick()}function p(){e.onPositiveClick()}function b(v){e.onClickoutside(v)}const g=W(null);return qe(g,v=>{v&&br(()=>{const w=v.el;w&&t.value!==w&&(t.value=w)})}),je(hc,t),je(pc,null),je(mc,null),{mergedTheme:a.mergedThemeRef,appear:a.appearRef,isMounted:a.isMountedRef,mergedClsPrefix:a.mergedClsPrefixRef,bodyRef:t,scrollbarRef:r,displayed:o,childNodeRef:g,handleClickOutside:b,handlePositiveClick:p,handleNegativeClick:h,handleCloseClick:f,handleAfterLeave:u,handleBeforeLeave:c,handleEnter:d}},render(){const{$slots:e,$attrs:t,handleEnter:r,handleAfterLeave:o,handleBeforeLeave:n,handleClickOutside:i,preset:a,mergedClsPrefix:l}=this;let s=null;if(!a){if(s=as(e),!s){Kr("modal","default slot is empty");return}s=lr(s),s.props=Xr({class:`${l}-modal`},t,s.props||{})}return this.displayDirective==="show"||this.displayed||this.show?Cr(m("div",{role:"none",class:`${l}-modal-body-wrapper`},m(Em,{ref:"scrollbarRef",theme:this.mergedTheme.peers.Scrollbar,themeOverrides:this.mergedTheme.peerOverrides.Scrollbar,contentClass:`${l}-modal-scroll-content`},{default:()=>m(Sm,{disabled:!this.trapFocus,active:this.show,onEsc:this.onEsc,autoFocus:this.autoFocus},{default:()=>{var d;return m(At,{name:"fade-in-scale-up-transition",appear:(d=this.appear)!==null&&d!==void 0?d:this.isMounted,onEnter:r,onAfterEnter:this.onAfterEnter,onAfterLeave:o,onBeforeLeave:n},{default:()=>Cr(this.preset==="confirm"||this.preset==="dialog"?m(Sv,Object.assign({},this.$attrs,{class:[`${l}-modal`,this.$attrs.class],ref:"bodyRef",theme:this.mergedTheme.peers.Dialog,themeOverrides:this.mergedTheme.peerOverrides.Dialog},Vt(this.$props,wv),{"aria-modal":"true"}),e):this.preset==="card"?m(Oc,Object.assign({},this.$attrs,{ref:"bodyRef",class:[`${l}-modal`,this.$attrs.class],theme:this.mergedTheme.peers.Card,themeOverrides:this.mergedTheme.peerOverrides.Card},Vt(this.$props,F6),{"aria-modal":"true",role:"dialog"}),e):this.childNodeRef=s,[[li,this.show],[Cs,i,void 0,{capture:!0}]])})}})})),[[li,this.displayDirective==="if"||this.displayed||this.show]]):null}}),ck=z([M("modal-container",` - position: fixed; - left: 0; - top: 0; - height: 0; - width: 0; - display: flex; - `),M("modal-mask",` - position: fixed; - left: 0; - right: 0; - top: 0; - bottom: 0; - background-color: rgba(0, 0, 0, .4); - `,[mi({enterDuration:".25s",leaveDuration:".25s",enterCubicBezier:"var(--n-bezier-ease-out)",leaveCubicBezier:"var(--n-bezier-ease-out)"})]),M("modal-body-wrapper",` - position: fixed; - left: 0; - right: 0; - top: 0; - bottom: 0; - overflow: visible; - `,[M("modal-scroll-content",` - min-height: 100%; - display: flex; - position: relative; - `)]),M("modal",` - align-self: center; - color: var(--n-text-color); - margin: auto; - box-shadow: var(--n-box-shadow); - `,[vi({duration:".25s",enterScale:".5"})])]);const dk=Object.assign(Object.assign(Object.assign(Object.assign({},ze.props),{show:Boolean,unstableShowMask:{type:Boolean,default:!0},maskClosable:{type:Boolean,default:!0},preset:String,to:[String,Object],displayDirective:{type:String,default:"if"},transformOrigin:{type:String,default:"mouse"},zIndex:Number,autoFocus:{type:Boolean,default:!0},trapFocus:{type:Boolean,default:!0},closeOnEsc:{type:Boolean,default:!0}}),Bc),{onEsc:Function,"onUpdate:show":[Function,Array],onUpdateShow:[Function,Array],onAfterEnter:Function,onBeforeLeave:Function,onAfterLeave:Function,onClose:Function,onPositiveClick:Function,onNegativeClick:Function,onMaskClick:Function,internalDialog:Boolean,internalAppear:{type:Boolean,default:void 0},overlayStyle:[String,Object],onBeforeHide:Function,onAfterHide:Function,onHide:Function});var Pv=oe({name:"Modal",inheritAttrs:!1,props:dk,setup(e){const t=W(null),{mergedClsPrefixRef:r,namespaceRef:o,inlineThemeDisabled:n}=lt(e),i=ze("Modal","-modal",ck,nk,e,r),a=xp(64),l=bp(),s=xi(),d=e.internalDialog?be(_v,null):null;function c(x){const{onUpdateShow:S,"onUpdate:show":E,onHide:y}=e;S&&Be(S,x),E&&Be(E,x),y&&!x&&y(x)}function u(){const{onClose:x}=e;x?Promise.resolve(x()).then(S=>{S!==!1&&c(!1)}):c(!1)}function f(){const{onPositiveClick:x}=e;x?Promise.resolve(x()).then(S=>{S!==!1&&c(!1)}):c(!1)}function h(){const{onNegativeClick:x}=e;x?Promise.resolve(x()).then(S=>{S!==!1&&c(!1)}):c(!1)}function p(){const{onBeforeLeave:x,onBeforeHide:S}=e;x&&Be(x),S&&S()}function b(){const{onAfterLeave:x,onAfterHide:S}=e;x&&Be(x),S&&S()}function g(x){var S;const{onMaskClick:E}=e;E&&E(x),e.maskClosable&&!((S=t.value)===null||S===void 0)&&S.contains(x.target)&&c(!1)}function v(x){var S;(S=e.onEsc)===null||S===void 0||S.call(e),e.closeOnEsc&&c(!1)}je(Cp,{getMousePosition:()=>{if(d){const{clickedRef:x,clickPositionRef:S}=d;if(x.value&&S.value)return S.value}return a.value?l.value:null},mergedClsPrefixRef:r,mergedThemeRef:i,isMountedRef:s,appearRef:Oe(e,"internalAppear"),transformOriginRef:Oe(e,"transformOrigin")});const w=L(()=>{const{common:{cubicBezierEaseOut:x},self:{boxShadow:S,color:E,textColor:y}}=i.value;return{"--n-bezier-ease-out":x,"--n-box-shadow":S,"--n-color":E,"--n-text-color":y}}),$=n?_t("theme-class",void 0,w,e):void 0;return{mergedClsPrefix:r,namespace:o,isMounted:s,containerRef:t,presetProps:L(()=>Vt(e,lk)),handleEsc:v,handleAfterLeave:b,handleClickoutside:g,handleBeforeLeave:p,doUpdateShow:c,handleNegativeClick:h,handlePositiveClick:f,handleCloseClick:u,cssVars:n?void 0:w,themeClass:$==null?void 0:$.themeClass,onRender:$==null?void 0:$.onRender}},render(){const{mergedClsPrefix:e}=this;return m(Ec,{to:this.to,show:this.show},{default:()=>{var t,r;return(t=this.onRender)===null||t===void 0||t.call(this),Cr(m("div",{role:"none",ref:"containerRef",class:[`${e}-modal-container`,this.themeClass,this.namespace],style:this.cssVars},this.unstableShowMask?m(At,{name:"fade-in-transition",key:"mask",appear:(r=this.internalAppear)!==null&&r!==void 0?r:this.isMounted},{default:()=>this.show?m("div",{"aria-hidden":!0,ref:"containerRef",class:`${e}-modal-mask`}):null}):null,m(sk,Object.assign({style:this.overlayStyle},this.$attrs,{ref:"bodyWrapper",displayDirective:this.displayDirective,show:this.show,preset:this.preset,autoFocus:this.autoFocus,trapFocus:this.trapFocus},this.presetProps,{onEsc:this.handleEsc,onClose:this.handleCloseClick,onNegativeClick:this.handleNegativeClick,onPositiveClick:this.handlePositiveClick,onBeforeLeave:this.handleBeforeLeave,onAfterEnter:this.onAfterEnter,onAfterLeave:this.handleAfterLeave,onClickoutside:this.handleClickoutside}),this.$slots)),[[qa,{zIndex:this.zIndex,enabled:this.show}]])}})}});const uk=Object.assign(Object.assign({},Qa),{closeOnEsc:{type:Boolean,default:!0},internalStyle:[String,Object],maskClosable:{type:Boolean,default:!0},onPositiveClick:Function,onNegativeClick:Function,onClose:Function,onMaskClick:Function}),fk=oe({name:"DialogEnvironment",props:Object.assign(Object.assign({},uk),{internalKey:{type:String,required:!0},to:[String,Object],onInternalAfterLeave:{type:Function,required:!0}}),setup(e){const t=W(!0);function r(){e.onInternalAfterLeave(e.internalKey)}function o(d){const{onPositiveClick:c}=e;c?Promise.resolve(c(d)).then(u=>{u!==!1&&l()}):l()}function n(d){const{onNegativeClick:c}=e;c?Promise.resolve(c(d)).then(u=>{u!==!1&&l()}):l()}function i(){const{onClose:d}=e;d?Promise.resolve(d()).then(c=>{c!==!1&&l()}):l()}function a(d){const{onMaskClick:c,maskClosable:u}=e;c&&(c(d),u&&l())}function l(){t.value=!1}function s(d){t.value=d}return{show:t,hide:l,handleUpdateShow:s,handleAfterLeave:r,handleCloseClick:i,handleNegativeClick:n,handlePositiveClick:o,handleMaskClick:a}},render(){const{handlePositiveClick:e,handleUpdateShow:t,handleNegativeClick:r,handleCloseClick:o,handleAfterLeave:n,handleMaskClick:i,to:a,maskClosable:l,show:s}=this;return m(Pv,{show:s,onUpdateShow:t,onMaskClick:i,to:a,maskClosable:l,onAfterLeave:n,closeOnEsc:this.closeOnEsc,internalAppear:!0,internalDialog:!0},{default:()=>m(Sv,Object.assign({},Vt(this.$props,wv),{style:this.internalStyle,onClose:o,onNegativeClick:r,onPositiveClick:e}))})}}),hk={injectionKey:String,to:[String,Object]},pk=oe({name:"DialogProvider",props:hk,setup(){const e=W([]),t={};function r(l={}){const s=dn(),d=ar(Object.assign(Object.assign({},l),{key:s,destroy:()=>{t[`n-dialog-${s}`].hide()}}));return e.value.push(d),d}const o=["info","success","warning","error"].map(l=>s=>r(Object.assign(Object.assign({},s),{type:l})));function n(l){const{value:s}=e;s.splice(s.findIndex(d=>d.key===l),1)}function i(){Object.values(t).forEach(l=>l.hide())}const a={create:r,destroyAll:i,info:o[0],success:o[1],warning:o[2],error:o[3]};return je(rk,a),je(_v,{clickedRef:xp(64),clickPositionRef:bp()}),Object.assign(Object.assign({},a),{dialogList:e,dialogInstRefs:t,handleAfterLeave:n})},render(){var e,t;return m(ot,null,[this.dialogList.map(r=>m(fk,sc(r,["destroy","style"],{internalStyle:r.style,to:this.to,ref:o=>{o===null?delete this.dialogInstRefs[`n-dialog-${r.key}`]:this.dialogInstRefs[`n-dialog-${r.key}`]=o},internalKey:r.key,onInternalAfterLeave:this.handleAfterLeave}))),(t=(e=this.$slots).default)===null||t===void 0?void 0:t.call(e)])}}),kv=e=>{const{textColor1:t,dividerColor:r,fontWeightStrong:o}=e;return{textColor:t,color:r,fontWeight:o}},mk={name:"Divider",common:Ke,self:kv};var vO=mk;const vk={name:"Divider",common:de,self:kv};var gk=vk;const bk=e=>{const{modalColor:t,textColor1:r,textColor2:o,boxShadow3:n,lineHeight:i,fontWeightStrong:a,dividerColor:l,closeColor:s,closeColorHover:d,closeColorPressed:c}=e;return{bodyPadding:"16px 24px",headerPadding:"16px 24px",footerPadding:"16px 24px",color:t,textColor:o,titleTextColor:r,titleFontSize:"18px",titleFontWeight:a,boxShadow:n,lineHeight:i,headerBorderBottom:`1px solid ${l}`,footerBorderTop:`1px solid ${l}`,closeColor:s,closeColorHover:d,closeColorPressed:c,closeSize:"18px"}},xk={name:"Drawer",common:de,peers:{Scrollbar:Ut},self:bk};var Ck=xk,yk={actionMargin:"0 0 0 20px"};const wk={name:"DynamicInput",common:de,peers:{Input:ur,Button:qt},self(){return yk}};var Sk=wk,Tv={gapSmall:"4px 8px",gapMedium:"8px 12px",gapLarge:"12px 16px"};const _k={name:"Space",self(){return Tv}};var Ev=_k;const $k=()=>Tv,Pk={name:"Space",self:$k};var kk=Pk;const Tk=Object.assign(Object.assign({},ze.props),{align:String,justify:{type:String,default:"start"},inline:Boolean,vertical:Boolean,size:{type:[String,Number,Array],default:"medium"},itemStyle:[String,Object],wrap:{type:Boolean,default:!0}});var Ek=oe({name:"Space",props:Tk,setup(e){const{mergedClsPrefixRef:t,mergedRtlRef:r}=lt(e),o=ze("Space","-space",void 0,kk,e,t);return{rtlEnabled:Pn("Space",r,t),mergedClsPrefix:t,margin:L(()=>{const{size:i}=e;if(Array.isArray(i))return{horizontal:i[0],vertical:i[1]};if(typeof i=="number")return{horizontal:i,vertical:i};const{self:{[ae("gap",i)]:a}}=o.value,{row:l,col:s}=CC(a);return{horizontal:tu(s),vertical:tu(l)}})}},render(){const{vertical:e,align:t,inline:r,justify:o,itemStyle:n,margin:i,wrap:a,mergedClsPrefix:l,rtlEnabled:s}=this,d=So(EC(this));if(!d.length)return null;const c=`${i.horizontal}px`,u=`${i.horizontal/2}px`,f=`${i.vertical}px`,h=`${i.vertical/2}px`,p=d.length-1,b=o.startsWith("space-");return m("div",{role:"none",class:[`${l}-space`,s&&`${l}-space--rtl`],style:{display:r?"inline-flex":"flex",flexDirection:e?"column":"row",justifyContent:["start","end"].includes(o)?"flex-"+o:o,flexWrap:!a||e?"nowrap":"wrap",marginTop:e?"":`-${h}`,marginBottom:e?"":`-${h}`,alignItems:t}},d.map((g,v)=>m("div",{role:"none",style:[n,{maxWidth:"100%"},e?{marginBottom:v!==p?f:""}:s?{marginLeft:b?o==="space-between"&&v===p?"":u:v!==p?c:"",marginRight:b?o==="space-between"&&v===0?"":u:"",paddingTop:h,paddingBottom:h}:{marginRight:b?o==="space-between"&&v===p?"":u:v!==p?c:"",marginLeft:b?o==="space-between"&&v===0?"":u:"",paddingTop:h,paddingBottom:h}]},g)))}});const Rk={name:"DynamicTags",common:de,peers:{Input:ur,Button:qt,Tag:Lm,Space:Ev},self(){return{inputWidth:"64px"}}};var zk=Rk;const Ak={name:"Element",common:de};var Ok=Ak,Ik={feedbackPadding:"4px 0 0 2px",feedbackHeightSmall:"24px",feedbackHeightMedium:"24px",feedbackHeightLarge:"26px",feedbackFontSizeSmall:"13px",feedbackFontSizeMedium:"14px",feedbackFontSizeLarge:"14px",labelFontSizeLeftSmall:"14px",labelFontSizeLeftMedium:"14px",labelFontSizeLeftLarge:"15px",labelFontSizeTopSmall:"13px",labelFontSizeTopMedium:"14px",labelFontSizeTopLarge:"14px",labelHeightSmall:"24px",labelHeightMedium:"26px",labelHeightLarge:"28px",labelPaddingVertical:"0 0 8px 2px",labelPaddingHorizontal:"0 12px 0 0",labelTextAlignVertical:"left",labelTextAlignHorizontal:"right"};const Rv=e=>{const{heightSmall:t,heightMedium:r,heightLarge:o,textColor1:n,errorColor:i,warningColor:a,lineHeight:l,textColor3:s}=e;return Object.assign(Object.assign({},Ik),{blankHeightSmall:t,blankHeightMedium:r,blankHeightLarge:o,lineHeight:l,labelTextColor:n,asteriskColor:i,feedbackTextColorError:i,feedbackTextColorWarning:a,feedbackTextColor:s})},Mk={name:"Form",common:Ke,self:Rv};var zv=Mk;const Bk={name:"Form",common:de,self:Rv};var Lk=Bk,Dk=M("form",[K("inline",` - width: 100%; - display: inline-flex; - align-items: flex-start; - align-content: space-around; - `,[M("form-item",{width:"auto",marginRight:"18px"},[z("&:last-child",{marginRight:0})])])]);const Pi="n-form",Av="n-form-item-insts";var Fk=globalThis&&globalThis.__awaiter||function(e,t,r,o){function n(i){return i instanceof r?i:new r(function(a){a(i)})}return new(r||(r=Promise))(function(i,a){function l(c){try{d(o.next(c))}catch(u){a(u)}}function s(c){try{d(o.throw(c))}catch(u){a(u)}}function d(c){c.done?i(c.value):n(c.value).then(l,s)}d((o=o.apply(e,t||[])).next())})};const Hk=Object.assign(Object.assign({},ze.props),{inline:Boolean,labelWidth:[Number,String],labelAlign:String,labelPlacement:{type:String,default:"top"},model:{type:Object,default:()=>{}},rules:Object,disabled:Boolean,size:String,showRequireMark:{type:Boolean,default:void 0},requireMarkPlacement:String,showFeedback:{type:Boolean,default:!0},onSubmit:{type:Function,default:e=>e.preventDefault()},showLabel:{type:Boolean,default:void 0},validateMessages:Object});var jk=oe({name:"Form",props:Hk,setup(e){const{mergedClsPrefixRef:t}=lt(e);ze("Form","-form",Dk,zv,e,t);const r={},o=W(void 0),n=s=>{const d=o.value;(d===void 0||s>=d)&&(o.value=s)};function i(s,d=()=>!0){return Fk(this,void 0,void 0,function*(){return yield new Promise((c,u)=>{const f=[];for(const h of er(r)){const p=r[h];for(const b of p)b.path&&f.push(b.internalValidate(null,d))}Promise.all(f).then(h=>{if(h.some(p=>!p.valid)){const p=h.filter(b=>b.errors).map(b=>b.errors);s&&s(p),u(p)}else s&&s(),c()})})})}function a(){for(const s of er(r)){const d=r[s];for(const c of d)c.restoreValidation()}}return je(Pi,{props:e,maxChildLabelWidthRef:o,deriveMaxChildLabelWidth:n}),je(Av,{formItems:r}),Object.assign({validate:i,restoreValidation:a},{mergedClsPrefix:t})},render(){const{mergedClsPrefix:e}=this;return m("form",{class:[`${e}-form`,this.inline&&`${e}-form--inline`],onSubmit:this.onSubmit},this.$slots)}});function xo(){return xo=Object.assign||function(e){for(var t=1;t1?t-1:0),o=1;o=i)return l;switch(l){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch{return"[Circular]"}break;default:return l}});return a}return e}function qk(e){return e==="string"||e==="url"||e==="hex"||e==="email"||e==="date"||e==="pattern"}function xt(e,t){return!!(e==null||t==="array"&&Array.isArray(e)&&!e.length||qk(t)&&typeof e=="string"&&!e)}function Gk(e,t,r){var o=[],n=0,i=e.length;function a(l){o.push.apply(o,l||[]),n++,n===i&&r(o)}e.forEach(function(l){t(l,a)})}function of(e,t,r){var o=0,n=e.length;function i(a){if(a&&a.length){r(a);return}var l=o;o=o+1,l()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+\.)+[a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}))$/,url:new RegExp("^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$","i"),hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},Wn={integer:function(t){return Wn.number(t)&&parseInt(t,10)===t},float:function(t){return Wn.number(t)&&!Wn.integer(t)},array:function(t){return Array.isArray(t)},regexp:function(t){if(t instanceof RegExp)return!0;try{return!!new RegExp(t)}catch{return!1}},date:function(t){return typeof t.getTime=="function"&&typeof t.getMonth=="function"&&typeof t.getYear=="function"&&!isNaN(t.getTime())},number:function(t){return isNaN(t)?!1:typeof t=="number"},object:function(t){return typeof t=="object"&&!Wn.array(t)},method:function(t){return typeof t=="function"},email:function(t){return typeof t=="string"&&t.length<=320&&!!t.match(Rl.email)},url:function(t){return typeof t=="string"&&t.length<=2048&&!!t.match(Rl.url)},hex:function(t){return typeof t=="string"&&!!t.match(Rl.hex)}},e8=function(t,r,o,n,i){if(t.required&&r===void 0){Ov(t,r,o,n,i);return}var a=["integer","float","array","regexp","object","method","email","number","date","url","hex"],l=t.type;a.indexOf(l)>-1?Wn[l](r)||n.push(Wt(i.messages.types[l],t.fullField,t.type)):l&&typeof r!==t.type&&n.push(Wt(i.messages.types[l],t.fullField,t.type))},t8=function(t,r,o,n,i){var a=typeof t.len=="number",l=typeof t.min=="number",s=typeof t.max=="number",d=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,c=r,u=null,f=typeof r=="number",h=typeof r=="string",p=Array.isArray(r);if(f?u="number":h?u="string":p&&(u="array"),!u)return!1;p&&(c=r.length),h&&(c=r.replace(d,"_").length),a?c!==t.len&&n.push(Wt(i.messages[u].len,t.fullField,t.len)):l&&!s&&ct.max?n.push(Wt(i.messages[u].max,t.fullField,t.max)):l&&s&&(ct.max)&&n.push(Wt(i.messages[u].range,t.fullField,t.min,t.max))},No="enum",r8=function(t,r,o,n,i){t[No]=Array.isArray(t[No])?t[No]:[],t[No].indexOf(r)===-1&&n.push(Wt(i.messages[No],t.fullField,t[No].join(", ")))},o8=function(t,r,o,n,i){if(t.pattern){if(t.pattern instanceof RegExp)t.pattern.lastIndex=0,t.pattern.test(r)||n.push(Wt(i.messages.pattern.mismatch,t.fullField,r,t.pattern));else if(typeof t.pattern=="string"){var a=new RegExp(t.pattern);a.test(r)||n.push(Wt(i.messages.pattern.mismatch,t.fullField,r,t.pattern))}}},He={required:Ov,whitespace:Qk,type:e8,range:t8,enum:r8,pattern:o8},n8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r,"string")&&!t.required)return o();He.required(t,r,n,a,i,"string"),xt(r,"string")||(He.type(t,r,n,a,i),He.range(t,r,n,a,i),He.pattern(t,r,n,a,i),t.whitespace===!0&&He.whitespace(t,r,n,a,i))}o(a)},i8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r)&&!t.required)return o();He.required(t,r,n,a,i),r!==void 0&&He.type(t,r,n,a,i)}o(a)},a8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(r===""&&(r=void 0),xt(r)&&!t.required)return o();He.required(t,r,n,a,i),r!==void 0&&(He.type(t,r,n,a,i),He.range(t,r,n,a,i))}o(a)},l8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r)&&!t.required)return o();He.required(t,r,n,a,i),r!==void 0&&He.type(t,r,n,a,i)}o(a)},s8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r)&&!t.required)return o();He.required(t,r,n,a,i),xt(r)||He.type(t,r,n,a,i)}o(a)},c8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r)&&!t.required)return o();He.required(t,r,n,a,i),r!==void 0&&(He.type(t,r,n,a,i),He.range(t,r,n,a,i))}o(a)},d8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r)&&!t.required)return o();He.required(t,r,n,a,i),r!==void 0&&(He.type(t,r,n,a,i),He.range(t,r,n,a,i))}o(a)},u8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(r==null&&!t.required)return o();He.required(t,r,n,a,i,"array"),r!=null&&(He.type(t,r,n,a,i),He.range(t,r,n,a,i))}o(a)},f8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r)&&!t.required)return o();He.required(t,r,n,a,i),r!==void 0&&He.type(t,r,n,a,i)}o(a)},h8="enum",p8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r)&&!t.required)return o();He.required(t,r,n,a,i),r!==void 0&&He[h8](t,r,n,a,i)}o(a)},m8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r,"string")&&!t.required)return o();He.required(t,r,n,a,i),xt(r,"string")||He.pattern(t,r,n,a,i)}o(a)},v8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r,"date")&&!t.required)return o();if(He.required(t,r,n,a,i),!xt(r,"date")){var s;r instanceof Date?s=r:s=new Date(r),He.type(t,s,n,a,i),s&&He.range(t,s.getTime(),n,a,i)}}o(a)},g8=function(t,r,o,n,i){var a=[],l=Array.isArray(r)?"array":typeof r;He.required(t,r,n,a,i,l),o(a)},zl=function(t,r,o,n,i){var a=t.type,l=[],s=t.required||!t.required&&n.hasOwnProperty(t.field);if(s){if(xt(r,a)&&!t.required)return o();He.required(t,r,n,l,i,a),xt(r,a)||He.type(t,r,n,l,i)}o(l)},b8=function(t,r,o,n,i){var a=[],l=t.required||!t.required&&n.hasOwnProperty(t.field);if(l){if(xt(r)&&!t.required)return o();He.required(t,r,n,a,i)}o(a)},Qn={string:n8,method:i8,number:a8,boolean:l8,regexp:s8,integer:c8,float:d8,array:u8,object:f8,enum:p8,pattern:m8,date:v8,url:zl,hex:zl,email:zl,required:g8,any:b8};function ks(){return{default:"Validation error on field %s",required:"%s is required",enum:"%s must be one of %s",whitespace:"%s cannot be empty",date:{format:"%s date %s is invalid for format %s",parse:"%s date could not be parsed, %s is invalid ",invalid:"%s date %s is invalid"},types:{string:"%s is not a %s",method:"%s is not a %s (function)",array:"%s is not an %s",object:"%s is not an %s",number:"%s is not a %s",date:"%s is not a %s",boolean:"%s is not a %s",integer:"%s is not an %s",float:"%s is not a %s",regexp:"%s is not a valid %s",email:"%s is not a valid %s",url:"%s is not a valid %s",hex:"%s is not a valid %s"},string:{len:"%s must be exactly %s characters",min:"%s must be at least %s characters",max:"%s cannot be longer than %s characters",range:"%s must be between %s and %s characters"},number:{len:"%s must equal %s",min:"%s cannot be less than %s",max:"%s cannot be greater than %s",range:"%s must be between %s and %s"},array:{len:"%s must be exactly %s in length",min:"%s cannot be less than %s in length",max:"%s cannot be greater than %s in length",range:"%s must be between %s and %s in length"},pattern:{mismatch:"%s value %s does not match pattern %s"},clone:function(){var t=JSON.parse(JSON.stringify(this));return t.clone=this.clone,t}}}var Ts=ks(),ki=function(){function e(r){this.rules=null,this._messages=Ts,this.define(r)}var t=e.prototype;return t.define=function(o){var n=this;if(!o)throw new Error("Cannot configure a schema with no rules");if(typeof o!="object"||Array.isArray(o))throw new Error("Rules must be an object");this.rules={},Object.keys(o).forEach(function(i){var a=o[i];n.rules[i]=Array.isArray(a)?a:[a]})},t.messages=function(o){return o&&(this._messages=lf(ks(),o)),this._messages},t.validate=function(o,n,i){var a=this;n===void 0&&(n={}),i===void 0&&(i=function(){});var l=o,s=n,d=i;if(typeof s=="function"&&(d=s,s={}),!this.rules||Object.keys(this.rules).length===0)return d&&d(null,l),Promise.resolve(l);function c(b){var g=[],v={};function w(x){if(Array.isArray(x)){var S;g=(S=g).concat.apply(S,x)}else g.push(x)}for(var $=0;$e.size!==void 0?e.size:(t==null?void 0:t.props.size)!==void 0?t.props.size:"medium")}}function C8(e){const t=be(Pi,null),r=L(()=>{if(o.value==="top")return;const{labelWidth:f}=e;if(f!==void 0&&f!=="auto")return Qt(f);if(f==="auto"||(t==null?void 0:t.props.labelWidth)==="auto"){const h=t==null?void 0:t.maxChildLabelWidthRef.value;return h!==void 0?Qt(h):void 0}if((t==null?void 0:t.props.labelWidth)!==void 0)return Qt(t.props.labelWidth)}),o=L(()=>{const{labelPlacement:f}=e;return f!==void 0?f:t!=null&&t.props.labelPlacement?t.props.labelPlacement:"top"}),n=L(()=>{const{labelAlign:f}=e;if(f)return f;if(t!=null&&t.props.labelAlign)return t.props.labelAlign}),i=L(()=>{var f;return[(f=e.labelProps)===null||f===void 0?void 0:f.style,e.labelStyle,{width:r.value}]}),a=L(()=>{const{showRequireMark:f}=e;return f!==void 0?f:t==null?void 0:t.props.showRequireMark}),l=L(()=>{const{requireMarkPlacement:f}=e;return f!==void 0?f:(t==null?void 0:t.props.requireMarkPlacement)||"right"}),s=W(!1),d=L(()=>{const{validationStatus:f}=e;if(f!==void 0)return f;if(s.value)return"error"}),c=L(()=>{const{showFeedback:f}=e;return f!==void 0?f:(t==null?void 0:t.props.showFeedback)!==void 0?t.props.showFeedback:!0}),u=L(()=>{const{showLabel:f}=e;return f!==void 0?f:(t==null?void 0:t.props.showLabel)!==void 0?t.props.showLabel:!0});return{validationErrored:s,mergedLabelStyle:i,mergedLabelPlacement:o,mergedLabelAlign:n,mergedShowRequireMark:a,mergedRequireMarkPlacement:l,mergedValidationStatus:d,mergedShowFeedback:c,mergedShowLabel:u}}function y8(e){const t=be(Pi,null),r=L(()=>{const{rulePath:a}=e;if(a!==void 0)return a;const{path:l}=e;if(l!==void 0)return l}),o=L(()=>{const a=[],{rule:l}=e;if(l!==void 0&&(Array.isArray(l)?a.push(...l):a.push(l)),t){const{rules:s}=t.props,{value:d}=r;if(s!==void 0&&d!==void 0){const c=Pc(s,d);c!==void 0&&(Array.isArray(c)?a.push(...c):a.push(c))}}return a}),n=L(()=>o.value.some(a=>a.required)),i=L(()=>n.value||e.required);return{mergedRules:o,mergedRequired:i}}var w8=oe({name:"FormItemFeedback",props:{clsPrefix:{type:String,required:!0},explains:Array,feedback:String},render(){var e;const{$slots:t,feedback:r,clsPrefix:o}=this;return t.default?t.default():r?m("div",{key:r,class:`${o}-form-item-feedback__line`},r):(e=this.explains)===null||e===void 0?void 0:e.map(n=>m("div",{key:n,class:`${o}-form-item-feedback__line`},n))}});const{cubicBezierEaseInOut:sf}=yr;function S8({name:e="fade-down",fromOffset:t="-4px",enterDuration:r=".3s",leaveDuration:o=".3s",enterCubicBezier:n=sf,leaveCubicBezier:i=sf}={}){return[z(`&.${e}-transition-enter-from, &.${e}-transition-leave-to`,{opacity:0,transform:`translateY(${t})`}),z(`&.${e}-transition-enter-to, &.${e}-transition-leave-from`,{opacity:1,transform:"translateY(0)"}),z(`&.${e}-transition-leave-active`,{transition:`opacity ${o} ${i}, transform ${o} ${i}`}),z(`&.${e}-transition-enter-active`,{transition:`opacity ${r} ${n}, transform ${r} ${n}`})]}var _8=M("form-item",{display:"grid",lineHeight:"var(--n-line-height)"},[M("form-item-label",` - grid-area: label; - align-items: center; - line-height: 1.25; - text-align: var(--n-label-text-align); - font-size: var(--n-label-font-size); - height: var(--n-label-height); - padding: var(--n-label-padding); - color: var(--n-label-text-color); - transition: color .3s var(--n-bezier); - box-sizing: border-box; - `,[F("asterisk",` - color: var(--n-asterisk-color); - transition: color .3s var(--n-bezier); - `),F("asterisk-placeholder",` - visibility: hidden; - `)]),M("form-item-blank",{gridArea:"blank",minHeight:"var(--n-blank-height)"}),K("left-labelled",` - grid-template-areas: - "label blank" - "label feedback"; - grid-template-columns: auto minmax(0, 1fr); - `,[M("form-item-label",` - height: var(--n-blank-height); - line-height: var(--n-blank-height); - box-sizing: border-box; - white-space: nowrap; - flex-shrink: 0; - flex-grow: 0; - `)]),K("top-labelled",` - grid-template-areas: - "label" - "blank" - "feedback"; - grid-template-rows: var(--n-label-height) 1fr; - grid-template-columns: minmax(0, 100%); - `,[K("no-label",` - grid-template-areas: - "blank" - "feedback"; - grid-template-rows: 1fr; - `),M("form-item-label",{display:"flex",alignItems:"flex-end",justifyContent:"var(--n-label-text-align)"})]),M("form-item-blank",` - box-sizing: border-box; - display: flex; - align-items: center; - position: relative; - `),M("form-item-feedback-wrapper",` - grid-area: feedback; - box-sizing: border-box; - min-height: var(--n-feedback-height); - font-size: var(--n-feedback-font-size); - line-height: 1.25; - transform-origin: top left; - `,[z("&:not(:empty)",` - padding: var(--n-feedback-padding); - `),M("form-item-feedback",{transition:"color .3s var(--n-bezier)",color:"var(--n-feedback-text-color)"},[K("warning",{color:"var(--n-feedback-text-color-warning)"}),K("error",{color:"var(--n-feedback-text-color-error)"}),S8({fromOffset:"-3px",enterDuration:".3s",leaveDuration:".2s"})])])]),cf=globalThis&&globalThis.__awaiter||function(e,t,r,o){function n(i){return i instanceof r?i:new r(function(a){a(i)})}return new(r||(r=Promise))(function(i,a){function l(c){try{d(o.next(c))}catch(u){a(u)}}function s(c){try{d(o.throw(c))}catch(u){a(u)}}function d(c){c.done?i(c.value):n(c.value).then(l,s)}d((o=o.apply(e,t||[])).next())})};const Lc=Object.assign(Object.assign({},ze.props),{label:String,labelWidth:[Number,String],labelStyle:[String,Object],labelAlign:String,labelPlacement:String,path:String,first:Boolean,rulePath:String,required:Boolean,showRequireMark:{type:Boolean,default:void 0},requireMarkPlacement:String,showFeedback:{type:Boolean,default:void 0},rule:[Object,Array],size:String,ignorePathChange:Boolean,validationStatus:String,feedback:String,showLabel:{type:Boolean,default:void 0},labelProps:Object}),$8=er(Lc);function df(e,t){return(...r)=>{try{const o=e(...r);return!t&&(typeof o=="boolean"||o instanceof Error||Array.isArray(o))||(o==null?void 0:o.then)?o:(o===void 0||Kr("form-item/validate",`You return a ${typeof o} typed value in the validator method, which is not recommended. Please use `+(t?"`Promise`":"`boolean`, `Error` or `Promise`")+" typed value instead."),!0)}catch(o){Kr("form-item/validate","An error is catched in the validation, so the validation won't be done. Your callback in `validate` method of `n-form` or `n-form-item` won't be called in this validation."),console.error(o);return}}}var P8=oe({name:"FormItem",props:Lc,setup(e){hy(Av,"formItems",Oe(e,"path"));const{mergedClsPrefixRef:t,inlineThemeDisabled:r}=lt(e),o=be(Pi,null),n=x8(e),i=C8(e),{validationErrored:a}=i,{mergedRequired:l,mergedRules:s}=y8(e),{mergedSize:d}=n,{mergedLabelPlacement:c,mergedLabelAlign:u}=i,f=W([]),h=W(dn()),p=L(()=>{const{feedback:T}=e;return T!=null?!0:f.value.length}),b=o?Oe(o.props,"disabled"):W(!1),g=ze("Form","-form-item",_8,zv,e,t);qe(Oe(e,"path"),()=>{e.ignorePathChange||v()});function v(){f.value=[],a.value=!1,e.feedback&&(h.value=dn())}function w(){y("blur")}function $(){y("change")}function x(){y("focus")}function S(){y("input")}function E(T,N){return cf(this,void 0,void 0,function*(){let B,q,A,te;return typeof T=="string"?(B=T,q=N):T!==null&&typeof T=="object"&&(B=T.trigger,q=T.callback,A=T.shouldRuleBeApplied,te=T.options),yield new Promise((se,_e)=>{y(B,A,te).then(({valid:Ae,errors:Re})=>{Ae?(q&&q(),se()):(q&&q(Re),_e(Re))})})})}const y=(T=null,N=()=>!0,B={suppressWarning:!0})=>cf(this,void 0,void 0,function*(){const{path:q}=e;B?B.first||(B.first=e.first):B={};const{value:A}=s,te=o?Pc(o.props.model,q||""):void 0,se=(T?A.filter(Ee=>Array.isArray(Ee.trigger)?Ee.trigger.includes(T):Ee.trigger===T):A).filter(N).map(Ee=>{const $e=Object.assign({},Ee);return $e.validator&&($e.validator=df($e.validator,!1)),$e.asyncValidator&&($e.asyncValidator=df($e.asyncValidator,!0)),$e});if(!se.length)return yield Promise.resolve({valid:!0});const _e=q!=null?q:"__n_no_path__",Ae=new ki({[_e]:se}),{validateMessages:Re}=(o==null?void 0:o.props)||{};return Re&&Ae.messages(Re),yield new Promise(Ee=>{Ae.validate({[_e]:te},B,($e,it)=>{$e!=null&&$e.length?(f.value=$e.map(O=>(O==null?void 0:O.message)||""),a.value=!0,Ee({valid:!1,errors:$e})):(v(),Ee({valid:!0}))})})});je(ss,{path:Oe(e,"path"),disabled:b,mergedSize:n.mergedSize,mergedValidationStatus:i.mergedValidationStatus,restoreValidation:v,handleContentBlur:w,handleContentChange:$,handleContentFocus:x,handleContentInput:S});const _={validate:E,restoreValidation:v,internalValidate:y},R=W(null);Ot(()=>{R.value!==null&&(o==null||o.deriveMaxChildLabelWidth(Number(getComputedStyle(R.value).width.slice(0,-2))))});const P=L(()=>{var T;const{value:N}=d,{value:B}=c,q=B==="top"?"vertical":"horizontal",{common:{cubicBezierEaseInOut:A},self:{labelTextColor:te,asteriskColor:se,lineHeight:_e,feedbackTextColor:Ae,feedbackTextColorWarning:Re,feedbackTextColorError:Ee,feedbackPadding:$e,[ae("labelHeight",N)]:it,[ae("blankHeight",N)]:O,[ae("feedbackFontSize",N)]:V,[ae("feedbackHeight",N)]:D,[ae("labelPadding",q)]:ce,[ae("labelTextAlign",q)]:ue,[ae(ae("labelFontSize",B),N)]:xe}}=g.value;let G=(T=u.value)!==null&&T!==void 0?T:ue;return B==="top"&&(G=G==="right"?"flex-end":"flex-start"),{"--n-bezier":A,"--n-line-height":_e,"--n-blank-height":O,"--n-label-font-size":xe,"--n-label-text-align":G,"--n-label-height":it,"--n-label-padding":ce,"--n-asterisk-color":se,"--n-label-text-color":te,"--n-feedback-padding":$e,"--n-feedback-font-size":V,"--n-feedback-height":D,"--n-feedback-text-color":Ae,"--n-feedback-text-color-warning":Re,"--n-feedback-text-color-error":Ee}}),j=_t("form-item",L(()=>{var T;return`${d.value[0]}${c.value[0]}${((T=u.value)===null||T===void 0?void 0:T[0])||""}`}),P,e);return Object.assign(Object.assign(Object.assign(Object.assign({labelElementRef:R,mergedClsPrefix:t,mergedRequired:l,hasFeedback:p,feedbackId:h,explains:f},i),n),_),{cssVars:r?void 0:P,themeClass:j==null?void 0:j.themeClass,onRender:j==null?void 0:j.onRender})},render(){var e;const{$slots:t,mergedClsPrefix:r,mergedShowLabel:o,mergedShowRequireMark:n,mergedRequireMarkPlacement:i,onRender:a}=this,l=n!==void 0?n:this.mergedRequired;return a==null||a(),m("div",{class:[`${r}-form-item`,this.themeClass,`${r}-form-item--${this.mergedSize}-size`,`${r}-form-item--${this.mergedLabelPlacement}-labelled`,!o&&`${r}-form-item--no-label`],style:this.cssVars},o&&(this.label||t.label)?m("label",Object.assign({},this.labelProps,{class:[(e=this.labelProps)===null||e===void 0?void 0:e.class,`${r}-form-item-label`],style:this.mergedLabelStyle,ref:"labelElementRef"}),i!=="left"?t.label?t.label():this.label:null,l?m("span",{class:`${r}-form-item-label__asterisk`},i!=="left"?"\xA0*":"*\xA0"):i==="right-hanging"&&m("span",{class:`${r}-form-item-label__asterisk-placeholder`},"\xA0*"),i==="left"?t.label?t.label():this.label:null):null,m("div",{class:[`${r}-form-item-blank`,this.mergedValidationStatus&&`${r}-form-item-blank--${this.mergedValidationStatus}`]},t),this.mergedShowFeedback?m("div",{key:this.feedbackId,class:`${r}-form-item-feedback-wrapper`},m(At,{name:"fade-down-transition",mode:"out-in"},{default:()=>{const s=m(w8,{clsPrefix:r,explains:this.explains,feedback:this.feedback},{default:t.feedback}),{hasFeedback:d,mergedValidationStatus:c}=this;return d||t.feedback?c==="warning"?m("div",{key:"controlled-warning",class:`${r}-form-item-feedback ${r}-form-item-feedback--warning`},s):c==="error"?m("div",{key:"controlled-error",class:`${r}-form-item-feedback ${r}-form-item-feedback--error`},s):c==="success"?m("div",{key:"controlled-success",class:`${r}-form-item-feedback ${r}-form-item-feedback--success`},s):m("div",{key:"controlled-default",class:`${r}-form-item-feedback`},s):null}})):null)}});const k8=Array.apply(null,{length:24}).map((e,t)=>{const r=t+1,o=`calc(100% / 24 * ${r})`;return[K(`${r}-span`,{width:o}),K(`${r}-offset`,{marginLeft:o}),K(`${r}-push`,{left:o}),K(`${r}-pull`,{right:o})]});var T8=z([M("row",{width:"100%",display:"flex",flexWrap:"wrap"}),M("col",{verticalAlign:"top",boxSizing:"border-box",display:"inline-block",position:"relative",zIndex:"auto"},[F("box",{position:"relative",zIndex:"auto",width:"100%",height:"100%"}),k8])]);const Iv="n-row",Dc={gutter:{type:[Array,Number,String],default:0},alignItems:String,justifyContent:String},E8=er(Dc);var R8=oe({name:"Row",props:Dc,setup(e){const{mergedClsPrefixRef:t}=lt(e);Jr("-legacy-grid",T8,t);const r=ht(()=>{const{gutter:n}=e;return Array.isArray(n)&&n[1]||0}),o=ht(()=>{const{gutter:n}=e;return Array.isArray(n)?n[0]:Number(n)});return je(Iv,{mergedClsPrefixRef:t,gutterRef:Oe(e,"gutter"),verticalGutterRef:r,horizontalGutterRef:o}),{mergedClsPrefix:t,styleMargin:ht(()=>`-${Qt(r.value,{c:.5})} -${Qt(o.value,{c:.5})}`),styleWidth:ht(()=>`calc(100% + ${Qt(o.value)})`)}},render(){return m("div",{class:`${this.mergedClsPrefix}-row`,style:{margin:this.styleMargin,width:this.styleWidth,alignItems:this.alignItems,justifyContent:this.justifyContent}},this.$slots)}});const Fc={span:{type:[String,Number],default:1},push:{type:[String,Number],default:0},pull:{type:[String,Number],default:0},offset:{type:[String,Number],default:0}},z8=er(Fc);var A8=oe({name:"Col",props:Fc,setup(e){const t=be(Iv,null);return t||Da("col","`n-col` must be placed inside `n-row`."),{mergedClsPrefix:t.mergedClsPrefixRef,gutter:t.gutterRef,stylePadding:L(()=>`${Qt(t.verticalGutterRef.value,{c:.5})} ${Qt(t.horizontalGutterRef.value,{c:.5})}`),mergedPush:L(()=>Number(e.push)-Number(e.pull))}},render(){const{$slots:e,span:t,mergedPush:r,offset:o,stylePadding:n,gutter:i,mergedClsPrefix:a}=this;return m("div",{class:[`${a}-col`,{[`${a}-col--${t}-span`]:!0,[`${a}-col--${r}-push`]:r>0,[`${a}-col--${-r}-pull`]:r<0,[`${a}-col--${o}-offset`]:o}],style:{padding:n}},i?m("div",null,e):e)}});const Hc=Object.assign(Object.assign({},Fc),Lc),O8=er(Hc);var I8=oe({name:"FormItemCol",props:Hc,setup(){const e=W(null);return{formItemInstRef:e,validate:(...o)=>{const{value:n}=e;if(n)return n.validate(...o)},restoreValidation:()=>{const{value:o}=e;if(o)return o.restoreValidation()}}},render(){return m(A8,Vt(this.$props,z8),{default:()=>{const e=Vt(this.$props,$8);return m(P8,Object.assign({ref:"formItemInstRef"},e),this.$slots)}})}});const M8=Object.assign(Object.assign({},Dc),Hc);var B8=oe({name:"FormItemRow",props:M8,setup(){const e=W(null);return{formItemColInstRef:e,validate:(...o)=>{const{value:n}=e;if(n)return n.validate(...o)},restoreValidation:()=>{const{value:o}=e;if(o)return o.restoreValidation()}}},render(){return m(R8,Vt(this.$props,E8),{default:()=>{const e=Vt(this.$props,O8);return m(I8,Object.assign(Object.assign({ref:"formItemColInstRef"},e),{span:24}),this.$slots)}})}}),L8=oe({name:"GlobalStyle",setup(){if(typeof document=="undefined")return;const e=be(Gr,null),{body:t}=document,{style:r}=t;let o=!1,n=!0;Yr(()=>{xr(()=>{var i,a;const{textColor2:l,fontSize:s,fontFamily:d,bodyColor:c,cubicBezierEaseInOut:u,lineHeight:f}=e?Xo({},((i=e.mergedThemeRef.value)===null||i===void 0?void 0:i.common)||Ke,(a=e.mergedThemeOverridesRef.value)===null||a===void 0?void 0:a.common):Ke;if(o||!t.hasAttribute("n-styled")){r.backgroundColor=c,r.color=l,r.fontSize=s,r.fontFamily=d,r.lineHeight=f;const h=`color .3s ${u}, background-color .3s ${u}`;n?setTimeout(()=>{r.transition=h},0):r.transition=h,t.setAttribute("n-styled",""),o=!0,n=!1}})}),Xs(()=>{o&&t.removeAttribute("n-styled")})},render(){return null}});const D8={name:"GradientText",common:de,self(e){const{primaryColor:t,successColor:r,warningColor:o,errorColor:n,infoColor:i,primaryColorSuppl:a,successColorSuppl:l,warningColorSuppl:s,errorColorSuppl:d,infoColorSuppl:c,fontWeightStrong:u}=e;return{fontWeight:u,rotate:"252deg",colorStartPrimary:t,colorEndPrimary:a,colorStartInfo:i,colorEndInfo:c,colorStartWarning:o,colorEndWarning:s,colorStartError:n,colorEndError:d,colorStartSuccess:r,colorEndSuccess:l}}};var F8=D8;const H8=e=>{const{primaryColor:t,baseColor:r}=e;return{color:t,iconColor:r}},j8={name:"IconWrapper",common:de,self:H8};var N8=j8;function W8(){return{toolbarIconColor:"rgba(255, 255, 255, .9)",toolbarColor:"rgba(0, 0, 0, .35)",toolbarBoxShadow:"none",toolbarBorderRadius:"24px"}}const V8={name:"Image",common:Ke,peers:{Tooltip:Ic},self:W8},K8={name:"InputNumber",common:de,peers:{Button:qt,Input:ur},self(e){const{textColorDisabled:t}=e;return{iconColorDisabled:t}}};var U8=K8;const q8={name:"Layout",common:de,peers:{Scrollbar:Ut},self(e){const{textColor2:t,bodyColor:r,popoverColor:o,cardColor:n,dividerColor:i,scrollbarColor:a,scrollbarColorHover:l}=e;return{textColor:t,textColorInverted:t,color:r,colorEmbedded:r,headerColor:n,headerColorInverted:n,footerColor:n,footerColorInverted:n,headerBorderColor:i,headerBorderColorInverted:i,footerBorderColor:i,footerBorderColorInverted:i,siderBorderColor:i,siderBorderColorInverted:i,siderColor:n,siderColorInverted:n,siderToggleButtonBorder:"1px solid transparent",siderToggleButtonColor:o,siderToggleButtonIconColor:t,siderToggleButtonIconColorInverted:t,siderToggleBarColor:ye(r,a),siderToggleBarColorHover:ye(r,l),__invertScrollbar:"false"}}};var G8=q8;const Mv=e=>{const{textColor2:t,cardColor:r,modalColor:o,popoverColor:n,dividerColor:i,borderRadius:a,fontSize:l}=e;return{textColor:t,color:r,colorModal:o,colorPopover:n,borderColor:i,borderColorModal:ye(o,i),borderColorPopover:ye(n,i),borderRadius:a,fontSize:l}},Y8={name:"List",common:Ke,self:Mv};var gO=Y8;const X8={name:"List",common:de,self:Mv};var Z8=X8;const J8={name:"LoadingBar",common:de,self(e){const{primaryColor:t}=e;return{colorError:"red",colorLoading:t,height:"2px"}}};var Q8=J8;const eT={name:"Log",common:de,peers:{Scrollbar:Ut,Code:tv},self(e){const{textColor2:t,inputColor:r,fontSize:o,primaryColor:n}=e;return{loaderFontSize:o,loaderTextColor:t,loaderColor:r,loaderBorder:"1px solid #0000",loadingColor:n}}};var tT=eT;const rT={name:"Mention",common:de,peers:{InternalSelectMenu:Si,Input:ur},self(e){const{boxShadow2:t}=e;return{menuBoxShadow:t}}};var oT=rT;function nT(e,t,r,o){return{itemColorHoverInverted:"#0000",itemColorActiveInverted:t,itemColorActiveHoverInverted:t,itemColorActiveCollapsedInverted:t,itemTextColorInverted:e,itemTextColorHoverInverted:r,itemTextColorChildActiveInverted:r,itemTextColorActiveInverted:r,itemTextColorActiveHoverInverted:r,itemTextColorHorizontalInverted:e,itemTextColorHoverHorizontalInverted:r,itemTextColorChildActiveHorizontalInverted:r,itemTextColorActiveHorizontalInverted:r,itemTextColorActiveHoverHorizontalInverted:r,itemIconColorInverted:e,itemIconColorHoverInverted:r,itemIconColorActiveInverted:r,itemIconColorActiveHoverInverted:r,itemIconColorChildActiveInverted:r,itemIconColorCollapsedInverted:e,itemIconColorHorizontalInverted:e,itemIconColorHoverHorizontalInverted:r,itemIconColorActiveHorizontalInverted:r,itemIconColorActiveHoverHorizontalInverted:r,itemIconColorChildActiveHorizontalInverted:r,arrowColorInverted:e,arrowColorHoverInverted:r,arrowColorActiveInverted:r,arrowColorActiveHoverInverted:r,arrowColorChildActiveInverted:r,groupTextColorInverted:o}}const Bv=e=>{const{borderRadius:t,textColor3:r,primaryColor:o,textColor2:n,textColor1:i,fontSize:a,dividerColor:l,hoverColor:s,primaryColorHover:d}=e;return Object.assign({borderRadius:t,color:"#0000",groupTextColor:r,itemColorHover:s,itemColorActive:ee(o,{alpha:.1}),itemColorActiveHover:ee(o,{alpha:.1}),itemColorActiveCollapsed:ee(o,{alpha:.1}),itemTextColor:n,itemTextColorHover:n,itemTextColorActive:o,itemTextColorActiveHover:o,itemTextColorChildActive:o,itemTextColorHorizontal:n,itemTextColorHoverHorizontal:d,itemTextColorActiveHorizontal:o,itemTextColorActiveHoverHorizontal:o,itemTextColorChildActiveHorizontal:o,itemIconColor:i,itemIconColorHover:i,itemIconColorActive:o,itemIconColorActiveHover:o,itemIconColorChildActive:o,itemIconColorCollapsed:i,itemIconColorHorizontal:i,itemIconColorHoverHorizontal:d,itemIconColorActiveHorizontal:o,itemIconColorActiveHoverHorizontal:o,itemIconColorChildActiveHorizontal:o,itemHeight:"42px",arrowColor:n,arrowColorHover:n,arrowColorActive:o,arrowColorActiveHover:o,arrowColorChildActive:o,colorInverted:"#0000",borderColorHorizontal:"#0000",fontSize:a,dividerColor:l},nT("#BBB",o,"#FFF","#AAA"))},iT={name:"Menu",common:Ke,peers:{Tooltip:Ic,Dropdown:uv},self:Bv};var aT=iT;const lT={name:"Menu",common:de,peers:{Tooltip:Za,Dropdown:fv},self(e){const{primaryColor:t,primaryColorSuppl:r}=e,o=Bv(e);return o.itemColorActive=ee(t,{alpha:.15}),o.itemColorActiveHover=ee(t,{alpha:.15}),o.itemColorActiveCollapsed=ee(t,{alpha:.15}),o.itemColorActiveInverted=r,o.itemColorActiveHoverInverted=r,o.itemColorActiveCollapsedInverted=r,o}};var sT=lT,cT={margin:"0 0 8px 0",padding:"10px 20px",maxWidth:"720px",minWidth:"420px",iconMargin:"0 10px 0 0",closeMargin:"0 0 0 12px",closeSize:"16px",iconSize:"20px",fontSize:"14px"};const Lv=e=>{const{textColor2:t,closeColor:r,closeColorHover:o,closeColorPressed:n,infoColor:i,successColor:a,errorColor:l,warningColor:s,popoverColor:d,boxShadow2:c,primaryColor:u,lineHeight:f,borderRadius:h}=e;return Object.assign(Object.assign({},cT),{textColor:t,textColorInfo:t,textColorSuccess:t,textColorError:t,textColorWarning:t,textColorLoading:t,color:d,colorInfo:d,colorSuccess:d,colorError:d,colorWarning:d,colorLoading:d,boxShadow:c,boxShadowInfo:c,boxShadowSuccess:c,boxShadowError:c,boxShadowWarning:c,boxShadowLoading:c,iconColor:t,iconColorInfo:i,iconColorSuccess:a,iconColorWarning:s,iconColorError:l,iconColorLoading:u,closeColor:r,closeColorHover:o,closeColorPressed:n,closeColorInfo:r,closeColorHoverInfo:o,closeColorPressedInfo:n,closeColorSuccess:r,closeColorHoverSuccess:o,closeColorPressedSuccess:n,closeColorError:r,closeColorHoverError:o,closeColorPressedError:n,closeColorWarning:r,closeColorHoverWarning:o,closeColorPressedWarning:n,closeColorLoading:r,closeColorHoverLoading:o,closeColorPressedLoading:n,loadingColor:u,lineHeight:f,borderRadius:h})},dT={name:"Message",common:Ke,self:Lv};var uT=dT;const fT={name:"Message",common:de,self:Lv};var hT=fT,pT={closeMargin:"18px 14px",closeSize:"16px",width:"365px",padding:"16px"};const mT=e=>{const{textColor2:t,successColor:r,infoColor:o,warningColor:n,errorColor:i,popoverColor:a,closeColor:l,closeColorHover:s,textColor1:d,textColor3:c,borderRadius:u,fontWeightStrong:f,boxShadow2:h,lineHeight:p,fontSize:b}=e;return Object.assign(Object.assign({},pT),{borderRadius:u,lineHeight:p,fontSize:b,headerFontWeight:f,iconColor:t,iconColorSuccess:r,iconColorInfo:o,iconColorWarning:n,iconColorError:i,color:a,textColor:t,closeColor:l,closeColorHover:s,closeColorPressed:l,headerTextColor:d,descriptionTextColor:c,actionTextColor:t,boxShadow:h})},vT={name:"Notification",common:de,peers:{Scrollbar:Ut},self:mT};var gT=vT,bT={titleFontSize:"18px",backSize:"22px"};function xT(e){const{textColor1:t,textColor2:r,textColor3:o,fontSize:n,fontWeightStrong:i,primaryColorHover:a,primaryColorPressed:l}=e;return Object.assign(Object.assign({},bT),{titleFontWeight:i,fontSize:n,titleTextColor:t,backColor:r,backColorHover:a,backColorPressed:l,subtitleTextColor:o})}const CT={name:"PageHeader",common:de,self:xT};var yT={iconSize:"22px"};const Dv=e=>{const{fontSize:t,warningColor:r}=e;return Object.assign(Object.assign({},yT),{fontSize:t,iconColor:r})},bO={name:"Popconfirm",common:Ke,peers:{Button:Xa,Popover:_i},self:Dv},wT={name:"Popconfirm",common:de,peers:{Button:qt,Popover:zo},self:Dv};var ST=wT;const _T={name:"Popselect",common:de,peers:{Popover:zo,InternalSelectMenu:Si}};var $T=_T;const Fv=e=>{const{infoColor:t,successColor:r,warningColor:o,errorColor:n,textColor2:i,progressRailColor:a,fontSize:l,fontWeight:s}=e;return{fontSize:l,fontSizeCircle:"28px",fontWeightCircle:s,railColor:a,railHeight:"8px",iconSizeCircle:"36px",iconSizeLine:"18px",iconColor:t,iconColorInfo:t,iconColorSuccess:r,iconColorWarning:o,iconColorError:n,textColorCircle:i,textColorLineInner:"rgb(255, 255, 255)",textColorLineOuter:i,fillColor:t,fillColorInfo:t,fillColorSuccess:r,fillColorWarning:o,fillColorError:n,lineBgProcessing:"linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, .5) 100%)"}},PT={name:"Progress",common:Ke,self:Fv};var kT=PT;const TT={name:"Progress",common:de,self(e){const t=Fv(e);return t.textColorLineInner="rgb(0, 0, 0)",t.lineBgProcessing="linear-gradient(90deg, rgba(255, 255, 255, .3) 0%, rgba(255, 255, 255, .5) 100%)",t}};var Hv=TT;const ET={name:"Rate",common:de,self(e){const{railColor:t}=e;return{itemColor:t,itemColorActive:"#CCAA33",itemSize:"20px",sizeSmall:"16px",sizeMedium:"20px",sizeLarge:"24px"}}};var RT=ET,zT={titleFontSizeSmall:"26px",titleFontSizeMedium:"32px",titleFontSizeLarge:"40px",titleFontSizeHuge:"48px",fontSizeSmall:"14px",fontSizeMedium:"14px",fontSizeLarge:"15px",fontSizeHuge:"16px",iconSizeSmall:"64px",iconSizeMedium:"80px",iconSizeLarge:"100px",iconSizeHuge:"125px",iconColor418:void 0,iconColor404:void 0,iconColor403:void 0,iconColor500:void 0};const jv=e=>{const{textColor2:t,textColor1:r,errorColor:o,successColor:n,infoColor:i,warningColor:a,lineHeight:l,fontWeightStrong:s}=e;return Object.assign(Object.assign({},zT),{lineHeight:l,titleFontWeight:s,titleTextColor:r,textColor:t,iconColorError:o,iconColorSuccess:n,iconColorInfo:i,iconColorWarning:a})},AT={name:"Result",common:Ke,self:jv};var xO=AT;const OT={name:"Result",common:de,self:jv};var IT=OT,MT={railHeight:"4px",railWidthVertical:"4px",handleSize:"18px",dotHeight:"8px",dotWidth:"8px",dotBorderRadius:"4px"};const BT={name:"Slider",common:de,self(e){const t="0 2px 8px 0 rgba(0, 0, 0, 0.12)",{railColor:r,modalColor:o,primaryColorSuppl:n,popoverColor:i,textColor2:a,cardColor:l,borderRadius:s,fontSize:d,opacityDisabled:c}=e;return Object.assign(Object.assign({},MT),{fontSize:d,railColor:r,railColorHover:r,fillColor:n,fillColorHover:n,opacityDisabled:c,handleColor:"#FFF",dotColor:l,dotColorModal:o,dotColorPopover:i,handleBoxShadow:"0px 2px 4px 0 rgba(0, 0, 0, 0.4)",handleBoxShadowHover:"0px 2px 4px 0 rgba(0, 0, 0, 0.4)",handleBoxShadowActive:"0px 2px 4px 0 rgba(0, 0, 0, 0.4)",handleBoxShadowFocus:"0px 2px 4px 0 rgba(0, 0, 0, 0.4)",indicatorColor:i,indicatorBoxShadow:t,indicatorTextColor:a,indicatorBorderRadius:s,dotBorder:`2px solid ${r}`,dotBorderActive:`2px solid ${n}`,dotBoxShadow:""})}};var LT=BT;const Nv=e=>{const{opacityDisabled:t,heightTiny:r,heightSmall:o,heightMedium:n,heightLarge:i,heightHuge:a,primaryColor:l,fontSize:s}=e;return{fontSize:s,textColor:l,sizeTiny:r,sizeSmall:o,sizeMedium:n,sizeLarge:i,sizeHuge:a,color:l,opacitySpinning:t}},DT={name:"Spin",common:Ke,self:Nv};var FT=DT;const HT={name:"Spin",common:de,self:Nv};var jT=HT;const Wv=e=>{const{textColor2:t,textColor3:r,fontSize:o,fontWeight:n}=e;return{labelFontSize:o,labelFontWeight:n,valueFontWeight:n,labelTextColor:r,valuePrefixTextColor:t,valueSuffixTextColor:t,valueTextColor:t}},NT={name:"Statistic",common:Ke,self:Wv};var CO=NT;const WT={name:"Statistic",common:de,self:Wv};var VT=WT,KT={stepHeaderFontSizeSmall:"14px",stepHeaderFontSizeMedium:"16px",indicatorIndexFontSizeSmall:"14px",indicatorIndexFontSizeMedium:"16px",indicatorSizeSmall:"22px",indicatorSizeMedium:"28px",indicatorIconSizeSmall:"14px",indicatorIconSizeMedium:"18px"};const UT=e=>{const{fontWeightStrong:t,baseColor:r,textColorDisabled:o,primaryColor:n,errorColor:i,textColor1:a,textColor2:l}=e;return Object.assign(Object.assign({},KT),{stepHeaderFontWeight:t,indicatorTextColorProcess:r,indicatorTextColorWait:o,indicatorTextColorFinish:n,indicatorTextColorError:i,indicatorBorderColorProcess:n,indicatorBorderColorWait:o,indicatorBorderColorFinish:n,indicatorBorderColorError:i,indicatorColorProcess:n,indicatorColorWait:"#0000",indicatorColorFinish:"#0000",indicatorColorError:"#0000",splitorColorProcess:o,splitorColorWait:o,splitorColorFinish:n,splitorColorError:o,headerTextColorProcess:a,headerTextColorWait:o,headerTextColorFinish:o,headerTextColorError:i,descriptionTextColorProcess:l,descriptionTextColorWait:o,descriptionTextColorFinish:o,descriptionTextColorError:i})},qT={name:"Steps",common:de,self:UT};var GT=qT,YT={buttonHeightSmall:"14px",buttonHeightMedium:"18px",buttonHeightLarge:"22px",buttonWidthSmall:"14px",buttonWidthMedium:"18px",buttonWidthLarge:"22px",buttonWidthPressedSmall:"20px",buttonWidthPressedMedium:"24px",buttonWidthPressedLarge:"28px",railHeightSmall:"18px",railHeightMedium:"22px",railHeightLarge:"26px",railWidthSmall:"32px",railWidthMedium:"40px",railWidthLarge:"48px"};const XT={name:"Switch",common:de,self(e){const{primaryColorSuppl:t,opacityDisabled:r,borderRadius:o,primaryColor:n,textColor2:i,baseColor:a}=e,l="rgba(255, 255, 255, .20)";return Object.assign(Object.assign({},YT),{iconColor:a,textColor:i,loadingColor:t,opacityDisabled:r,railColor:l,railColorActive:t,buttonBoxShadow:"0px 2px 4px 0 rgba(0, 0, 0, 0.4)",buttonColor:"#FFF",railBorderRadiusSmall:o,railBorderRadiusMedium:o,railBorderRadiusLarge:o,buttonBorderRadiusSmall:o,buttonBorderRadiusMedium:o,buttonBorderRadiusLarge:o,boxShadowFocus:`0 0 8px 0 ${ee(n,{alpha:.3})}`})}};var ZT=XT,JT={thPaddingSmall:"6px",thPaddingMedium:"12px",thPaddingLarge:"12px",tdPaddingSmall:"6px",tdPaddingMedium:"12px",tdPaddingLarge:"12px"};const QT=e=>{const{dividerColor:t,cardColor:r,modalColor:o,popoverColor:n,tableHeaderColor:i,tableColorStriped:a,textColor1:l,textColor2:s,borderRadius:d,fontWeightStrong:c,lineHeight:u,fontSizeSmall:f,fontSizeMedium:h,fontSizeLarge:p}=e;return Object.assign(Object.assign({},JT),{fontSizeSmall:f,fontSizeMedium:h,fontSizeLarge:p,lineHeight:u,borderRadius:d,borderColor:ye(r,t),borderColorModal:ye(o,t),borderColorPopover:ye(n,t),tdColor:r,tdColorModal:o,tdColorPopover:n,tdColorStriped:ye(r,a),tdColorStripedModal:ye(o,a),tdColorStripedPopover:ye(n,a),thColor:ye(r,i),thColorModal:ye(o,i),thColorPopover:ye(n,i),thTextColor:l,tdTextColor:s,thFontWeight:c})},eE={name:"Table",common:de,self:QT};var tE=eE,rE={tabFontSizeSmall:"14px",tabFontSizeMedium:"14px",tabFontSizeLarge:"16px",tabGapSmallLine:"36px",tabGapMediumLine:"36px",tabGapLargeLine:"36px",tabPaddingSmallLine:"6px 0",tabPaddingMediumLine:"10px 0",tabPaddingLargeLine:"14px 0",tabGapSmallBar:"36px",tabGapMediumBar:"36px",tabGapLargeBar:"36px",tabPaddingSmallBar:"4px 0",tabPaddingMediumBar:"6px 0",tabPaddingLargeBar:"10px 0",tabGapSmallCard:"4px",tabGapMediumCard:"4px",tabGapLargeCard:"4px",tabPaddingSmallCard:"6px 10px",tabPaddingMediumCard:"8px 12px",tabPaddingLargeCard:"8px 16px",tabPaddingSmallSegment:"4px 0",tabPaddingMediumSegment:"6px 0",tabPaddingLargeSegment:"8px 0",tabGapSmallSegment:"0",tabGapMediumSegment:"0",tabGapLargeSegment:"0",panePaddingSmall:"8px 0 0 0",panePaddingMedium:"12px 0 0 0",panePaddingLarge:"16px 0 0 0"};const Vv=e=>{const{textColor2:t,primaryColor:r,textColorDisabled:o,closeColor:n,closeColorHover:i,closeColorPressed:a,tabColor:l,baseColor:s,dividerColor:d,fontWeight:c,textColor1:u,borderRadius:f,fontSize:h,fontWeightStrong:p}=e;return Object.assign(Object.assign({},rE),{colorSegment:l,tabFontSizeCard:h,tabTextColorLine:u,tabTextColorActiveLine:r,tabTextColorHoverLine:r,tabTextColorDisabledLine:o,tabTextColorSegment:u,tabTextColorActiveSegment:t,tabTextColorHoverSegment:t,tabTextColorDisabledSegment:o,tabTextColorBar:u,tabTextColorActiveBar:r,tabTextColorHoverBar:r,tabTextColorDisabledBar:o,tabTextColorCard:u,tabTextColorHoverCard:u,tabTextColorActiveCard:r,tabTextColorDisabledCard:o,barColor:r,closeColor:n,closeColorHover:i,closeColorPressed:a,tabColor:l,tabColorSegment:s,tabBorderColor:d,tabFontWeightActive:c,tabFontWeight:c,tabBorderRadius:f,paneTextColor:t,fontWeightStrong:p})},oE={name:"Tabs",common:Ke,self:Vv};var nE=oE;const iE={name:"Tabs",common:de,self(e){const t=Vv(e),{inputColor:r}=e;return t.colorSegment=r,t.tabColorSegment=r,t}};var aE=iE;const Kv=e=>{const{textColor1:t,textColor2:r,fontWeightStrong:o,fontSize:n}=e;return{fontSize:n,titleTextColor:t,textColor:r,titleFontWeight:o}},lE={name:"Thing",common:Ke,self:Kv};var yO=lE;const sE={name:"Thing",common:de,self:Kv};var cE=sE,dE={titleMarginMedium:"0",titleMarginLarge:"-2px 0 0 0",titleFontSizeMedium:"14px",titleFontSizeLarge:"16px",iconSizeMedium:"14px",iconSizeLarge:"14px"};const uE={name:"Timeline",common:de,self(e){const{textColor3:t,infoColorSuppl:r,errorColorSuppl:o,successColorSuppl:n,warningColorSuppl:i,textColor1:a,textColor2:l,railColor:s,fontWeightStrong:d,fontSize:c}=e;return Object.assign(Object.assign({},dE),{contentFontSize:c,titleFontWeight:d,circleBorder:`2px solid ${t}`,circleBorderInfo:`2px solid ${r}`,circleBorderError:`2px solid ${o}`,circleBorderSuccess:`2px solid ${n}`,circleBorderWarning:`2px solid ${i}`,iconColor:t,iconColorInfo:r,iconColorError:o,iconColorSuccess:n,iconColorWarning:i,titleTextColor:a,contentTextColor:l,metaTextColor:t,lineColor:s})}};var fE=uE,hE={extraFontSize:"12px",width:"440px"};const pE={name:"Transfer",common:de,peers:{Checkbox:$i,Scrollbar:Ut,Input:ur,Empty:wi,Button:qt},self(e){const{iconColorDisabled:t,iconColor:r,fontWeight:o,fontSizeLarge:n,fontSizeMedium:i,fontSizeSmall:a,heightLarge:l,heightMedium:s,heightSmall:d,borderRadius:c,inputColor:u,tableHeaderColor:f,textColor1:h,textColorDisabled:p,textColor2:b,hoverColor:g}=e;return Object.assign(Object.assign({},hE),{itemHeightSmall:d,itemHeightMedium:s,itemHeightLarge:l,fontSizeSmall:a,fontSizeMedium:i,fontSizeLarge:n,borderRadius:c,borderColor:"#0000",listColor:u,headerColor:f,titleTextColor:h,titleTextColorDisabled:p,extraTextColor:b,filterDividerColor:"#0000",itemTextColor:b,itemTextColorDisabled:p,itemColorPending:g,titleFontWeight:o,iconColor:r,iconColorDisabled:t})}};var mE=pE;const vE=e=>{const{borderRadiusSmall:t,hoverColor:r,pressedColor:o,primaryColor:n,textColor3:i,textColor2:a,textColorDisabled:l,fontSize:s}=e;return{fontSize:s,nodeBorderRadius:t,nodeColorHover:r,nodeColorPressed:o,nodeColorActive:ee(n,{alpha:.1}),arrowColor:i,nodeTextColor:a,nodeTextColorDisabled:l,loadingColor:n,dropMarkColor:n}},gE={name:"Tree",common:de,peers:{Checkbox:$i,Scrollbar:Ut},self(e){const{primaryColor:t}=e,r=vE(e);return r.nodeColorActive=ee(t,{alpha:.15}),r}};var Uv=gE;const bE={name:"TreeSelect",common:de,peers:{Tree:Uv,Empty:wi,InternalSelection:zc}};var xE=bE,CE={headerFontSize1:"30px",headerFontSize2:"22px",headerFontSize3:"18px",headerFontSize4:"16px",headerFontSize5:"16px",headerFontSize6:"16px",headerMargin1:"28px 0 20px 0",headerMargin2:"28px 0 20px 0",headerMargin3:"28px 0 20px 0",headerMargin4:"28px 0 18px 0",headerMargin5:"28px 0 18px 0",headerMargin6:"28px 0 18px 0",headerPrefixWidth1:"16px",headerPrefixWidth2:"16px",headerPrefixWidth3:"12px",headerPrefixWidth4:"12px",headerPrefixWidth5:"12px",headerPrefixWidth6:"12px",headerBarWidth1:"4px",headerBarWidth2:"4px",headerBarWidth3:"3px",headerBarWidth4:"3px",headerBarWidth5:"3px",headerBarWidth6:"3px",pMargin:"16px 0 16px 0",liMargin:".25em 0 0 0",olPadding:"0 0 0 2em",ulPadding:"0 0 0 2em"};const yE=e=>{const{primaryColor:t,textColor2:r,borderColor:o,lineHeight:n,fontSize:i,borderRadiusSmall:a,dividerColor:l,fontWeightStrong:s,textColor1:d,textColor3:c,infoColor:u,warningColor:f,errorColor:h,successColor:p,codeColor:b}=e;return Object.assign(Object.assign({},CE),{aTextColor:t,blockquoteTextColor:r,blockquotePrefixColor:o,blockquoteLineHeight:n,blockquoteFontSize:i,codeBorderRadius:a,liTextColor:r,liLineHeight:n,liFontSize:i,hrColor:l,headerFontWeight:s,headerTextColor:d,pTextColor:r,pTextColor1Depth:d,pTextColor2Depth:r,pTextColor3Depth:c,pLineHeight:n,pFontSize:i,headerBarColor:t,headerBarColorPrimary:t,headerBarColorInfo:u,headerBarColorError:h,headerBarColorWarning:f,headerBarColorSuccess:p,textColor:r,textColor1Depth:d,textColor2Depth:r,textColor3Depth:c,textColorPrimary:t,textColorInfo:u,textColorSuccess:p,textColorWarning:f,textColorError:h,codeTextColor:r,codeColor:b,codeBorder:"1px solid #0000"})},wE={name:"Typography",common:de,self:yE};var SE=wE;const qv=e=>{const{iconColor:t,primaryColor:r,errorColor:o,textColor2:n,successColor:i,opacityDisabled:a,actionColor:l,borderColor:s,hoverColor:d,lineHeight:c,borderRadius:u,fontSize:f}=e;return{fontSize:f,lineHeight:c,borderRadius:u,draggerColor:l,draggerBorder:`1px dashed ${s}`,draggerBorderHover:`1px dashed ${r}`,itemColorHover:d,itemColorHoverError:ee(o,{alpha:.06}),itemTextColor:n,itemTextColorError:o,itemTextColorSuccess:i,itemIconColor:t,itemDisabledOpacity:a,itemBorderImageCardError:`1px solid ${o}`,itemBorderImageCard:`1px solid ${s}`}},_E={name:"Upload",common:Ke,peers:{Button:Xa,Progress:kT},self:qv};var wO=_E;const $E={name:"Upload",common:de,peers:{Button:qt,Progress:Hv},self(e){const{errorColor:t}=e,r=qv(e);return r.itemColorHoverError=ee(t,{alpha:.09}),r}};var PE=$E;const kE={name:"Watermark",common:de,self(e){const{fontFamily:t}=e;return{fontFamily:t}}};var TE=kE;const EE={name:"Image",common:de,peers:{Tooltip:Za},self:e=>{const{textColor2:t}=e;return{toolbarIconColor:t,toolbarColor:"rgba(0, 0, 0, .35)",toolbarBoxShadow:"none",toolbarBorderRadius:"24px"}}},RE=m("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M6 5C5.75454 5 5.55039 5.17688 5.50806 5.41012L5.5 5.5V14.5C5.5 14.7761 5.72386 15 6 15C6.24546 15 6.44961 14.8231 6.49194 14.5899L6.5 14.5V5.5C6.5 5.22386 6.27614 5 6 5ZM13.8536 5.14645C13.68 4.97288 13.4106 4.9536 13.2157 5.08859L13.1464 5.14645L8.64645 9.64645C8.47288 9.82001 8.4536 10.0894 8.58859 10.2843L8.64645 10.3536L13.1464 14.8536C13.3417 15.0488 13.6583 15.0488 13.8536 14.8536C14.0271 14.68 14.0464 14.4106 13.9114 14.2157L13.8536 14.1464L9.70711 10L13.8536 5.85355C14.0488 5.65829 14.0488 5.34171 13.8536 5.14645Z",fill:"currentColor"})),zE=m("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M13.5 5C13.7455 5 13.9496 5.17688 13.9919 5.41012L14 5.5V14.5C14 14.7761 13.7761 15 13.5 15C13.2545 15 13.0504 14.8231 13.0081 14.5899L13 14.5V5.5C13 5.22386 13.2239 5 13.5 5ZM5.64645 5.14645C5.82001 4.97288 6.08944 4.9536 6.28431 5.08859L6.35355 5.14645L10.8536 9.64645C11.0271 9.82001 11.0464 10.0894 10.9114 10.2843L10.8536 10.3536L6.35355 14.8536C6.15829 15.0488 5.84171 15.0488 5.64645 14.8536C5.47288 14.68 5.4536 14.4106 5.58859 14.2157L5.64645 14.1464L9.79289 10L5.64645 5.85355C5.45118 5.65829 5.45118 5.34171 5.64645 5.14645Z",fill:"currentColor"})),AE=m("svg",{viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg"},m("path",{d:"M4.089 4.216l.057-.07a.5.5 0 0 1 .638-.057l.07.057L10 9.293l5.146-5.147a.5.5 0 0 1 .638-.057l.07.057a.5.5 0 0 1 .057.638l-.057.07L10.707 10l5.147 5.146a.5.5 0 0 1 .057.638l-.057.07a.5.5 0 0 1-.638.057l-.07-.057L10 10.707l-5.146 5.147a.5.5 0 0 1-.638.057l-.07-.057a.5.5 0 0 1-.057-.638l.057-.07L9.293 10L4.146 4.854a.5.5 0 0 1-.057-.638l.057-.07l-.057.07z",fill:"currentColor"})),jc=Object.assign(Object.assign({},ze.props),{showToolbar:{type:Boolean,default:!0},showToolbarTooltip:Boolean});var OE=z([z("body >",[M("image-container","position: fixed;")]),M("image-preview-container",` - position: fixed; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: flex; - `),M("image-preview-overlay",` - z-index: -1; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - background: rgba(0, 0, 0, .3); - `,[mi()]),M("image-preview-toolbar",` - z-index: 1; - position: absolute; - left: 50%; - transform: translateX(-50%); - border-radius: var(--n-toolbar-border-radius); - height: 48px; - bottom: 40px; - padding: 0 12px; - background: var(--n-toolbar-color); - box-shadow: var(--n-toolbar-box-shadow); - color: var(--n-toolbar-icon-color); - transition: color .3s var(--n-bezier); - display: flex; - align-items: center; - `,[M("base-icon",` - padding: 0 8px; - font-size: 28px; - cursor: pointer; - `),mi()]),M("image-preview-wrapper",` - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: flex; - pointer-events: none; - `,[vi()]),M("image-preview",` - user-select: none; - pointer-events: all; - margin: auto; - max-height: 100vh; - max-width: 100vw; - transition: transform .3s var(--n-bezier); - `),M("image",` - display: inline-flex; - max-height: 100%; - max-width: 100%; - `,[ut("preview-disabled",` - cursor: pointer; - `),z("img",` - border-radius: inherit; - `)])]),Gv=oe({name:"ImagePreview",props:Object.assign(Object.assign({},jc),{onNext:Function,onPrev:Function,clsPrefix:{type:String,required:!0}}),setup(e){const t=ze("Image","-image",OE,V8,e,Oe(e,"clsPrefix"));let r=null;const o=W(null),n=W(null),i=W(void 0),a=W(!1),l=W(!1),{localeRef:s}=em("Image");function d(){const{value:O}=n;if(!r||!O)return;const{style:V}=O,D=r.getBoundingClientRect(),ce=D.left+D.width/2,ue=D.top+D.height/2;V.transformOrigin=`${ce}px ${ue}px`}function c(O){var V,D;switch(O.code){case"ArrowLeft":(V=e.onPrev)===null||V===void 0||V.call(e);break;case"ArrowRight":(D=e.onNext)===null||D===void 0||D.call(e);break;case"Escape":_e();break}}qe(a,O=>{O?nt("keydown",document,c):Ze("keydown",document,c)}),It(()=>{Ze("keydown",document,c)});let u=0,f=0,h=0,p=0,b=0,g=0,v=0,w=0,$=!1;function x(O){const{clientX:V,clientY:D}=O;h=V-u,p=D-f,ip(se)}function S(O){const{mouseUpClientX:V,mouseUpClientY:D,mouseDownClientX:ce,mouseDownClientY:ue}=O,xe=ce-V,G=ue-D,Z=`vertical${G>0?"Top":"Bottom"}`,C=`horizontal${xe>0?"Left":"Right"}`;return{moveVerticalDirection:Z,moveHorizontalDirection:C,deltaHorizontal:xe,deltaVertical:G}}function E(O){const{value:V}=o;if(!V)return{offsetX:0,offsetY:0};const D=V.getBoundingClientRect(),{moveVerticalDirection:ce,moveHorizontalDirection:ue,deltaHorizontal:xe,deltaVertical:G}=O||{};let Z=0,C=0;return D.width<=window.innerWidth?Z=0:D.left>0?Z=(D.width-window.innerWidth)/2:D.right0?C=(D.height-window.innerHeight)/2:D.bottom.5){P-=.5,se(!1);const O=E();P+=.5,se(!1),P-=.5,h=O.offsetX,p=O.offsetY,se()}}function se(O=!0){const{value:V}=o;if(!V)return;const{style:D}=V,ce=`transform-origin: center; transform: translateX(${h}px) translateY(${p}px) rotate(${j}deg) scale(${P});`;$?D.cssText="cursor: grabbing; transition: none;"+ce:D.cssText="cursor: grab;"+ce+(O?"":"transition: none;"),O||V.offsetHeight}function _e(){a.value=!a.value,l.value=!0}const Ae={setPreviewSrc:O=>{i.value=O},setThumbnailEl:O=>{r=O},toggleShow:_e};function Re(O,V){if(e.showToolbarTooltip){const{value:D}=t;return m(cv,{to:!1,theme:D.peers.Tooltip,themeOverrides:D.peerOverrides.Tooltip},{default:()=>s.value[V],trigger:()=>O})}else return O}const Ee=L(()=>{const{common:{cubicBezierEaseInOut:O},self:{toolbarIconColor:V,toolbarBorderRadius:D,toolbarBoxShadow:ce,toolbarColor:ue}}=t.value;return{"--n-bezier":O,"--n-toolbar-icon-color":V,"--n-toolbar-color":ue,"--n-toolbar-border-radius":D,"--n-toolbar-box-shadow":ce}}),{inlineThemeDisabled:$e}=lt(),it=$e?_t("image-preview",void 0,Ee,e):void 0;return Object.assign({previewRef:o,previewWrapperRef:n,previewSrc:i,show:a,appear:xi(),displayed:l,handleWheel(O){O.preventDefault()},handlePreviewMousedown:_,handlePreviewDblclick:R,syncTransformOrigin:d,handleAfterLeave:()=>{j=0,P=1,l.value=!1},handleDragStart:O=>{O.preventDefault()},zoomIn:A,zoomOut:te,rotateCounterclockwise:B,rotateClockwise:q,handleSwitchPrev:T,handleSwitchNext:N,withTooltip:Re,cssVars:$e?void 0:Ee,themeClass:it==null?void 0:it.themeClass,onRender:it==null?void 0:it.onRender},Ae)},render(){var e,t;const{clsPrefix:r}=this;return m(ot,null,(t=(e=this.$slots).default)===null||t===void 0?void 0:t.call(e),m(Ec,{show:this.show},{default:()=>{var o;return this.show||this.displayed?((o=this.onRender)===null||o===void 0||o.call(this),Cr(m("div",{class:[`${r}-image-preview-container`,this.themeClass],style:this.cssVars,onWheel:this.handleWheel},m(At,{name:"fade-in-transition",appear:this.appear},{default:()=>this.show?m("div",{class:`${r}-image-preview-overlay`,onClick:this.toggleShow}):null}),this.showToolbar?m(At,{name:"fade-in-transition",appear:this.appear},{default:()=>{if(!this.show)return null;const{withTooltip:n}=this;return m("div",{class:`${r}-image-preview-toolbar`},this.onPrev?m(ot,null,n(m(Bt,{clsPrefix:r,onClick:this.handleSwitchPrev},{default:()=>RE}),"tipPrevious"),n(m(Bt,{clsPrefix:r,onClick:this.handleSwitchNext},{default:()=>zE}),"tipNext")):null,n(m(Bt,{clsPrefix:r,onClick:this.rotateCounterclockwise},{default:()=>m(k$,null)}),"tipCounterclockwise"),n(m(Bt,{clsPrefix:r,onClick:this.rotateClockwise},{default:()=>m(P$,null)}),"tipClockwise"),n(m(Bt,{clsPrefix:r,onClick:this.zoomOut},{default:()=>m(E$,null)}),"tipZoomOut"),n(m(Bt,{clsPrefix:r,onClick:this.zoomIn},{default:()=>m(T$,null)}),"tipZoomIn"),n(m(Bt,{clsPrefix:r,onClick:this.toggleShow},{default:()=>AE}),"tipClose"))}}):null,m(At,{name:"fade-in-scale-up-transition",onAfterLeave:this.handleAfterLeave,appear:this.appear,onEnter:this.syncTransformOrigin,onBeforeLeave:this.syncTransformOrigin},{default:()=>Cr(m("div",{class:`${r}-image-preview-wrapper`,ref:"previewWrapperRef"},m("img",{draggable:!1,onMousedown:this.handlePreviewMousedown,onDblclick:this.handlePreviewDblclick,class:`${r}-image-preview`,key:this.previewSrc,src:this.previewSrc,ref:"previewRef",onDragstart:this.handleDragStart})),[[li,this.show]])})),[[qa,{enabled:this.show}]])):null}}))}});const Yv="n-image-group",IE=jc;var SO=oe({name:"ImageGroup",props:IE,setup(e){let t;const{mergedClsPrefixRef:r}=lt(e),o=`c${dn()}`,n=Zr(),i=s=>{var d;t=s,(d=l.value)===null||d===void 0||d.setPreviewSrc(s)};function a(s){if(!(n!=null&&n.proxy))return;const c=n.proxy.$el.parentElement.querySelectorAll(`.${o}:not([data-error=true])`);if(!c.length)return;const u=Array.from(c).findIndex(f=>f.dataset.previewSrc===t);~u?i(c[(u+s+c.length)%c.length].dataset.previewSrc):i(c[0].dataset.previewSrc)}je(Yv,{mergedClsPrefixRef:r,setPreviewSrc:i,setThumbnailEl:s=>{var d;(d=l.value)===null||d===void 0||d.setThumbnailEl(s)},toggleShow:()=>{var s;(s=l.value)===null||s===void 0||s.toggleShow()},groupId:o});const l=W(null);return{mergedClsPrefix:r,previewInstRef:l,next:()=>a(1),prev:()=>a(-1)}},render(){return m(Gv,{theme:this.theme,themeOverrides:this.themeOverrides,clsPrefix:this.mergedClsPrefix,ref:"previewInstRef",onPrev:this.prev,onNext:this.next,showToolbar:this.showToolbar,showToolbarTooltip:this.showToolbarTooltip},this.$slots)}});const ME=Object.assign({alt:String,height:[String,Number],imgProps:Object,objectFit:{type:String,default:"fill"},previewSrc:String,fallbackSrc:String,width:[String,Number],src:String,previewDisabled:Boolean,loadDescription:String,onError:Function,onLoad:Function},jc);var BE=oe({name:"Image",props:ME,inheritAttrs:!1,setup(e){const t=W(null),r=W(!1),o=Oe(e,"imgProps"),n=W(null),i=be(Yv,null),{mergedClsPrefixRef:a}=i||lt(e),l={click:()=>{if(e.previewDisabled||r.value)return;const s=e.previewSrc||e.src;if(i){i.setPreviewSrc(s),i.setThumbnailEl(t.value),i.toggleShow();return}const{value:d}=n;!d||(d.setPreviewSrc(s),d.setThumbnailEl(t.value),d.toggleShow())}};return xr(()=>{var s;e.src,(s=e.imgProps)===null||s===void 0||s.src,r.value=!1}),Object.assign({mergedClsPrefix:a,groupId:i==null?void 0:i.groupId,previewInstRef:n,imageRef:t,imgProps:o,showError:r,mergedOnError:s=>{r.value=!0;const{onError:d,imgProps:{onError:c}={}}=e;d==null||d(s),c==null||c(s)},mergedOnLoad:s=>{const{onLoad:d,imgProps:{onLoad:c}={}}=e;d==null||d(s),c==null||c(s)}},l)},render(){const{mergedClsPrefix:e,imgProps:t={},$attrs:r}=this,o=m("img",Object.assign({},t,{class:[this.groupId,t.class],ref:"imageRef",width:this.width||t.width,height:this.height||t.height,src:this.showError?this.fallbackSrc:this.src||t.src,alt:this.alt||t.alt,"aria-label":this.alt||t.alt,onClick:this.click,onError:this.mergedOnError,onLoad:this.mergedOnLoad,style:[t.style||"",{objectFit:this.objectFit}],"data-error":this.showError,"data-preview-src":this.previewSrc||this.src}));return m("div",Object.assign({},r,{role:"none",class:[r.class,`${e}-image`,(this.previewDisabled||this.showError)&&`${e}-image--preview-disabled`]}),this.groupId?o:m(Gv,{theme:this.theme,themeOverrides:this.themeOverrides,clsPrefix:e,ref:"previewInstRef",showToolbar:this.showToolbar,showToolbarTooltip:this.showToolbarTooltip},{default:()=>o}))}});const LE="n-layout-sider",Ti="n-menu",Nc="n-submenu",Wc="n-menu-item-group",Ui=8;function Vc(e){const t=be(Ti),{props:r,mergedCollapsedRef:o}=t,n=be(Nc,null),i=be(Wc,null),a=L(()=>r.mode==="horizontal"),l=L(()=>a.value?r.dropdownPlacement:"tmNodes"in e?"right-start":"right"),s=L(()=>{var f;return Math.max((f=r.collapsedIconSize)!==null&&f!==void 0?f:r.iconSize,r.iconSize)}),d=L(()=>{var f;return!a.value&&e.root&&o.value&&(f=r.collapsedIconSize)!==null&&f!==void 0?f:r.iconSize}),c=L(()=>{if(a.value)return;const{collapsedWidth:f,indent:h,rootIndent:p}=r,{root:b,isGroup:g}=e,v=p===void 0?h:p;if(b)return o.value?f/2-s.value/2:v;if(i)return h/2+i.paddingLeftRef.value;if(n)return(g?h/2:h)+n.paddingLeftRef.value}),u=L(()=>{const{collapsedWidth:f,indent:h,rootIndent:p}=r,{value:b}=s,{root:g}=e;return a.value||!g||!o.value?Ui:(p===void 0?h:p)+b+Ui-(f+b)/2});return{dropdownPlacement:l,activeIconSize:d,maxIconSize:s,paddingLeft:c,iconMarginRight:u,NMenu:t,NSubmenu:n}}const Kc={internalKey:{type:[String,Number],required:!0},root:Boolean,isGroup:Boolean,level:{type:Number,required:!0},title:[String,Function],extra:[String,Function]},Xv=Object.assign(Object.assign({},Kc),{tmNodes:{type:Array,required:!0}}),DE=oe({name:"MenuOptionGroup",props:Xv,setup(e){je(Nc,null);const t=Vc(e);je(Wc,{paddingLeftRef:t.paddingLeft});const{mergedClsPrefixRef:r,props:o}=be(Ti);return function(){const{value:n}=r,i=t.paddingLeft.value;return m("div",{class:`${n}-menu-item-group`,role:"group"},m("span",{class:`${n}-menu-item-group-title`,style:i!==void 0?`padding-left: ${i}px;`:void 0},Ct(e.title),e.extra?m(ot,null," ",Ct(e.extra)):null),m("div",null,e.tmNodes.map(a=>Uc(a,o))))}}});var Zv=oe({name:"MenuOptionContent",props:{collapsed:Boolean,disabled:Boolean,title:[String,Function],icon:Function,extra:[String,Function],showArrow:Boolean,childActive:Boolean,hover:Boolean,paddingLeft:Number,selected:Boolean,maxIconSize:{type:Number,required:!0},activeIconSize:{type:Number,required:!0},iconMarginRight:{type:Number,required:!0},clsPrefix:{type:String,required:!0},onClick:Function,tmNode:{type:Object,required:!0}},setup(e){const{props:t}=be(Ti);return{menuProps:t,style:L(()=>{const{paddingLeft:r}=e;return{paddingLeft:r&&`${r}px`}}),iconStyle:L(()=>{const{maxIconSize:r,activeIconSize:o,iconMarginRight:n}=e;return{width:`${r}px`,height:`${r}px`,fontSize:`${o}px`,marginRight:`${n}px`}})}},render(){const{clsPrefix:e,tmNode:t,menuProps:{renderIcon:r,renderLabel:o,renderExtra:n,expandIcon:i}}=this,a=r?r(t.rawNode):Ct(this.icon);return m("div",{onClick:this.onClick,role:"none",class:[`${e}-menu-item-content`,{[`${e}-menu-item-content--selected`]:this.selected,[`${e}-menu-item-content--collapsed`]:this.collapsed,[`${e}-menu-item-content--child-active`]:this.childActive,[`${e}-menu-item-content--disabled`]:this.disabled,[`${e}-menu-item-content--hover`]:this.hover}],style:this.style},a&&m("div",{class:`${e}-menu-item-content__icon`,style:this.iconStyle,role:"none"},[a]),m("div",{class:`${e}-menu-item-content-header`,role:"none"},o?o(t.rawNode):Ct(this.title),this.extra||n?m("span",{class:`${e}-menu-item-content-header__extra`}," ",n?n(t.rawNode):Ct(this.extra)):null),this.showArrow?m(Bt,{ariaHidden:!0,class:`${e}-menu-item-content__arrow`,clsPrefix:e},{default:()=>i?i(t.rawNode):m($$,null)}):null)}});const Jv=Object.assign(Object.assign({},Kc),{rawNodes:{type:Array,default:()=>[]},tmNodes:{type:Array,default:()=>[]},tmNode:{type:Object,required:!0},disabled:{type:Boolean,default:!1},icon:Function,onClick:Function}),FE=oe({name:"Submenu",props:Jv,setup(e){const t=Vc(e),{NMenu:r,NSubmenu:o}=t,{props:n,mergedCollapsedRef:i,mergedThemeRef:a}=r,l=L(()=>{const{disabled:f}=e;return o!=null&&o.mergedDisabledRef.value||n.disabled?!0:f}),s=W(!1);je(Nc,{paddingLeftRef:t.paddingLeft,mergedDisabledRef:l}),je(Wc,null);function d(){const{onClick:f}=e;f&&f()}function c(){l.value||(i.value||r.toggleExpand(e.internalKey),d())}function u(f){s.value=f}return{menuProps:n,mergedTheme:a,doSelect:r.doSelect,inverted:r.invertedRef,isHorizontal:r.isHorizontalRef,mergedClsPrefix:r.mergedClsPrefixRef,maxIconSize:t.maxIconSize,activeIconSize:t.activeIconSize,iconMarginRight:t.iconMarginRight,dropdownPlacement:t.dropdownPlacement,dropdownShow:s,paddingLeft:t.paddingLeft,mergedDisabled:l,mergedValue:r.mergedValueRef,childActive:ht(()=>r.activePathRef.value.includes(e.internalKey)),collapsed:L(()=>n.mode==="horizontal"?!1:i.value?!0:!r.mergedExpandedKeysRef.value.includes(e.internalKey)),dropdownEnabled:L(()=>!l.value&&(n.mode==="horizontal"||i.value)),handlePopoverShowChange:u,handleClick:c}},render(){var e;const{mergedClsPrefix:t,menuProps:{renderIcon:r,renderLabel:o}}=this,n=()=>{const{isHorizontal:a,paddingLeft:l,collapsed:s,mergedDisabled:d,maxIconSize:c,activeIconSize:u,title:f,childActive:h,icon:p,handleClick:b,dropdownShow:g,iconMarginRight:v,tmNode:w}=this;return m(Zv,{tmNode:w,paddingLeft:l,collapsed:s,disabled:d,iconMarginRight:v,maxIconSize:c,activeIconSize:u,title:f,showArrow:!a,childActive:h,clsPrefix:t,icon:p,hover:g,onClick:b})},i=()=>m(Ka,null,{default:()=>{const{tmNodes:a,collapsed:l}=this;return l?null:m("div",{class:`${t}-submenu-children`,role:"menu"},a.map(s=>Uc(s,this.menuProps)))}});return this.root?m(F4,Object.assign({},(e=this.menuProps)===null||e===void 0?void 0:e.dropdownProps,{themeOverrides:this.mergedTheme.peerOverrides.Dropdown,theme:this.mergedTheme.peers.Dropdown,builtinThemeOverrides:{fontSizeLarge:"14px",optionIconSizeLarge:"18px"},value:this.mergedValue,size:"large",trigger:"hover",disabled:!this.dropdownEnabled,placement:this.dropdownPlacement,keyField:this.menuProps.keyField,labelField:this.menuProps.labelField,childrenField:this.menuProps.childrenField,onUpdateShow:this.handlePopoverShowChange,options:this.rawNodes,onSelect:this.doSelect,inverted:this.inverted,renderIcon:r,renderLabel:o}),{default:()=>m("div",{class:`${t}-submenu`,role:"menuitem","aria-expanded":!this.collapsed},n(),this.isHorizontal?null:i())}):m("div",{class:`${t}-submenu`,role:"menuitem","aria-expanded":!this.collapsed},n(),i())}}),Qv=Object.assign(Object.assign({},Kc),{tmNode:{type:Object,required:!0},disabled:Boolean,icon:Function,onClick:Function}),HE=oe({name:"MenuOption",props:Qv,setup(e){const t=Vc(e),{NSubmenu:r,NMenu:o}=t,{props:n,mergedClsPrefixRef:i,mergedCollapsedRef:a}=o,l=r?r.mergedDisabledRef:{value:!1},s=L(()=>l.value||e.disabled);function d(u){const{onClick:f}=e;f&&f(u)}function c(u){s.value||(o.doSelect(e.internalKey,e.tmNode.rawNode),d(u))}return{mergedClsPrefix:i,dropdownPlacement:t.dropdownPlacement,paddingLeft:t.paddingLeft,iconMarginRight:t.iconMarginRight,maxIconSize:t.maxIconSize,activeIconSize:t.activeIconSize,mergedTheme:o.mergedThemeRef,menuProps:n,dropdownEnabled:ht(()=>e.root&&a.value&&n.mode!=="horizontal"&&!s.value),selected:L(()=>o.mergedValueRef.value===e.internalKey),mergedDisabled:s,handleClick:c}},render(){const{mergedClsPrefix:e,mergedTheme:t,tmNode:r,menuProps:{renderLabel:o}}=this;return m("div",{role:"menuitem",class:[`${e}-menu-item`]},m(cv,{theme:t.peers.Tooltip,themeOverrides:t.peerOverrides.Tooltip,trigger:"hover",placement:this.dropdownPlacement,disabled:!this.dropdownEnabled||this.title===void 0,internalExtraClass:["menu-tooltip"]},{default:()=>o?o(r.rawNode):Ct(this.title),trigger:()=>m(Zv,{tmNode:r,clsPrefix:e,paddingLeft:this.paddingLeft,iconMarginRight:this.iconMarginRight,maxIconSize:this.maxIconSize,activeIconSize:this.activeIconSize,selected:this.selected,title:this.title,extra:this.extra,disabled:this.mergedDisabled,icon:this.icon,onClick:this.handleClick})}))}});var jE=oe({name:"MenuDivider",setup(){const e=be(Ti),{mergedClsPrefixRef:t,isHorizontalRef:r}=e;return()=>r.value?null:m("div",{class:`${t.value}-menu-divider`})}});const NE=er(Xv),WE=er(Qv),VE=er(Jv);function KE(e){return e.type==="divider"||e.type==="render"}function UE(e){return e.type==="divider"}function Uc(e,t){const{rawNode:r}=e;if(KE(r))return UE(r)?m(jE,Object.assign({key:e.key},r.props)):void 0;const{labelField:o}=t,{key:n,level:i,isGroup:a}=e,l=Object.assign(Object.assign({},r),{title:r.title||r[o],extra:r.titleExtra||r.extra,key:n,internalKey:n,level:i,root:i===0,isGroup:a});return e.children?e.isGroup?m(DE,Vt(l,NE,{tmNodes:e.children,key:n})):m(FE,Vt(l,VE,{key:n,rawNodes:r[t.childrenField],tmNodes:e.children,tmNode:e})):m(HE,Vt(l,WE,{key:n,tmNode:e}))}var qE=z([M("menu",` - background-color: var(--n-color); - color: var(--n-item-text-color); - overflow: hidden; - transition: background-color .3s var(--n-bezier); - box-sizing: border-box; - font-size: var(--n-font-size); - padding-bottom: 6px; - `,[K("horizontal",` - display: inline-flex; - padding-bottom: 0; - `,[M("submenu","margin: 0;"),M("menu-item","margin: 0;"),M("menu-item-content",` - padding: 0 20px; - border-bottom: 2px solid #0000; - `,[z("&::before","display: none;"),K("selected","border-bottom: 2px solid var(--n-border-color-horizontal)")]),M("menu-item-content",[K("selected",[F("icon","color: var(--n-item-icon-color-active-horizontal);"),M("menu-item-content-header",` - color: var(--n-item-text-color-active-horizontal); - `,[z("a","color: var(--n-item-text-color-active-horizontal);"),F("extra","color: var(--n-item-text-color-active-horizontal);")])]),K("child-active",` - border-bottom: 2px solid var(--n-border-color-horizontal); - `,[M("menu-item-content-header",` - color: var(--n-item-text-color-child-active-horizontal); - `,[z("a",` - color: var(--n-item-text-color-child-active-horizontal); - `),F("extra",` - color: var(--n-item-text-color-child-active-horizontal); - `)]),F("icon",` - color: var(--n-item-icon-color-child-active-horizontal); - `)]),ut("disabled",[K("selected, child-active",[Bn(null,[F("icon","color: var(--n-item-icon-color-active-hover-horizontal);"),M("menu-item-content-header",` - color: var(--n-item-text-color-active-hover-horizontal); - `,[z("a","color: var(--n-item-text-color-active-hover-horizontal);"),F("extra","color: var(--n-item-text-color-active-hover-horizontal);")])])]),Bn("border-bottom: 2px solid var(--n-border-color-horizontal);",[F("icon",` - color: var(--n-item-icon-color-hover-horizontal); - `),M("menu-item-content-header",` - color: var(--n-item-text-color-hover-horizontal); - `,[z("a",` - color: var(--n-item-text-color-hover-horizontal); - `),F("extra",` - color: var(--n-item-text-color-hover-horizontal); - `)])])]),M("menu-item-content-header",[z("a","color: var(--n-item-text-color-horizontal);")])])]),K("collapsed",[M("menu-item",[K("selected",[z("&::before",` - background-color: var(--n-item-color-active-collapsed) !important; - `)])]),M("menu-item-content",[M("menu-item-content-header","opacity: 0;"),F("arrow","opacity: 0;"),F("icon","color: var(--n-item-icon-color-collapsed);")])]),M("menu-item",` - height: var(--n-item-height); - margin-top: 6px; - position: relative; - `),M("menu-item-content",` - box-sizing: border-box; - line-height: 1.75; - height: 100%; - display: grid; - grid-template-areas: "icon content arrow"; - grid-template-columns: auto 1fr auto; - align-items: center; - cursor: pointer; - position: relative; - padding-right: 18px; - transition: - background-color .3s var(--n-bezier), - padding-left .3s var(--n-bezier), - border-color .3s var(--n-bezier); - `,[z("> *","z-index: 1;"),z("&::before",` - z-index: auto; - content: ""; - background-color: #0000; - position: absolute; - left: 8px; - right: 8px; - top: 0; - bottom: 0; - pointer-events: none; - border-radius: var(--n-border-radius); - transition: background-color .3s var(--n-bezier); - `),K("disabled",` - opacity: .45; - cursor: not-allowed; - `),K("collapsed",[F("arrow","transform: rotate(0);")]),K("selected",[z("&::before","background-color: var(--n-item-color-active);"),F("arrow","color: var(--n-arrow-color-active);"),F("icon","color: var(--n-item-icon-color-active);"),M("menu-item-content-header",` - color: var(--n-item-text-color-active); - `,[z("a","color: var(--n-item-text-color-active);"),F("extra","color: var(--n-item-text-color-active);")])]),K("child-active",[M("menu-item-content-header",` - color: var(--n-item-text-color-child-active); - `,[z("a",` - color: var(--n-item-text-color-child-active); - `),F("extra",` - color: var(--n-item-text-color-child-active); - `)]),F("arrow",` - color: var(--n-arrow-color-child-active); - `),F("icon",` - color: var(--n-item-icon-color-child-active); - `)]),ut("disabled",[K("selected, child-active",[Bn(null,[F("arrow","color: var(--n-arrow-color-active-hover);"),F("icon","color: var(--n-item-icon-color-active-hover);"),M("menu-item-content-header",` - color: var(--n-item-text-color-active-hover); - `,[z("a","color: var(--n-item-text-color-active-hover);"),F("extra","color: var(--n-item-text-color-active-hover);")])])]),K("selected",[Bn(null,[z("&::before","background-color: var(--n-item-color-active-hover);")])]),Bn(null,[z("&::before","background-color: var(--n-item-color-hover);"),F("arrow",` - color: var(--n-arrow-color-hover); - `),F("icon",` - color: var(--n-item-icon-color-hover); - `),M("menu-item-content-header",` - color: var(--n-item-text-color-hover); - `,[z("a",` - color: var(--n-item-text-color-hover); - `),F("extra",` - color: var(--n-item-text-color-hover); - `)])])]),F("icon",` - grid-area: icon; - color: var(--n-item-icon-color); - transition: - color .3s var(--n-bezier), - font-size .3s var(--n-bezier), - margin-right .3s var(--n-bezier); - box-sizing: content-box; - display: inline-flex; - align-items: center; - justify-content: center; - `),F("arrow",` - grid-area: arrow; - font-size: 16px; - color: var(--n-arrow-color); - transform: rotate(180deg); - opacity: 1; - transition: - color .3s var(--n-bezier), - transform 0.2s var(--n-bezier), - opacity 0.2s var(--n-bezier); - `),M("menu-item-content-header",` - grid-area: content; - transition: - color .3s var(--n-bezier), - opacity .3s var(--n-bezier); - opacity: 1; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - color: var(--n-item-text-color); - `,[z("a",` - text-decoration: none; - transition: color .3s var(--n-bezier); - color: var(--n-item-text-color); - `,[z("&::before",` - content: ""; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - `)]),F("extra",` - font-size: .93em; - color: var(--n-group-text-color); - transition: color .3s var(--n-bezier); - `)])]),M("submenu",` - cursor: pointer; - position: relative; - margin-top: 6px; - `,[M("menu-item-content",` - height: var(--n-item-height); - `),M("submenu-children",` - overflow: hidden; - padding: 0; - `,[jm({duration:".2s"})])]),M("menu-item-group",[M("menu-item-group-title",` - margin-top: 6px; - color: var(--n-group-text-color); - cursor: default; - font-size: .93em; - height: 36px; - display: flex; - align-items: center; - transition: - padding-left .3s var(--n-bezier), - color .3s var(--n-bezier); - `)])]),M("menu-tooltip",[z("a",` - color: inherit; - text-decoration: none; - `)]),M("menu-divider",` - transition: background-color .3s var(--n-bezier); - background-color: var(--n-divider-color); - height: 1px; - margin: 6px 18px; - `)]);function Bn(e,t){return[K("hover",e,t),z("&:hover",e,t)]}const GE=Object.assign(Object.assign({},ze.props),{options:{type:Array,default:()=>[]},collapsed:{type:Boolean,default:void 0},collapsedWidth:{type:Number,default:48},iconSize:{type:Number,default:20},collapsedIconSize:{type:Number,default:24},rootIndent:Number,indent:{type:Number,default:32},labelField:{type:String,default:"label"},keyField:{type:String,default:"key"},childrenField:{type:String,default:"children"},defaultExpandAll:Boolean,defaultExpandedKeys:Array,expandedKeys:Array,value:[String,Number],defaultValue:{type:[String,Number],default:null},mode:{type:String,default:"vertical"},watchProps:{type:Array,default:void 0},disabled:Boolean,inverted:Boolean,"onUpdate:expandedKeys":[Function,Array],onUpdateExpandedKeys:[Function,Array],onUpdateValue:[Function,Array],"onUpdate:value":[Function,Array],expandIcon:Function,renderIcon:Function,renderLabel:Function,renderExtra:Function,dropdownPlacement:{type:String,default:"bottom"},dropdownProps:Object,accordion:Boolean,items:Array,onOpenNamesChange:[Function,Array],onSelect:[Function,Array],onExpandedNamesChange:[Function,Array],expandedNames:Array,defaultExpandedNames:Array});var YE=oe({name:"Menu",props:GE,setup(e){const{mergedClsPrefixRef:t,inlineThemeDisabled:r}=lt(e),o=ze("Menu","-menu",qE,aT,e,t),n=be(LE,null),i=L(()=>{var _;const{collapsed:R}=e;if(R!==void 0)return R;if(n){const{collapseModeRef:P,collapsedRef:j}=n;if(P.value==="width")return(_=j.value)!==null&&_!==void 0?_:!1}return!1}),a=L(()=>{const{keyField:_,childrenField:R}=e;return lm(e.items||e.options,{getChildren(P){return P[R]},getKey(P){var j;return(j=P[_])!==null&&j!==void 0?j:P.name}})}),l=L(()=>new Set(a.value.treeNodes.map(_=>_.key))),{watchProps:s}=e,d=W(null);s!=null&&s.includes("defaultValue")?xr(()=>{d.value=e.defaultValue}):d.value=e.defaultValue;const c=Oe(e,"value"),u=hn(c,d),f=W([]),h=()=>{f.value=e.defaultExpandAll?a.value.getNonLeafKeys():e.defaultExpandedNames||e.defaultExpandedKeys||a.value.getPath(u.value,{includeSelf:!1}).keyPath};s!=null&&s.includes("defaultExpandedKeys")?xr(h):h();const p=di(e,["expandedNames","expandedKeys"]),b=hn(p,f),g=L(()=>a.value.treeNodes),v=L(()=>a.value.getPath(u.value).keyPath);je(Ti,{props:e,mergedCollapsedRef:i,mergedThemeRef:o,mergedValueRef:u,mergedExpandedKeysRef:b,activePathRef:v,mergedClsPrefixRef:t,isHorizontalRef:L(()=>e.mode==="horizontal"),invertedRef:Oe(e,"inverted"),doSelect:w,toggleExpand:x});function w(_,R){const{"onUpdate:value":P,onUpdateValue:j,onSelect:T}=e;j&&Be(j,_,R),P&&Be(P,_,R),T&&Be(T,_,R),d.value=_}function $(_){const{"onUpdate:expandedKeys":R,onUpdateExpandedKeys:P,onExpandedNamesChange:j,onOpenNamesChange:T}=e;R&&Be(R,_),P&&Be(P,_),j&&Be(j,_),T&&Be(T,_),f.value=_}function x(_){const R=Array.from(b.value),P=R.findIndex(j=>j===_);if(~P)R.splice(P,1);else{if(e.accordion&&l.value.has(_)){const j=R.findIndex(T=>l.value.has(T));j>-1&&R.splice(j,1)}R.push(_)}$(R)}const S=_=>{const R=a.value.getPath(_!=null?_:u.value,{includeSelf:!1}).keyPath;if(!R.length)return;const P=Array.from(b.value),j=new Set([...P,...R]);e.accordion&&l.value.forEach(T=>{j.has(T)&&!R.includes(T)&&j.delete(T)}),$(Array.from(j))},E=L(()=>{const{inverted:_}=e,{common:{cubicBezierEaseInOut:R},self:P}=o.value,{borderRadius:j,borderColorHorizontal:T,fontSize:N,itemHeight:B,dividerColor:q}=P,A={"--n-divider-color":q,"--n-bezier":R,"--n-font-size":N,"--n-border-color-horizontal":T,"--n-border-radius":j,"--n-item-height":B};return _?(A["--n-group-text-color"]=P.groupTextColorInverted,A["--n-color"]=P.colorInverted,A["--n-item-text-color"]=P.itemTextColorInverted,A["--n-item-text-color-hover"]=P.itemTextColorHoverInverted,A["--n-item-text-color-active"]=P.itemTextColorActiveInverted,A["--n-item-text-color-child-active"]=P.itemTextColorChildActiveInverted,A["--n-item-text-color-active-hover"]=P.itemTextColorActiveHoverInverted,A["--n-item-icon-color"]=P.itemIconColorInverted,A["--n-item-icon-color-hover"]=P.itemIconColorHoverInverted,A["--n-item-icon-color-active"]=P.itemIconColorActiveInverted,A["--n-item-icon-color-active-hover"]=P.itemIconColorActiveHoverInverted,A["--n-item-icon-color-child-active"]=P.itemIconColorChildActiveInverted,A["--n-item-icon-color-collapsed"]=P.itemIconColorCollapsedInverted,A["--n-item-text-color-horizontal"]=P.itemTextColorHorizontalInverted,A["--n-item-text-color-hover-horizontal"]=P.itemTextColorHoverHorizontalInverted,A["--n-item-text-color-active-horizontal"]=P.itemTextColorActiveHorizontalInverted,A["--n-item-text-color-child-active-horizontal"]=P.itemTextColorChildActiveHorizontalInverted,A["--n-item-text-color-active-hover-horizontal"]=P.itemTextColorActiveHoverHorizontalInverted,A["--n-item-icon-color-horizontal"]=P.itemIconColorHorizontalInverted,A["--n-item-icon-color-hover-horizontal"]=P.itemIconColorHoverHorizontalInverted,A["--n-item-icon-color-active-horizontal"]=P.itemIconColorActiveHorizontalInverted,A["--n-item-icon-color-active-hover-horizontal"]=P.itemIconColorActiveHoverHorizontalInverted,A["--n-item-icon-color-child-active-horizontal"]=P.itemIconColorChildActiveHorizontalInverted,A["--n-arrow-color"]=P.arrowColorInverted,A["--n-arrow-color-hover"]=P.arrowColorHoverInverted,A["--n-arrow-color-active"]=P.arrowColorActiveInverted,A["--n-arrow-color-active-hover"]=P.arrowColorActiveHoverInverted,A["--n-arrow-color-child-active"]=P.arrowColorChildActiveInverted,A["--n-item-color-hover"]=P.itemColorHoverInverted,A["--n-item-color-active"]=P.itemColorActiveInverted,A["--n-item-color-active-hover"]=P.itemColorActiveHoverInverted,A["--n-item-color-active-collapsed"]=P.itemColorActiveCollapsedInverted):(A["--n-group-text-color"]=P.groupTextColor,A["--n-color"]=P.color,A["--n-item-text-color"]=P.itemTextColor,A["--n-item-text-color-hover"]=P.itemTextColorHover,A["--n-item-text-color-active"]=P.itemTextColorActive,A["--n-item-text-color-child-active"]=P.itemTextColorChildActive,A["--n-item-text-color-active-hover"]=P.itemTextColorActiveHover,A["--n-item-icon-color"]=P.itemIconColor,A["--n-item-icon-color-hover"]=P.itemIconColorHover,A["--n-item-icon-color-active"]=P.itemIconColorActive,A["--n-item-icon-color-active-hover"]=P.itemIconColorActiveHover,A["--n-item-icon-color-child-active"]=P.itemIconColorChildActive,A["--n-item-icon-color-collapsed"]=P.itemIconColorCollapsed,A["--n-item-text-color-horizontal"]=P.itemTextColorHorizontal,A["--n-item-text-color-hover-horizontal"]=P.itemTextColorHoverHorizontal,A["--n-item-text-color-active-horizontal"]=P.itemTextColorActiveHorizontal,A["--n-item-text-color-child-active-horizontal"]=P.itemTextColorChildActiveHorizontal,A["--n-item-text-color-active-hover-horizontal"]=P.itemTextColorActiveHoverHorizontal,A["--n-item-icon-color-horizontal"]=P.itemIconColorHorizontal,A["--n-item-icon-color-hover-horizontal"]=P.itemIconColorHoverHorizontal,A["--n-item-icon-color-active-horizontal"]=P.itemIconColorActiveHorizontal,A["--n-item-icon-color-active-hover-horizontal"]=P.itemIconColorActiveHoverHorizontal,A["--n-item-icon-color-child-active-horizontal"]=P.itemIconColorChildActiveHorizontal,A["--n-arrow-color"]=P.arrowColor,A["--n-arrow-color-hover"]=P.arrowColorHover,A["--n-arrow-color-active"]=P.arrowColorActive,A["--n-arrow-color-active-hover"]=P.arrowColorActiveHover,A["--n-arrow-color-child-active"]=P.arrowColorChildActive,A["--n-item-color-hover"]=P.itemColorHover,A["--n-item-color-active"]=P.itemColorActive,A["--n-item-color-active-hover"]=P.itemColorActiveHover,A["--n-item-color-active-collapsed"]=P.itemColorActiveCollapsed),A}),y=r?_t("menu",L(()=>e.inverted?"a":"b"),E,e):void 0;return{mergedClsPrefix:t,controlledExpandedKeys:p,uncontrolledExpanededKeys:f,mergedExpandedKeys:b,uncontrolledValue:d,mergedValue:u,activePath:v,tmNodes:g,mergedTheme:o,mergedCollapsed:i,cssVars:r?void 0:E,themeClass:y==null?void 0:y.themeClass,onRender:y==null?void 0:y.onRender,showOption:S}},render(){const{mergedClsPrefix:e,mode:t,themeClass:r,onRender:o}=this;return o==null||o(),m("div",{role:t==="horizontal"?"menubar":"menu",class:[`${e}-menu`,r,`${e}-menu--${t}`,this.mergedCollapsed&&`${e}-menu--collapsed`],style:this.cssVars},this.tmNodes.map(n=>Uc(n,this.$props)))}});const eg={icon:Function,type:{type:String,default:"info"},content:[String,Number,Function],showIcon:{type:Boolean,default:!0},closable:Boolean,keepAliveOnHover:Boolean,onClose:Function,onMouseenter:Function,onMouseleave:Function},tg="n-message-api",rg="n-message-provider";var XE=z([M("message-wrapper",` - margin: var(--n-margin); - z-index: 0; - transform-origin: top center; - display: flex; - `,[jm({overflow:"visible",originalTransition:"transform .3s var(--n-bezier)",enterToProps:{transform:"scale(1)"},leaveToProps:{transform:"scale(0.85)"}})]),M("message",` - box-sizing: border-box; - display: flex; - align-items: center; - transition: - color .3s var(--n-bezier), - box-shadow .3s var(--n-bezier), - background-color .3s var(--n-bezier), - opacity .3s var(--n-bezier), - transform .3s var(--n-bezier), - margin-bottom .3s var(--n-bezier); - padding: var(--n-padding); - border-radius: var(--n-border-radius); - flex-wrap: nowrap; - overflow: hidden; - max-width: var(--n-max-width); - color: var(--n-text-color); - background-color: var(--n-color); - box-shadow: var(--n-box-shadow); - `,[F("content",` - display: inline-block; - line-height: var(--n-line-height); - font-size: var(--n-font-size); - `),F("icon",` - position: relative; - margin: var(--n-icon-margin); - height: var(--n-icon-size); - width: var(--n-icon-size); - font-size: var(--n-icon-size); - flex-shrink: 0; - `,[["default","info","success","warning","error","loading"].map(e=>K(`${e}-type`,[z("> *",` - color: var(--n-icon-color-${e}); - transition: color .3s var(--n-bezier); - `)])),z("> *",` - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - `,[pi()])]),F("close",` - font-size: var(--n-close-size); - margin: var(--n-close-margin); - transition: color .3s var(--n-bezier); - flex-shrink: 0; - `,[z("&:hover",` - color: var(--n-close-color-hover); - `),z("&:active",` - color: var(--n-close-color-pressed); - `)])]),M("message-container",` - z-index: 6000; - position: fixed; - height: 0; - overflow: visible; - display: flex; - flex-direction: column; - align-items: center; - `,[K("top",` - top: 12px; - left: 0; - right: 0; - `),K("top-left",` - top: 12px; - left: 12px; - right: 0; - align-items: flex-start; - `),K("top-right",` - top: 12px; - left: 0; - right: 12px; - align-items: flex-end; - `),K("bottom",` - bottom: 4px; - left: 0; - right: 0; - justify-content: flex-end; - `),K("bottom-left",` - bottom: 4px; - left: 12px; - right: 0; - justify-content: flex-end; - align-items: flex-start; - `),K("bottom-right",` - bottom: 4px; - left: 0; - right: 12px; - justify-content: flex-end; - align-items: flex-end; - `)])]);const ZE={info:()=>m(rm,null),success:()=>m(om,null),warning:()=>m(nm,null),error:()=>m(tm,null),default:()=>null};var JE=oe({name:"Message",props:Object.assign(Object.assign({},eg),{render:Function}),setup(e){const{inlineThemeDisabled:t}=lt(),{props:r,mergedClsPrefixRef:o}=be(rg),n=ze("Message","-message",XE,uT,r,o),i=L(()=>{const{type:l}=e,{common:{cubicBezierEaseInOut:s},self:{padding:d,margin:c,maxWidth:u,iconMargin:f,closeMargin:h,closeSize:p,iconSize:b,fontSize:g,lineHeight:v,borderRadius:w,iconColorInfo:$,iconColorSuccess:x,iconColorWarning:S,iconColorError:E,iconColorLoading:y,[ae("textColor",l)]:_,[ae("boxShadow",l)]:R,[ae("color",l)]:P,[ae("closeColor",l)]:j,[ae("closeColorPressed",l)]:T,[ae("closeColorHover",l)]:N}}=n.value;return{"--n-bezier":s,"--n-margin":c,"--n-padding":d,"--n-max-width":u,"--n-font-size":g,"--n-icon-margin":f,"--n-icon-size":b,"--n-close-size":p,"--n-close-margin":h,"--n-text-color":_,"--n-color":P,"--n-box-shadow":R,"--n-icon-color-info":$,"--n-icon-color-success":x,"--n-icon-color-warning":S,"--n-icon-color-error":E,"--n-icon-color-loading":y,"--n-close-color":j,"--n-close-color-pressed":T,"--n-close-color-hover":N,"--n-line-height":v,"--n-border-radius":w}}),a=t?_t("message",L(()=>e.type[0]),i,{}):void 0;return{mergedClsPrefix:o,messageProviderProps:r,handleClose(){var l;(l=e.onClose)===null||l===void 0||l.call(e)},cssVars:t?void 0:i,themeClass:a==null?void 0:a.themeClass,onRender:a==null?void 0:a.onRender,placement:r.placement}},render(){const{render:e,type:t,closable:r,content:o,mergedClsPrefix:n,cssVars:i,themeClass:a,onRender:l,icon:s,handleClose:d,showIcon:c}=this;l==null||l();let u;return m("div",{class:[`${n}-message-wrapper`,a],onMouseenter:this.onMouseenter,onMouseleave:this.onMouseleave,style:[{alignItems:this.placement.startsWith("top")?"flex-start":"flex-end"},i]},e?e(this.$props):m("div",{class:`${n}-message ${n}-message--${t}-type`},(u=QE(s,t,n))&&c?m("div",{class:`${n}-message__icon ${n}-message__icon--${t}-type`},m(Va,null,{default:()=>u})):null,m("div",{class:`${n}-message__content`},Ct(o)),r?m(yi,{clsPrefix:n,class:`${n}-message__close`,onClick:d}):null))}});function QE(e,t,r){if(typeof e=="function")return e();{const o=t==="loading"?m(Ua,{clsPrefix:r,strokeWidth:24,scale:.85}):ZE[t]();return o?m(Bt,{clsPrefix:r,key:t},{default:()=>o}):null}}var eR=oe({name:"MessageEnvironment",props:Object.assign(Object.assign({},eg),{duration:{type:Number,default:3e3},onAfterLeave:Function,onLeave:Function,internalKey:{type:String,required:!0},onInternalAfterLeave:Function,onHide:Function,onAfterHide:Function}),setup(e){let t=null;const r=W(!0);Ot(()=>{o()});function o(){const{duration:c}=e;c&&(t=window.setTimeout(a,c))}function n(c){c.currentTarget===c.target&&t!==null&&(window.clearTimeout(t),t=null)}function i(c){c.currentTarget===c.target&&o()}function a(){const{onHide:c}=e;r.value=!1,t&&(window.clearTimeout(t),t=null),c&&c()}function l(){const{onClose:c}=e;c&&c(),a()}function s(){const{onAfterLeave:c,onInternalAfterLeave:u,onAfterHide:f,internalKey:h}=e;c&&c(),u&&u(h),f&&f()}function d(){a()}return{show:r,hide:a,handleClose:l,handleAfterLeave:s,handleMouseleave:i,handleMouseenter:n,deactivate:d}},render(){return m(Ka,{appear:!0,onAfterLeave:this.handleAfterLeave,onLeave:this.onLeave},{default:()=>[this.show?m(JE,{content:this.content,type:this.type,icon:this.icon,showIcon:this.showIcon,closable:this.closable,onClose:this.handleClose,onMouseenter:this.keepAliveOnHover?this.handleMouseenter:void 0,onMouseleave:this.keepAliveOnHover?this.handleMouseleave:void 0}):null]})}});const tR=Object.assign(Object.assign({},ze.props),{to:[String,Object],duration:{type:Number,default:3e3},keepAliveOnHover:Boolean,max:Number,placement:{type:String,default:"top"},closable:Boolean,containerStyle:[String,Object]});var rR=oe({name:"MessageProvider",props:tR,setup(e){const{mergedClsPrefixRef:t}=lt(e),r=W([]),o=W({}),n={create(s,d){return i(s,Object.assign({type:"default"},d))},info(s,d){return i(s,Object.assign(Object.assign({},d),{type:"info"}))},success(s,d){return i(s,Object.assign(Object.assign({},d),{type:"success"}))},warning(s,d){return i(s,Object.assign(Object.assign({},d),{type:"warning"}))},error(s,d){return i(s,Object.assign(Object.assign({},d),{type:"error"}))},loading(s,d){return i(s,Object.assign(Object.assign({},d),{type:"loading"}))},destroyAll:l};je(rg,{props:e,mergedClsPrefixRef:t}),je(tg,n);function i(s,d){const c=dn(),u=ar(Object.assign(Object.assign({},d),{content:s,key:c,destroy:()=>{o.value[c].hide()}})),{max:f}=e;return f&&r.value.length>=f&&r.value.shift(),r.value.push(u),u}function a(s){r.value.splice(r.value.findIndex(d=>d.key===s),1),delete o.value[s]}function l(){Object.values(o.value).forEach(s=>{s.hide()})}return Object.assign({mergedClsPrefix:t,messageRefs:o,messageList:r,handleAfterLeave:a},n)},render(){var e,t,r;return m(ot,null,(t=(e=this.$slots).default)===null||t===void 0?void 0:t.call(e),this.messageList.length?m(gh,{to:(r=this.to)!==null&&r!==void 0?r:"body"},m("div",{class:[`${this.mergedClsPrefix}-message-container`,`${this.mergedClsPrefix}-message-container--${this.placement}`],key:"message-container",style:this.containerStyle},this.messageList.map(o=>m(eR,Object.assign({ref:n=>{n&&(this.messageRefs[o.key]=n)},internalKey:o.key,onInternalAfterLeave:this.handleAfterLeave},sc(o,["destroy"],void 0),{duration:o.duration===void 0?this.duration:o.duration,keepAliveOnHover:o.keepAliveOnHover===void 0?this.keepAliveOnHover:o.keepAliveOnHover,closable:o.closable===void 0?this.closable:o.closable}))))):null)}});function oR(){const e=be(tg,null);return e===null&&Da("use-message","No outer founded. See prerequisite in https://www.naiveui.com/en-US/os-theme/components/message for more details. If you want to use `useMessage` outside setup, please check https://www.naiveui.com/zh-CN/os-theme/components/message#Q-&-A."),e}const nR={name:"Skeleton",common:de,self(e){const{heightSmall:t,heightMedium:r,heightLarge:o,borderRadius:n}=e;return{color:"rgba(255, 255, 255, 0.12)",colorEnd:"rgba(255, 255, 255, 0.18)",borderRadius:n,heightSmall:t,heightMedium:r,heightLarge:o}}};var iR=z([z("@keyframes spin-rotate",` - from { - transform: rotate(0); - } - to { - transform: rotate(360deg); - } - `),M("spin-container",{position:"relative"},[M("spin-body",` - position: absolute; - top: 50%; - left: 50%; - transform: translateX(-50%) translateY(-50%); - `,[mi()])]),M("spin-body",` - display: inline-flex; - align-items: center; - justify-content: center; - flex-direction: column; - `),M("spin",` - display: inline-flex; - height: var(--n-size); - width: var(--n-size); - font-size: var(--n-size); - color: var(--n-color); - `,[K("rotate",` - animation: spin-rotate 2s linear infinite; - `)]),M("spin-description",` - display: inline-block; - font-size: var(--n-font-size); - color: var(--n-text-color); - transition: color .3s var(--n-bezier); - margin-top: 8px; - `),M("spin-content",` - opacity: 1; - transition: opacity .3s var(--n-bezier); - pointer-events: all; - `,[K("spinning",` - user-select: none; - pointer-events: none; - opacity: var(--n-opacity-spinning); - `)])]);const aR={small:20,medium:18,large:16},lR=Object.assign(Object.assign({},ze.props),{description:String,stroke:String,size:{type:[String,Number],default:"medium"},show:{type:Boolean,default:!0},strokeWidth:Number,rotate:{type:Boolean,default:!0},spinning:{type:Boolean,validator:()=>!0,default:void 0}});var sR=oe({name:"Spin",props:lR,setup(e){const{mergedClsPrefixRef:t,inlineThemeDisabled:r}=lt(e),o=ze("Spin","-spin",iR,FT,e,t),n=L(()=>{const{size:a}=e,{common:{cubicBezierEaseInOut:l},self:s}=o.value,{opacitySpinning:d,color:c,textColor:u}=s,f=typeof a=="number"?xC(a):s[ae("size",a)];return{"--n-bezier":l,"--n-opacity-spinning":d,"--n-size":f,"--n-color":c,"--n-text-color":u}}),i=r?_t("spin",L(()=>{const{size:a}=e;return typeof a=="number"?String(a):a[0]}),n,e):void 0;return{mergedClsPrefix:t,compitableShow:di(e,["spinning","show"]),mergedStrokeWidth:L(()=>{const{strokeWidth:a}=e;if(a!==void 0)return a;const{size:l}=e;return aR[typeof l=="number"?"medium":l]}),cssVars:r?void 0:n,themeClass:i==null?void 0:i.themeClass,onRender:i==null?void 0:i.onRender}},render(){var e,t;const{$slots:r,mergedClsPrefix:o,description:n}=this,i=r.icon&&this.rotate,a=(n||r.description)&&m("div",{class:`${o}-spin-description`},n||((e=r.description)===null||e===void 0?void 0:e.call(r))),l=r.icon?m("div",{class:[`${o}-spin-body`,this.themeClass]},m("div",{class:[`${o}-spin`,i&&`${o}-spin--rotate`],style:r.default?"":this.cssVars},r.icon()),a):m("div",{class:[`${o}-spin-body`,this.themeClass]},m(Ua,{clsPrefix:o,style:r.default?"":this.cssVars,stroke:this.stroke,"stroke-width":this.mergedStrokeWidth,class:`${o}-spin`}),a);return(t=this.onRender)===null||t===void 0||t.call(this),r.default?m("div",{class:[`${o}-spin-container`,this.themeClass],style:this.cssVars},m("div",{class:[`${o}-spin-content`,this.compitableShow&&`${o}-spin-content--spinning`]},r),m(At,{name:"fade-in-transition"},{default:()=>this.compitableShow?l:null})):l}});const qc="n-tabs",og={tab:[String,Number,Object,Function],name:{type:[String,Number],required:!0},disabled:Boolean,displayDirective:{type:String,default:"if"},closable:{type:Boolean,default:void 0},tabProps:Object,label:[String,Number,Object,Function]};var cR=oe({__TAB_PANE__:!0,name:"TabPane",alias:["TabPanel"],props:og,setup(e){const t=be(qc,null);return t||Da("tab-pane","`n-tab-pane` must be placed inside `n-tabs`."),{style:t.paneStyleRef,class:t.paneClassRef,mergedClsPrefix:t.mergedClsPrefixRef}},render(){return m("div",{class:[`${this.mergedClsPrefix}-tab-pane`,this.class],style:this.style},this.$slots)}});const dR=Object.assign({internalLeftPadded:Boolean,internalAddable:Boolean,internalCreatedByPane:Boolean},sc(og,["displayDirective"]));var Es=oe({__TAB__:!0,inheritAttrs:!1,name:"Tab",props:dR,setup(e){const{mergedClsPrefixRef:t,valueRef:r,typeRef:o,closableRef:n,tabStyleRef:i,tabChangeIdRef:a,onBeforeLeaveRef:l,triggerRef:s,handleAdd:d,activateTab:c,handleClose:u}=be(qc);return{trigger:s,mergedClosable:L(()=>{if(e.internalAddable)return!1;const{closable:f}=e;return f===void 0?n.value:f}),style:i,clsPrefix:t,value:r,type:o,handleClose(f){f.stopPropagation(),!e.disabled&&u(e.name)},activateTab(){if(e.disabled)return;if(e.internalAddable){d();return}const{name:f}=e,h=++a.id;if(f!==r.value){const{value:p}=l;p?Promise.resolve(p(e.name,r.value)).then(b=>{b&&a.id===h&&c(f)}):c(f)}}}},render(){const{internalAddable:e,clsPrefix:t,name:r,disabled:o,label:n,tab:i,value:a,mergedClosable:l,style:s,trigger:d,$slots:{default:c}}=this,u=n!=null?n:i;return m("div",{class:`${t}-tabs-tab-wrapper`},this.internalLeftPadded?m("div",{class:`${t}-tabs-tab-pad`}):null,m("div",Object.assign({key:r,"data-name":r,"data-disabled":o?!0:void 0},Xr({class:[`${t}-tabs-tab`,a===r&&`${t}-tabs-tab--active`,o&&`${t}-tabs-tab--disabled`,l&&`${t}-tabs-tab--closable`,e&&`${t}-tabs-tab--addable`],onClick:d==="click"?this.activateTab:void 0,onMouseenter:d==="hover"?this.activateTab:void 0,style:e?void 0:s},this.internalCreatedByPane?this.tabProps||{}:this.$attrs)),m("span",{class:`${t}-tabs-tab__label`},e?m(ot,null,m("div",{class:`${t}-tabs-tab__height-placeholder`},"\xA0"),m(Bt,{clsPrefix:t},{default:()=>m(b$,null)})):c?c():typeof u=="object"?u:Ct(u!=null?u:r)),l&&this.type==="card"?m(yi,{clsPrefix:t,class:`${t}-tabs-tab__close`,onClick:this.handleClose,disabled:o}):null))}}),uR=M("tabs",` - box-sizing: border-box; - width: 100%; - transition: - background-color .3s var(--n-bezier), - border-color .3s var(--n-bezier); -`,[M("tabs-rail",` - padding: 3px; - border-radius: var(--n-tab-border-radius); - width: 100%; - background-color: var(--n-color-segment); - transition: background-color .3s var(--n-bezier); - display: flex; - align-items: center; - `,[M("tabs-tab-wrapper",` - flex-basis: 0; - flex-grow: 1; - display: flex; - align-items: center; - justify-content: center; - `,[M("tabs-tab",` - overflow: hidden; - border-radius: var(--n-tab-border-radius); - width: 100%; - display: flex; - align-items: center; - justify-content: center; - `,[K("active",` - font-weight: var(--n-font-weight-strong); - color: var(--n-tab-text-color-active); - background-color: var(--n-tab-color-segment); - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .08); - `),z("&:hover",` - color: var(--n-tab-text-color-hover); - `)])])]),K("flex",[M("tabs-nav",{width:"100%"},[M("tabs-wrapper",{width:"100%"},[M("tabs-tab",{marginRight:0})])])]),M("tabs-nav",` - box-sizing: border-box; - line-height: 1.5; - display: flex; - transition: border-color .3s var(--n-bezier); - `,[F("prefix, suffix",` - display: flex; - align-items: center; - `),F("prefix","padding-right: 16px;"),F("suffix","padding-left: 16px;")]),M("tabs-nav-scroll-wrapper",` - flex: 1; - position: relative; - overflow: hidden; - `,[K("shadow-before",[z("&::before",` - box-shadow: inset 10px 0 8px -8px rgba(0, 0, 0, .12); - `)]),K("shadow-after",[z("&::after",` - box-shadow: inset -10px 0 8px -8px rgba(0, 0, 0, .12); - `)]),z("&::before, &::after",` - transition: box-shadow .3s var(--n-bezier); - pointer-events: none; - content: ""; - position: absolute; - top: 0; - bottom: 0; - width: 20px; - z-index: 1; - `),z("&::before",` - left: 0; - `),z("&::after",` - right: 0; - `)]),M("tabs-nav-scroll-content",` - display: flex; - position: relative; - min-width: 100%; - width: fit-content; - `),M("tabs-wrapper",` - display: inline-flex; - flex-wrap: nowrap; - position: relative; - `),M("tabs-tab-wrapper",` - display: flex; - flex-wrap: nowrap; - flex-shrink: 0; - flex-grow: 0; - `),M("tabs-tab",` - cursor: pointer; - white-space: nowrap; - flex-wrap: nowrap; - display: inline-flex; - align-items: center; - color: var(--n-tab-text-color); - font-size: var(--n-tab-font-size); - background-clip: padding-box; - padding: var(--n-tab-padding); - transition: - box-shadow .3s var(--n-bezier), - color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - border-color .3s var(--n-bezier); - `,[K("disabled",{cursor:"not-allowed"}),F("close",` - margin-left: 8px; - font-size: 14px; - transition: color .3s var(--n-bezier); - `),F("label",` - display: flex; - align-items: center; - `)]),M("tabs-bar",` - position: absolute; - bottom: 0; - height: 2px; - border-radius: 1px; - background-color: var(--n-bar-color); - transition: - left .2s var(--n-bezier), - max-width .2s var(--n-bezier), - background-color .3s var(--n-bezier); - `,[K("transition-disabled",` - transition: none; - `),K("disabled",` - background-color: var(--n-tab-text-color-disabled) - `)]),M("tabs-pane-wrapper",` - position: relative; - overflow: hidden; - transition: max-height .2s var(--n-bezier); - `),M("tab-pane",` - color: var(--n-pane-text-color); - width: 100%; - padding: var(--n-pane-padding); - transition: - color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - opacity .2s var(--n-bezier); - left: 0; - right: 0; - top: 0; - `,[z("&.next-transition-leave-active, &.prev-transition-leave-active, &.next-transition-enter-active, &.prev-transition-enter-active",` - transition: - color .3s var(--n-bezier), - background-color .3s var(--n-bezier), - transform .2s var(--n-bezier), - opacity .2s var(--n-bezier); - `),z("&.next-transition-leave-active, &.prev-transition-leave-active",` - position: absolute; - `),z("&.next-transition-enter-from, &.prev-transition-leave-to",` - transform: translateX(32px); - opacity: 0; - `),z("&.next-transition-leave-to, &.prev-transition-enter-from",` - transform: translateX(-32px); - opacity: 0; - `),z("&.next-transition-leave-from, &.next-transition-enter-to, &.prev-transition-leave-from, &.prev-transition-enter-to",` - transform: translateX(0); - opacity: 1; - `)]),M("tabs-tab-pad",` - width: var(--n-tab-gap); - flex-grow: 0; - flex-shrink: 0; - `),K("line-type, bar-type",[M("tabs-tab",` - font-weight: var(--n-tab-font-weight-active); - box-sizing: border-box; - vertical-align: bottom; - `,[z("&:hover",{color:"var(--n-tab-text-color-hover)"}),K("active",{color:"var(--n-tab-text-color-active)"}),K("disabled",{color:"var(--n-tab-text-color-disabled)"})])]),M("tabs-nav",[K("line-type",[F("prefix, suffix",` - transition: border-color .3s var(--n-bezier); - border-bottom: 1px solid var(--n-tab-border-color); - `),M("tabs-nav-scroll-content",` - transition: border-color .3s var(--n-bezier); - border-bottom: 1px solid var(--n-tab-border-color); - `),M("tabs-bar",` - border-radius: 0; - bottom: -1px; - `)]),K("card-type",[F("prefix, suffix",` - transition: border-color .3s var(--n-bezier); - border-bottom: 1px solid var(--n-tab-border-color); - `),M("tabs-pad",` - flex-grow: 1; - transition: border-color .3s var(--n-bezier); - border-bottom: 1px solid var(--n-tab-border-color); - `),M("tabs-tab-pad",` - transition: border-color .3s var(--n-bezier); - border-bottom: 1px solid var(--n-tab-border-color); - `),M("tabs-tab",` - font-weight: var(--n-tab-font-weight); - border: 1px solid var(--n-tab-border-color); - border-top-left-radius: var(--n-tab-border-radius); - border-top-right-radius: var(--n-tab-border-radius); - background-color: var(--n-tab-color); - box-sizing: border-box; - position: relative; - vertical-align: bottom; - display: flex; - justify-content: space-between; - font-size: var(--n-tab-font-size); - color: var(--n-tab-text-color); - `,[K("addable",` - padding-left: 8px; - padding-right: 8px; - font-size: 16px; - `,[F("height-placeholder",` - width: 0; - font-size: var(--n-tab-font-size); - `),ut("disabled",[z("&:hover",` - color: var(--n-tab-text-color-hover); - `)])]),K("closable","padding-right: 6px;"),K("active",` - border-bottom: 1px solid #0000; - background-color: #0000; - font-weight: var(--n-tab-font-weight-active); - color: var(--n-tab-text-color-active); - `),K("disabled","color: var(--n-tab-text-color-disabled);")]),M("tabs-scroll-padding","border-bottom: 1px solid var(--n-tab-border-color);")])])]);const fR=Object.assign(Object.assign({},ze.props),{value:[String,Number],defaultValue:[String,Number],trigger:{type:String,default:"click"},type:{type:String,default:"bar"},closable:Boolean,justifyContent:String,size:{type:String,default:"medium"},tabStyle:[String,Object],barWidth:Number,paneClass:String,paneStyle:[String,Object],addable:[Boolean,Object],tabsPadding:{type:Number,default:0},animated:Boolean,onBeforeLeave:Function,onAdd:Function,"onUpdate:value":[Function,Array],onUpdateValue:[Function,Array],onClose:[Function,Array],labelSize:String,activeName:[String,Number],onActiveNameChange:[Function,Array]});var hR=oe({name:"Tabs",props:fR,setup(e,{slots:t}){var r,o,n,i;const{mergedClsPrefixRef:a,inlineThemeDisabled:l}=lt(e),s=ze("Tabs","-tabs",uR,nE,e,a),d=W(null),c=W(null),u=W(null),f=W(null),h=W(null),p=W(!0),b=W(!0),g=di(e,["labelSize","size"]),v=di(e,["activeName","value"]),w=W((o=(r=v.value)!==null&&r!==void 0?r:e.defaultValue)!==null&&o!==void 0?o:t.default?(i=(n=So(t.default())[0])===null||n===void 0?void 0:n.props)===null||i===void 0?void 0:i.name:null),$=hn(v,w),x={id:0},S=L(()=>{if(!(!e.justifyContent||e.type==="card"))return{display:"flex",justifyContent:e.justifyContent}});qe($,()=>{x.id=0,_()});function E(){var G;const{value:Z}=$;return Z===null?null:(G=d.value)===null||G===void 0?void 0:G.querySelector(`[data-name="${Z}"]`)}function y(G){if(e.type==="card")return;const{value:Z}=c;if(!!Z&&G){const C=`${a.value}-tabs-bar--disabled`,{barWidth:k}=e;if(G.dataset.disabled==="true"?Z.classList.add(C):Z.classList.remove(C),k&&G.offsetWidth>=k){const H=Math.floor((G.offsetWidth-k)/2)+G.offsetLeft;Z.style.left=`${H}px`,Z.style.maxWidth=`${k}px`}else Z.style.left=`${G.offsetLeft}px`,Z.style.maxWidth=`${G.offsetWidth}px`;Z.style.width="8192px"}}function _(){if(e.type==="card")return;const G=E();G&&y(G)}const R=W(null);let P=0;function j(){const G=R.value;if(G){P=G.getBoundingClientRect().height;const Z=`${P}px`;G.style.height=Z,G.style.maxHeight=Z}}function T(G){const Z=R.value;if(Z){const C=G.getBoundingClientRect().height;Z.style.maxHeight=`${C}px`,Z.style.height=`${Math.max(P,C)}px`}}function N(){const G=R.value;G&&(G.style.maxHeight="",G.style.height="")}const B={value:[]},q=W("next");function A(G){const Z=$.value;let C="next";for(const k of B.value){if(k===Z)break;if(k===G){C="prev";break}}q.value=C,te(G)}function te(G){const{onActiveNameChange:Z,onUpdateValue:C,"onUpdate:value":k}=e;Z&&Be(Z,G),C&&Be(C,G),k&&Be(k,G),w.value=G}function se(G){const{onClose:Z}=e;Z&&Be(Z,G)}let _e=!0,Ae=0;const Re=yl(function(Z){var C;if(Z.contentRect.width===0&&Z.contentRect.height===0||Ae===Z.contentRect.width)return;Ae=Z.contentRect.width;const{type:k}=e;if((k==="line"||k==="bar")&&_e){const{value:H}=c;if(!H)return;const U=`${a.value}-tabs-bar--transition-disabled`;H.classList.add(U),_(),H.classList.remove(U)}k!=="segment"&&V((C=h.value)===null||C===void 0?void 0:C.$el)},64),Ee=W(!1);function $e(G){var Z;const{target:C,contentRect:{width:k}}=G,H=C.parentElement.offsetWidth;if(!Ee.value)HU.$el.offsetWidth&&(Ee.value=!1)}V((Z=h.value)===null||Z===void 0?void 0:Z.$el)}const it=yl($e,64);function O(){const{onAdd:G}=e;G&&G(),br(()=>{const Z=E(),{value:C}=h;!Z||!C||C.scrollTo({left:Z.offsetLeft,top:0,behavior:"smooth"})})}function V(G){if(!G)return;const{scrollLeft:Z,scrollWidth:C,offsetWidth:k}=G;p.value=Z<=0,b.value=Z+k>=C}const D=yl(G=>{V(G.target)},64);je(qc,{triggerRef:Oe(e,"trigger"),tabStyleRef:Oe(e,"tabStyle"),paneClassRef:Oe(e,"paneClass"),paneStyleRef:Oe(e,"paneStyle"),mergedClsPrefixRef:a,typeRef:Oe(e,"type"),closableRef:Oe(e,"closable"),valueRef:$,tabChangeIdRef:x,onBeforeLeaveRef:Oe(e,"onBeforeLeave"),activateTab:A,handleClose:se,handleAdd:O}),vp(()=>{_()}),xr(()=>{const{value:G}=u;if(!G)return;const{value:Z}=a,C=`${Z}-tabs-nav-scroll-wrapper--shadow-before`,k=`${Z}-tabs-nav-scroll-wrapper--shadow-after`;p.value?G.classList.remove(C):G.classList.add(C),b.value?G.classList.remove(k):G.classList.add(k)});const ce={syncBarPosition:()=>{_()}},ue=L(()=>{const{value:G}=g,{type:Z}=e,C={card:"Card",bar:"Bar",line:"Line",segment:"Segment"}[Z],k=`${G}${C}`,{self:{barColor:H,closeColor:U,closeColorHover:X,closeColorPressed:ne,tabColor:le,tabBorderColor:Y,paneTextColor:J,tabFontWeight:Q,tabBorderRadius:ve,tabFontWeightActive:pe,colorSegment:me,fontWeightStrong:we,tabColorSegment:De,[ae("panePadding",G)]:Ye,[ae("tabPadding",k)]:Fe,[ae("tabGap",k)]:Je,[ae("tabTextColor",Z)]:re,[ae("tabTextColorActive",Z)]:he,[ae("tabTextColorHover",Z)]:Se,[ae("tabTextColorDisabled",Z)]:Ne,[ae("tabFontSize",G)]:rt},common:{cubicBezierEaseInOut:Ue}}=s.value;return{"--n-bezier":Ue,"--n-color-segment":me,"--n-bar-color":H,"--n-tab-font-size":rt,"--n-tab-text-color":re,"--n-tab-text-color-active":he,"--n-tab-text-color-disabled":Ne,"--n-tab-text-color-hover":Se,"--n-pane-text-color":J,"--n-tab-border-color":Y,"--n-tab-border-radius":ve,"--n-close-color":U,"--n-close-color-hover":X,"--n-close-color-pressed":ne,"--n-tab-color":le,"--n-tab-font-weight":Q,"--n-tab-font-weight-active":pe,"--n-tab-padding":Fe,"--n-tab-gap":Je,"--n-pane-padding":Ye,"--n-font-weight-strong":we,"--n-tab-color-segment":De}}),xe=l?_t("tabs",L(()=>`${g.value[0]}${e.type[0]}`),ue,e):void 0;return Object.assign({mergedClsPrefix:a,mergedValue:$,renderedNames:new Set,tabsPaneWrapperRef:R,tabsElRef:d,barElRef:c,addTabInstRef:f,xScrollInstRef:h,scrollWrapperElRef:u,addTabFixed:Ee,tabWrapperStyle:S,handleNavResize:Re,mergedSize:g,handleScroll:D,handleTabsResize:it,cssVars:l?void 0:ue,themeClass:xe==null?void 0:xe.themeClass,animationDirection:q,renderNameListRef:B,onAnimationBeforeLeave:j,onAnimationEnter:T,onAnimationAfterEnter:N,onRender:xe==null?void 0:xe.onRender},ce)},render(){const{mergedClsPrefix:e,type:t,addTabFixed:r,addable:o,mergedSize:n,renderNameListRef:i,onRender:a,$slots:{default:l,prefix:s,suffix:d}}=this;a==null||a();const c=l?So(l()).filter(g=>g.type.__TAB_PANE__===!0):[],u=l?So(l()).filter(g=>g.type.__TAB__===!0):[],f=!u.length,h=t==="card",p=t==="segment",b=!h&&!p&&this.justifyContent;return i.value=[],m("div",{class:[`${e}-tabs`,this.themeClass,`${e}-tabs--${t}-type`,`${e}-tabs--${n}-size`,b&&`${e}-tabs--flex`],style:this.cssVars},m("div",{class:[`${e}-tabs-nav--${t}-type`,`${e}-tabs-nav`]},bt(s,g=>g&&m("div",{class:`${e}-tabs-nav__prefix`},g)),p?m("div",{class:`${e}-tabs-rail`},f?c.map((g,v)=>(i.value.push(g.props.name),m(Es,Object.assign({},g.props,{internalCreatedByPane:!0,internalLeftPadded:v!==0}),g.children?{default:g.children.tab}:void 0))):u.map((g,v)=>(i.value.push(g.props.name),v===0?g:hf(g)))):m(vn,{onResize:this.handleNavResize},{default:()=>m("div",{class:`${e}-tabs-nav-scroll-wrapper`,ref:"scrollWrapperElRef"},m(FP,{ref:"xScrollInstRef",onScroll:this.handleScroll},{default:()=>{const g=m("div",{style:this.tabWrapperStyle,class:`${e}-tabs-wrapper`},b?null:m("div",{class:`${e}-tabs-scroll-padding`,style:{width:`${this.tabsPadding}px`}}),f?c.map((w,$)=>(i.value.push(w.props.name),Al(m(Es,Object.assign({},w.props,{internalCreatedByPane:!0,internalLeftPadded:$!==0&&!b}),w.children?{default:w.children.tab}:void 0)))):u.map((w,$)=>(i.value.push(w.props.name),Al($!==0&&!b?hf(w):w))),!r&&o&&h?ff(o,(f?c.length:u.length)!==0):null,b?null:m("div",{class:`${e}-tabs-scroll-padding`,style:{width:`${this.tabsPadding}px`}}));let v=g;return h&&o&&(v=m(vn,{onResize:this.handleTabsResize},{default:()=>g})),m("div",{ref:"tabsElRef",class:`${e}-tabs-nav-scroll-content`},v,h?m("div",{class:`${e}-tabs-pad`}):null,h?null:m("div",{ref:"barElRef",class:`${e}-tabs-bar`}))}}))}),r&&o&&h?ff(o,!0):null,bt(d,g=>g&&m("div",{class:`${e}-tabs-nav__suffix`},g))),f&&(this.animated?m("div",{ref:"tabsPaneWrapperRef",class:`${e}-tabs-pane-wrapper`},uf(c,this.mergedValue,this.renderedNames,this.onAnimationBeforeLeave,this.onAnimationEnter,this.onAnimationAfterEnter,this.animationDirection)):uf(c,this.mergedValue,this.renderedNames)))}});function uf(e,t,r,o,n,i,a){const l=[];return e.forEach(s=>{const{name:d,displayDirective:c,"display-directive":u}=s.props,f=p=>c===p||u===p,h=t===d;if(s.key!==void 0&&(s.key=d),h||f("show")||f("show:lazy")&&r.has(d)){r.has(d)||r.add(d);const p=!f("if");l.push(p?Cr(s,[[li,h]]):s)}}),a?m(rc,{name:`${a}-transition`,onBeforeLeave:o,onEnter:n,onAfterEnter:i},{default:()=>l}):l}function ff(e,t){return m(Es,{ref:"addTabInstRef",key:"__addable",name:"__addable",internalCreatedByPane:!0,internalAddable:!0,internalLeftPadded:t,disabled:typeof e=="object"&&e.disabled})}function hf(e){const t=lr(e);return t.props?t.props.internalLeftPadded=!0:t.props={internalLeftPadded:!0},t}function Al(e){return Array.isArray(e.dynamicProps)?e.dynamicProps.includes("internalLeftPadded")||e.dynamicProps.push("internalLeftPadded"):e.dynamicProps=["internalLeftPadded"],e}const pR={name:"dark",common:de,Alert:M3,Anchor:j3,AutoComplete:X3,Avatar:qm,AvatarGroup:i6,BackTop:s6,Badge:d6,Breadcrumb:C6,Button:qt,Calendar:z6,Card:ev,Carousel:W6,Cascader:Y6,Checkbox:$i,Code:tv,Collapse:Q6,CollapseTransition:r4,ColorPicker:I6,DataTable:C4,DatePicker:U4,Descriptions:X4,Dialog:yv,Divider:gk,Drawer:Ck,Dropdown:fv,DynamicInput:Sk,DynamicTags:zk,Element:Ok,Empty:wi,Ellipsis:lv,Form:Lk,GradientText:F8,Icon:T4,IconWrapper:N8,Image:EE,Input:ur,InputNumber:U8,Layout:G8,List:Z8,LoadingBar:Q8,Log:tT,Menu:sT,Mention:oT,Message:hT,Modal:ak,Notification:gT,PageHeader:CT,Pagination:iv,Popconfirm:ST,Popover:zo,Popselect:$T,Progress:Hv,Radio:sv,Rate:RT,Result:IT,Scrollbar:Ut,Select:ov,Skeleton:nR,Slider:LT,Space:Ev,Spin:jT,Statistic:VT,Steps:GT,Switch:ZT,Table:tE,Tabs:aE,Tag:Lm,Thing:cE,TimePicker:bv,Timeline:fE,Tooltip:Za,Transfer:mE,Tree:Uv,TreeSelect:xE,Typography:SE,Upload:PE,Watermark:TE};var Gc={exports:{}},ng=function(t,r){return function(){for(var n=new Array(arguments.length),i=0;i=0)return;o==="set-cookie"?r[o]=(r[o]?r[o]:[]).concat([n]):r[o]=r[o]?r[o]+", "+n:n}}),r},mf=Ht,KR=mf.isStandardBrowserEnv()?function(){var t=/(msie|trident)/i.test(navigator.userAgent),r=document.createElement("a"),o;function n(i){var a=i;return t&&(r.setAttribute("href",a),a=r.href),r.setAttribute("href",a),{href:r.href,protocol:r.protocol?r.protocol.replace(/:$/,""):"",host:r.host,search:r.search?r.search.replace(/^\?/,""):"",hash:r.hash?r.hash.replace(/^#/,""):"",hostname:r.hostname,port:r.port,pathname:r.pathname.charAt(0)==="/"?r.pathname:"/"+r.pathname}}return o=n(window.location.href),function(a){var l=mf.isString(a)?n(a):a;return l.protocol===o.protocol&&l.host===o.host}}():function(){return function(){return!0}}();function Zc(e){this.message=e}Zc.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")};Zc.prototype.__CANCEL__=!0;var tl=Zc,Gi=Ht,UR=BR,qR=LR,GR=sg,YR=NR,XR=VR,ZR=KR,Il=ug,JR=dg,QR=tl,vf=function(t){return new Promise(function(o,n){var i=t.data,a=t.headers,l=t.responseType,s;function d(){t.cancelToken&&t.cancelToken.unsubscribe(s),t.signal&&t.signal.removeEventListener("abort",s)}Gi.isFormData(i)&&delete a["Content-Type"];var c=new XMLHttpRequest;if(t.auth){var u=t.auth.username||"",f=t.auth.password?unescape(encodeURIComponent(t.auth.password)):"";a.Authorization="Basic "+btoa(u+":"+f)}var h=YR(t.baseURL,t.url);c.open(t.method.toUpperCase(),GR(h,t.params,t.paramsSerializer),!0),c.timeout=t.timeout;function p(){if(!!c){var g="getAllResponseHeaders"in c?XR(c.getAllResponseHeaders()):null,v=!l||l==="text"||l==="json"?c.responseText:c.response,w={data:v,status:c.status,statusText:c.statusText,headers:g,config:t,request:c};UR(function(x){o(x),d()},function(x){n(x),d()},w),c=null}}if("onloadend"in c?c.onloadend=p:c.onreadystatechange=function(){!c||c.readyState!==4||c.status===0&&!(c.responseURL&&c.responseURL.indexOf("file:")===0)||setTimeout(p)},c.onabort=function(){!c||(n(Il("Request aborted",t,"ECONNABORTED",c)),c=null)},c.onerror=function(){n(Il("Network Error",t,null,c)),c=null},c.ontimeout=function(){var v=t.timeout?"timeout of "+t.timeout+"ms exceeded":"timeout exceeded",w=t.transitional||JR;t.timeoutErrorMessage&&(v=t.timeoutErrorMessage),n(Il(v,t,w.clarifyTimeoutError?"ETIMEDOUT":"ECONNABORTED",c)),c=null},Gi.isStandardBrowserEnv()){var b=(t.withCredentials||ZR(h))&&t.xsrfCookieName?qR.read(t.xsrfCookieName):void 0;b&&(a[t.xsrfHeaderName]=b)}"setRequestHeader"in c&&Gi.forEach(a,function(v,w){typeof i=="undefined"&&w.toLowerCase()==="content-type"?delete a[w]:c.setRequestHeader(w,v)}),Gi.isUndefined(t.withCredentials)||(c.withCredentials=!!t.withCredentials),l&&l!=="json"&&(c.responseType=t.responseType),typeof t.onDownloadProgress=="function"&&c.addEventListener("progress",t.onDownloadProgress),typeof t.onUploadProgress=="function"&&c.upload&&c.upload.addEventListener("progress",t.onUploadProgress),(t.cancelToken||t.signal)&&(s=function(g){!c||(n(!g||g&&g.type?new QR("canceled"):g),c.abort(),c=null)},t.cancelToken&&t.cancelToken.subscribe(s),t.signal&&(t.signal.aborted?s():t.signal.addEventListener("abort",s))),i||(i=null),c.send(i)})},Tt=Ht,gf=OR,ez=cg,tz=dg,rz={"Content-Type":"application/x-www-form-urlencoded"};function bf(e,t){!Tt.isUndefined(e)&&Tt.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}function oz(){var e;return(typeof XMLHttpRequest!="undefined"||typeof process!="undefined"&&Object.prototype.toString.call(process)==="[object process]")&&(e=vf),e}function nz(e,t,r){if(Tt.isString(e))try{return(t||JSON.parse)(e),Tt.trim(e)}catch(o){if(o.name!=="SyntaxError")throw o}return(r||JSON.stringify)(e)}var rl={transitional:tz,adapter:oz(),transformRequest:[function(t,r){return gf(r,"Accept"),gf(r,"Content-Type"),Tt.isFormData(t)||Tt.isArrayBuffer(t)||Tt.isBuffer(t)||Tt.isStream(t)||Tt.isFile(t)||Tt.isBlob(t)?t:Tt.isArrayBufferView(t)?t.buffer:Tt.isURLSearchParams(t)?(bf(r,"application/x-www-form-urlencoded;charset=utf-8"),t.toString()):Tt.isObject(t)||r&&r["Content-Type"]==="application/json"?(bf(r,"application/json"),nz(t)):t}],transformResponse:[function(t){var r=this.transitional||rl.transitional,o=r&&r.silentJSONParsing,n=r&&r.forcedJSONParsing,i=!o&&this.responseType==="json";if(i||n&&Tt.isString(t)&&t.length)try{return JSON.parse(t)}catch(a){if(i)throw a.name==="SyntaxError"?ez(a,this,"E_JSON_PARSE"):a}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(t){return t>=200&&t<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};Tt.forEach(["delete","get","head"],function(t){rl.headers[t]={}});Tt.forEach(["post","put","patch"],function(t){rl.headers[t]=Tt.merge(rz)});var Jc=rl,iz=Ht,az=Jc,lz=function(t,r,o){var n=this||az;return iz.forEach(o,function(a){t=a.call(n,t,r)}),t},fg=function(t){return!!(t&&t.__CANCEL__)},xf=Ht,Ml=lz,sz=fg,cz=Jc,dz=tl;function Bl(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new dz("canceled")}var uz=function(t){Bl(t),t.headers=t.headers||{},t.data=Ml.call(t,t.data,t.headers,t.transformRequest),t.headers=xf.merge(t.headers.common||{},t.headers[t.method]||{},t.headers),xf.forEach(["delete","get","head","post","put","patch","common"],function(n){delete t.headers[n]});var r=t.adapter||cz.adapter;return r(t).then(function(n){return Bl(t),n.data=Ml.call(t,n.data,n.headers,t.transformResponse),n},function(n){return sz(n)||(Bl(t),n&&n.response&&(n.response.data=Ml.call(t,n.response.data,n.response.headers,t.transformResponse))),Promise.reject(n)})},jt=Ht,hg=function(t,r){r=r||{};var o={};function n(c,u){return jt.isPlainObject(c)&&jt.isPlainObject(u)?jt.merge(c,u):jt.isPlainObject(u)?jt.merge({},u):jt.isArray(u)?u.slice():u}function i(c){if(jt.isUndefined(r[c])){if(!jt.isUndefined(t[c]))return n(void 0,t[c])}else return n(t[c],r[c])}function a(c){if(!jt.isUndefined(r[c]))return n(void 0,r[c])}function l(c){if(jt.isUndefined(r[c])){if(!jt.isUndefined(t[c]))return n(void 0,t[c])}else return n(void 0,r[c])}function s(c){if(c in r)return n(t[c],r[c]);if(c in t)return n(void 0,t[c])}var d={url:a,method:a,data:a,baseURL:l,transformRequest:l,transformResponse:l,paramsSerializer:l,timeout:l,timeoutMessage:l,withCredentials:l,adapter:l,responseType:l,xsrfCookieName:l,xsrfHeaderName:l,onUploadProgress:l,onDownloadProgress:l,decompress:l,maxContentLength:l,maxBodyLength:l,transport:l,httpAgent:l,httpsAgent:l,cancelToken:l,socketPath:l,responseEncoding:l,validateStatus:s};return jt.forEach(Object.keys(t).concat(Object.keys(r)),function(u){var f=d[u]||i,h=f(u);jt.isUndefined(h)&&f!==s||(o[u]=h)}),o},pg={version:"0.26.1"},fz=pg.version,Qc={};["object","boolean","number","function","string","symbol"].forEach(function(e,t){Qc[e]=function(o){return typeof o===e||"a"+(t<1?"n ":" ")+e}});var Cf={};Qc.transitional=function(t,r,o){function n(i,a){return"[Axios v"+fz+"] Transitional option '"+i+"'"+a+(o?". "+o:"")}return function(i,a,l){if(t===!1)throw new Error(n(a," has been removed"+(r?" in "+r:"")));return r&&!Cf[a]&&(Cf[a]=!0,console.warn(n(a," has been deprecated since v"+r+" and will be removed in the near future"))),t?t(i,a,l):!0}};function hz(e,t,r){if(typeof e!="object")throw new TypeError("options must be an object");for(var o=Object.keys(e),n=o.length;n-- >0;){var i=o[n],a=t[i];if(a){var l=e[i],s=l===void 0||a(l,i,e);if(s!==!0)throw new TypeError("option "+i+" must be "+s);continue}if(r!==!0)throw Error("Unknown option "+i)}}var pz={assertOptions:hz,validators:Qc},mg=Ht,mz=sg,yf=zR,wf=uz,ol=hg,vg=pz,Vo=vg.validators;function Ei(e){this.defaults=e,this.interceptors={request:new yf,response:new yf}}Ei.prototype.request=function(t,r){typeof t=="string"?(r=r||{},r.url=t):r=t||{},r=ol(this.defaults,r),r.method?r.method=r.method.toLowerCase():this.defaults.method?r.method=this.defaults.method.toLowerCase():r.method="get";var o=r.transitional;o!==void 0&&vg.assertOptions(o,{silentJSONParsing:Vo.transitional(Vo.boolean),forcedJSONParsing:Vo.transitional(Vo.boolean),clarifyTimeoutError:Vo.transitional(Vo.boolean)},!1);var n=[],i=!0;this.interceptors.request.forEach(function(h){typeof h.runWhen=="function"&&h.runWhen(r)===!1||(i=i&&h.synchronous,n.unshift(h.fulfilled,h.rejected))});var a=[];this.interceptors.response.forEach(function(h){a.push(h.fulfilled,h.rejected)});var l;if(!i){var s=[wf,void 0];for(Array.prototype.unshift.apply(s,n),s=s.concat(a),l=Promise.resolve(r);s.length;)l=l.then(s.shift(),s.shift());return l}for(var d=r;n.length;){var c=n.shift(),u=n.shift();try{d=c(d)}catch(f){u(f);break}}try{l=wf(d)}catch(f){return Promise.reject(f)}for(;a.length;)l=l.then(a.shift(),a.shift());return l};Ei.prototype.getUri=function(t){return t=ol(this.defaults,t),mz(t.url,t.params,t.paramsSerializer).replace(/^\?/,"")};mg.forEach(["delete","get","head","options"],function(t){Ei.prototype[t]=function(r,o){return this.request(ol(o||{},{method:t,url:r,data:(o||{}).data}))}});mg.forEach(["post","put","patch"],function(t){Ei.prototype[t]=function(r,o,n){return this.request(ol(n||{},{method:t,url:r,data:o}))}});var vz=Ei,gz=tl;function gn(e){if(typeof e!="function")throw new TypeError("executor must be a function.");var t;this.promise=new Promise(function(n){t=n});var r=this;this.promise.then(function(o){if(!!r._listeners){var n,i=r._listeners.length;for(n=0;n(localStorage.getItem("PAOPAO_TOKEN")&&(e.headers.Authorization="Bearer "+localStorage.getItem("PAOPAO_TOKEN")),e),e=>Promise.reject(e));ed.interceptors.response.use(e=>{const{data:t={},code:r=0}=(e==null?void 0:e.data)||{};if(+r==0)return t||{};Promise.reject((e==null?void 0:e.data)||{})},(e={})=>{var r;const{response:t={}}=e||{};return+(t==null?void 0:t.status)==401?(localStorage.removeItem("PAOPAO_TOKEN"),(t==null?void 0:t.data.code)!==10005?window.$message.warning((t==null?void 0:t.data.msg)||"\u9274\u6743\u5931\u8D25"):window.$store.commit("triggerAuth",!0)):window.$message.error(((r=t==null?void 0:t.data)==null?void 0:r.msg)||"\u8BF7\u6C42\u5931\u8D25"),Promise.reject((t==null?void 0:t.data)||{})});function ke(e){return ed(e)}const _f=e=>ke({method:"post",url:"/v1/auth/login",data:e}),Pz=e=>ke({method:"post",url:"/v1/auth/register",data:e}),Ll=(e="")=>ke({method:"get",url:"/v1/user/info",headers:{Authorization:`Bearer ${e}`}});var bg=(e,t)=>{const r=e.__vccOpts||e;for(const[o,n]of t)r[o]=n;return r};const kz={class:"auth-wrap"},Tz=sr(" \u767B\u5F55 "),Ez=sr(" \u6CE8\u518C "),Rz=oe({setup(e){const t=Ba(),r=W(!1),o=W(),n=ar({username:"",password:""}),i=W(),a=ar({username:"",password:"",repassword:""}),l={username:{required:!0,message:"\u8BF7\u8F93\u5165\u8D26\u6237\u540D"},password:{required:!0,message:"\u8BF7\u8F93\u5165\u5BC6\u7801"},repassword:[{required:!0,message:"\u8BF7\u8F93\u5165\u5BC6\u7801"},{validator:(c,u)=>!!a.password&&a.password.startsWith(u)&&a.password.length>=u.length,message:"\u4E24\u6B21\u5BC6\u7801\u8F93\u5165\u4E0D\u4E00\u81F4",trigger:"input"}]},s=c=>{var u;c.preventDefault(),c.stopPropagation(),(u=o.value)==null||u.validate(f=>{f||(r.value=!0,_f({username:n.username,password:n.password}).then(h=>{const p=(h==null?void 0:h.token)||"";return localStorage.setItem("PAOPAO_TOKEN",p),Ll(p)}).then(h=>{window.$message.success("\u767B\u5F55\u6210\u529F"),r.value=!1,t.commit("updateUserinfo",h),t.commit("triggerAuth",!1),n.username="",n.password=""}).catch(h=>{r.value=!1}))})},d=c=>{var u;c.preventDefault(),c.stopPropagation(),(u=i.value)==null||u.validate(f=>{f||(r.value=!0,Pz({username:a.username,password:a.password}).then(h=>_f({username:a.username,password:a.password})).then(h=>{const p=(h==null?void 0:h.token)||"";return localStorage.setItem("PAOPAO_TOKEN",p),Ll(p)}).then(h=>{window.$message.success("\u6CE8\u518C\u6210\u529F"),r.value=!1,t.commit("updateUserinfo",h),t.commit("triggerAuth",!1),a.username="",a.password="",a.repassword=""}).catch(h=>{r.value=!1}))})};return Ot(()=>{const c=localStorage.getItem("PAOPAO_TOKEN")||"";c?Ll(c).then(u=>{t.commit("updateUserinfo",u),t.commit("triggerAuth",!1)}).catch(u=>{t.commit("userLogout")}):t.commit("userLogout")}),(c,u)=>{const f=Km,h=B8,p=jk,b=Ca,g=cR,v=hR,w=Oc,$=Pv;return st(),mo($,{show:Me(t).state.authModalShow,"onUpdate:show":u[5]||(u[5]=x=>Me(t).state.authModalShow=x),class:"auth-card",preset:"card",size:"small","mask-closable":!1,bordered:!1,style:{width:"360px"}},{default:Xe(()=>[Le("div",kz,[ge(w,{bordered:!1},{default:Xe(()=>[ge(v,{"default-value":Me(t).state.authModelTab,size:"large","justify-content":"space-evenly"},{default:Xe(()=>[ge(g,{name:"signin",tab:"\u767B\u5F55"},{default:Xe(()=>[ge(p,{ref_key:"loginRef",ref:o,model:Me(n),rules:{username:{required:!0,message:"\u8BF7\u8F93\u5165\u8D26\u6237\u540D"},password:{required:!0,message:"\u8BF7\u8F93\u5165\u5BC6\u7801"}}},{default:Xe(()=>[ge(h,{label:"\u8D26\u6237",path:"username"},{default:Xe(()=>[ge(f,{value:Me(n).username,"onUpdate:value":u[0]||(u[0]=x=>Me(n).username=x),placeholder:"\u8BF7\u8F93\u5165\u7528\u6237\u540D",onKeyup:jn(Hn(s,["prevent"]),["enter"])},null,8,["value","onKeyup"])]),_:1}),ge(h,{label:"\u5BC6\u7801",path:"password"},{default:Xe(()=>[ge(f,{type:"password","show-password-on":"mousedown",value:Me(n).password,"onUpdate:value":u[1]||(u[1]=x=>Me(n).password=x),placeholder:"\u8BF7\u8F93\u5165\u8D26\u6237\u5BC6\u7801",onKeyup:jn(Hn(s,["prevent"]),["enter"])},null,8,["value","onKeyup"])]),_:1})]),_:1},8,["model"]),ge(b,{type:"primary",block:"",secondary:"",strong:"",loading:r.value,onClick:s},{default:Xe(()=>[Tz]),_:1},8,["loading"])]),_:1}),ge(g,{name:"signup",tab:"\u6CE8\u518C"},{default:Xe(()=>[ge(p,{ref_key:"registerRef",ref:i,model:Me(a),rules:l},{default:Xe(()=>[ge(h,{label:"\u7528\u6237\u540D",path:"username"},{default:Xe(()=>[ge(f,{value:Me(a).username,"onUpdate:value":u[2]||(u[2]=x=>Me(a).username=x),placeholder:"\u7528\u6237\u540D\u6CE8\u518C\u540E\u65E0\u6CD5\u4FEE\u6539"},null,8,["value"])]),_:1}),ge(h,{label:"\u5BC6\u7801",path:"password"},{default:Xe(()=>[ge(f,{type:"password","show-password-on":"mousedown",placeholder:"\u5BC6\u7801\u4E0D\u5C11\u4E8E6\u4F4D",value:Me(a).password,"onUpdate:value":u[3]||(u[3]=x=>Me(a).password=x),onKeyup:jn(Hn(d,["prevent"]),["enter"])},null,8,["value","onKeyup"])]),_:1}),ge(h,{label:"\u91CD\u590D\u5BC6\u7801",path:"repassword"},{default:Xe(()=>[ge(f,{type:"password","show-password-on":"mousedown",placeholder:"\u8BF7\u518D\u6B21\u8F93\u5165\u5BC6\u7801",value:Me(a).repassword,"onUpdate:value":u[4]||(u[4]=x=>Me(a).repassword=x),onKeyup:jn(Hn(d,["prevent"]),["enter"])},null,8,["value","onKeyup"])]),_:1})]),_:1},8,["model"]),ge(b,{type:"primary",block:"",secondary:"",strong:"",loading:r.value,onClick:d},{default:Xe(()=>[Ez]),_:1},8,["loading"])]),_:1})]),_:1},8,["default-value"])]),_:1})])]),_:1},8,["show"])}}});var zz=bg(Rz,[["__scopeId","data-v-66895776"]]);const _O=e=>ke({method:"get",url:"/v1/posts",params:e}),Az=e=>ke({method:"get",url:"/v1/tags",params:e}),$O=e=>ke({method:"get",url:"/v1/post",params:e}),PO=e=>ke({method:"get",url:"/v1/post/star",params:e}),kO=e=>ke({method:"post",url:"/v1/post/star",data:e}),TO=e=>ke({method:"get",url:"/v1/post/collection",params:e}),EO=e=>ke({method:"post",url:"/v1/post/collection",data:e}),RO=e=>ke({method:"get",url:"/v1/post/comments",params:e}),zO=e=>ke({method:"get",url:"/v1/user/contacts",params:e}),AO=e=>ke({method:"post",url:"/v1/post",data:e}),OO=e=>ke({method:"delete",url:"/v1/post",data:e}),IO=e=>ke({method:"post",url:"/v1/post/lock",data:e}),MO=e=>ke({method:"post",url:"/v1/post/stick",data:e}),BO=e=>ke({method:"post",url:"/v1/post/visibility",data:e}),LO=e=>ke({method:"post",url:"/v1/post/comment",data:e}),DO=e=>ke({method:"delete",url:"/v1/post/comment",data:e}),FO=e=>ke({method:"post",url:"/v1/post/comment/reply",data:e}),HO=e=>ke({method:"delete",url:"/v1/post/comment/reply",data:e}),Oz={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Iz=Le("path",{d:"M128 80V64a48.14 48.14 0 0 1 48-48h224a48.14 48.14 0 0 1 48 48v368l-80-64",fill:"none",stroke:"currentColor","stroke-linejoin":"round","stroke-width":"32"},null,-1),Mz=Le("path",{d:"M320 96H112a48.14 48.14 0 0 0-48 48v352l152-128l152 128V144a48.14 48.14 0 0 0-48-48z",fill:"none",stroke:"currentColor","stroke-linejoin":"round","stroke-width":"32"},null,-1),Bz=[Iz,Mz];var Lz=oe({name:"BookmarksOutline",render:function(t,r){return st(),Et("svg",Oz,Bz)}});const Dz={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Fz=Le("path",{d:"M431 320.6c-1-3.6 1.2-8.6 3.3-12.2a33.68 33.68 0 0 1 2.1-3.1A162 162 0 0 0 464 215c.3-92.2-77.5-167-173.7-167c-83.9 0-153.9 57.1-170.3 132.9a160.7 160.7 0 0 0-3.7 34.2c0 92.3 74.8 169.1 171 169.1c15.3 0 35.9-4.6 47.2-7.7s22.5-7.2 25.4-8.3a26.44 26.44 0 0 1 9.3-1.7a26 26 0 0 1 10.1 2l56.7 20.1a13.52 13.52 0 0 0 3.9 1a8 8 0 0 0 8-8a12.85 12.85 0 0 0-.5-2.7z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-miterlimit":"10","stroke-width":"32"},null,-1),Hz=Le("path",{d:"M66.46 232a146.23 146.23 0 0 0 6.39 152.67c2.31 3.49 3.61 6.19 3.21 8s-11.93 61.87-11.93 61.87a8 8 0 0 0 2.71 7.68A8.17 8.17 0 0 0 72 464a7.26 7.26 0 0 0 2.91-.6l56.21-22a15.7 15.7 0 0 1 12 .2c18.94 7.38 39.88 12 60.83 12A159.21 159.21 0 0 0 284 432.11",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-miterlimit":"10","stroke-width":"32"},null,-1),jz=[Fz,Hz];var Nz=oe({name:"ChatbubblesOutline",render:function(t,r){return st(),Et("svg",Dz,jz)}});const Wz={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Vz=Le("path",{d:"M80 212v236a16 16 0 0 0 16 16h96V328a24 24 0 0 1 24-24h80a24 24 0 0 1 24 24v136h96a16 16 0 0 0 16-16V212",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),Kz=Le("path",{d:"M480 256L266.89 52c-5-5.28-16.69-5.34-21.78 0L32 256",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),Uz=Le("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M400 179V64h-48v69"},null,-1),qz=[Vz,Kz,Uz];var $f=oe({name:"HomeOutline",render:function(t,r){return st(),Et("svg",Wz,qz)}});const Gz={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},Yz=Le("path",{d:"M321.89 171.42C233 114 141 155.22 56 65.22c-19.8-21-8.3 235.5 98.1 332.7c77.79 71 197.9 63.08 238.4-5.92s18.28-163.17-70.61-220.58z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),Xz=Le("path",{d:"M173 253c86 81 175 129 292 147",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),Zz=[Yz,Xz];var Jz=oe({name:"LeafOutline",render:function(t,r){return st(),Et("svg",Gz,Zz)}});const Qz={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},eA=Le("path",{d:"M304 336v40a40 40 0 0 1-40 40H104a40 40 0 0 1-40-40V136a40 40 0 0 1 40-40h152c22.09 0 48 17.91 48 40v40",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),tA=Le("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M368 336l80-80l-80-80"},null,-1),rA=Le("path",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32",d:"M176 256h256"},null,-1),oA=[eA,tA,rA];var Pf=oe({name:"LogOutOutline",render:function(t,r){return st(),Et("svg",Qz,oA)}});const nA={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},iA=Sh('',6),aA=[iA];var lA=oe({name:"MegaphoneOutline",render:function(t,r){return st(),Et("svg",nA,aA)}});const sA={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},cA=Le("path",{d:"M402 168c-2.93 40.67-33.1 72-66 72s-63.12-31.32-66-72c-3-42.31 26.37-72 66-72s69 30.46 66 72z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),dA=Le("path",{d:"M336 304c-65.17 0-127.84 32.37-143.54 95.41c-2.08 8.34 3.15 16.59 11.72 16.59h263.65c8.57 0 13.77-8.25 11.72-16.59C463.85 335.36 401.18 304 336 304z",fill:"none",stroke:"currentColor","stroke-miterlimit":"10","stroke-width":"32"},null,-1),uA=Le("path",{d:"M200 185.94c-2.34 32.48-26.72 58.06-53 58.06s-50.7-25.57-53-58.06C91.61 152.15 115.34 128 147 128s55.39 24.77 53 57.94z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),fA=Le("path",{d:"M206 306c-18.05-8.27-37.93-11.45-59-11.45c-52 0-102.1 25.85-114.65 76.2c-1.65 6.66 2.53 13.25 9.37 13.25H154",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-miterlimit":"10","stroke-width":"32"},null,-1),hA=[cA,dA,uA,fA];var pA=oe({name:"PeopleOutline",render:function(t,r){return st(),Et("svg",sA,hA)}});const mA={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},vA=Le("path",{d:"M456.69 421.39L362.6 327.3a173.81 173.81 0 0 0 34.84-104.58C397.44 126.38 319.06 48 222.72 48S48 126.38 48 222.72s78.38 174.72 174.72 174.72A173.81 173.81 0 0 0 327.3 362.6l94.09 94.09a25 25 0 0 0 35.3-35.3zM97.92 222.72a124.8 124.8 0 1 1 124.8 124.8a124.95 124.95 0 0 1-124.8-124.8z",fill:"currentColor"},null,-1),gA=[vA];var bA=oe({name:"Search",render:function(t,r){return st(),Et("svg",mA,gA)}});const xA={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},CA=Le("path",{d:"M262.29 192.31a64 64 0 1 0 57.4 57.4a64.13 64.13 0 0 0-57.4-57.4zM416.39 256a154.34 154.34 0 0 1-1.53 20.79l45.21 35.46a10.81 10.81 0 0 1 2.45 13.75l-42.77 74a10.81 10.81 0 0 1-13.14 4.59l-44.9-18.08a16.11 16.11 0 0 0-15.17 1.75A164.48 164.48 0 0 1 325 400.8a15.94 15.94 0 0 0-8.82 12.14l-6.73 47.89a11.08 11.08 0 0 1-10.68 9.17h-85.54a11.11 11.11 0 0 1-10.69-8.87l-6.72-47.82a16.07 16.07 0 0 0-9-12.22a155.3 155.3 0 0 1-21.46-12.57a16 16 0 0 0-15.11-1.71l-44.89 18.07a10.81 10.81 0 0 1-13.14-4.58l-42.77-74a10.8 10.8 0 0 1 2.45-13.75l38.21-30a16.05 16.05 0 0 0 6-14.08c-.36-4.17-.58-8.33-.58-12.5s.21-8.27.58-12.35a16 16 0 0 0-6.07-13.94l-38.19-30A10.81 10.81 0 0 1 49.48 186l42.77-74a10.81 10.81 0 0 1 13.14-4.59l44.9 18.08a16.11 16.11 0 0 0 15.17-1.75A164.48 164.48 0 0 1 187 111.2a15.94 15.94 0 0 0 8.82-12.14l6.73-47.89A11.08 11.08 0 0 1 213.23 42h85.54a11.11 11.11 0 0 1 10.69 8.87l6.72 47.82a16.07 16.07 0 0 0 9 12.22a155.3 155.3 0 0 1 21.46 12.57a16 16 0 0 0 15.11 1.71l44.89-18.07a10.81 10.81 0 0 1 13.14 4.58l42.77 74a10.8 10.8 0 0 1-2.45 13.75l-38.21 30a16.05 16.05 0 0 0-6.05 14.08c.33 4.14.55 8.3.55 12.47z",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"32"},null,-1),yA=[CA];var wA=oe({name:"SettingsOutline",render:function(t,r){return st(),Et("svg",xA,yA)}});const SA={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},_A=Le("rect",{x:"48",y:"144",width:"416",height:"288",rx:"48",ry:"48",fill:"none",stroke:"currentColor","stroke-linejoin":"round","stroke-width":"32"},null,-1),$A=Le("path",{d:"M411.36 144v-30A50 50 0 0 0 352 64.9L88.64 109.85A50 50 0 0 0 48 159v49",fill:"none",stroke:"currentColor","stroke-linejoin":"round","stroke-width":"32"},null,-1),PA=Le("path",{d:"M368 320a32 32 0 1 1 32-32a32 32 0 0 1-32 32z",fill:"currentColor"},null,-1),kA=[_A,$A,PA];var TA=oe({name:"WalletOutline",render:function(t,r){return st(),Et("svg",SA,kA)}});const EA={key:0,class:"rightbar-wrap"},RA={class:"search-wrap"},zA={class:"post-num"},AA={class:"copyright"},OA=["href"],IA=["href"],MA=oe({setup(e){const t=W([]),r=W(!1),o=W(""),n=Ba(),i=Uh(),a="2022 paopao.info",l="Roc's Me",s="",d="\u6CE1\u6CE1(PaoPao)\u5F00\u6E90\u793E\u533A",c="https://paopao.info",u=()=>{r.value=!0,Az({type:"hot",num:12}).then(p=>{t.value=p,r.value=!1}).catch(p=>{r.value=!1})},f=p=>p>=1e3?(p/1e3).toFixed(1)+"k":p,h=()=>{i.push({name:"home",query:{q:o.value}})};return Ot(()=>{u()}),(p,b)=>{const g=Jo,v=Km,w=bh("router-link"),$=sR,x=Oc,S=Ek;return Me(n).state.collapsedRight?Yl("",!0):(st(),Et("div",EA,[Le("div",RA,[ge(v,{round:"",clearable:"",placeholder:"\u641C\u4E00\u641C...",value:o.value,"onUpdate:value":b[0]||(b[0]=E=>o.value=E),onKeyup:jn(Hn(h,["prevent"]),["enter"])},{prefix:Xe(()=>[ge(g,{component:Me(bA)},null,8,["component"])]),_:1},8,["value","onKeyup"])]),ge(x,{title:"\u70ED\u95E8\u8BDD\u9898",embedded:"",bordered:!1,size:"small"},{default:Xe(()=>[ge($,{show:r.value},{default:Xe(()=>[(st(!0),Et(ot,null,W0(t.value,E=>(st(),Et("div",{class:"hot-tag-item",key:E.id},[ge(w,{class:"hash-link",to:{name:"home",query:{q:E.tag,t:"tag"}}},{default:Xe(()=>[sr(" #"+uo(E.tag),1)]),_:2},1032,["to"]),Le("div",zA,uo(f(E.quote_num)),1)]))),128))]),_:1},8,["show"])]),_:1}),ge(x,{class:"copyright-wrap",embedded:"",bordered:!1,size:"small"},{default:Xe(()=>[Le("div",AA,"\xA9 "+uo(Me(a)),1),Le("div",null,[ge(S,null,{default:Xe(()=>[Le("a",{href:Me(s),target:"_blank",class:"hash-link"},uo(Me(l)),9,OA),Le("a",{href:Me(c),target:"_blank",class:"hash-link"},uo(Me(d)),9,IA)]),_:1})])]),_:1})]))}}});var BA=bg(MA,[["__scopeId","data-v-0dc4cb5d"]]);const LA={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},DA=Sh('',1),FA=[DA];var kf=oe({name:"Hash",render:function(t,r){return st(),Et("svg",LA,FA)}});const jO=(e={})=>ke({method:"get",url:"/v1/captcha",params:e}),NO=e=>ke({method:"post",url:"/v1/captcha",data:e}),WO=e=>ke({method:"post",url:"/v1/user/whisper",data:e}),VO=e=>ke({method:"post",url:"/v1/friend/requesting",data:e}),KO=e=>ke({method:"post",url:"/v1/friend/add",data:e}),UO=e=>ke({method:"post",url:"/v1/friend/reject",data:e}),qO=e=>ke({method:"post",url:"/v1/friend/delete",data:e}),GO=e=>ke({method:"post",url:"/v1/user/phone",data:e}),YO=e=>ke({method:"post",url:"/v1/user/activate",data:e}),XO=e=>ke({method:"post",url:"/v1/user/password",data:e}),ZO=e=>ke({method:"post",url:"/v1/user/nickname",data:e}),JO=e=>ke({method:"post",url:"/v1/user/avatar",data:e}),Tf=(e={})=>ke({method:"get",url:"/v1/user/msgcount/unread",params:e}),QO=e=>ke({method:"get",url:"/v1/user/messages",params:e}),eI=e=>ke({method:"post",url:"/v1/user/message/read",data:e}),tI=e=>ke({method:"get",url:"/v1/user/collections",params:e}),rI=e=>ke({method:"get",url:"/v1/user/profile",params:e}),oI=e=>ke({method:"get",url:"/v1/user/posts",params:e}),nI=e=>ke({method:"get",url:"/v1/user/wallet/bills",params:e}),iI=e=>ke({method:"post",url:"/v1/user/recharge",data:e}),aI=e=>ke({method:"get",url:"/v1/user/recharge",params:e}),lI=e=>ke({method:"get",url:"/v1/suggest/users",params:e}),sI=e=>ke({method:"get",url:"/v1/suggest/tags",params:e}),cI=e=>ke({method:"get",url:"/v1/attachment/precheck",params:e}),dI=e=>ke({method:"get",url:"/v1/attachment",params:e}),uI=e=>ke({method:"post",url:"/v1/admin/user/status",data:e});var HA="/assets/logo.52afee68.png";const jA={class:"sidebar-wrap"},NA={class:"logo-wrap"},WA={key:0,class:"user-wrap"},VA={class:"user-info"},KA={class:"nickname"},UA={class:"nickname-txt"},qA={class:"username"},GA={class:"user-mini-wrap"},YA={key:1,class:"user-wrap"},XA={class:"login-wrap"},ZA=sr(" \u767B\u5F55 "),JA=sr(" \u6CE8\u518C "),QA=oe({setup(e){const t=Ba(),r=Zx(),o=Uh(),n=W(!1),i=W(r.name||""),a=W();qe(r,()=>{i.value=r.name}),qe(t.state,()=>{t.state.userInfo.id>0?a.value||(Tf().then(p=>{n.value=p.count>0}).catch(p=>{console.log(p)}),a.value=setInterval(()=>{Tf().then(p=>{n.value=p.count>0}).catch(p=>{console.log(p)})},5e3)):a.value&&clearInterval(a.value)}),Ot(()=>{window.onresize=()=>{t.commit("triggerCollapsedLeft",document.body.clientWidth<=821),t.commit("triggerCollapsedRight",document.body.clientWidth<=821)}});const l=L(()=>{const p=[{label:"\u5E7F\u573A",key:"home",icon:()=>m($f),href:"/"},{label:"\u8BDD\u9898",key:"topic",icon:()=>m(kf),href:"/topic"}];return"false".toLowerCase()==="true"&&p.push({label:"\u516C\u544A",key:"anouncement",icon:()=>m(lA),href:"/anouncement"}),p.push({label:"\u4E3B\u9875",key:"profile",icon:()=>m(Jz),href:"/profile"}),p.push({label:"\u6D88\u606F",key:"messages",icon:()=>m(Nz),href:"/messages"}),p.push({label:"\u6536\u85CF",key:"collection",icon:()=>m(Lz),href:"/collection"}),p.push({label:"\u597D\u53CB",key:"contacts",icon:()=>m(pA),href:"/contacts"}),"false".toLocaleLowerCase()==="true"&&p.push({label:"\u94B1\u5305",key:"wallet",icon:()=>m(TA),href:"/wallet"}),p.push({label:"\u8BBE\u7F6E",key:"setting",icon:()=>m(wA),href:"/setting"}),t.state.userInfo.id>0?p:[{label:"\u5E7F\u573A",key:"home",icon:()=>m($f),href:"/"},{label:"\u8BDD\u9898",key:"topic",icon:()=>m(kf),href:"/topic"}]}),s=p=>"href"in p?m("div",{},p.label):p.label,d=p=>p.key==="messages"?m(v6,{dot:!0,show:n.value,processing:!0},{default:()=>m(Jo,{color:p.key===i.value?"var(--n-item-icon-color-active)":"var(--n-item-icon-color)"},{default:p.icon})}):m(Jo,null,{default:p.icon}),c=(p,b={})=>{i.value=p,o.push({name:p})},u=()=>{r.path==="/"&&t.commit("refresh"),c("home")},f=p=>{t.commit("triggerAuth",!0),t.commit("triggerAuthKey",p)},h=()=>{t.commit("userLogout")};return window.$store=t,window.$message=oR(),(p,b)=>{const g=BE,v=YE,w=o6,$=Ca;return st(),Et("div",jA,[Le("div",NA,[ge(g,{class:"logo-img",width:"36",src:Me(HA),"preview-disabled":!0,onClick:u},null,8,["src"])]),ge(v,{accordion:!0,collapsed:Me(t).state.collapsedLeft,"collapsed-width":64,"icon-size":24,options:Me(l),"render-label":s,"render-icon":d,value:i.value,"onUpdate:value":c},null,8,["collapsed","options","value"]),Me(t).state.userInfo.id>0?(st(),Et("div",WA,[ge(w,{class:"user-avatar",round:"",size:34,src:Me(t).state.userInfo.avatar},null,8,["src"]),Le("div",VA,[Le("div",KA,[Le("span",UA,uo(Me(t).state.userInfo.nickname),1),ge($,{class:"logout",quaternary:"",circle:"",size:"tiny",onClick:h},{icon:Xe(()=>[ge(Me(Jo),null,{default:Xe(()=>[ge(Me(Pf))]),_:1})]),_:1})]),Le("div",qA,"@"+uo(Me(t).state.userInfo.username),1)]),Le("div",GA,[ge($,{class:"logout",quaternary:"",circle:"",onClick:h},{icon:Xe(()=>[ge(Me(Jo),{size:24},{default:Xe(()=>[ge(Me(Pf))]),_:1})]),_:1})])])):(st(),Et("div",YA,[Le("div",XA,[ge($,{strong:"",secondary:"",round:"",type:"primary",onClick:b[0]||(b[0]=x=>f("signin"))},{default:Xe(()=>[ZA]),_:1}),ge($,{strong:"",secondary:"",round:"",type:"info",onClick:b[1]||(b[1]=x=>f("signup"))},{default:Xe(()=>[JA]),_:1})])]))])}}});const eO={"has-sider":"",class:"main-wrap",position:"static"},tO={class:"content-wrap"},rO=oe({setup(e){const t=Ba(),r=L(()=>t.state.theme==="dark"?pR:null);return(o,n)=>{const i=QA,a=bh("router-view"),l=BA,s=zz,d=pk,c=rR,u=L8,f=n4;return st(),mo(f,{theme:Me(r)},{default:Xe(()=>[ge(c,null,{default:Xe(()=>[ge(d,null,{default:Xe(()=>{var h;return[Le("div",{class:ya(["app-container",{dark:((h=Me(r))==null?void 0:h.name)==="dark"}])},[Le("div",eO,[ge(i),Le("div",tO,[ge(a,{class:"app-wrap"},{default:Xe(({Component:p})=>[(st(),mo(h0,null,[o.$route.meta.keepAlive?(st(),mo(xd(p),{key:0})):Yl("",!0)],1024)),o.$route.meta.keepAlive?Yl("",!0):(st(),mo(xd(p),{key:0}))]),_:1})]),ge(l)]),ge(s)],2)]}),_:1})]),_:1}),ge(u)]),_:1},8,["theme"])}}});I1(rO).use(qh).use(vC).mount("#app");export{lI as $,je as A,So as B,EC as C,dO as D,Wm as E,Xa as F,yk as G,ss as H,em as I,Ca as J,_o as K,b$ as L,AC as M,Bt as N,hO as O,Uf as P,Ge as Q,dn as R,qe as S,Tr as T,nt as U,st as V,Et as W,pO as X,Le as Y,Ba as Z,Km as _,m4 as a,bC as a$,sI as a0,Ot as a1,Me as a2,ge as a3,Xe as a4,mo as a5,Yl as a6,Hn as a7,sr as a8,uo as a9,dc as aA,pp as aB,gO as aC,$n as aD,fm as aE,br as aF,V0 as aG,Zo as aH,T3 as aI,Ct as aJ,xr as aK,$3 as aL,Mm as aM,RC as aN,vi as aO,a4 as aP,lm as aQ,di as aR,xi as aS,pn as aT,dm as aU,um as aV,hm as aW,At as aX,Cr as aY,li as aZ,Cs as a_,ot as aa,W0 as ab,AO as ac,o6 as ad,Jo as ae,cv as af,Ek as ag,bg as ah,Zx as ai,Uh as aj,_O as ak,bh as al,iO as am,fO as an,gr as ao,uc as ap,Yr as aq,It as ar,YT as as,pi as at,xC as au,tu as av,cc as aw,Va as ax,Ua as ay,Oc as az,ee as b,Jr as b$,mO as b0,p0 as b1,Xr as b2,vn as b3,ip as b4,km as b5,Gr as b6,cO as b7,n3 as b8,uO as b9,wO as bA,gh as bB,vO as bC,er as bD,bO as bE,Vt as bF,sc as bG,Ya as bH,Sh as bI,FO as bJ,HO as bK,DO as bL,oO as bM,nO as bN,LO as bO,PO as bP,TO as bQ,OO as bR,IO as bS,MO as bT,BO as bU,kO as bV,EO as bW,F4 as bX,$O as bY,RO as bZ,sR as b_,ap as ba,fy as bb,Em as bc,Qt as bd,Da as be,fc as bf,Zr as bg,lr as bh,aO as bi,jn as bj,xd as bk,BE as bl,SO as bm,cI as bn,dI as bo,Pv as bp,yO as bq,wr as br,om as bs,tm as bt,nm as bu,rm as bv,kT as bw,Ka as bx,y$ as by,jm as bz,Ke as c,Az as c0,cR as c1,hR as c2,ya as c3,oI as c4,Ic as c5,rk as c6,WO as c7,VO as c8,oR as c9,YO as cA,ZO as cB,NO as cC,P8 as cD,A8 as cE,R8 as cF,jk as cG,xO as cH,ar as ca,rI as cb,qO as cc,uI as cd,O3 as ce,ye as cf,yi as cg,KO as ch,UO as ci,eI as cj,v6 as ck,QO as cl,tI as cm,zO as cn,mu as co,Op as cp,dr as cq,CO as cr,Ll as cs,nI as ct,iI as cu,aI as cv,jO as cw,JO as cx,XO as cy,GO as cz,oe as d,lO as e,wp as f,hn as g,m as h,be as i,ht as j,Be as k,M as l,F as m,z as n,K as o,ut as p,ze as q,W as r,L as s,Oe as t,lt as u,ae as v,Kr as w,Pn as x,_t as y,bt as z}; diff --git a/web/dist/assets/main-nav.9110259b.js b/web/dist/assets/main-nav.9110259b.js deleted file mode 100644 index 7e8d8466..00000000 --- a/web/dist/assets/main-nav.9110259b.js +++ /dev/null @@ -1,100 +0,0 @@ -import{ao as G,ap as Ce,aq as Be,ar as ze,r as N,c as Re,as as Se,b as Me,l as Q,m as t,at as ee,n as U,o as w,p as te,d as V,u as Ve,q as oe,f as $e,t as Le,g as Fe,s as T,v as _,au as q,av as h,y as Te,aw as K,h as r,z as k,ax as Oe,ay as Ee,k as Y,V as z,W as J,Y as W,Z as Ae,aj as Ne,a1 as Pe,a5 as X,a4 as M,a3 as O,a2 as E,a6 as ne,a8 as De,a9 as We,ae as Ie,J as He,az as je}from"./index.f480f018.js";let A=0;const Ue=typeof window!="undefined"&&window.matchMedia!==void 0,y=N(null);let c,x;function P(e){e.matches&&(y.value="dark")}function D(e){e.matches&&(y.value="light")}function qe(){c=window.matchMedia("(prefers-color-scheme: dark)"),x=window.matchMedia("(prefers-color-scheme: light)"),c.matches?y.value="dark":x.matches?y.value="light":y.value=null,c.addEventListener?(c.addEventListener("change",P),x.addEventListener("change",D)):c.addListener&&(c.addListener(P),x.addListener(D))}function Ke(){"removeEventListener"in c?(c.removeEventListener("change",P),x.removeEventListener("change",D)):"removeListener"in c&&(c.removeListener(P),x.removeListener(D)),c=void 0,x=void 0}let ae=!0;function Ye(){return Ue?(A===0&&qe(),ae&&(ae=Ce())&&(Be(()=>{A+=1}),ze(()=>{A-=1,A===0&&Ke()})),G(y)):G(y)}const Xe=e=>{const{primaryColor:o,opacityDisabled:i,borderRadius:s,textColor3:l}=e,f="rgba(0, 0, 0, .14)";return Object.assign(Object.assign({},Se),{iconColor:l,textColor:"white",loadingColor:o,opacityDisabled:i,railColor:f,railColorActive:o,buttonBoxShadow:"0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05)",buttonColor:"#FFF",railBorderRadiusSmall:s,railBorderRadiusMedium:s,railBorderRadiusLarge:s,buttonBorderRadiusSmall:s,buttonBorderRadiusMedium:s,buttonBorderRadiusLarge:s,boxShadowFocus:`0 0 0 2px ${Me(o,{alpha:.2})}`})},Je={name:"Switch",common:Re,self:Xe};var Ze=Je,Ge=Q("switch",` - height: var(--n-height); - min-width: var(--n-width); - vertical-align: middle; - user-select: none; - display: inline-flex; - outline: none; - justify-content: center; - align-items: center; -`,[t("children-placeholder",` - height: var(--n-rail-height); - display: flex; - flex-direction: column; - overflow: hidden; - pointer-events: none; - visibility: hidden; - `),t("rail-placeholder",` - display: flex; - flex-wrap: none; - `),t("button-placeholder",` - width: calc(1.75 * var(--n-rail-height)); - height: var(--n-rail-height); - `),Q("base-loading",` - position: absolute; - top: 50%; - left: 50%; - transform: translateX(-50%) translateY(-50%); - font-size: calc(var(--n-button-width) - 4px); - color: var(--n-loading-color); - transition: color .3s var(--n-bezier); - `,[ee({originalTransform:"translateX(-50%) translateY(-50%)"})]),t("checked, unchecked",` - transition: color .3s var(--n-bezier); - color: var(--n-text-color); - box-sizing: border-box; - position: absolute; - white-space: nowrap; - top: 0; - bottom: 0; - display: flex; - align-items: center; - line-height: 1; - `),t("checked",` - right: 0; - padding-right: calc(1.25 * var(--n-rail-height) - var(--n-offset)); - `),t("unchecked",` - left: 0; - justify-content: flex-end; - padding-left: calc(1.25 * var(--n-rail-height) - var(--n-offset)); - `),U("&:focus",[t("rail",` - box-shadow: var(--n-box-shadow-focus); - `)]),w("round",[t("rail",{borderRadius:"calc(var(--n-rail-height) / 2)"},[t("button",{borderRadius:"calc(var(--n-button-height) / 2)"})])]),te("disabled",[te("icon",[w("pressed",[t("rail",[t("button",{maxWidth:"var(--n-button-width-pressed)"})])]),t("rail",[U("&:active",[t("button",{maxWidth:"var(--n-button-width-pressed)"})])]),w("active",[w("pressed",[t("rail",[t("button",{left:"calc(100% - var(--n-offset) - var(--n-button-width-pressed))"})])]),t("rail",[U("&:active",[t("button",{left:"calc(100% - var(--n-offset) - var(--n-button-width-pressed))"})])])])])]),w("active",[t("rail",[t("button",{left:"calc(100% - (var(--n-rail-height) + var(--n-button-width)) / 2)"})])]),t("rail",` - overflow: hidden; - height: var(--n-rail-height); - min-width: var(--n-rail-width); - border-radius: var(--n-rail-border-radius); - cursor: pointer; - position: relative; - transition: - background .3s var(--n-bezier), - box-shadow .3s var(--n-bezier); - background-color: var(--n-rail-color); - `,[t("button-icon",` - color: var(--n-icon-color); - transition: color .3s var(--n-bezier); - font-size: calc(var(--n-button-height) - 4px); - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: flex; - justify-content: center; - align-items: center; - line-height: 1; - `,[ee()]),t("button",` - align-items: center; - top: var(--n-offset); - left: var(--n-offset); - height: var(--n-button-width); - width: var(--n-button-width-pressed); - max-width: var(--n-button-width); - border-radius: var(--n-button-border-radius); - background-color: var(--n-button-color); - box-shadow: var(--n-button-box-shadow); - box-sizing: border-box; - cursor: inherit; - content: ""; - position: absolute; - transition: - background-color .3s var(--n-bezier), - left .3s var(--n-bezier), - opacity .3s var(--n-bezier), - max-width .3s var(--n-bezier), - box-shadow .3s var(--n-bezier); - `)]),w("active",[t("rail","background-color: var(--n-rail-color-active);")]),w("disabled",[t("rail",` - cursor: not-allowed; - opacity: .5; - `)]),w("loading",[t("rail",` - pointer-events: none; - `)])]);const Qe=Object.assign(Object.assign({},oe.props),{size:{type:String,default:"medium"},value:{type:[String,Number,Boolean],default:void 0},loading:Boolean,defaultValue:{type:[String,Number,Boolean],default:!1},disabled:{type:Boolean,default:void 0},round:{type:Boolean,default:!0},"onUpdate:value":[Function,Array],onUpdateValue:[Function,Array],checkedValue:{type:[String,Number,Boolean],default:!0},uncheckedValue:{type:[String,Number,Boolean],default:!1},railStyle:Function,onChange:[Function,Array]});var et=V({name:"Switch",props:Qe,setup(e){const{mergedClsPrefixRef:o,inlineThemeDisabled:i}=Ve(e),s=oe("Switch","-switch",Ge,Ze,e,o),l=$e(e),{mergedSizeRef:f,mergedDisabledRef:d}=l,C=N(e.defaultValue),v=Le(e,"value"),u=Fe(v,C),p=T(()=>u.value===e.checkedValue),g=N(!1),a=N(!1),m=T(()=>{const{railStyle:n}=e;if(!!n)return n({focused:a.value,checked:p.value})});function b(n){const{"onUpdate:value":$,onChange:L,onUpdateValue:F}=e,{nTriggerFormInput:I,nTriggerFormChange:H}=l;$&&Y($,n),F&&Y(F,n),L&&Y(L,n),C.value=n,I(),H()}function ie(){const{nTriggerFormFocus:n}=l;n()}function re(){const{nTriggerFormBlur:n}=l;n()}function se(){e.loading||d.value||(u.value!==e.checkedValue?b(e.checkedValue):b(e.uncheckedValue))}function le(){a.value=!0,ie()}function ce(){a.value=!1,re(),g.value=!1}function de(n){e.loading||d.value||n.code==="Space"&&(u.value!==e.checkedValue?b(e.checkedValue):b(e.uncheckedValue),g.value=!1)}function ue(n){e.loading||d.value||n.code==="Space"&&(n.preventDefault(),g.value=!0)}const Z=T(()=>{const{value:n}=f,{self:{opacityDisabled:$,railColor:L,railColorActive:F,buttonBoxShadow:I,buttonColor:H,boxShadowFocus:he,loadingColor:fe,textColor:ve,iconColor:ge,[_("buttonHeight",n)]:R,[_("buttonWidth",n)]:me,[_("buttonWidthPressed",n)]:be,[_("railHeight",n)]:S,[_("railWidth",n)]:j,[_("railBorderRadius",n)]:we,[_("buttonBorderRadius",n)]:pe},common:{cubicBezierEaseInOut:_e}}=s.value,ke=q((h(S)-h(R))/2),xe=q(Math.max(h(S),h(R))),ye=h(S)>h(R)?j:q(h(j)+h(R)-h(S));return{"--n-bezier":_e,"--n-button-border-radius":pe,"--n-button-box-shadow":I,"--n-button-color":H,"--n-button-width":me,"--n-button-width-pressed":be,"--n-button-height":R,"--n-height":xe,"--n-offset":ke,"--n-opacity-disabled":$,"--n-rail-border-radius":we,"--n-rail-color":L,"--n-rail-color-active":F,"--n-rail-height":S,"--n-rail-width":j,"--n-width":ye,"--n-box-shadow-focus":he,"--n-loading-color":fe,"--n-text-color":ve,"--n-icon-color":ge}}),B=i?Te("switch",T(()=>f.value[0]),Z,e):void 0;return{handleClick:se,handleBlur:ce,handleFocus:le,handleKeyup:de,handleKeydown:ue,mergedRailStyle:m,pressed:g,mergedClsPrefix:o,mergedValue:u,checked:p,mergedDisabled:d,cssVars:i?void 0:Z,themeClass:B==null?void 0:B.themeClass,onRender:B==null?void 0:B.onRender}},render(){const{mergedClsPrefix:e,mergedDisabled:o,checked:i,mergedRailStyle:s,onRender:l,$slots:f}=this;l==null||l();const{checked:d,unchecked:C,icon:v,"checked-icon":u,"unchecked-icon":p}=f,g=!(K(v)&&K(u)&&K(p));return r("div",{role:"switch","aria-checked":i,class:[`${e}-switch`,this.themeClass,g&&`${e}-switch--icon`,i&&`${e}-switch--active`,o&&`${e}-switch--disabled`,this.round&&`${e}-switch--round`,this.loading&&`${e}-switch--loading`,this.pressed&&`${e}-switch--pressed`],tabindex:this.mergedDisabled?void 0:0,style:this.cssVars,onClick:this.handleClick,onFocus:this.handleFocus,onBlur:this.handleBlur,onKeyup:this.handleKeyup,onKeydown:this.handleKeydown},r("div",{class:`${e}-switch__rail`,"aria-hidden":"true",style:s},k(d,a=>k(C,m=>a||m?r("div",{"aria-hidden":!0,class:`${e}-switch__children-placeholder`},r("div",{class:`${e}-switch__rail-placeholder`},r("div",{class:`${e}-switch__button-placeholder`}),a),r("div",{class:`${e}-switch__rail-placeholder`},r("div",{class:`${e}-switch__button-placeholder`}),m)):null)),r("div",{class:`${e}-switch__button`},k(v,a=>k(u,m=>k(p,b=>r(Oe,null,{default:()=>this.loading?r(Ee,{key:"loading",clsPrefix:e,strokeWidth:20}):this.checked&&(m||a)?r("div",{class:`${e}-switch__button-icon`,key:m?"checked-icon":"icon"},m||a):!this.checked&&(b||a)?r("div",{class:`${e}-switch__button-icon`,key:b?"unchecked-icon":"icon"},b||a):null})))),k(d,a=>a&&r("div",{key:"checked",class:`${e}-switch__checked`},a)),k(C,a=>a&&r("div",{key:"unchecked",class:`${e}-switch__unchecked`},a)))))}});const tt={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},nt=W("path",{d:"M14.71 6.71a.996.996 0 0 0-1.41 0L8.71 11.3a.996.996 0 0 0 0 1.41l4.59 4.59a.996.996 0 1 0 1.41-1.41L10.83 12l3.88-3.88c.39-.39.38-1.03 0-1.41z",fill:"currentColor"},null,-1),at=[nt];var ot=V({name:"ChevronLeftRound",render:function(o,i){return z(),J("svg",tt,at)}});const it={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},rt=W("path",{d:"M9.37 5.51A7.35 7.35 0 0 0 9.1 7.5c0 4.08 3.32 7.4 7.4 7.4c.68 0 1.35-.09 1.99-.27A7.014 7.014 0 0 1 12 19c-3.86 0-7-3.14-7-7c0-2.93 1.81-5.45 4.37-6.49zM12 3a9 9 0 1 0 9 9c0-.46-.04-.92-.1-1.36a5.389 5.389 0 0 1-4.4 2.26a5.403 5.403 0 0 1-3.14-9.8c-.44-.06-.9-.1-1.36-.1z",fill:"currentColor"},null,-1),st=[rt];var lt=V({name:"DarkModeOutlined",render:function(o,i){return z(),J("svg",it,st)}});const ct={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},dt=W("path",{d:"M12 9c1.65 0 3 1.35 3 3s-1.35 3-3 3s-3-1.35-3-3s1.35-3 3-3m0-2c-2.76 0-5 2.24-5 5s2.24 5 5 5s5-2.24 5-5s-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58a.996.996 0 0 0-1.41 0a.996.996 0 0 0 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37a.996.996 0 0 0-1.41 0a.996.996 0 0 0 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0a.996.996 0 0 0 0-1.41l-1.06-1.06zm1.06-10.96a.996.996 0 0 0 0-1.41a.996.996 0 0 0-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36a.996.996 0 0 0 0-1.41a.996.996 0 0 0-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z",fill:"currentColor"},null,-1),ut=[dt];var ht=V({name:"LightModeOutlined",render:function(o,i){return z(),J("svg",ct,ut)}});const ft={class:"navbar"},gt=V({props:{title:{default:""},back:{type:Boolean,default:!1},theme:{type:Boolean,default:!0}},setup(e){const o=e,i=Ae(),s=Ne(),l=d=>{d?(localStorage.setItem("PAOPAO_THEME","dark"),i.commit("triggerTheme","dark")):(localStorage.setItem("PAOPAO_THEME","light"),i.commit("triggerTheme","light"))},f=()=>{window.history.length<=1?s.push({path:"/"}):s.go(-1)};return Pe(()=>{localStorage.getItem("PAOPAO_THEME")||l(Ye()==="dark")}),(d,C)=>{const v=Ie,u=He,p=et,g=je;return z(),X(g,{size:"small",bordered:!0,class:"nav-title-card"},{header:M(()=>[W("div",ft,[e.back?(z(),X(u,{key:0,class:"back-btn",onClick:f,quaternary:"",circle:"",size:"small"},{icon:M(()=>[O(v,null,{default:M(()=>[O(E(ot))]),_:1})]),_:1})):ne("",!0),De(" "+We(o.title)+" ",1),o.theme?(z(),X(p,{key:1,value:E(i).state.theme==="dark","onUpdate:value":l,size:"small",class:"theme-switch-wrap"},{"checked-icon":M(()=>[O(v,{component:E(ht)},null,8,["component"])]),"unchecked-icon":M(()=>[O(v,{component:E(lt)},null,8,["component"])]),_:1},8,["value"])):ne("",!0)])]),_:1})}}});export{gt as _}; diff --git a/web/dist/assets/post-item.03452002.js b/web/dist/assets/post-item.03452002.js deleted file mode 100644 index 4844606e..00000000 --- a/web/dist/assets/post-item.03452002.js +++ /dev/null @@ -1 +0,0 @@ -import{p as O,H as $,C as j,B as D,_ as E,a as F,b as L,c as M}from"./content.ef1e095a.js";import{d as R,ai as S,aj as I,Z as P,s as W,al as Y,V as o,W as f,a3 as i,am as Z,a2 as t,a4 as n,aa as A,ab as G,a7 as v,Y as u,a8 as p,a9 as c,a5 as r,a6 as _,ad as J,an as K,ae as Q,ag as U}from"./index.f480f018.js";import{f as X}from"./formatTime.02109bf5.js";import{_ as tt}from"./Thing.eef6b133.js";const et={class:"nickname-wrap"},st={class:"username-wrap"},at=p(" \u7F6E\u9876 "),nt=p(" \u79C1\u5BC6 "),ot=p(" \u597D\u53CB\u53EF\u89C1 "),it={class:"timestamp"},rt=["innerHTML"],_t={class:"opt-item"},ct={class:"opt-item"},pt={class:"opt-item"},ht=R({props:{post:null},setup(x){const C=x;S();const m=I(),B=P(),e=W(()=>{let a=Object.assign({texts:[],imgs:[],videos:[],links:[],attachments:[],charge_attachments:[]},C.post);return a.contents.map(s=>{(+s.type==1||+s.type==2)&&a.texts.push(s),+s.type==3&&a.imgs.push(s),+s.type==4&&a.videos.push(s),+s.type==6&&a.links.push(s),+s.type==7&&a.attachments.push(s),+s.type==8&&a.charge_attachments.push(s)}),a}),k=a=>{m.push({name:"post",query:{id:a}})},b=(a,s)=>{if(a.target.dataset.detail){const l=a.target.dataset.detail.split(":");if(l.length===2){B.commit("refresh"),l[0]==="tag"?m.push({name:"home",query:{q:l[1],t:"tag"}}):m.push({name:"user",query:{username:l[1]}});return}}k(s)};return(a,s)=>{const l=J,z=Y("router-link"),d=K,y=E,w=F,T=L,q=M,h=Q,N=U,V=tt;return o(),f("div",{class:"post-item",onClick:s[2]||(s[2]=g=>k(t(e).id))},[i(V,{"content-indented":""},Z({avatar:n(()=>[i(l,{round:"",size:30,src:t(e).user.avatar},null,8,["src"])]),header:n(()=>[u("span",et,[i(z,{onClick:s[0]||(s[0]=v(()=>{},["stop"])),class:"username-link",to:{name:"user",query:{username:t(e).user.username}}},{default:n(()=>[p(c(t(e).user.nickname),1)]),_:1},8,["to"])]),u("span",st," @"+c(t(e).user.username),1),t(e).is_top?(o(),r(d,{key:0,class:"top-tag",type:"warning",size:"small",round:""},{default:n(()=>[at]),_:1})):_("",!0),t(e).visibility==1?(o(),r(d,{key:1,class:"top-tag",type:"error",size:"small",round:""},{default:n(()=>[nt]),_:1})):_("",!0),t(e).visibility==2?(o(),r(d,{key:2,class:"top-tag",type:"info",size:"small",round:""},{default:n(()=>[ot]),_:1})):_("",!0)]),"header-extra":n(()=>[u("span",it,c(t(e).ip_loc?t(e).ip_loc+" \xB7 ":t(e).ip_loc)+" "+c(t(X)(t(e).created_on)),1)]),footer:n(()=>[t(e).attachments.length>0?(o(),r(y,{key:0,attachments:t(e).attachments},null,8,["attachments"])):_("",!0),t(e).charge_attachments.length>0?(o(),r(y,{key:1,attachments:t(e).charge_attachments,price:t(e).attachment_price},null,8,["attachments","price"])):_("",!0),t(e).imgs.length>0?(o(),r(w,{key:2,imgs:t(e).imgs},null,8,["imgs"])):_("",!0),t(e).videos.length>0?(o(),r(T,{key:3,videos:t(e).videos},null,8,["videos"])):_("",!0),t(e).links.length>0?(o(),r(q,{key:4,links:t(e).links},null,8,["links"])):_("",!0)]),action:n(()=>[i(N,{justify:"space-between"},{default:n(()=>[u("div",_t,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t($))]),_:1}),p(" "+c(t(e).upvote_count),1)]),u("div",ct,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t(j))]),_:1}),p(" "+c(t(e).comment_count),1)]),u("div",pt,[i(h,{size:"18",class:"opt-item-icon"},{default:n(()=>[i(t(D))]),_:1}),p(" "+c(t(e).collection_count),1)])]),_:1})]),_:2},[t(e).texts.length>0?{name:"description",fn:n(()=>[(o(!0),f(A,null,G(t(e).texts,g=>(o(),f("span",{key:g.id,class:"post-text",onClick:s[1]||(s[1]=v(H=>b(H,t(e).id),["stop"])),innerHTML:t(O)(g.content).content},null,8,rt))),128))])}:void 0]),1024)])}}});export{ht as _}; diff --git a/web/dist/assets/post-skeleton.39a35f5b.js b/web/dist/assets/post-skeleton.39a35f5b.js deleted file mode 100644 index 57595403..00000000 --- a/web/dist/assets/post-skeleton.39a35f5b.js +++ /dev/null @@ -1 +0,0 @@ -import{ah as r,d as c,V as s,W as n,ab as l,Y as a,a3 as t,aa as p}from"./index.f480f018.js";import{b as d}from"./Skeleton.57e98fe3.js";const i={class:"user"},u={class:"content"},m=c({props:{num:{default:1}},setup(o){return(v,f)=>{const e=d;return s(!0),n(p,null,l(new Array(o.num),_=>(s(),n("div",{class:"skeleton-item",key:_},[a("div",i,[t(e,{circle:"",size:"small"})]),a("div",u,[t(e,{text:"",repeat:3}),t(e,{text:"",style:{width:"60%"}})])]))),128)}}});var h=r(m,[["__scopeId","data-v-a6d56894"]]);export{h as _}; diff --git a/web/dist/index.html b/web/dist/index.html index a71980a3..729d3d7c 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -6,8 +6,8 @@ 泡泡 - - + + diff --git a/web/src/components/compose.vue b/web/src/components/compose.vue index 42b28006..b4faf3ec 100644 --- a/web/src/components/compose.vue +++ b/web/src/components/compose.vue @@ -340,7 +340,7 @@ const loadSuggestionUsers = debounce((k) => { }) .then((res) => { let options: MentionOption[] = []; - res.map((i) => { + res.suggest.map((i) => { options.push({ label: i, value: i, @@ -361,7 +361,7 @@ const loadSuggestionTags = debounce((k) => { }) .then((res) => { let options: MentionOption[] = []; - res.map((i) => { + res.suggest.map((i) => { options.push({ label: i, value: i, diff --git a/web/src/components/post-attachment.vue b/web/src/components/post-attachment.vue index a3d01bf8..689e8eae 100644 --- a/web/src/components/post-attachment.vue +++ b/web/src/components/post-attachment.vue @@ -96,7 +96,7 @@ const execDownloadAction = () => { id: attachmentID.value, }) .then((res) => { - window.open(res.replace('http://', 'https://'), '_blank'); + window.open(res.signed_url.replace('http://', 'https://'), '_blank'); }) .catch((err) => { console.log(err); diff --git a/web/src/components/rightbar.vue b/web/src/components/rightbar.vue index 1d680183..58da2402 100644 --- a/web/src/components/rightbar.vue +++ b/web/src/components/rightbar.vue @@ -84,7 +84,7 @@ const loadTags = () => { num: 12, }) .then((res) => { - tags.value = res; + tags.value = res.topics; loading.value = false; }) .catch((err) => { diff --git a/web/src/types/NetReq.d.ts b/web/src/types/NetReq.d.ts index 9fd63578..b317c587 100644 --- a/web/src/types/NetReq.d.ts +++ b/web/src/types/NetReq.d.ts @@ -24,14 +24,21 @@ declare module NetReq { pager: Item.PagerProps } - type UserGetSuggestUsers = string[] - type UserGetSuggestTags = string[] + interface UserGetSuggestUsers { + suggest: string[] + } + + interface UserGetSuggestTags { + suggest: string[] + } interface UserPrecheckAttachment { paid: number } - type UserGetAttachment = string + interface UserGetAttachment { + signed_url: string + } interface UserGetUnreadMsgCount { count: number @@ -151,7 +158,9 @@ declare module NetReq { status: boolean } - type PostGetTags = Item.TagProps[] + interface PostGetTags { + topics: Item.TagProps[] + } interface PostGetPostComments { /** 评论列表 */ diff --git a/web/src/views/Topic.vue b/web/src/views/Topic.vue index 303accb2..dd91b9b5 100644 --- a/web/src/views/Topic.vue +++ b/web/src/views/Topic.vue @@ -54,7 +54,7 @@ const loadTags = () => { num: 50, }) .then((res) => { - tags.value = res; + tags.value = res.topics; loading.value = false; }) .catch((err) => {